[Arduino TFT] Weather clock based on ESP8266 and SSD1306

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. Software code
      • 2.1 Main project code
      • 2.2 Gentle weather
      • 2.3 Font pictures (too large)

1. Preface


Use esp8266 to drive oled 1306 to achieve:

  • date time
  • City temperature information
  • Forecast information for the next three days

2. Software code

2.1 Main project code

Esp8266_Clock_Weather.ino

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>

#include <time.h>
#include <sys/time.h>
#include <coredecls.h>

#include "SSD1306Wire.h" //Use this for 0.96 inches
#include "OLEDDisplayUi.h"
#include "HeFeng.h"
#include "WeatherStationFonts.h"
#include "WeatherStationImages.h"

/****************************
   Begin Settings
 ******************************/
const char* WIFI_SSID = "CMCC-pm3h"; //Fill in your WIFI name and password
const char* WIFI_PWD = "hw2htwv4";

//Because too many people use my secret key, the number of times I can obtain it exceeds the limit, so I will not provide the secret key. You can go to https://dev.heweather.com/ to get a free one.
const char* HEFENG_KEY = "f78a1c10fe5c490b8f3dc3946fe00975";//Fill in your Hefeng weather key
const char* HEFENG_LOCATION = "101280107";//Fill in your city ID, you can check it at https://where.heweather.com/index.html

#define TZ 8 // China time zone is 8
#define DST_MN 0 //Default is 0

const int UPDATE_INTERVAL_SECS = 30 * 60; // Update weather every 30 minutes

const int I2C_DISPLAY_ADDRESS = 0x3c; //I2c address default

