【Arduino TFT】Arduino uzlib库,用于解压gzip流,解析和风天气返回数据

news2024/11/18 7:35:44

忘记过去,超越自己

  • ❤️ 博客主页 单片机菜鸟哥,一个野生非专业硬件IOT爱好者 ❤️
  • ❤️ 本篇创建记录 2023-10-21 ❤️
  • ❤️ 本篇更新记录 2023-10-21 ❤️
  • 🎉 欢迎关注 🔎点赞 👍收藏 ⭐️留言📝
  • 🙏 此博客均由博主单独编写,不存在任何商业团队运营,如发现错误,请留言轰炸哦!及时修正!感谢支持!
  • 🔥 Arduino ESP8266教程累计帮助过超过1W+同学入门学习硬件网络编程,入选过选修课程,刊登过无线电杂志 🔥零基础从入门到熟悉Arduino平台下开发ESP8266,同时会涉及网络编程知识。专栏文章累计超过60篇,分为基础篇、网络篇、应用篇、高级篇,涵盖ESP8266大部分开发技巧。

快速导航
单片机菜鸟的博客快速索引(快速找到你要的)

如果觉得有用,麻烦点赞收藏,您的支持是博主创作的动力。

文章目录

    • 1. 前言
    • 2. 相关代码

1. 前言

在做和风天气获取天气信息的时候,由于和风天气采用Gzip压缩方式返回数据流,返回的数据需要解压。

默认,已经申请了和风天气免费Key
https://dev.qweather.com/docs/api/weather/weather-now/
在这里插入图片描述

而刚好有一个Arduino库用于这种功能,

https://github.com/tignioj/ArduinoUZlib
在这里插入图片描述

2. 相关代码

和风天气API采用HTTPS方式获取相关天气数据,并且返回数据采用GZIP压缩方式。
获取数据后,使用UZlib库里的 int result=ArduinoUZlib::decompress(inbuff, size, outbuf,outsize);函数进行解压。

HeFeng.h代码


#pragma once
#include <ArduinoJson.h>

typedef struct HeFengCurrentData {

  String cond_txt;
  String fl;
  String tmp;
  String hum;
  String wind_sc;
  String iconMeteCon;
}
HeFengCurrentData;
typedef struct HeFengForeData {
  String dateStr;
  String tmp_min;
  String tmp_max;
  String iconMeteCon;

}
HeFengForeData;
class HeFeng {
  private:
    String getMeteConIcon(String cond_code);
    bool fetchBuffer(const char* url);
    static uint8_t _buffer[1024 * 3]; //gzip流最大缓冲区
    static size_t _bufferSize;
  public:
    HeFeng();
    void doUpdateCurr(HeFengCurrentData *data, String key, String location);
    void doUpdateFore(HeFengForeData *data, String key, String location);
};

HeFeng.cpp代码


#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>
#include "ArduinoUZlib.h" // gzip库
#include "HeFeng.h"

uint8_t HeFeng::_buffer[1024 * 3];
size_t HeFeng::_bufferSize = 0;

HeFeng::HeFeng() {
}

bool HeFeng::fetchBuffer(const char *url)
{
    _bufferSize = 0;
    std::unique_ptr<WiFiClientSecure> client(new WiFiClientSecure);
    client->setInsecure();
    HTTPClient https;
    Serial.print("[HTTPS] begin...now\n");
    if (https.begin(*client, url))
    {
        https.addHeader("Accept-Encoding", "gzip");
        https.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0");
        int httpCode = https.GET();
        if (httpCode > 0)
        {
            if (httpCode == HTTP_CODE_OK)
            {
                int len = https.getSize(); // get length of document (is -1 when Server sends no Content-Length header)
                static uint8_t buff[128 * 1] = {0}; // create buffer for read
                int offset = 0;                 // read all data from server
                while (https.connected() && (len > 0 || len == -1))
                {
                    size_t size = client->available(); // get available data size
                    if (size)
                    {
                        int c = client->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size));
                        memcpy(_buffer + offset, buff, sizeof(uint8_t) * c);
                        offset += c;
                        if (len > 0)
                        {
                            len -= c;
                        }
                    }
                    delay(1);
                }
                _bufferSize = offset;
            }
        }
        else
        {
            Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
        }
        https.end();
    }else{
        Serial.printf("Unable to connect\n");
    }
    Serial.print("[HTTPS] end...now\n");
    return _bufferSize > 0;
}

