一级a做爰网站免费,中国十大搜索引擎网站,工信部信息备案网站首页,西安千叶网站建设今天是第七专题#xff0c;主要内容是#xff1a;导入ArduinoUZlib功能库#xff0c;借助该库把从【和风天气】官网返回的经过Gzip压缩的JSON数据#xff0c;进行解压缩和t解析#xff0c;在串口监视器上输出解析后的JSON信息。 如您需要了解其它专题的内容#xff0c;请… 今天是第七专题主要内容是导入ArduinoUZlib功能库借助该库把从【和风天气】官网返回的经过Gzip压缩的JSON数据进行解压缩和t解析在串口监视器上输出解析后的JSON信息。 如您需要了解其它专题的内容请点击下面的链接。 第一专题内容请参考连接点亮SPI-TFT屏幕和UI布局设计 第二专题内容请参考WIFI模式设置及连接 第三专题内容请参考连接SHT30传感器获取并显示当前环境温湿度数据I2C 第四专题内容请参考通过NTPClient库获取实时网络时间并显示在TFT屏幕上 第五专题内容请参考获取关于城市天气实况和天气预报的JSON信息心知天气版 第六专题内容请参考解析天气信息JSON数据并显示在 TFT 屏幕上心知天气版
一、【心知天气】官网JSON数据特点 1、订阅模式。和风天气开发服务采用订阅模式当你创建项目时至少需要选择一种订阅。使用和风天气的服务订阅非常简单和自由免费或者你只需要为你实际使用的部分付费。现有三种订阅模式免费订阅、标准订阅、高级订阅。 每种订阅模式均可获取完整的天气信息数据。区别主要体现在数据请求量和更新频率方面。 2、经过压缩的JSON数据。通过官网API接口返回的JSON数据是进行Gzip压缩后的JSON数据客户端需要先进行解压缩然后再借助ArduinoJson功能库解析出解压缩后JSON数据比心知天气返回JSON数据增加了一个解压缩过程。 3、获取和风天气数据的方法。如果需要获得通过官网API接口返回的天气信息数据需要首先心知天气注册账号、创建项目、选择订阅模式然后获取API访问密钥KEY。具体操作方法网上有很多文档可供参考请自行查询比如如何获取和风天气Web API的KEY
二、添加ArduinoUZlib功能库 1. ArduinoUZlib 的功能。该库是从uzlib移植到Arduino框架的功能库主要用来解压https请求服务器返回的gzip数据。这个库占用内存比较小。 2. 添加库方法。该库暂时无法从 PlatformIO 界面 ------- Libraries 加入。 具体方法是1进入该库 Github 网站下载 zip 压缩文件。
2解压 zip 文件生 成ArduinoUZlib-main 文件夹。 3将此文件夹复制到 项目目录下的 lib 文件夹内就可以使用该库的全部功能了。 三、主要功能函数 该库使用方法简单方便主要是通过调用 ArduinoUZlib::decompress(inbuff, size, outbuf,outsize) 这个功能函数来实现。
size_t size stream-available(); // 还剩下多少数据没有读完
uint8_t inbuff[size]; // 准备一个数组来装流数据有多少装多少
stream-readBytes(inbuff, size); // 将http流数据写入inbuff中
uint8_t *outbufNULL; //解压后的输出流
uint32_t outsize0; // 解压后多大在调用解压方法后会被赋值。
// 调用解压函数
int resultArduinoUZlib::decompress(inbuff, size, outbuf,outsize);
// 输出解密后的数据到控制台。
Serial.write(outbuf,outsize); 详细内容可参考该库 example 目录下的示例StreamHttpsClientGzipDemo用来解压缩返回的 gzip数据。
/**StreamHTTPClient.inoCreated on: 24.05.2015*/
#include ArduinoJson.h
#include Arduino.h
#include ArduinoUZlib.h
#include ESP8266WiFi.h
#include ESP8266WiFiMulti.h#include ESP8266HTTPClient.h
ESP8266WiFiMulti WiFiMulti;// ESP.getFreeHeap(), ESP.getMinFreeHeap(), ESP.getHeapSize(), ESP.getMaxAllocHeap()
void heap(){Serial.print(FREE_HEAP[);Serial.print(ESP.getFreeHeap());Serial.print(]\n);
}
void setup() {Serial.begin(115200);// Serial.setDebugOutput(true);Serial.println();Serial.println();Serial.println();for (uint8_t t 4; t 0; t--) {Serial.printf([SETUP] WAIT %d...\n, t);Serial.flush();delay(1000);}WiFi.mode(WIFI_STA);WiFiMulti.addAP(ssid, password);
}
void log(const char *str) {Serial.println(str);
}static uint8_t buffer[1280]{0};
size_t readBytesSize0;void fetchBuffer() {if ((WiFiMulti.run() WL_CONNECTED)) {std::unique_ptrBearSSL::WiFiClientSecure client(new BearSSL::WiFiClientSecure);client-setInsecure();Serial.print([HTTPS] begin...\n);HTTPClient https;if (https.begin(*client, https://192.168.2.144:8082/test)) {https.addHeader(Accept-Encoding, gzip);Serial.print([HTTPS] GET...\n);// start connection and send HTTP headerint httpCode https.GET();if (httpCode 0) {// HTTP header has been send and Server response header has been handledSerial.printf([HTTPS] GET... code: %d\n, httpCode);// file found at serverif (httpCode HTTP_CODE_OK) {// get length of document (is -1 when Server sends no Content-Length header)int len https.getSize();// create buffer for readstatic uint8_t buff[128] { 0 };// read all data from serverint offset0;Serial.println(allocate);// 为什么这里分配内存会报错// if(inbufNULL) inbuf(uint8_t*)malloc(sizeof(uint8_t)*128);while (https.connected() (len 0 || len -1)) {// get available data sizesize_t size client-available();if (size) {// read up to 128 byteint c client-readBytes(buff, ((size sizeof(buff)) ? sizeof(buff) : size));// int c client-readBytes(buff, size);// Serial.println(memcpy);memcpy(bufferoffset, buff, sizeof(uint8_t)*c);offsetc;if(c0 c!16) {log(rb);Serial.printf(%d,, buff[c-3]);Serial.printf(%d,, buff[c-2]);Serial.printf(%d,, buff[c-1]);log(\nrb end);}// write it to Serial// Serial.write(buff, c);if (len 0) {len - c;}}delay(1);}readBytesSizeoffset;Serial.printf(offset%d\n, offset);Serial.write(buffer, offset);Serial.print([HTTPS] connection closed or file end.\n);}} else {Serial.printf([HTTPS] GET... failed, error: %s\n, https.errorToString(httpCode).c_str());}https.end();} else {Serial.printf(Unable to connect\n);}}
}void loop() {uint8_t *outbuf1NULL;// wait for WiFi connectionfetchBuffer();Serial.printf(\nAfter fetch, buffer size%d\n, readBytesSize);delay(1000);if(readBytesSize) {// write it to Seriallog(buf);Serial.printf(%d,, readBytesSize-3);Serial.printf(%d,, readBytesSize-2);Serial.printf(%d,, readBytesSize-1);log(\nbuf end); Serial.write(buffer,readBytesSize);uint32_t out_size0;int resultArduinoUZlib::decompress(buffer, readBytesSize, outbuf1, out_size);printf(outsize%d, result\n, out_size,result);parseJSON((char*)outbuf1, out_size);// Serial.write(outbuf,out_size);}else {Serial.println(no avali size!);}
if (outbuf1!NULL){free(outbuf1);outbuf1NULL;
}Serial.println(Wait 10s before the next round...);delay(5000);
}void parseJSON(char *input, int inputLength) {// char* input;// size_t inputLength; (optional)DynamicJsonDocument doc(6144);DeserializationError error deserializeJson(doc, input, inputLength);if (error) {Serial.print(F(deserializeJson() failed: ));Serial.println(error.f_str());return;}const char* code doc[code]; // 200const char* updateTime doc[updateTime]; // 2022-12-05T15:3508:00const char* fxLink doc[fxLink]; // http://hfx.link/1u0r1for (JsonObject hourly_item : doc[hourly].asJsonArray()) {// const char* hourly_item_fxTime hourly_item[fxTime]; // 2022-12-05T17:0008:00, ...const char* hourly_item_fxTime hourly_item[fxTime]; // 2022-12-05T17:0008:00, ...const char* hourly_item_temp hourly_item[temp]; // 15, 13, 13, 12, 11, 11, 10, 10, ...Serial.printf(%s,, hourly_item_temp);const char* hourly_item_icon hourly_item[icon]; // 100, 150, 150, 150, 150, 150, 150, ...const char* hourly_item_text hourly_item[text]; // 晴, 晴, 晴, 晴, 晴, 晴, 晴, 多云, 多云, ...const char* hourly_item_wind360 hourly_item[wind360]; // 22, 24, 30, 33, 33, 31, 30, ...const char* hourly_item_windDir hourly_item[windDir]; // 东北风, 东北风, 东北风, 东北风, 东北风, 东北风, ...const char* hourly_item_windScale hourly_item[windScale]; // 3-4, 3-4, 3-4, 3-4, 3-4, ...const char* hourly_item_windSpeed hourly_item[windSpeed]; // 16, 16, 16, 16, 14, 14, ...const char* hourly_item_humidity hourly_item[humidity]; // 57, 63, 63, 65, 66, 67, 68, ...const char* hourly_item_pop hourly_item[pop]; // 1, 3, 6, 6, 6, 6, 6, 6, 7, 7, ...const char* hourly_item_precip hourly_item[precip]; // 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, ...const char* hourly_item_pressure hourly_item[pressure]; // 1013, 1013, 1012, 1012, 1012, ...const char* hourly_item_cloud hourly_item[cloud]; // 5, 5, 4, 4, 7, 9, 11, 33, 54, ...const char* hourly_item_dew hourly_item[dew]; // 7, 6, 6, 6, 5, 5, 5, 5, 5, 4, ...}Serial.println();JsonArray refer_sources doc[refer][sources];const char* refer_sources_0 refer_sources[0]; // QWeatherconst char* refer_sources_1 refer_sources[1]; // NMCconst char* refer_sources_2 refer_sources[2]; // ECMWFconst char* refer_license_0 doc[refer][license][0]; // CC BY-SA 4.0}
四、和风天气JSON数据的解压缩实现 这是个实现解压缩和风天气JSON数据的简单示例1将服务器进行Gzip压缩后返回的JSON数据接收并保存到缓冲区 buffer 中2调用 ArduinoUZlib::decompress(inbuffer, size, outbuffer,outsize) 解压 buffer 中的经过压缩的JSON数据同时将解压后JSON数据保存到输出 outbuffer 中3调用 ArduinoJson 库的 deserializeJson(doc, outbuffer) 函数对明文JSON数据进行解析并保存到实况天气数据结构 wd 中然后通过串口监视器输出。 具体内容请仔细阅读下面的代码实现。
// 实时天气
struct weather_data
{int code -1; // API状态码具体含义请参考状态码String updateTime ; // 当前API的最近更新时间String now_obsTime ; // 数据观测时间String now_temp 0; // 温度默认单位摄氏度int now_feelsLike 0; // 体感温度默认单位摄氏度String now_icon ; // 天气状况和图标的代码图标可通过天气状况和图标下载String now_text ; // 天气状况的文字描述包括阴晴雨雪等天气状态的描述String now_wind360 -1; // 风向360角度String now_windDir ; // 风向String now_windScale -1; // 风力等级int now_windSpeed -1; // 风速公里/小时int now_humidity -1; // 相对湿度百分比数值int now_precip -1; // 当前小时累计降水量默认单位毫米int now_pressure -1; // 大气压强默认单位百帕int now_vis -1; // 能见度默认单位公里
} wd;void get_now_weather_data(JsonDocument doc);size_t readBytesSize 0;// 用来存放解压前的JSON数据
static uint8_t buffer[1280] {0};// 用来存放解压后的JSON数据
uint8_t *outbuffer NULL;// 获取实时天气数据
void get_now_Weather()
{// 检查WIFI是否连接if ((WiFi.status() WL_CONNECTED)){// 准备发起请求std::unique_ptrBearSSL::WiFiClientSecure client(new BearSSL::WiFiClientSecure);client-setInsecure();Serial.print([HTTPS] begin...\n);HTTPClient https;if (https.begin(*client, https://devapi.qweather.com/v7/weather/now?key key location cityid)){https.addHeader(Accept-Encoding, gzip);Serial.print([HTTPS] GET...\n);// start connection and send HTTP headerint httpCode https.GET();if (httpCode 0){// HTTP header has been send and Server response header has been handledSerial.printf([HTTPS] GET... code: %d\n, httpCode);// file found at serverif (httpCode HTTP_CODE_OK){// get length of document (is -1 when Server sends no Content-Length header)int len https.getSize();// create buffer for readstatic uint8_t buff[128] {0};// read all data from serverint offset 0;// 为什么这里分配内存会报错// if(inbufNULL) inbuf(uint8_t*)malloc(sizeof(uint8_t)*128);while (https.connected() (len 0 || len -1)){// get available data sizesize_t size client-available();if (size){// read up to 128 byteint c client-readBytes(buff, ((size sizeof(buff)) ? sizeof(buff) : size));memcpy(buffer offset, buff, sizeof(uint8_t) * c);offset c;// write it to Serial// Serial.write(buff, c);if (len 0){len - c;}}delay(1);}readBytesSize offset;delay(1000);if (readBytesSize){// write it to SerialSerial.write(buffer, readBytesSize);Serial.println();uint32_t out_size 0;ArduinoUZlib::decompress(buffer, readBytesSize, outbuffer, out_size);Serial.write(outbuffer, out_size);// 调用解析函数JsonDocument doc;DeserializationError err deserializeJson(doc, outbuffer);if (err.code() DeserializationError::Ok){get_now_weather_data(doc);}else{Serial.println(数据解析出错);}}else{Serial.println(no avali size!);}if (outbuffer ! NULL){free(outbuffer);outbuffer NULL;}}}else{Serial.printf([HTTPS] GET... failed, error: %s\n, https.errorToString(httpCode).c_str());}https.end();}else{Serial.printf(Unable to connect\n);}}
}void get_now_weather_data(JsonDocument doc)
{// 将数据保存到weahter_data 的结构体方便后续调用Serial.println();wd.code doc[code];wd.updateTime doc[updateTime].asString().substring(0, 16);wd.now_obsTime doc[now][obsTime].asString().substring(0, 16);wd.updateTime.replace(T, );wd.now_obsTime.replace(T, );wd.now_temp doc[now][temp].asString();wd.now_feelsLike doc[now][feelsLike].asint();wd.now_icon doc[now][icon].asString();wd.now_text doc[now][text].asString();wd.now_wind360 doc[now][wind360].asString();wd.now_windDir doc[now][windDir].asString();wd.now_windScale doc[now][windScale].asString();wd.now_windSpeed doc[now][windSpeed].asint();wd.now_humidity doc[now][humidity].asint();wd.now_precip doc[now][precip].asint();wd.now_pressure doc[now][pressure].asint();wd.now_vis doc[now][vis].asint();Serial.print(wd.code: );Serial.println(wd.code);Serial.print(wd.updateTime: );Serial.println(wd.updateTime);Serial.print(wd.now_obsTime: );Serial.println(wd.now_obsTime);Serial.print(wd.now_temp: );Serial.println(wd.now_temp);Serial.print(wd.now_feelsLike: );Serial.println(wd.now_feelsLike);Serial.print(wd.now_icon: );Serial.println(wd.now_icon);Serial.print(wd.now_text: );Serial.println(wd.now_text);Serial.print(wd.now_wind360: );Serial.println(wd.now_wind360);Serial.print(wd.now_windDir: );Serial.println(wd.now_windDir);Serial.print(wd.now_windScale: );Serial.println(wd.now_windScale);Serial.print(wd.now_windSpeed: );Serial.println(wd.now_windSpeed);Serial.print(wd.now_humidity: );Serial.println(wd.now_humidity);Serial.print(wd.now_precip: );Serial.println(wd.now_precip);Serial.print(wd.now_pressure: );Serial.println(wd.now_pressure);Serial.print(wd.now_vis: );Serial.println(wd.now_vis);
}
五、解压缩JSON数据源代码下载和运行效果展示 百度网盘下载UZlib_Qweather_CompressedJsonData_7 提取码ivfq 友情提示1请务必将 ssid 和 password 修改成您所在环境的名称和密码2请务必const String key 修改成您自己申请的和风天气API密钥。 如果您能在串口监视器看到如下信息那么恭喜您程序运行成功了。 参考文档 1. JSON 基本使用_json怎么用-CSDN博客 2. 如何获取和风天气Web API的KEY简要步骤_天气预报web api key-CSDN博客 3. JSON——概述、JSON语法、序列化和反序列化_所有文档都可以通过json序列化吗-CSDN博客