const String WDAY_NAMES[] = {<!-- -->"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; //week
const String MONTH_NAMES[] = {<!-- -->"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; //Month

/****************************
   End Settings
 ******************************/
 
SSD1306Wire display(I2C_DISPLAY_ADDRESS, SDA, SCL); // Use this for 0.96 inches
OLEDDisplayUi ui( & amp;display );

HeFengCurrentData currentWeather; //instantiate object
HeFengForeData foreWeather[3];
HeFeng HeFengClient;

#define TZ_MN ((TZ)*60) //Time conversion
#define TZ_SEC ((TZ)*3600)
#define DST_SEC ((DST_MN)*60)

time_t now; //instantiation time

bool readyForWeatherUpdate = false; // Weather update flag
bool first = true; //First update flag
long timeSinceLastWUpdate = 0; //Time since last update
long timeSinceLastCurrUpdate = 0; //Time since the last weather update

void drawProgress(OLEDDisplay *display, int percentage, String label); //Declare the function in advance
void updateData(OLEDDisplay *display);
void updateDatas(OLEDDisplay *display);
void drawDateTime(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
void drawCurrentWeather(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
void drawForecast(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
void drawForecastDetails(OLEDDisplay *display, int x, int y, int dayIndex);
void drawHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state);
void setReadyForWeatherUpdate();

//Add frame
//This array holds function pointers to all frames
//The frame is a single view that slides from right to left
FrameCallback frames[] = {<!-- --> drawDateTime, drawCurrentWeather, drawForecast };
//Number of pages
int numberOfFrames = 3;

OverlayCallback overlays[] = {<!-- --> drawHeaderOverlay }; //Overlay callback function
int numberOfOverlays = 1; //Number of overlays

void setup() {<!-- -->
  Serial.begin(115200);
  Serial.println();
  Serial.println();

  //Screen initialization
  display.init();
  display.clear();
  display.display();

  display.flipScreenVertically(); //Screen flip
  display.setContrast(120); //Screen brightness

  wifiConnect();

  ui.setTargetFPS(30); //Refresh frequency

  ui.setActiveSymbol(activeSymbole); //Set active symbol
  ui.setInactiveSymbol(inactiveSymbole); //Set the inactive symbol
  // symbol position
  // You can change this to TOP, LEFT, BOTTOM, RIGHT
  ui.setIndicatorPosition(BOTTOM);
  // Define the position of the first frame in the column
  ui.setIndicatorDirection(LEFT_RIGHT);
  //Screen switching direction
  // You can change the screen switching direction used SLIDE_LEFT, SLIDE_RIGHT, SLIDE_TOP, SLIDE_DOWN
  ui.setFrameAnimation(SLIDE_LEFT);
  ui.setFrames(frames, numberOfFrames); // Set frames
  ui.setTimePerFrame(5000); //Set switching time
  ui.setOverlays(overlays, numberOfOverlays); //Set overlays
  // UI is responsible for initializing the display
  ui.init();
  display.flipScreenVertically(); //Screen flipped

  configTime(TZ_SEC, DST_SEC, "ntp.ntsc.ac.cn", "ntp1.aliyun.com"); //ntp gets the time, you can also use other "pool.ntp.org",\ "0.cn.pool.ntp.org","1.cn.pool.ntp.org","ntp1.aliyun.com"
  delay(200);
}

void loop() {<!-- -->
  if (first) {<!-- --> //First load
    updateDatas( & amp;display);
    first = false;
  }
  if (millis() - timeSinceLastWUpdate > (1000L * UPDATE_INTERVAL_SECS)) {<!-- --> //Screen refresh
    setReadyForWeatherUpdate();
    timeSinceLastWUpdate = millis();
  }

  if (readyForWeatherUpdate & amp; & amp; ui.getUiState()->frameState == FIXED) {<!-- --> //Weather update
    updateData();
  }

  int remainingTimeBudget = ui.update(); //Remaining time budget

  if (remainingTimeBudget > 0) {<!-- -->
    //You can work here if you are below your time budget.
    delay(remainingTimeBudget);
  }
  
}

void wifiConnect() {<!-- --> //WIFI password connection, please comment on Web configuration
  WiFi.begin(WIFI_SSID, WIFI_PWD);
  while (WiFi.status() != WL_CONNECTED) {<!-- -->
    Serial.print('.');
    delay(80);
    display.clear();
    display.drawXbm(34, 0, bili_Logo_width, bili_Logo_height, bili_Logo_5);
    display.display();
    delay(80);
    display.clear();
    display.drawXbm(34, 0, bili_Logo_width, bili_Logo_height, bili_Logo_6);
    display.display();
    delay(80);
    display.clear();
    display.drawXbm(34, 0, bili_Logo_width, bili_Logo_height, bili_Logo_7);
    display.display();
    delay(80);
    display.clear();
    display.drawXbm(34, 0, bili_Logo_width, bili_Logo_height, bili_Logo_8);
    display.display();
    delay(80);
    display.clear();
    display.drawXbm(34, 0, bili_Logo_width, bili_Logo_height, bili_Logo_1);
    display.display();
    delay(80);
    display.clear();
    display.drawXbm(34, 0, bili_Logo_width, bili_Logo_height, bili_Logo_2);
    display.display();
    delay(80);
    display.clear();
    display.drawXbm(34, 0, bili_Logo_width, bili_Logo_height, bili_Logo_3);
    display.display();
    delay(80);
    display.clear();
    display.drawXbm(34, 0, bili_Logo_width, bili_Logo_height, bili_Logo_4);
    display.display();
  }
  Serial.println("");
  delay(500);
}

void drawProgress(OLEDDisplay *display, int percentage, String label) {<!-- --> //Drawing progress
  display->clear();
  display->setTextAlignment(TEXT_ALIGN_CENTER);
  display->setFont(ArialMT_Plain_10);
  display->drawString(64, 10, label);
  display->drawProgressBar(2, 28, 124, 10, percentage);
  display->display();
}

void updateData(void) {<!-- --> //Weather update
  HeFengClient.doUpdateCurr( & currentWeather, HEFENG_KEY, HEFENG_LOCATION);
  HeFengClient.doUpdateFore(foreWeather, HEFENG_KEY, HEFENG_LOCATION);
  readyForWeatherUpdate = false;
}

void updateDatas(OLEDDisplay *display) {<!-- --> //First weather update
  drawProgress(display, 33, "Updating weather...");
  HeFengClient.doUpdateCurr( & currentWeather, HEFENG_KEY, HEFENG_LOCATION);
  
  drawProgress(display, 66, "Updating forecasts...");
  HeFengClient.doUpdateFore(foreWeather, HEFENG_KEY, HEFENG_LOCATION);
  
  readyForWeatherUpdate = false;
  drawProgress(display, 100, "Done...");
  delay(200);
  
}

void drawDateTime(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {<!-- --> //Display time
  now = time(nullptr);
  struct tm* timeInfo;
  timeInfo = localtime( & amp;now);
  char buff[16];

  display->setTextAlignment(TEXT_ALIGN_CENTER);
  display->setFont(ArialMT_Plain_16);
  String date = WDAY_NAMES[timeInfo->tm_wday];

  sprintf_P(buff, PSTR(" d- d- d %s"), timeInfo->tm_year + 1900, timeInfo->tm_mon + 1, timeInfo->tm_mday, WDAY_NAMES[timeInfo->tm_wday].c_str ());
  display->drawString(64 + x, 5 + y, String(buff));
  display->setFont(ArialMT_Plain_24);

  sprintf_P(buff, PSTR(" d: d: d"), timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec);
  display->drawString(64 + x, 22 + y, String(buff));
  display->setTextAlignment(TEXT_ALIGN_LEFT);
}

void drawCurrentWeather(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {<!-- --> //Display weather
  display->setFont(ArialMT_Plain_10);
  display->setTextAlignment(TEXT_ALIGN_CENTER);
  display->drawString(64 + x, 38 + y, currentWeather.cond_txt + " | Wind: " + currentWeather.wind_sc + " ");

  display->setFont(ArialMT_Plain_24);
  display->setTextAlignment(TEXT_ALIGN_LEFT);
  String temp = currentWeather.tmp + "°C" ;
  display->drawString(60 + x, 3 + y, temp);
  display->setFont(ArialMT_Plain_10);
  display->drawString(62 + x, 26 + y, currentWeather.fl + "°C | " + currentWeather.hum + "%");
  display->setFont(Meteocons_Plain_36);
  display->setTextAlignment(TEXT_ALIGN_CENTER);
  display->drawString(32 + x, 0 + y, currentWeather.iconMeteCon);
}

void drawForecast(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {<!-- --> //Weather forecast
  drawForecastDetails(display, x, y, 0);
  drawForecastDetails(display, x + 44, y, 1);
  drawForecastDetails(display, x + 88, y, 2);
}

void drawForecastDetails(OLEDDisplay *display, int x, int y, int dayIndex) {<!-- --> //Weather forecast
  display->setTextAlignment(TEXT_ALIGN_CENTER);
  display->setFont(ArialMT_Plain_10);
  display->drawString(x + 20, y, foreWeather[dayIndex].dateStr);
  display->setFont(Meteocons_Plain_21);
  display->drawString(x + 20, y + 12, foreWeather[dayIndex].iconMeteCon);

  String temp = foreWeather[dayIndex].tmp_min + " | " + foreWeather[dayIndex].tmp_max;
  display->setFont(ArialMT_Plain_10);
  display->drawString(x + 20, y + 34, temp);
  display->setTextAlignment(TEXT_ALIGN_LEFT);
}

void drawHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state) {<!-- --> //Drawing header overlay
  now = time(nullptr);
  struct tm* timeInfo;
  timeInfo = localtime( & amp;now);
  char buff[14];
  sprintf_P(buff, PSTR(" d: d"), timeInfo->tm_hour, timeInfo->tm_min);

  display->setColor(WHITE);
  display->setFont(ArialMT_Plain_10);
  display->setTextAlignment(TEXT_ALIGN_LEFT);
  display->drawString(6, 54, String(buff));
  display->setTextAlignment(TEXT_ALIGN_RIGHT);
  display->drawHorizontalLine(0, 52, 128);
}

void setReadyForWeatherUpdate() {<!-- --> //Get ready for weather updates
  Serial.println("Setting readyForUpdate to true");
  readyForWeatherUpdate = true;
}

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

2.2 Japanese weather

  • 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 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
#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="">

2.3 Font image (too large)

  • WeatherStationFonts.h
  • WeatherStationImages.h