void HeFeng::doUpdateCurr(HeFengCurrentData *data, String key, String location) {  //获取天气

  String url = "https://devapi.qweather.com/v7/weather/now?lang=en&gzip=n&location=" + location + "&key=" + key;
  Serial.print("[HTTPS] begin...now\n");
  fetchBuffer(url.c_str()); // HTTPS获取数据流
  if (_bufferSize){
     Serial.print("bufferSize:");
     Serial.println(_bufferSize, DEC);
     uint8_t *outBuf=NULL;
     size_t outLen = 0;
     ArduinoUZlib::decompress(_buffer, _bufferSize, outBuf, outLen); // GZIP解压
     // 输出解密后的数据到控制台。
     Serial.write(outBuf,outLen);
     if(outBuf && outLen){
         DynamicJsonDocument  jsonBuffer(2048);
         deserializeJson(jsonBuffer, (char*)outBuf,outLen);
         JsonObject root = jsonBuffer.as<JsonObject>();

         String tmp = root["now"]["temp"];//温度
         data->tmp = tmp;
         String fl = root["now"]["feelsLike"];//体感温度
         data->fl = fl;
         String hum = root["now"]["humidity"];//湿度
         data->hum = hum;
         String wind_sc = root["now"]["windScale"];//风力
         data->wind_sc = wind_sc;
         String cond_code = root["now"]["icon"];//天气图标
         String meteConIcon = getMeteConIcon(cond_code);
         String cond_txt = root["now"]["text"];//天气
         data->cond_txt = cond_txt;
         data->iconMeteCon = meteConIcon;

         jsonBuffer.clear();
      } else {
         Serial.println("doUpdateCurr failed");
         data->tmp = "-1";
         data->fl = "-1";
         data->hum = "-1";
         data->wind_sc = "-1";
         data->cond_txt = "no network";
         data->iconMeteCon = ")";
      }
      //一定要记得释放内存
      if(outBuf != NULL) {
         free(outBuf);
         outBuf=NULL;
      }
     _bufferSize = 0;
  }
}

void HeFeng::doUpdateFore(HeFengForeData *data, String key, String location) {  //获取预报

  String url = "https://devapi.qweather.com/v7/weather/3d?lang=en&gzip=n&location=" + location + "&key=" + key;
  Serial.print("[HTTPS] begin...forecast\n");
  fetchBuffer(url.c_str()); // HTTPS获取数据流
  if (_bufferSize){
     Serial.print("bufferSize:");
     Serial.println(_bufferSize, DEC);
     uint8_t *outBuf=NULL;
     size_t outLen = 0;
     ArduinoUZlib::decompress(_buffer, _bufferSize, outBuf, outLen); // GZIP解压
     // 输出解密后的数据到控制台。
     Serial.write(outBuf,outLen);
     if(outBuf && outLen){
         DynamicJsonDocument  jsonBuffer(2048);
         deserializeJson(jsonBuffer, (char*)outBuf,outLen);
         JsonObject root = jsonBuffer.as<JsonObject>();

         int i;
         for (i = 0; i < 3; i++) {
           String dateStr = root["daily"][i]["fxDate"];
           data[i].dateStr = dateStr.substring(5, dateStr.length());
           String tmp_min = root["daily"][i]["tempMin"];
           data[i].tmp_min = tmp_min;
           String tmp_max = root["daily"][i]["tempMax"];
           data[i].tmp_max = tmp_max;
           String cond_code = root["daily"][i]["iconDay"];
           String meteConIcon = getMeteConIcon(cond_code);
           data[i].iconMeteCon = meteConIcon;
         }

         jsonBuffer.clear();
      } else {
         int i;
         for (i = 0; i < 3; i++) {
           data[i].tmp_min = "-1";
           data[i].tmp_max = "-1";
           data[i].dateStr = "N/A";
           data[i].iconMeteCon = ")";
         }
      }
      //一定要记得释放内存
      if(outBuf != NULL) {
         free(outBuf);
         outBuf=NULL;
      }
     _bufferSize = 0;
  }
}

