[Arduino TFT] Arduino uzlib library, used to decompress gzip streams and parse wind and weather return data

Forget the past and surpass yourself

  • Blog homepage Microcontroller rookie brother, a wild non-professional hardware IOT enthusiast
  • Creation record of this article 2023-10-21
  • Update record of this article 2023-10-21
  • Welcome to follow Like Collection Leave a message
  • This blog is written by the blogger alone and is not operated by any commercial team. If you find any errors, please leave a message! Correct in time! Thanks for the support!
  • The Arduino ESP8266 tutorial has helped more than 10,000 students get started learning hardware network programming. They have been selected for elective courses and have been published in radio magazines. From getting started to being familiar with the Arduino platform, developing ESP8266 will also involve network programming knowledge. There are more than 60 column articles in total, divided into basic articles, network articles, application articles, and advanced articles, covering most of the ESP8266 development techniques.

Quick Navigation
Microcontroller novice’s blog quick index (quickly find what you want)

If you find it useful, please like and save it. Your support is the motivation for the blogger’s creation.

Article directory

    • 1 Introduction
    • 2. Related code

1. Preface

When getting weather information from Zephyr Weather, since Zephyr Weather uses Gzip compression to return the data stream, the returned data needs to be decompressed.

By default, the Zephyr Weather Free Key has been applied for
https://dev.qweather.com/docs/api/weather/weather-now/

And there happens to be an Arduino library for this function,

https://github.com/tignioj/ArduinoUZlib

2. Related code

Zefeng Weather API uses HTTPS to obtain relevant weather data, and the returned data uses GZIP compression.
After obtaining the data, use the int result=ArduinoUZlib::decompress(inbuff, size, outbuf,outsize); function in the UZlib library to decompress it.

HeFeng.h code

#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 stream maximum buffer
    static size_t _bufferSize;
  public:
    HeFeng();
    void doUpdateCurr(HeFengCurrentData *data, String key, String location);
    void doUpdateFore(HeFengForeData *data, String key, String location);
};

</code><img class="look-more-preCode contentImg-no-view" src="//i2.wp.com/csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreBlack. png" alt="" title="">