String HeFeng::getMeteConIcon(String cond_code) {  //获取天气图标  见 https://dev.qweather.com/docs/start/icons/
  if (cond_code == "100" || cond_code == "150" || cond_code == "9006") {//晴 Sunny/Clear
    return "B";
  }
  if (cond_code == "101") {//多云 Cloudy
    return "Y";
  }
  if (cond_code == "102") {//少云 Few Clouds
    return "N";
  }
  if (cond_code == "103" || cond_code == "153") {//晴间多云 Partly Cloudy/
    return "H";
  }
  if (cond_code == "104" || cond_code == "154") {//阴 Overcast
    return "D";
  }
  if (cond_code == "300" || cond_code == "301") {//阵雨 Shower Rain 301-强阵雨 Heavy Shower Rain
    return "T";
  }
  if (cond_code == "302" || cond_code == "303") {//302-雷阵雨  Thundershower / 303-强雷阵雨
    return "P";
  }
  if (cond_code == "304" || cond_code == "313" || cond_code == "404" || cond_code == "405" || cond_code == "406") {
    //304-雷阵雨伴有冰雹 Freezing Rain
    //313-冻雨 Freezing Rain
    //404-雨夹雪 Sleet
    //405-雨雪天气 Rain And Snow
    //406-阵雨夹雪  Shower Snow
    return "X";
  }
  if (cond_code == "305" || cond_code == "308" || cond_code == "309" || cond_code == "314" || cond_code == "399") {
    //305-小雨 Light Rain
    //308-极端降雨 Extreme Rain
    //309-毛毛雨/细雨 Drizzle Rain
    //314-小到中雨 Light to moderate rain
    //399-雨 Light to moderate rain
    return "Q";
  }
  if (cond_code == "306" || cond_code == "307" || cond_code == "310" || cond_code == "311" || cond_code == "312" || cond_code == "315" || cond_code == "316" || cond_code == "317" || cond_code == "318") {
    //306-中雨 Moderate Rain
    //307-大雨 Heavy Rain
    //310-暴雨  Storm
    //311-大暴雨 Heavy Storm
    //312-特大暴雨 Severe Storm
    //315-中到大雨 Moderate to heavy rain
    //316-大到暴雨 Heavy rain to storm
    //317-暴雨到大暴雨 Storm to heavy storm
    //318-大暴雨到特大暴雨 Heavy to severe storm
    return "R";
  }
  if (cond_code == "400" || cond_code == "408") {
    //400-小雪 Light Snow
    //408-小到中雪 Light to moderate snow
    return "U";
  }
  if (cond_code == "401" || cond_code == "402" || cond_code == "403" || cond_code == "409" || cond_code == "410") {
    //401-中雪 Moderate Snow
    //402-大雪 Heavy Snow
    //403-暴雪 Snowstorm
    //409-中到大雪 Moderate to heavy snow
    //410-大到暴雪 Heavy snow to snowstorm
    return "W";
  }
  if (cond_code == "407") {
    //407-阵雪 Snow Flurry
    return "V";
  }
  if (cond_code == "499" || cond_code == "901") {
    //499-雪 Snow
    //901-冷 Cold
    return "G";
  }
  if (cond_code == "500") {
    //500-薄雾 Mist
    return "E";
  }
  if (cond_code == "501" || cond_code == "509" || cond_code == "510" || cond_code == "514" || cond_code == "515") {
    //501-雾 Foggy
    return "M";
  }
  if (cond_code == "502" || cond_code == "511" || cond_code == "512" || cond_code == "513") {
    //502-霾 Haze
    return "L";
  }
  if (cond_code == "503" || cond_code == "504" || cond_code == "507" || cond_code == "508") {
    //503-扬沙 Sand
    return "F";
  }
  
  if (cond_code == "999") {//未知
    return ")";
  }
  if (cond_code == "213") {
    return "O";
  }
  if (cond_code == "200" || cond_code == "201" || cond_code == "202" || cond_code == "203" || cond_code == "204" || cond_code == "205" || cond_code == "206" || cond_code == "207" || cond_code == "208" || cond_code == "209" || cond_code == "210" || cond_code == "211" || cond_code == "212") {
    return "S";
  }
  return ")";
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1118404.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

开源WAF--Safeline(雷池)测试手册

长亭科技—雷池(SafeLine)社区版 官方网站:长亭雷池 WAF 社区版 (chaitin.cn) WAF 工作在应用层&#xff0c;对基于 HTTP/HTTPS 协议的 Web 系统有着更好的防护效果&#xff0c;使其免于受到黑客的攻击 1.1 雷池的搭建 1.1.1 配置需求 操作系统&#xff1a;Linux 指令架构&am…

【框架源码篇 03】Spring源码手写篇-手写AOP

Spring源码手写篇-手写AOP 手写IoC和DI后已经实现的类图结构。 一、AOP分析 1.AOP是什么? AOP[Aspect Oriented Programming] 面向切面编程&#xff0c;在不改变类的代码的情况下&#xff0c;对类方法进行功能的增强。 2.我们要做什么&#xff1f; 我们需要在前面手写IoC&…

[Spring] SpringBoot2 简介(一)—— 基础配置

目录 一、SpringBoot 简介 1、Spring 的缺点 2、SpringBoot 功能 二、SpringBoot 入门案例 1、实现步骤 2、访问服务器 3、入门小结 4、Idea 快速构建 SpringBoot 工程 5、起步依赖无需版本号 6、主启动类的在项目中的位置&#xff08;*重要*&#xff09; 三、Sprin…

[AUTOSAR][诊断管理][$10] 会话模式控制

文章目录 一、简介二、指令格式请求: 10 SF会话参数记录有P2Server_max(2byte)和P2*Server_max(2byte),高位在前的表示方式。否定相应:7F SID NRC(否定相应码)三、示例代码(1) uds10_session_ctl.c一、简介 $10服务是Diagnostic Session Control诊断会话控制,子功能有01…

机器学习 | Python决策树算法

基本原理 决策树的基本原理是将数据分成不同的子集,使每个子集尽可能纯净。 这意味着子集中的数据属于同一类别或具有相似的属性。 为了做到这一点,决策树会选择一个特征,并根据该特征将数据分成两个子集。 它会选择那个特征,该特征在划分后的子集中具有最好的纯度,通…

Python获取微信公众号文章数据

这是一个通过 Python mitmproxy 库 实现获取某个微信公众号下全部文章数据的解决方案。首先需要创建一个 Python 虚拟环境&#xff0c;并进入虚拟环境下&#xff1a; $ python -m venv venv $ venv/Scripts/activate我们需要使用 mitmproxy 库 来建立一个网络代理&#xff0c;…

设计模式篇---组合模式

文章目录 概念结构实例总结 概念 组合模式&#xff1a;组合多个对象形成树形结构以表示具有部分-整体关系的层次结构。组合模式让客户端可以统一对待单个对象和组合对象。 当我们开发中遇到树形结构的业务时&#xff0c;可以考虑使用组合模式。&#xff08;我也没有想明白为啥…

基于springboot实现财务管理系统项目【项目源码+论文说明】

基于springboot实现财务管理系统演示 摘要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#x…

Ubuntu的EFI分区无法删除

本文解决的问题&#xff1a;双系统装完后需要删除ubuntu的分区&#xff0c;但是EFI系统分区无法删除。 第一步&#xff1a;cmd中输入命令 diskpart 并回车&#xff0c;如图中①&#xff1b; 第二步&#xff1a;在弹出窗口②中依次输入如下命令即可删除EFI分区&#xff1b; /…

基于springboot实现藏区特产销售平台项目【项目源码+论文说明】

基于springboot实现藏区特产销售管理平台演示 摘要 “互联网”的战略实施后&#xff0c;很多行业的信息化水平都有了很大的提升。但是目前很多藏区特产销售信息仍是通过人工管理的方式进行&#xff0c;需要在各个岗位投入大量的人力进行很多重复性工作&#xff0c;使得对人力物…

USRP-2944 配件讲解,如何选择对应的配件

USRP-2944 产品图片 产品官网价格信息 查看附件和价格 硬件服务 NI硬件服务计划通过简化物流&#xff0c;延长正常运行时间以及根据业界标准维护数据的可追溯性&#xff0c;帮助您节省系统组装、设置和维护所需的时间和金钱。这些计划涵盖多年期维修服务&#xff0c;同时还提…

Python 循环

Python有两个基本的循环命令&#xff1a; while循环for循环 while循环 使用while循环&#xff0c;我们可以在条件为真的情况下执行一组语句。 示例&#xff0c;打印i&#xff0c;只要i小于6&#xff1a; i 1 while i < 6:print(i)i 1注意&#xff1a;记得增加i的值&a…

微机原理:汇编语言语句类型与格式

文章目录 壹、语句类型1、语句分类2、常用伪代码和运算符2.1数据定义伪指令2.1.1字节定义伪指令DB&#xff08;8位&#xff09;2.1.2字定义伪指令DW&#xff08;16位&#xff09;2.1.3双字节伪指令DD2.1.4 多字节定义DF/DQ/DT&#xff08;了解&#xff09; 2.2 常用运算符2.2.1…

数据结构-- 并查集

0. 引入 并查集是来解决等价问题的数据结构。 离散数学中的二元关系。 等价关系需满足自反性、对称性、传递性。 a ∈ S , a R a a R b & b R a a R b ∩ b R c > a R c a \in S, aRa \\ aRb \& bRa \\ aRb \cap bRc >aRc a∈S,aRaaRb&bRaaRb∩bRc>a…

【MATLAB源码-第53期】m代码基于粒子群算法(PSO)的三维路径规划,显示最优路径和适应度曲线。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 粒子群算法&#xff08;Particle Swarm Optimization&#xff0c;简称PSO&#xff09;是一种模拟鸟群觅食行为的启发式优化方法。以下是其详细描述&#xff1a; 基本思想&#xff1a; 鸟群在寻找食物时&#xff0c;每只鸟都会…

拦截器以及统一功能的实现

目录 引言 实现一个简单的拦截器 拦截器小结 统一访问前缀 统一异常处理 统一返回参数 ControllerAdvice 引言 HandlerInterceptor是Spring MVC框架提供的一个拦截器接口&#xff0c;它用于对请求进行拦截和处理。在Spring MVC中&#xff0c;拦截器可以用于实现一些通用的功能…

什么是t检验?

t检验&#xff08;t-test&#xff09;是一种统计方法&#xff0c;用于比较两组数据之间的平均值是否存在显著差异。它通常用于分析两组样本的平均值是否具有统计学上的显著性差异。t检验基于正态分布的假设&#xff0c;它计算两组数据之间的t值&#xff0c;然后通过与t分布表进…

YOLO目标检测——人脸口罩佩戴数据集【(含对应voc、coco和yolo三种格式标签】

实际项目应用&#xff1a;公共场所监控场景下的大密度人群检测是否佩戴口罩&#xff0c;以及戴口罩的人证比对&#xff08;安检刷脸不用摘口罩&#xff09;、手机解锁、刷脸考勤等身份认证场景。数据集说明&#xff1a;人脸口罩佩戴检测数据集&#xff0c;真实场景的高质量图片…

reactnative 底部tab页面@react-navigation/bottom-tabs

使用react-navigation/native做的页面导航和tab‘ 官网&#xff1a;https://reactnavigation.org/docs/getting-started 效果图 安装 npm install react-navigation/nativenpm install react-navigation/bottom-tabs封装tabbar.js import { View, StyleSheet, Image } from …

【JavaEE】死锁问题 -- 多线程篇(5)

死锁问题 1. 死锁是什么?2. 如何避免死锁? 1. 死锁是什么? 概念 死锁是这样一种情形: 多个线程同时被阻塞, 它们中的一个或者全部都在等待某个资源被释放, 由于线程被无限期的阻塞, 因此程序不能正常终止。 死锁的三种常见的场景 一个线程, 一把锁, 但是是不可重入锁, 该线程…