HeFeng.cpp code

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>
#include "ArduinoUZlib.h" // gzip library
#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\\
");
    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() & amp; & amp; (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\\
", https.errorToString(httpCode).c_str());
        }
        https.end();
    }else{<!-- -->
        Serial.printf("Unable to connect\\
");
    }
    Serial.print("[HTTPS] end...now\\
");
    return _bufferSize > 0;
}

void HeFeng::doUpdateCurr(HeFengCurrentData *data, String key, String location) {<!-- --> //Get the weather

  String url = "https://devapi.qweather.com/v7/weather/now?lang=en & amp;gzip=n & amp;location=" + location + " & amp;key=" + key;
  Serial.print("[HTTPS] begin...now\\
");
  fetchBuffer(url.c_str()); // HTTPS gets the data stream
  if (_bufferSize){<!-- -->
     Serial.print("bufferSize:");
     Serial.println(_bufferSize, DEC);
     uint8_t *outBuf=NULL;
     size_t outLen = 0;
     ArduinoUZlib::decompress(_buffer, _bufferSize, outBuf, outLen); // GZIP decompression
     // Output the decrypted data to the console.
     Serial.write(outBuf,outLen);
     if(outBuf & amp; & amp; outLen){<!-- -->
         DynamicJsonDocument jsonBuffer(2048);
         deserializeJson(jsonBuffer, (char*)outBuf,outLen);
         JsonObject root = jsonBuffer.as<JsonObject>();

         String tmp = root["now"]["temp"];//Temperature
         data->tmp = tmp;
         String fl = root["now"]["feelsLike"];//Feeling temperature
         data->fl = fl;
         String hum = root["now"]["humidity"];//Humidity
         data->hum = hum;
         String wind_sc = root["now"]["windScale"];//wind power
         data->wind_sc = wind_sc;
         String cond_code = root["now"]["icon"];//Weather icon
         String meteConIcon = getMeteConIcon(cond_code);
         String cond_txt = root["now"]["text"];//Weather
         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 = ")";
      }
      //Be sure to remember to release memory
      if(outBuf != NULL) {<!-- -->
         free(outBuf);
         outBuf=NULL;
      }
     _bufferSize = 0;
  }
}

void HeFeng::doUpdateFore(HeFengForeData *data, String key, String location) {<!-- --> //Get the forecast

  String url = "https://devapi.qweather.com/v7/weather/3d?lang=en & amp;gzip=n & amp;location=" + location + " & amp;key=" + key;
  Serial.print("[HTTPS] begin...forecast\\
");
  fetchBuffer(url.c_str()); // HTTPS gets the data stream
  if (_bufferSize){<!-- -->
     Serial.print("bufferSize:");
     Serial.println(_bufferSize, DEC);
     uint8_t *outBuf=NULL;
     size_t outLen = 0;
     ArduinoUZlib::decompress(_buffer, _bufferSize, outBuf, outLen); // GZIP decompression
     // Output the decrypted data to the console.
     Serial.write(outBuf,outLen);
     if(outBuf & amp; & amp; 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 = ")";
         }
      }
      //Be sure to remember to release memory
      if(outBuf != NULL) {<!-- -->
         free(outBuf);
         outBuf=NULL;
      }
     _bufferSize = 0;
  }
}

String HeFeng::getMeteConIcon(String cond_code) {<!-- --> //Get the weather icon. See https://dev.qweather.com/docs/start/icons/
  if (cond_code == "100" || cond_code == "150" || cond_code == "9006") {<!-- -->//clear Sunny/Clear
    return "B";
  }
  if (cond_code == "101") {<!-- -->//Cloudy Cloudy
    return "Y";
  }
  if (cond_code == "102") {<!-- -->//Shaoyun Few Clouds
    return "N";
  }
  if (cond_code == "103" || cond_code == "153") {<!-- -->//Partly Cloudy/
    return "H";
  }
  if (cond_code == "104" || cond_code == "154") {<!-- -->//Yin 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 Thundershower / 303-Strong Thundershower
    return "P";
  }
  if (cond_code == "304" || cond_code == "313" || cond_code == "404" || cond_code == "405" || cond_code == "406" ) {<!-- -->
    //304-Thundershowers with hail Freezing Rain
    //313-Freezing Rain Freezing Rain
    //404-Sleet Sleet
    //405-Rain And Snow 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 Extreme Rain
    //309-Drizzle/Drizzle Drizzle Rain
    //314-Light to moderate rain Light to moderate rain
    //399-Rain 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 Moderate Rain
    //307-Heavy Rain Heavy Rain
    //310-Heavy rainstorm
    //311-Heavy Storm Heavy Storm
    //312-Severe Storm
    //315-Moderate to heavy rain Moderate to heavy rain
    //316-Heavy rain to storm
    //317-Storm to heavy storm Storm to heavy storm
    //318-Heavy to severe storm Heavy to severe storm
    return "R";
  }
  if (cond_code == "400" || cond_code == "408") {<!-- -->
    //400-Light Snow
    //408-Light to moderate snow 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 Heavy Snow
    //403-Blizzard Snowstorm
    //409-Moderate to heavy snow 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 Snow
    //901-Cold Cold
    return "G";
  }
  if (cond_code == "500") {<!-- -->
    //500-Mist 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 Haze
    return "L";
  }
  if (cond_code == "503" || cond_code == "504" || cond_code == "507" || cond_code == "508") {<!-- -->
    //503-Sand
    return "F";
  }
  
  if (cond_code == "999") {<!-- -->//Unknown
    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 ")";
}

</code><img class="look-more-preCode contentImg-no-view" src="//i2.wp.com/csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreBlack. png" alt="" title="">