开源天气时钟项目删减和更新

开源天气时钟项目删减和更新


  • 📌原项目开源地址:https://gitee.com/liuzewen/ESP8266-SSD1306-Watch-mini

  • ✨本文只针对Arduino IDE平台代码进行删减和更新。
    在这里插入图片描述

  • 📺按键菜单功能
    在这里插入图片描述
    在这里插入图片描述

  • 🌼天气时钟功能整体架构描述
    在这里插入图片描述

  • 🔖代码中所使用的库,都可以在Arduino IDE管理库当中下载到。

  • TimeLib
    在这里插入图片描述

  • ArduinoJson库(直接安装最新的库)
    在这里插入图片描述

  • U8g2

在这里插入图片描述

  • DS3231
    在这里插入图片描述

📜其余库为自带库。(ESP8266HTTPClientWire

🌻API接口

  • 📌老黄历免费API接口:天行数据密匙免费申请地址:https://www.tianapi.com/
  • ✨每天限制调用次数为:100次,每天更新频率不要高于15分钟每次。
  • 📍心知天气免费API接口:api.seniverse.com

🍁城市选择,可以自定义设定4个目标城市:设置方法如下:

void city_int(void){
  strcpy(citys[0].city_name,"株洲");strcpy(citys[0].city_id,"zhuzhou");//第一个为OLED默认显示城市
  strcpy(citys[1].city_name,"北京");strcpy(citys[1].city_id,"beijing");
  strcpy(citys[2].city_name,"上海");strcpy(citys[2].city_id,"shanghai");
  strcpy(citys[3].city_name,"长沙");strcpy(citys[3].city_id,"changsha");
}
  • 🎈哔哩哔哩站ID自己更换为自己的ID好即可。

🚩OLED接口说明

OLED 默认采用的是1.3寸的I2C接口,(SDA:D2,SCL:D1)保留0.96寸oled屏幕函数接口,启用相关函数即可。

U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); // 1.3寸,默认引脚:sda:D2,SCL:D1
//U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE, /* clock=*/D6, /* data=*/D5); // 1.3寸,指定引脚
//U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);//0.96寸,默认引脚
//U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE, /* clock=*/22, /* data=*/21); //0.96寸,指定引脚

⛳入网说明

  • 🔖在weather.h头文件中,找到定义的地方,将WIFI信息修改成自己的WIFI信息。
#ifndef STASSID
#define STASSID "MERCURY_D268G"
#define STAPSK  "pba5ayzk"
#endif

✅按键功能(强大)

  • 🌿按键引脚定义
#define UP_KEY      D3 //向上(递增)
#define M_KEY       D5 //长按进入菜单设置界面,短按确认。
#define DOWN_KEY    D6 //向下(递减)
#define WAKE_UP     D7 //原来是控制RGB—WS2812,修改后没有配置,可以利用此引脚来接单总线外设例如DS18B20,DHT11
  • 🌿功能画面显示可以通过按键来切换显示内容。

📓菜单功能一览表

在这里插入图片描述

📝主程序代码

/*
@功能:基于ESP8266的天气时钟

*/
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266mDNS.h>
#include <ArduinoOTA.h>
#include <ArduinoJson.h>//点击这里会自动打开管理库页面: http://librarymanager/All#ArduinoJson
//#include <EEPROM.h>
#include <Ticker.h>//点击这里会自动打开管理库页面: http://librarymanager/All#Ticker
#include <math.h>
//#include <FastLED.h>
#include <WiFiUdp.h>
#include <TimeLib.h>//点击这里会自动打开管理库页面: http://librarymanager/All#TimeLib
#include <U8g2lib.h>//点击这里会自动打开管理库页面: http://librarymanager/All#U8g2
#include "weather.h"
#include <DS3231.h>//点击这里会自动打开管理库页面: http://librarymanager/All#DS3231
#include <Wire.h>

//引入字体
#include"font.h"

//视频播放服务器地址
//const char* badapple_Server = "192.168.0.113";//你的电脑IP,win+R后,输入ipconfig查看
//const int badapple_Port = 715;//上位机中默认端口

//short badapple_Status = 0;
//uint8_t badapple[1024]={}; //128 * 64 / 8 = 1024


//显示器定时关闭定时器
Ticker openDisplay;

//DS3231初始化
DS3231 Clock;
bool Century=false;
bool h12;
bool PM;

//网络时钟定义
static const char ntpServerName[] = "time1.aliyun.com";//NTP服务器
const int timeZone = 8;     //时区
WiFiUDP Udp;
unsigned int localPort = 8888;  // local port to listen for UDP 端口
time_t prevDisplay = 0; // when the digital clock was displayed

U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); // 1.3寸,默认引脚:sda:D2,SCL:D1
//U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE, /* clock=*/D6, /* data=*/D5); // 1.3寸,指定引脚
//U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);//0.96寸,默认引脚
//U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE, /* clock=*/22, /* data=*/21); //0.96寸,指定引脚

//天气WiFiClient
WiFiClient client;
//哔哩哔哩HTTPClient
HTTPClient bilibili_client1;
HTTPClient bilibili_client2;
//badapple的WiFiClient
//WiFiClient badapple_client;

void offDisplay();//关屏幕回调函数
uint8_t KEY_Scan(uint8_t mode);//按键扫描函数1
uint8_t KEY_Scan2(void);//按键扫描函数2
char *num_week(uint8_t dayofweek,int Mode);//计算星期
void page_int(char * name,uint8_t cur,uint8_t row,long time);//初始化所有页码
void gpio_int(void);//初始化IO口
void city_int(void);//初始化城市结构体数组
void OLED_int(void);//初始化0.96OLED
void bilibili_int(void);//初始化bilibili请求
void bilibili_http_get(void);//从http更新哔哩哔哩数据
void get_time(void);//获取时间到TIME_NOW,由TIME_MODE决定是DS3231时间还是NTP网络时间
void Desktop1(void);//桌面1(天气时钟)
void Desktop2(void);//桌面2(bilibili粉丝数)
void set_page(void);//设置界面
void update_time(void);//更新NTP时间到DS3231

void Http_NongLi();//获取农历json数据

bool autoConfig(void);//自动联网
//void smartConfig(void);//smartConfig智能配网
bool sendRequest(const char* host, const char* cityid, const char* apiKey); //发送连接
bool skipResponseHeaders(void); 
void readReponseContent(char* content, size_t maxSize); 
void stopConnect(void);//停止请求
void clrEsp8266ResponseBuffer(void);//清理缓存
bool parseUserData(char* content);//拷贝信息进userDatd内
void classified_weather(void);//对天气按照天气图标进行分类
void drawWeather(void);//画天气图标
void HariChord(int frame);//几何动画
void boot_animation(void);//开机动画
void print_firmware_information(void);//打印系统参数,固件版本信息
//void BasicOTAINT(void);//OTA无线升级初始化

void FONT_16_2(const unsigned char chr,int *point);//十六进制转数组

time_t getNtpTime(void);
void sendNTPpacket(IPAddress &address);

void setup(){
  Serial.begin(BAUD_RATE);//串口初始化
   print_firmware_information();//打印版本信息
    WiFi.mode(WIFI_STA); //设置ESP32工作模式为无线终端模式
  WiFi.begin(STASSID, STAPSK);
    // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  WIFI_MODE =1;
  Serial.println(WiFi.SSID().c_str());
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  gpio_int();//初始化IO口
  city_int();//初始化城市列表
  OLED_int();//初始化0.96OLED
  delay(100);
  boot_animation();//开机动画
  ESP.wdtEnable(5000);//看门狗初始化
  //配置网络
  u8g2.begin();          //初始化OLED
   Udp.begin(localPort);
   setSyncProvider(getNtpTime);
   setSyncInterval(300);
   Wire.begin();//初始化IIC总线
      //NTP网络时钟就绪
   get_time();//获取一次网络时间,后面的农历json需要当前日期作为参数调用
   bilibili_int();//初始化bilibili请求
  
   //初始各标志位时间
   LastWeatherTime = millis();//天气获取
   LastRtcTime = millis();//时间刷新

   DATA_UPDATA = 1;
   LED_OFF;//关灯
   delay(500);
    Http_NongLi();//农历数据
   DebugPrintln("*********************************初始化结束,进入loop函数!***********************************");
}

void loop(){
  if(WIFI_MODE){
    //检测client客户端是否连接
    while (!client.connected()){
    if (!client.connect(host, 80)){  
      LED_PWM;//闪灯
      delay(300);          
      ESP.wdtFeed();// 喂 狗      
      } 
    }
   
    //获取天气
    if(millis()-LastWeatherTime >= WeatherDelay||DATA_UPDATA){
      DATA_UPDATA = 0;
//      if(RGB_KEY==1)

//      u8g2.clearBuffer();
//      u8g2.setFont(u8g2_font_wqy14_t_gb2312a);
//      u8g2.setCursor(16, 36);
//      u8g2.print("更新信息中......"); 
//      u8g2.sendBuffer();
      LastWeatherTime = millis();
      LED_ON;
      delay(100);
      LED_OFF;
      if(Desktop_Mode == TIME_WEATHER){
        if(sendRequest(host, citys[which_city-1].city_id, APIKEY) && skipResponseHeaders()){
          clrEsp8266ResponseBuffer();
          readReponseContent(response, sizeof(response));
          parseUserData(response);//拷贝需要的信息进userData
          classified_weather();
        }  
      }
      else if(Desktop_Mode == BILIBILI){
        bilibili_http_get();//请求哔哩哔哩数据
      }
    }

  }
        
 //获取本地时间并显示
  if(millis()-LastRtcTime >= RtcDelay){
    LastRtcTime = millis();
    get_time();
    Battery_capacity = analogRead(ADC_PIN);//获取电量
    switch (Desktop_Mode)
    {
      case TIME_WEATHER:
        Desktop1();
      break;
      case BILIBILI:
        Desktop2();
      break;
      default:
      break;
    }
  }
 //获取本地时间并显示
  if(millis()- NongLiTime >= NongLiDelay){
     Http_NongLi() ;
  }
  uint8_t KEY=KEY_Scan2();//扫描按键
  switch(KEY){
    case NO_KEY_PRES:
      //无按键按下,直接跳出,加快运行时间
    break;
    case UP_KEY_PRES:
    DebugPrintln("*************TIME_MODE切换***************");
/* 如果没有DS3231就不启用下面的语句 */
//    if(TIME_MODE == DS3231_TIME_MODE)
//      TIME_MODE = NTP_TIME_MODE;
//    else
//      TIME_MODE = DS3231_TIME_MODE;
    break;
    case M_KEY_PRES:
      u8g2.setPowerSave(LOW);
      openDisplay.once_ms(openOledTime, offDisplay);//定时器初始化
    break;
    case DOWN_KEY_PRES:
      //判断是否需要获取网络时间更新到DS3231上
      if(WIFI_MODE)
      update_time();
    break;
    case WAKE_UP_PRES:
      u8g2.setPowerSave(LOW);
      openDisplay.once_ms(openOledTime, offDisplay);//定时器初始化
    break;
    case M_KEY_LONG_PRES:
      set_page();
    break;
    case WAKE_UP_LONG_PRES:
      set_page();
    break;
  }

  ESP.wdtFeed();// 喂 狗
}

/*
@功能:定时关闭显示屏回调函数
*/
void offDisplay(){
  DebugPrintln("************5s后关闭OLED***************");
  u8g2.setPowerSave(HIGH);//关屏幕
}

/*
@功能:获取时间
@参数:0:DS3231_TIME_MODE
       1:NTP_TIME_MODE
*/
void get_time(void){
//  if(TIME_MODE){
    prevDisplay = now();
    TIME_NOW.years = year();
//    Serial.print(TIME_NOW.years);
    TIME_NOW.months = month();
//    Serial.print(TIME_NOW.months);
    TIME_NOW.days = day();
//    Serial.print(TIME_NOW.days);
    TIME_NOW.hours = hour();
    TIME_NOW.minutes = minute();
    TIME_NOW.seconds = second();
    TIME_NOW.weeks = weekday();
    /*
  }else{
    TIME_NOW.years = Clock.getYear()+2000;
    TIME_NOW.months = Clock.getMonth(Century);
    TIME_NOW.days = Clock.getDate();
    TIME_NOW.hours = Clock.getHour(h12, PM);
    TIME_NOW.minutes = Clock.getMinute();
    TIME_NOW.seconds = Clock.getSecond();
    TIME_NOW.weeks = Clock.getDoW();
  }
  */
}

/*
@功能:按键处理函数1
@参数:mode
       0:不支持连按
       1:支持连按
@返回值:0:无按键按下
*/
uint8_t KEY_Scan(uint8_t mode){   
  uint8_t key_up=1;//按键按松开标志
  if(mode)key_up=1;  //支持连按     
  if(key_up&&(KEYU==0||KEYM==0||KEYD==0||KEYW==0))
  {
    delay(4);//去抖动
    key_up=0;
    if(KEYU==0)return 1;
    else if(KEYM==0)return 2;
    else if(KEYD==0)return 3;
    else if(KEYW==0)return 4;
  }else if(KEYU==1||KEYM==1||KEYD==1||KEYW==1)key_up=1;
  return 0;// 无按键按下
}

/*
@功能:按键处理函数2
@返回值:短按||长按 下某个按键
*/
uint8_t KEY_Scan2(void){
  uint8_t KEY = KEY_Scan(0);
  switch(KEY)
  {
  case UP_KEY_PRES:
      up_pres_time = millis();
    break;
  case M_KEY_PRES:
      m_pres_time = millis();
    break;
  case DOWN_KEY_PRES:
      down_pres_time = millis();
    break;
  case WAKE_UP_PRES:
      wake_pres_time = millis();
  break;
  }
  while(KEYU==0||KEYM==0||KEYD==0||KEYW==0)
  {
    if(up_pres_time!=0 && millis()-up_pres_time >= key_long_pres_time){
      KEY = UP_KEY_LONG_PRES;
    }
    else if(m_pres_time!=0 && millis()-m_pres_time >= key_long_pres_time){
      KEY = M_KEY_LONG_PRES;
    }
    else if(down_pres_time!=0 && millis()-down_pres_time >= key_long_pres_time){
      KEY = DOWN_KEY_LONG_PRES;
    }
    else if(wake_pres_time!=0 && millis()-wake_pres_time >= key_long_pres_time){
      KEY = WAKE_UP_LONG_PRES;
    }
    ESP.wdtFeed();// 喂 狗   
  }
  up_pres_time = 0;
  m_pres_time = 0;
  down_pres_time = 0;
  wake_pres_time = 0;
  
  return KEY;
}

/*
@功能:判断星期并赋值
*/
char week1[10],week2[8],week3[2],week4[4];
char *num_week(uint8_t dayofweek,int Mode){
  switch(dayofweek)
  {
    case 1: 
    strcpy(week1,"Sunday");
    strcpy(week2,"周日");
    strcpy(week3,"Su");
    strcpy(week4,"日"); 
      break;
    case 2: 
    strcpy(week1,"Monday");
    strcpy(week2,"周一");
    strcpy(week3,"Mo");
    strcpy(week4,"一"); 
      break;
    case 3: 
    strcpy(week1,"Tuesday");
    strcpy(week2,"周二");
    strcpy(week3,"Tu");
    strcpy(week4,"二"); 
      break;
    case 4: 
    strcpy(week1,"Wednesday");
    strcpy(week2,"周三"); 
    strcpy(week3,"We");
    strcpy(week4,"三"); 
      break;
    case 5: 
    strcpy(week1,"Thursday");
    strcpy(week2,"周四"); 
    strcpy(week3,"Th");
    strcpy(week4,"四"); 
      break;
    case 6: 
    strcpy(week1,"Friday");
    strcpy(week2,"周五");
    strcpy(week3,"Fr"); 
    strcpy(week4,"五");
      break;
    case 7: 
    strcpy(week1,"Saturday");
    strcpy(week2,"周六"); 
    strcpy(week3,"Sa");
    strcpy(week4,"六");
      break;
    default:
    strcpy(week1,"NO");
    strcpy(week2,"无");
    strcpy(week3,"NO");
    strcpy(week4,"无");
      break; 
  }
  switch(Mode)
  {
    case 1: return week1; break;
    case 2: return week2; break;
    case 3: return week3; break;
    case 4: return week4; break;
  }
}

/*
@功能:初始化翻页参数
*/
void page_int(char * name,uint8_t cur,uint8_t row,long time){
  strcpy(set_up_page.name,name);
  set_up_page.cursor = cur;
  set_up_page.rows = row;
  set_up_page.time = time;
}

/*
@功能:初始化IO口
*/
void gpio_int(void){
  pinMode(LED,OUTPUT);
  pinMode(WAKE_UP,INPUT_PULLUP);
  pinMode(UP_KEY,INPUT_PULLUP);
  pinMode(M_KEY,INPUT_PULLUP);
  pinMode(DOWN_KEY,INPUT_PULLUP);
  LED_OFF;//关灯
}

/*
@功能:初始化城市结构体数组
*/
void city_int(void){
  strcpy(citys[0].city_name,"株洲");strcpy(citys[0].city_id,"zhuzhou");//第一个为OLED默认显示地点
  strcpy(citys[1].city_name,"北京");strcpy(citys[1].city_id,"beijing");
  strcpy(citys[2].city_name,"上海");strcpy(citys[2].city_id,"shanghai");
  strcpy(citys[3].city_name,"长沙");strcpy(citys[3].city_id,"changsha");
}

/*
@功能:初始化0.96OLED
*/
void OLED_int(void){
  u8g2.begin();
  u8g2.enableUTF8Print();
  u8g2.setDisplayRotation(U8G2_R0);//设置显示器方向
  U8G2_OLED_R = 0;//OLED方向标志位置0(水平)
  u8g2.setContrast(OLED_Brightness);//设置OLED亮度
  u8g2.setDrawColor(1);//设置绘制颜色
  u8g2.setPowerSave(LOW);//默认屏幕亮
}

/*
@功能:初始化bilibili请求
*/
void bilibili_int(void){
   //设置超时
   bilibili_client1.setTimeout(HTTP_TIMEOUT);
   bilibili_client2.setTimeout(HTTP_TIMEOUT);
   //设置哔哩哔哩请求url
   bilibili_client1.begin(client,String(bilibili_HOST) + "/x/relation/stat?vmid=" + String(bilibili_UID));//粉丝数
   bilibili_client2.begin(client,String(bilibili_HOST) + "/x/space/upstat?mid=" + String(bilibili_UID));//播放量
}

/*
@功能:从http更新哔哩哔哩数据
*/
void bilibili_http_get(void){
//  StaticJsonBuffer<1024> jsonBuffer;
//  StaticJsonDocument<256> jsonBuffer;
  
  int httpCode1 = bilibili_client1.GET();
  if(httpCode1 > 0 && httpCode1==HTTP_CODE_OK)
  {
    String response = bilibili_client1.getString();
    DebugPrintln(response);
//    JsonObject& root = jsonBuffer.parseObject(response);
       DynamicJsonDocument doc(1024);
DeserializationError error = deserializeJson(doc, response); 
//if (error)  return;
    BILI_NOW_DATE.follower = doc["data"]["follower"];
    BILI_NOW_DATE.following = doc["data"]["following"];
  }
  bilibili_client1.end();

  int httpCode2 = bilibili_client2.GET();
  if(httpCode2 > 0 && httpCode2==HTTP_CODE_OK)
  {
    String response = bilibili_client2.getString();
    DebugPrintln(response);
       DynamicJsonDocument doc(1024);
DeserializationError error = deserializeJson(doc, response);
//if (error)  return;

    BILI_NOW_DATE.view = doc["data"]["archive"]["view"];
    BILI_NOW_DATE.likes = doc["data"]["likes"];
  }
  bilibili_client2.end();
}

void Http_NongLi() {
   String nongli_line;
  String DateAddress = "http://api.tianapi.com/txapi/lunar/index?key="; 
   DateAddress +=tianxingkey;
   DateAddress +="&date=";
   DateAddress +=String(TIME_NOW.years);
   DateAddress +="-";
   DateAddress +=String(TIME_NOW.months);
   DateAddress +="-";
   DateAddress +=String(TIME_NOW.days);

  DebugPrintln(DateAddress.c_str());
     
  WiFiClient client;
  HTTPClient https;
  if (https.begin(client, DateAddress))
  { // HTTPS
    int httpCode = https.GET();
    if (httpCode > 0)
    {
      Serial.printf("[HTTPS] GET... code: %d\n", httpCode);
      if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY)
      {
        String str0 = https.getString();
       nongli_line = str0.substring(str0.lastIndexOf("lunardate"), str0.lastIndexOf(",\"lunar_festival"));
        nongli_line =  "{\"" + nongli_line + "}";
        DebugPrintln(nongli_line.c_str());
      } else {
        Serial.println(" connection failed!");
      }
      /*json数据静态解析*/
       StaticJsonDocument<48> doc;
  DeserializationError error = deserializeJson(doc, nongli_line);
  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.f_str());
//    return "error";
  }
//  const char* lubarmonth = doc["lubarmonth"]; // "七月"
//  const char* lunarday = doc["lunarday"]; // "十六"
  const char* lunarday = doc["lunardate"]; // "2022-12-16"
//  NongLiData = String(lubarmonth) + String(lunarday);
    NongLiData = String(lunarday);
  Serial.printf("农历: %s \r\n", NongLiData.c_str());
      //断开客户端与服务器连接工作
      client.stop();
      https.end();
    }
  }
}
/*
@功能:桌面1
@参数:time_show:系统时间
       userData:天气情况
*/
void Desktop1(void){

  u8g2.clearBuffer();
  //画天气图案(没有网络的话显示断网)
  if(WIFI_MODE == 1)
      drawWeather();
  else
  {
    u8g2.setFont(u8g2_font_open_iconic_all_2x_t);
    u8g2.drawGlyph(0, 16, 197);
  }

    //显示 年-月-日
    u8g2.setFont(u8g2_font_6x10_mf);
    u8g2.setCursor(67, 11);
    u8g2.print(TIME_NOW.years);
    
    u8g2.drawStr(91,11,".");
    
    u8g2.setCursor(97, 11);
    if(TIME_NOW.months>=10)
      u8g2.print(TIME_NOW.months);
    else{
      u8g2.print("0");
      u8g2.setCursor(104,11);
      u8g2.print(TIME_NOW.months);
    }
    
    u8g2.drawStr(109,11,".");

    u8g2.setCursor(115, 11);
    if(TIME_NOW.days>=10)
      u8g2.print(TIME_NOW.days);
    else{
      u8g2.print("0");
      u8g2.setCursor(123,11);
      u8g2.print(TIME_NOW.days);
    }

    //显示 IP地址
//    u8g2.drawStr(0,63,"IP:");
//    u8g2.setCursor(22, 63);
//    u8g2.print(WiFi.localIP());
  u8g2.setFont(u8g2_font_wqy14_t_gb2312a);
      String str = "农历:" + NongLiData;//农历内容显示
      u8g2.setCursor(0,63);
    u8g2.println(str.c_str());
    //显示 星期(day of week)
    u8g2.setFont(u8g2_font_wqy12_t_gb2312);
    u8g2.setCursor(114, 63);   
    u8g2.print(num_week(TIME_NOW.weeks,4)); 
//    u8g2.setCursor(112, 63);   
//    u8g2.print(num_week(TIME_NOW.weeks,2)); 
    
    //显示 时-分-秒
    u8g2.setFont(u8g2_font_inb21_mn); 
    u8g2.setCursor(3,42);
    if(TIME_NOW.hours>=10)
      u8g2.print(TIME_NOW.hours);
    else{
      u8g2.print("0");
      u8g2.setCursor(23,42);
      u8g2.print(TIME_NOW.hours);
    }
    u8g2.drawStr(42,40,":");
    u8g2.setCursor(60,42);
    if(TIME_NOW.minutes>=10)
      u8g2.print(TIME_NOW.minutes);
    else{
      u8g2.print("0");
      u8g2.setCursor(80,42);
      u8g2.print(TIME_NOW.minutes);
    }
    u8g2.setFont(u8g2_font_ncenR12_tf);
    u8g2.drawStr(100,42,":");
    u8g2.setCursor(110,42);
    if(TIME_NOW.seconds>=10)
      u8g2.print(TIME_NOW.seconds);
    else{
      u8g2.print("0");
      u8g2.setCursor(120,42);
      u8g2.print(TIME_NOW.seconds);
    }
    //显示电量
    //u8g2.drawRBox(100,18,(Battery_capacity*20)/1024,8,3);
    u8g2.drawRBox(102,18,20,8,3);
    u8g2.drawRBox(122,20,2,4,1);
    u8g2.sendBuffer();
}

/*
@功能:桌面2(bilibili粉丝数)
*/
void Desktop2(void){
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_wqy14_t_gb2312a);

  u8g2.drawXBMP(36,-1, bilibili_bmp_x, bilibili_bmp_y, bilibili_bmp);

  u8g2.setCursor(10, 16*2+1);
  u8g2.print("粉丝数:");
  u8g2.setCursor(70, 16*2+1);
  u8g2.print(BILI_NOW_DATE.follower);

  u8g2.setCursor(10, 16*3-1);
  u8g2.print("点赞数:");
  u8g2.setCursor(70, 16*3-1);
  u8g2.print(BILI_NOW_DATE.likes);

  u8g2.setCursor(10, 16*4-2);
  u8g2.print("播放量:");
  u8g2.setCursor(70, 16*4-2);
  u8g2.print(BILI_NOW_DATE.view);
  u8g2.sendBuffer();
}

/*
@功能:设置界面
*/
void set_page(void){
  int8_t x,y;
  bool x_r,y_r;
  page_int("设置",1,12,millis());//初始化页
  DebugPrintln("*************进入设置***************");
  openDisplay.detach();//关定时器
  u8g2.setPowerSave(LOW);//开显示屏
  
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_open_iconic_all_6x_t);
  u8g2.drawGlyph(40,55,129);
  u8g2.sendBuffer();
  delay(1000);
      
  while(true){
  //防止光标位置错
  //set_up_page.cursor = set_up_page.cursor<=1 ? 1:set_up_page.cursor;
  set_up_page.cursor = set_up_page.cursor < 1 ? set_up_page.rows:set_up_page.cursor;
  //set_up_page.cursor = set_up_page.cursor>=set_up_page.rows ? set_up_page.rows:set_up_page.cursor;
  set_up_page.cursor = set_up_page.cursor > set_up_page.rows ? 1:set_up_page.cursor;
  
  //刷新屏幕millis()-set_up_page.time >= set_up_page.refresh_time
  if(millis()-set_up_page.time >= set_up_page.refresh_time){
    set_up_page.time = millis();
    u8g2.clearBuffer();
    u8g2.setFont(u8g2_font_wqy14_t_gb2312a);
    uint8_t PAGE = (set_up_page.cursor%4 == 0 ? (set_up_page.cursor/4)-1:set_up_page.cursor/4);
    switch(PAGE)
    {
      case 0:
      u8g2.setCursor(20, 16*1-2);
      u8g2.print(" 1.桌面设置");
      u8g2.setCursor(20, 16*2-2);
      u8g2.print(" 2.屏幕设置");
      u8g2.setCursor(20, 16*3-2);
      u8g2.print(" 3.网络信息");
      u8g2.setCursor(20, 16*4-2);
      u8g2.print(" 4.智能配网");
      break;
      case 1:
      u8g2.setCursor(20, 16*1-2);
      u8g2.print(" 5.时间设置");
      u8g2.setCursor(20, 16*2-2);
      u8g2.print(" 6.天气设置");
      u8g2.setCursor(20, 16*3-2);
      u8g2.print(" 7.刷新时间");
      u8g2.setCursor(20, 16*4-2);
      u8g2.print(" 8.版本信息");
      break;
      case 2:
      u8g2.setCursor(20, 16*1-2);
      u8g2.print(" 9.RGB点阵屏");
      u8g2.setCursor(18, 16*2-2);
      u8g2.print("10.视频播放");
      u8g2.setCursor(18, 16*3-2);
      u8g2.print("11.烧屏测试");
      u8g2.setCursor(18, 16*4-2);
      u8g2.print("12.退出设置");
      break;
    }
    //显示光标
    u8g2.setFont(u8g2_font_open_iconic_all_1x_t);
    u8g2.drawGlyph(5, 16*(set_up_page.cursor%4==0? 4:set_up_page.cursor%4)-4,118);
    u8g2.sendBuffer();
  }
  
  uint8_t KEY=KEY_Scan2();//扫描按键2
  if(KEY == WAKE_UP_LONG_PRES)
    break;
  else if(KEY == M_KEY_LONG_PRES)
    break;
  switch(KEY)
  {
    case UP_KEY_PRES:
      set_up_page.cursor --;
    break;
    case M_KEY_PRES:
      u8g2.clearBuffer();
      u8g2.setFont(u8g2_font_wqy14_t_gb2312a);
      u8g2.setCursor(0,0);
      u8g2.print(set_up_page.cursor);
      u8g2.sendBuffer();      
      switch(set_up_page.cursor){
        case 1:
          while(true){
            if(millis()-set_up_page.time >= set_up_page.refresh_time){
              set_up_page.time = millis();//重新赋值
              u8g2.clearBuffer();
              u8g2.setFont(u8g2_font_wqy14_t_gb2312a);

              u8g2.setCursor(24, 16*1-2);
              u8g2.print("     桌面");
              u8g2.setCursor(20, 16*2-2);
              u8g2.print(" 1.天气时钟");
              u8g2.setCursor(20, 16*3-2);
              u8g2.print(" 2.bilibili粉丝");

              //显示光标
              u8g2.setFont(u8g2_font_open_iconic_all_1x_t);
              u8g2.drawGlyph(5, 16*(Desktop_Mode+1)-4,118);

              u8g2.sendBuffer();
            }
            uint8_t KEY=KEY_Scan2();//扫描按键
            if(KEY == M_KEY_PRES)
              break;
            if(KEY == DOWN_KEY_PRES){
              Desktop_Mode ++;
              Desktop_Mode = Desktop_Mode > 2 ? 2:Desktop_Mode;
            }
            if(KEY == UP_KEY_PRES){
              Desktop_Mode --;
              Desktop_Mode = Desktop_Mode < 1 ? 1:Desktop_Mode;
            }
            ESP.wdtFeed();// 喂 狗
          }
          u8g2.clearBuffer();
          switch (Desktop_Mode)
          {
          case TIME_WEATHER:
            u8g2.setFont(u8g2_font_cupcakemetoyourleader_tr);
            u8g2.drawStr(50,36,"Weather");
            u8g2.setFont(u8g2_font_open_iconic_all_6x_t);
            u8g2.drawGlyph(0, 52, 187);//正无穷标志
          break;
          case BILIBILI:
            u8g2.drawXBMP(32,-1, bilibili_head_x, bilibili_head_y, bilibili_head);
          break;
          default:
          break;
          }
          u8g2.sendBuffer();
          delay(1000);
          DATA_UPDATA = 1;
        break;
        case 2://亮度设置搞定
          while(true){
            if(millis()-set_up_page.time >= set_up_page.refresh_time){
              set_up_page.time = millis();//重新赋值
              u8g2.clearBuffer();
              u8g2.setFont(u8g2_font_wqy14_t_gb2312a);
              u8g2.setCursor(0,27);
              u8g2.print("屏幕亮度:");

              u8g2.setCursor(64,27);
              u8g2.print((OLED_Brightness*100)/255);
              u8g2.setCursor((OLED_Brightness*100)/255>=100 ? 88:80,27);
              u8g2.print("%");

              u8g2.drawRBox(0,36,(OLED_Brightness*128)/255,16,5);

              u8g2.sendBuffer();
            }
            uint8_t KEY=KEY_Scan2();//扫描按键
            if(KEY == M_KEY_PRES)
              break;
            if(KEY == UP_KEY_PRES){
              OLED_Brightness += 20;
              OLED_Brightness = OLED_Brightness > 255 ? 255:OLED_Brightness;
              u8g2.setContrast(OLED_Brightness);//设置OLED亮度
            }
            if(KEY == DOWN_KEY_PRES){
              OLED_Brightness -= 20;
              OLED_Brightness = OLED_Brightness < 21 ? 20:OLED_Brightness;
              u8g2.setContrast(OLED_Brightness);//设置OLED亮度
            }
            ESP.wdtFeed();// 喂 狗
          }
        break;
        case 3://已完成WIFI信息
          u8g2.clearBuffer();
          u8g2.setFont(u8g2_font_wqy14_t_gb2312a);
          u8g2.setCursor(36,16*1-2);
          u8g2.print("WIFI信息");
          u8g2.setCursor(0,16*2-2);
          u8g2.print("SSID:");
          u8g2.setCursor(37,16*2-2);
          u8g2.print(WiFi.SSID().c_str());
          u8g2.setCursor(0,16*3-2);
          u8g2.print("PSWD:");
          u8g2.setCursor(42,16*3-2);
          u8g2.print(WiFi.psk().c_str());
          u8g2.setCursor(0,16*4-2);
          u8g2.print("IP:");
          u8g2.setCursor(18,16*4-2);
          u8g2.print(WiFi.localIP());
          u8g2.sendBuffer();
          while(true){
            uint8_t KEY=KEY_Scan2();//扫描按键
            if(KEY == M_KEY_PRES)
              break;
            ESP.wdtFeed();// 喂 狗
          }
        break;
        case 4://已完成配网
          Get_SmartConfig = true;
          goto TIAOCHU;
        break;
        case 5://时间模式完成
          while(true){
            if(millis()-set_up_page.time >= set_up_page.refresh_time){
              set_up_page.time = millis();//重新赋值
              u8g2.clearBuffer();
              u8g2.setFont(u8g2_font_wqy14_t_gb2312a);
              u8g2.setCursor(36,16*1-2);
              u8g2.print("时间模式");
              if(TIME_MODE==DS3231_TIME_MODE){
                u8g2.setCursor(36,16*3-2);
                u8g2.print("DS3231源");
              }
              else{
                u8g2.setCursor(32,16*3-2);
                u8g2.print("NTP网络源");
              }
              u8g2.sendBuffer();
            }
            uint8_t KEY=KEY_Scan2();//扫描按键
            if(KEY == M_KEY_PRES)
              break;
            if(KEY == UP_KEY_PRES)
              TIME_MODE = !TIME_MODE;
            if(KEY == DOWN_KEY_PRES)
              TIME_MODE = !TIME_MODE;
            ESP.wdtFeed();// 喂 狗
          }
        break;
        case 6:
          while(true){
            if(millis()-set_up_page.time >= set_up_page.refresh_time){
              set_up_page.time = millis();//重新赋值
              u8g2.clearBuffer();
              u8g2.setFont(u8g2_font_wqy14_t_gb2312a);
              u8g2.setCursor(0,16*2-2);
              u8g2.print("城市名称:");
              u8g2.setCursor(70,16*2-2);
              u8g2.print(citys[which_city-1].city_name);
              u8g2.setCursor(0,16*3-2);
              u8g2.print("城市ID:");
              u8g2.setCursor(55,16*3-2);
              u8g2.print(citys[which_city-1].city_id);
              u8g2.sendBuffer();
            }
            uint8_t KEY=KEY_Scan2();//扫描按键
            if(KEY == M_KEY_PRES)
              break;
            if(KEY == UP_KEY_PRES){
              which_city += 1;
              which_city = which_city >= city_num ? city_num:which_city;
            }
            if(KEY == DOWN_KEY_PRES){
              which_city -= 1;
              which_city = which_city <= 1 ? 1:which_city;
            }
            ESP.wdtFeed();// 喂 狗
          }
          u8g2.clearBuffer();
          u8g2.setFont(u8g2_font_wqy14_t_gb2312a);
          u8g2.setCursor(0,16*3-8);
          u8g2.print("城市设置为:");
          u8g2.setCursor(90,16*3-8);
          u8g2.print(citys[which_city-1].city_name);
          u8g2.sendBuffer();
          delay(1000);
        break;
        case 7:
          while(true){
            if(millis()-set_up_page.time >= set_up_page.refresh_time){
              set_up_page.time = millis();//重新赋值
              u8g2.clearBuffer();
              u8g2.setFont(u8g2_font_wqy14_t_gb2312a);
              u8g2.setCursor(0,40);
              u8g2.print("更新时间:");
              u8g2.setCursor(WeatherDelay/(60*1000)>=10 ? 64:72,40);
              u8g2.print(WeatherDelay/(60*1000));
              u8g2.setCursor(80,40);
              u8g2.print(WeatherDelay%(60*1000)==0 ? ".0":".5");
              u8g2.setCursor(96,40);
              u8g2.print("分钟");
              u8g2.sendBuffer();
            }
            uint8_t KEY=KEY_Scan2();//扫描按键
            if(KEY == M_KEY_PRES)
              break;
            if(KEY == UP_KEY_PRES){
              WeatherDelay += 30*1000;
              WeatherDelay = WeatherDelay >=10*60*1000 ? 10*60*1000:WeatherDelay;
            }
            if(KEY == DOWN_KEY_PRES){
              WeatherDelay -= 30*1000;
              WeatherDelay = WeatherDelay <=30*1000 ? 30*1000:WeatherDelay;
            }
            ESP.wdtFeed();// 喂 狗
          }
        break;
        case 8://固件版本完成
          u8g2.clearBuffer();
          u8g2.setFont(u8g2_font_wqy14_t_gb2312a);
          u8g2.setCursor(36,16*1-2);
          u8g2.print("版本信息");
          u8g2.setCursor(0,16*2-2);
          u8g2.print("固件版本:");
          u8g2.setCursor(63,16*2-2);
          u8g2.print(Firmware_version);
          u8g2.setCursor(0,16*3-2);
          u8g2.print("固件大小:");
          u8g2.setCursor(63,16*3-2);
          u8g2.print(ESP.getSketchSize()/1024);
          u8g2.setCursor(84,16*3-2);
          u8g2.print("KBytes");
          while(true){
            uint8_t KEY=KEY_Scan2();//扫描按键
            if(KEY == M_KEY_PRES)
              break;
            ESP.wdtFeed();// 喂 狗
          }
        break;
        case 9://点阵开关完成
          while(true){
            if(millis()-set_up_page.time >= set_up_page.refresh_time){
              set_up_page.time = millis();//重新赋值
              u8g2.clearBuffer();
              u8g2.setFont(u8g2_font_wqy14_t_gb2312a);
              u8g2.setCursor(0,40);
              u8g2.print("RGB点阵屏:");
              u8g2.setCursor(85,40);
              if(RGB_KEY==1)
                u8g2.print("-开-");
              else
                u8g2.print("-关-");
              u8g2.sendBuffer();
            }
            uint8_t KEY=KEY_Scan2();//扫描按键
            if(KEY == M_KEY_PRES)
              break;
            if(KEY == UP_KEY_PRES){
              RGB_KEY = !RGB_KEY;
              }
            if(KEY == DOWN_KEY_PRES){
              RGB_KEY = !RGB_KEY;
              }
            ESP.wdtFeed();// 喂 狗
          }

        break;
  /*
        case 10:
          u8g2.clearBuffer();
          u8g2.setFont(u8g2_font_wqy14_t_gb2312a);
          u8g2.setCursor(36,40);
          u8g2.print("视频播放");
          u8g2.setCursor(88,40);
          u8g2.sendBuffer();
          while(true){
            if(badapple_Status==0 && WiFi.status()==WL_CONNECTED){
              badapple_Status=1;
              badapple_client.connect(badapple_Server, badapple_Port);
            }
            while(badapple_client.available()){ 
              badapple_client.read(badapple,1024);
              delay(75);
              u8g2.clearBuffer();
              u8g2.drawXBMP(0, 0, 128, 64, badapple);
              u8g2.sendBuffer();
              ESP.wdtFeed();// 喂 狗
            }
            uint8_t KEY=KEY_Scan2();//扫描按键
            if(KEY == M_KEY_PRES)
              break;
            ESP.wdtFeed();// 喂 狗
          }
          badapple_client.stop(); 
        break;
   */
        case 11:
          u8g2.clearBuffer();
          u8g2.drawRBox(0,-1,128,64,3);
          u8g2.sendBuffer();
          delay(3000);
          x = 0;
          y = 0;
          x_r = 1;
          y_r = 1;
          while(1){
            if(x_r)x++;else x--;
            if(y_r)y++;else y--;
            if(x>=127-8)x_r = 0;
            if(x<=0+8)x_r = 1;
            if(y>=63-8)y_r = 0;
            if(y<=0+8)y_r = 1;
            u8g2.clearBuffer();
            u8g2.drawDisc(x,y,5);
            u8g2.drawCircle(x,y,8);
            u8g2.sendBuffer();
            ESP.wdtFeed();// 喂 狗
            uint8_t KEY=KEY_Scan2();//扫描按键
            if(KEY == M_KEY_PRES)
              break;
          }
          for(int i = 0;i<=3;i++){
            for (int frame=0; frame < 36; frame++)
            {
              HariChord(frame);
              ESP.wdtFeed();// 喂 狗     
            }
 
            for (int frame=(36-1); frame >= 0; frame--)
            {
              HariChord(frame);
              ESP.wdtFeed();// 喂 狗     
            }
          }
        break;
        case 12:
          goto TIAOCHU;//goto语法跳出设置
        break;
      }
    break;
    case DOWN_KEY_PRES:
      set_up_page.cursor ++;
    break;
  }
    ESP.wdtFeed();// 喂 狗
  }
  TIAOCHU://goto语法
  DebugPrintln("*************退出设置***************");
  u8g2.firstPage();
  do{
    u8g2.setFont(u8g2_font_open_iconic_all_6x_t);
    u8g2.drawGlyph(35,60,64);
  }while (u8g2.nextPage());
  delay(1000);
}

/*
@功能:网络时间获取更新
*/
void update_time(void){
    prevDisplay = now();
    Serial.println("***********更新时间***********");
    Serial.print("网络时间是:   ");
    Serial.print(year());
    Serial.print(".");
    Serial.print(month());
    Serial.print(".");
    Serial.print(day());
    Serial.print(" ");
    Serial.print(hour());
    Serial.print(":");
    Serial.print(minute());
    Serial.print(":");
    Serial.print(second());
    Serial.print("    星期");
    Serial.println(num_week(weekday(),4));
    
    Clock.setClockMode(false);  // set to 24h
    Clock.setYear(year()-2000);
    Clock.setMonth(month());
    Clock.setDate(day());
    Clock.setDoW(weekday());
    Clock.setHour(hour());
    Clock.setMinute(minute());
    Clock.setSecond(second());
}

/*
@功能:autoConfig 默认WIFI连网
@说明:自动连接20s超过之后自动进入无网络模式
*/
bool autoConfig(void){
  WiFi.mode(WIFI_STA);     // 设 置 esp8266 工 作 模 式
  DebugPrint("联网至:");DebugPrintln(WiFi.SSID().c_str());DebugPrintln(WiFi.psk().c_str());
//  WiFi.begin(config.stassid,config.stapsw);//连接指定的WIFI
 WiFi.begin(ssid, password);
  //WiFi.begin(WiFi.SSID().c_str(),WiFi.psk().c_str());//连接上次连接的WIFI
  //WiFi.begin();
  delay(500);// 刚 启 动 模 块 的 话 延 时 稳 定 一 下
  u8g2.firstPage();
  do{
    u8g2.setFont(u8g2_font_wqy14_t_gb2312a);
    u8g2.setCursor(30, 36);
    u8g2.print("联网中......"); 
  }while (u8g2.nextPage());
  DebugPrint("AutoConfiging");
  for(int index=0;index<100;index++){//连接20s
    int wstatus = WiFi.status();
    if (wstatus == WL_CONNECTED){
      DebugPrintln("\nAutoConfig Success");
      DebugPrint("SSID:");
      DebugPrintln(WiFi.SSID().c_str());
      DebugPrint("PSW:");
      DebugPrintln(WiFi.psk().c_str());
      return true;
    }else{
      DebugPrint(".");
      delay(200);
      LED_PWM;
    } 
  }
  DebugPrintln("自动联网->失败!");

  u8g2.firstPage();
  do{
    u8g2.setFont(u8g2_font_wqy14_t_gb2312a);
    u8g2.setCursor(16, 36);
    u8g2.print("联网失败......"); 
  }while (u8g2.nextPage());

  return false; 
}



/*
@功能:发送请求指令
*/
bool sendRequest(const char* host, const char* cityid, const char* apiKey){
  // We now create a URI for the request   
  // 心 知 天 气
   String GetUrl = "/v3/weather/now.json?key=";   
   GetUrl += apiKey;
   GetUrl += "&location=";
   GetUrl += cityid;
   GetUrl += "&language=";
   GetUrl += language;
   // This will send the request to the server
   client.print(String("GET ") + GetUrl + " HTTP/1.1\r\n" + 
                "Host: " + host + "\r\n" +
                "Connection: close\r\n\r\n");
   DebugPrintln("create a request:");
   DebugPrintln(String("GET ") + GetUrl + " HTTP/1.1\r\n" +
                "Host: " + host + "\r\n" +
                "Connection: close\r\n");
   delay(1000);
   return true; 
}

/*
@功能:Desc跳过HTTP头,使我们在响应正文的开头
*/
bool skipResponseHeaders(){
  // HTTP headers end with an empty line
  bool ok = client.find(endOfHeaders);
  if(!ok){
    DebugPrintln("No response or invalid response!");
    }
    return ok;
}

/*
@功能:Desc从HTTP服务器响应中读取正文
*/
void readReponseContent(char* content, size_t maxSize){
  size_t length = client.readBytes(content, maxSize);
  delay(100);
  DebugPrintln("Get the data from Internet!");
  content[length] = 0;
  DebugPrintln(content);
  DebugPrintln("Read data Over!");
  client.flush();
  //这句代码需要加上不然会发现每隔一次client.find会失败
 }
 
 //关闭与HTTP服务器连接
 void stopConnect(){
  client.stop(); 
}   

void clrEsp8266ResponseBuffer(void){
  memset(response, 0, MAX_CONTENT_SIZE);//清空
}

bool parseUserData(char* content){
   DynamicJsonDocument doc(1024);   
DeserializationError  error = deserializeJson(doc, content);
if (error) {
    Serial.print(F("deserializeJson() failed with code "));
    Serial.println(error.c_str());
}      
    //复制我们感兴趣的字符串
   strcpy(userData.city, doc["results"][0]["location"]["name"]);
   strcpy(userData.weather_code, doc["results"][0]["now"]["code"]);
   strcpy(userData.temp, doc["results"][0]["now"]["temperature"]);
   return true;
}

/*
@功能:对所有天气情况按照显示图标进行分类
*/
void classified_weather(void){
  if(strcmp(userData.weather_code,WEATHER_CODE_DAY_SUN) == 0
  || strcmp(userData.weather_code,WEATHER_CODE_DAY_SUN1) == 0){
    userData.weather = SUN_DAY;
  }else if(strcmp(userData.weather_code,WEATHER_CODE_NIGHT_SUN) == 0
  || strcmp(userData.weather_code,WEATHER_CODE_NIGHT_SUN2) == 0 ){
    userData.weather = SUN_NIGHT;
  }else if(strcmp(userData.weather_code,WEATHER_CODE_DAY_PARTLY_CLOUDY) == 0
  || strcmp(userData.weather_code,WEATHER_CODE_NIGHT_PARTLY_CLOUDY)== 0){
    userData.weather = SUN_CLOUD;
  }else if(strcmp(userData.weather_code,WEATHER_CODE_CLOUDY) == 0
  || strcmp(userData.weather_code,WEATHER_CODE_DAY_MOSTLY_CLOUDY) == 0
  || strcmp(userData.weather_code,WEATHER_CODE_NIGHT_MOSTLY_CLOUDY) == 0
  || strcmp(userData.weather_code,WEATHER_CODE_OVERCAST) == 0){
    userData.weather = CLOUD;
  }else if(strcmp(userData.weather_code,WEATHER_CODE_SHOWER) == 0
  || strcmp(userData.weather_code,WEATHER_CODE_LIGHT_RAIN) == 0
  || strcmp(userData.weather_code,WEATHER_CODE_MODERATE_RAIN) == 0
  || strcmp(userData.weather_code,WEATHER_CODE_HEAVY_RAIN) == 0
  || strcmp(userData.weather_code,WEATHER_CODE_STORM) == 0
  || strcmp(userData.weather_code,WEATHER_CODE_HEAVY_STORM) == 0
  || strcmp(userData.weather_code,WEATHER_CODE_SEVERE_STORM) == 0){
    userData.weather = RAIN;
  }else if(strcmp(userData.weather_code,WEATHER_CODE_THUNDERSHOWER) == 0
  || strcmp(userData.weather_code,WEATHER_CODE_THUNDERSHOWER_WITH_HAIL) == 0){
    userData.weather = THUNDER;
  }else{
    userData.weather = CLOUD;
  } 
}

/*
@功能:绘制天气信息图标
*/
void drawWeather(void){
  u8g2.setFont(u8g2_font_open_iconic_weather_2x_t);
  switch(userData.weather)
  {
    case SUN_DAY:// 太 阳
       u8g2.drawGlyph(0, 16, 69);
       break;
    case SUN_NIGHT:// 太 阳
       u8g2.drawGlyph(0, 16, 66);
       break;
    case SUN_CLOUD:// 晴 间 多 云
       u8g2.drawGlyph(0, 16, 65);
       break;
    case CLOUD:// 多 云
       u8g2.drawGlyph(0, 16, 64);
       break;
    case RAIN:// 下 雨
       u8g2.drawGlyph(0, 16, 67);
       break;
    case THUNDER:// 打 雷
       u8g2.drawGlyph(0, 16, 67);
       break;         
   }
  u8g2.setFont(u8g2_font_9x15_t_symbols);// 绘 制 温 度
  u8g2.setCursor(20, 13);
  u8g2.print(userData.temp);
  u8g2.print("°C");
}

/*
@功能:几何动画
*/
void HariChord(int frame)
{
  int nFrames = 36;
  u8g2.clearBuffer();
  int n = 7;
  int r = frame * 64 / nFrames;
  float rot = frame * 2*PI / nFrames;
  for (int i=0; i<(n-1); i++)
  {
    float a = rot + i * 2*PI / n;
    int x1 = 64 + cos(a) * r;
    int y1 = 32 + sin(a) * r;
    for (int j=i+1; j<n; j++)
    {
      a = rot + j * 2*PI / n;
      int x2 = 64 + cos(a) * r;
      int y2 = 32 + sin(a) * r;
      u8g2.drawLine(x1,y1, x2,y2);
    }
    ESP.wdtFeed();// 喂 狗     
  }
  u8g2.sendBuffer();
}

/*
@功能:开机动画
*/
void boot_animation(){
  //爱心眼睛
  const static unsigned char FACE_Love[] PROGMEM ={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xFF,0xFF,0x00,0x00,0x00,0xFC,0xFF,0x3F,0x00,0x00,0x00,0xFE,0xFF,0xFF,0x03,0x00,0x80,0xFF,0xFF,0xFF,0x01,0x00,0x80,0xFF,0xFF,0xFF,0x0F,0x00,0xC0,0xFF,0xFF,0xFF,0x03,0x00,0xC0,0x07,0x00,0x00,0x1F,0x00,0xE0,0x03,0x00,0xC0,0x07,0x00,0xE0,0x01,0x00,0x00,0x3C,0x00,0xF0,0x00,0x00,0x00,0x0F,0x00,0xE0,0x00,0x00,0x00,0x38,0x00,0x78,0x00,0x00,0x00,0x1E,0x00,0x70,0x00,0x00,0x00,0x70,0x00,0x38,0x00,0x00,0x00,0x1C,0x00,0x70,0x00,0x00,0x00,0x70,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0xE0,0x07,0x3F,0xE0,0x00,0x0C,0xF0,0x81,0x0F,0x30,0x00,0x38,0xF0,0x8B,0x5F,0xE0,0x00,0x0C,0xF8,0xC2,0x1F,0x30,0x00,0x38,0xF8,0xD7,0xBF,0xE0,0x00,0x0C,0xFC,0xE5,0x2F,0x30,0x00,0x38,0xF8,0xFF,0xBF,0xE0,0x00,0x0C,0xFE,0xFF,0x5F,0x30,0x00,0x38,0xFC,0xFF,0x7F,0xE0,0x00,0x0C,0xFE,0xFF,0x5F,0x30,0x00,0x38,0xFC,0xFF,0xFF,0xE1,0x00,0x0C,0xFE,0xFF,0x7F,0x30,0x00,0x38,0xFC,0xFF,0xFF,0xE1,0x00,0x0C,0xFE,0xFF,0x7F,0x30,0x00,0x38,0xFC,0xFF,0xFF,0xE1,0x00,0x0C,0xFE,0xFF,0x7F,0x30,0x00,0x38,0xF8,0xFF,0xFF,0xE0,0x00,0x0C,0xFE,0xFF,0x7F,0x30,0x00,0x38,0xF8,0xFF,0xFF,0xE0,0x00,0x0C,0xFE,0xFF,0x7F,0x30,0x00,0x38,0xF8,0xFF,0xFF,0xE0,0x00,0x0C,0xFC,0xFF,0x3F,0x30,0x00,0x38,0xF0,0xFF,0x7F,0xE0,0x00,0x0C,0xF8,0xFF,0x1F,0x30,0x00,0x38,0xC0,0xFF,0x1F,0xE0,0x00,0x0C,0xF0,0xFF,0x0F,0x30,0x00,0x38,0x80,0xFF,0x0F,0xE0,0x00,0x0C,0xE0,0xFF,0x07,0x30,0x00,0x38,0x00,0xFF,0x07,0xE0,0x00,0x0C,0xC0,0xFF,0x03,0x30,0x00,0x38,0x00,0xFE,0x03,0xE0,0x00,0x0C,0x80,0xFF,0x01,0x30,0x00,0x38,0x00,0xFC,0x01,0xE0,0x00,0x0C,0x00,0x7E,0x00,0x30,0x00,0x38,0x00,0xF8,0x00,0xE0,0x00,0x0C,0x00,0x3C,0x00,0x30,0x00,0x38,0x00,0x70,0x00,0xE0,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x38,0x00,0x20,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x70,0x00,0x00,0x00,0x70,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x70,0x00,0x00,0x00,0x70,0x00,0x3C,0x00,0x00,0x00,0x3C,0x00,0xF0,0x00,0x00,0x00,0x78,0x00,0x38,0x00,0x00,0x00,0x1C,0x00,0xE0,0x01,0x00,0x00,0x3C,0x00,0x78,0x00,0x00,0x00,0x1E,0x00,0xC0,0x03,0x00,0x00,0x1E,0x00,0xF0,0x01,0x00,0x80,0x0F,0x00,0x80,0x1F,0x00,0xC0,0x0F,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0x00,0xFF,0xFF,0xFF,0x07,0x00,0xC0,0xFF,0xFF,0xFF,0x03,0x00,0x00,0xFC,0xFF,0xFF,0x01,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
  //睁眼
  const static unsigned char FACE_Neutral[] PROGMEM ={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xFF,0xFF,0x00,0x00,0x00,0xFC,0xFF,0x3F,0x00,0x00,0x00,0xFE,0xFF,0xFF,0x03,0x00,0x80,0xFF,0xFF,0xFF,0x01,0x00,0x80,0xFF,0xFF,0xFF,0x0F,0x00,0xC0,0xFF,0xFF,0xFF,0x03,0x00,0xC0,0x07,0x00,0x00,0x1F,0x00,0xE0,0x03,0x00,0xC0,0x07,0x00,0xE0,0x01,0x00,0x00,0x3C,0x00,0xF0,0x00,0x00,0x00,0x0F,0x00,0xE0,0x00,0x00,0x00,0x38,0x00,0x78,0x00,0x00,0x00,0x1E,0x00,0x70,0x00,0x00,0x00,0x70,0x00,0x38,0x00,0x00,0x00,0x1C,0x00,0x70,0x00,0x00,0x00,0x70,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x84,0x00,0xE0,0x00,0x0C,0x00,0x41,0x00,0x30,0x00,0x38,0x00,0x70,0x00,0xE0,0x00,0x0C,0x00,0x38,0x01,0x30,0x00,0x38,0x00,0xFC,0x01,0xE0,0x00,0x0C,0x00,0x7F,0x00,0x30,0x00,0x38,0x00,0xFE,0x03,0xE0,0x00,0x0C,0xA0,0xFF,0x05,0x30,0x00,0x38,0x00,0x7F,0x06,0xE0,0x00,0x0C,0x80,0x3F,0x01,0x30,0x00,0x38,0x40,0x7F,0x17,0xE0,0x00,0x0C,0xC0,0xDF,0x03,0x30,0x00,0x38,0x80,0xFF,0x0F,0xE0,0x00,0x0C,0xD0,0xFF,0x0B,0x30,0x00,0x38,0x80,0xFF,0x0F,0xE0,0x00,0x0C,0xC0,0xFF,0x03,0x30,0x00,0x38,0x80,0xFF,0x0F,0xE0,0x00,0x0C,0xD0,0xFF,0x0B,0x30,0x00,0x38,0x00,0xFF,0x07,0xE0,0x00,0x0C,0xC0,0xFF,0x03,0x30,0x00,0x38,0x40,0xFF,0x17,0xE0,0x00,0x0C,0x80,0xFF,0x01,0x30,0x00,0x38,0x00,0xFE,0x03,0xE0,0x00,0x0C,0xA0,0xFF,0x05,0x30,0x00,0x38,0x00,0xFC,0x01,0xE0,0x00,0x0C,0x00,0xFF,0x00,0x30,0x00,0x38,0x00,0x70,0x00,0xE0,0x00,0x0C,0x80,0x3C,0x01,0x30,0x00,0x38,0x00,0x84,0x00,0xE0,0x00,0x0C,0x00,0x42,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x70,0x00,0x00,0x00,0x70,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x70,0x00,0x00,0x00,0x70,0x00,0x3C,0x00,0x00,0x00,0x3C,0x00,0xF0,0x00,0x00,0x00,0x78,0x00,0x38,0x00,0x00,0x00,0x1C,0x00,0xE0,0x01,0x00,0x00,0x3C,0x00,0x78,0x00,0x00,0x00,0x1E,0x00,0xC0,0x03,0x00,0x00,0x1E,0x00,0xF0,0x01,0x00,0x80,0x0F,0x00,0x80,0x1F,0x00,0xC0,0x0F,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0x00,0xFF,0xFF,0xFF,0x07,0x00,0xC0,0xFF,0xFF,0xFF,0x03,0x00,0x00,0xFC,0xFF,0xFF,0x01,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
  //闭眼
  const static unsigned char FACE_Tired_middle[] PROGMEM ={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xFF,0xFF,0x00,0x00,0x00,0xFC,0xFF,0x3F,0x00,0x00,0x00,0xFE,0xFF,0xFF,0x03,0x00,0x80,0xFF,0xFF,0xFF,0x01,0x00,0x80,0xFF,0xFF,0xFF,0x0F,0x00,0xC0,0xFF,0xFF,0xFF,0x03,0x00,0xC0,0x07,0x00,0x00,0x1F,0x00,0xE0,0x03,0x00,0xC0,0x07,0x00,0xE0,0x01,0x00,0x00,0x3C,0x00,0xF0,0x00,0x00,0x00,0x0F,0x00,0xE0,0x00,0x00,0x00,0x38,0x00,0x78,0x00,0x00,0x00,0x1E,0x00,0x70,0x00,0x00,0x00,0x70,0x00,0x38,0x00,0x00,0x00,0x1C,0x00,0x70,0x00,0x00,0x00,0x70,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x38,0x00,0xF8,0xFF,0xFF,0xFF,0xFF,0x00,0xFC,0xFF,0xFF,0xFF,0x3F,0x00,0xF8,0xFF,0xFF,0xFF,0xFF,0x00,0xFC,0xFF,0xFF,0xFF,0x3F,0x00,0x38,0x40,0xFF,0x17,0xE0,0x00,0x1C,0xD0,0xDF,0x0B,0x38,0x00,0x38,0x80,0xFF,0x0F,0xE0,0x00,0x0C,0xC0,0xFF,0x0B,0x30,0x00,0x38,0x80,0xFF,0x0F,0xE0,0x00,0x0C,0xD0,0xFF,0x03,0x30,0x00,0x38,0x80,0xFF,0x0F,0xE0,0x00,0x0C,0xD0,0xFF,0x0B,0x30,0x00,0x38,0x00,0xFF,0x07,0xE0,0x00,0x0C,0xC0,0xFF,0x03,0x30,0x00,0x38,0x40,0xFF,0x17,0xE0,0x00,0x0C,0x80,0xFF,0x01,0x30,0x00,0x38,0x00,0xFE,0x03,0xE0,0x00,0x1C,0xA0,0xFF,0x05,0x38,0x00,0x70,0x00,0xFC,0x01,0x70,0x00,0x1C,0x00,0xFF,0x00,0x38,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x3C,0x80,0x3C,0x01,0x3C,0x00,0xF0,0x00,0x84,0x00,0x78,0x00,0x38,0x00,0x42,0x00,0x1C,0x00,0xE0,0x01,0x00,0x00,0x3C,0x00,0x78,0x00,0x00,0x00,0x1E,0x00,0xC0,0x03,0x00,0x00,0x1E,0x00,0xF0,0x01,0x00,0x80,0x0F,0x00,0x80,0x1F,0x00,0xC0,0x0F,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0x00,0xFF,0xFF,0xFF,0x07,0x00,0xC0,0xFF,0xFF,0xFF,0x03,0x00,0x00,0xFC,0xFF,0xFF,0x01,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
  
  u8g2.firstPage();
  do{u8g2.drawXBMP(20,0,89,64,FACE_Neutral);}
  while (u8g2.nextPage());
  delay(400);
  u8g2.firstPage();
  do{u8g2.drawXBMP(20,0,89,64,FACE_Tired_middle);}
  while (u8g2.nextPage());
  delay(100);
  u8g2.firstPage();
  do{u8g2.drawXBMP(20,0,89,64,FACE_Neutral);}
  while (u8g2.nextPage());
  delay(400);
  u8g2.firstPage();
  do{u8g2.drawXBMP(20,0,89,64,FACE_Tired_middle);}
  while (u8g2.nextPage());
  delay(100);
  u8g2.firstPage();
  do{u8g2.drawXBMP(20,0,89,64,FACE_Neutral);}
  while (u8g2.nextPage());
  delay(400);
  u8g2.firstPage();
  do{u8g2.drawXBMP(20,0,89,64,FACE_Love);}
  while (u8g2.nextPage());
  delay(300);
}

/*
@功能:打印系统参数,固件版本信息
*/
void print_firmware_information(void){
  FlashMode_t ideMode = ESP.getFlashChipMode();
  String coreVersion = ESP.getCoreVersion();
  Serial.println("\n");
  Serial.print(F("Arduino Core For ESP8266 Version: "));
  Serial.println(coreVersion);
  Serial.printf("\nESP8266芯片id: %u \n\n", ESP.getChipId());
  Serial.printf("天气时钟固件版本: %s \n\n", Firmware_version);
  Serial.print("固件编译时间:");
  Serial.print(__DATE__);
  Serial.print("   ");
  Serial.println(__TIME__);
  Serial.println();
  Serial.printf("固件大小: %u KBytes\n\n", ESP.getSketchSize()/1024);
  Serial.printf("剩余可用固件空间: %u KBytes\n\n", ESP.getFreeSketchSpace()/1024);
  Serial.printf("Flash real id:   %08X\n\n", ESP.getFlashChipId());
  Serial.printf("Flash 实际大小: %u KBytes\n\n", ESP.getFlashChipRealSize()/1024);
  Serial.printf("IDE配置Flash大小: %u KBytes\n\n", ESP.getFlashChipSize()/1024);
  Serial.printf("IDE配置Flash频率: %u MHz\n\n", ESP.getFlashChipSpeed()/1000000);
  Serial.printf("Flash ide mode:  %s\n\n", (ideMode == FM_QIO ? "QIO" : ideMode == FM_QOUT ? "QOUT" : ideMode == FM_DIO ? "DIO" : ideMode == FM_DOUT ? "DOUT" : "UNKNOWN"));
}


/*
@说明:十六进制转数组
*/
void FONT_16_2(const unsigned char chr,int *point){
   int a=chr;
   *point= a/128;
   a=a-128*(*point);point++;
   *point= a/64;
   a=a-64*(*point);point++;
   *point= a/32;
   a=a-32*(*point);point++;
   *point= a/16;
   a=a-16*(*point);point++;
   *point= a/8;
   a=a-8*(*point);point++;
   *point= a/4;
   a=a-4*(*point);point++;
   *point= a/2;
   a=a-2*(*point);point++;
   *point= a;
}



/*
@功能:获取网络时间部分代码
@说明:太复杂,不看~
*/
const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets

time_t getNtpTime(void){
  IPAddress ntpServerIP; // NTP server's ip address

  while (Udp.parsePacket() > 0) ; // discard any previously received packets
  Serial.println("Transmit NTP Request");
  // get a random server from the pool
  WiFi.hostByName(ntpServerName, ntpServerIP);
  Serial.print(ntpServerName);
  Serial.print(": ");
  Serial.println(ntpServerIP);
  sendNTPpacket(ntpServerIP);
  uint32_t beginWait = millis();
  while (millis() - beginWait < 1500) {
    int size = Udp.parsePacket();
    if (size >= NTP_PACKET_SIZE) {
      Serial.println("Receive NTP Response");
      Udp.read(packetBuffer, NTP_PACKET_SIZE);  // read packet into the buffer
      unsigned long secsSince1900;
      // convert four bytes starting at location 40 to a long integer
      secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
      secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
      secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
      secsSince1900 |= (unsigned long)packetBuffer[43];
      return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
    }
  }
  Serial.println("No NTP Response :-(");//没连接到NTP服务器
  return 0; // return 0 if unable to get the time
}

// send an NTP request to the time server at the given address
void sendNTPpacket(IPAddress &address)
{
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12] = 49;
  packetBuffer[13] = 0x4E;
  packetBuffer[14] = 49;
  packetBuffer[15] = 52;
  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer, NTP_PACKET_SIZE);
  Udp.endPacket();
}
  • 🛠开发板配置
    在这里插入图片描述

  • 📋 编译信息

使用 1.0  版本的库 ESP8266WiFi 在文件夹: C:\Users\Administrator\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\libraries\ESP8266WiFi 
使用 1.2  版本的库 ESP8266HTTPClient 在文件夹: C:\Users\Administrator\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\libraries\ESP8266HTTPClient 
使用 1.2  版本的库 ESP8266mDNS 在文件夹: C:\Users\Administrator\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\libraries\ESP8266mDNS 
使用 1.0  版本的库 ArduinoOTA 在文件夹: C:\Users\Administrator\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\libraries\ArduinoOTA 
使用 6.20.0  版本的库 ArduinoJson 在文件夹: C:\Users\Administrator\Documents\Arduino\libraries\ArduinoJson 
使用 1.0  版本的库 EEPROM 在文件夹: C:\Users\Administrator\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\libraries\EEPROM 
使用 1.0  版本的库 Ticker 在文件夹: C:\Users\Administrator\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\libraries\Ticker 
使用 1.6.1  版本的库 Time 在文件夹: C:\Users\Administrator\Documents\Arduino\libraries\Time 
使用 2.33.15  版本的库 U8g2 在文件夹: C:\Users\Administrator\Documents\Arduino\libraries\U8g2 
使用 1.1.0  版本的库 DS3231 在文件夹: C:\Users\Administrator\Documents\Arduino\libraries\DS3231 
使用 1.0  版本的库 Wire 在文件夹: C:\Users\Administrator\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\libraries\Wire 
使用 1.0  版本的库 SPI 在文件夹: C:\Users\Administrator\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\libraries\SPI 
"C:\\Users\\Administrator\\AppData\\Local\\Arduino15\\packages\\esp8266\\tools\\xtensa-lx106-elf-gcc\\3.0.4-gcc10.3-1757bed/bin/xtensa-lx106-elf-size" -A "d:\\arduino\\MyHexDir/ESP8266_weather_arduino.ino.elf"
项目使用了 705548 字节,占用了 (67%) 程序存储空间。最大为 1044464 字节。
全局变量使用了35768字节,(43%)的动态内存,余留46152字节局部变量。最大为81920字节。

📚程序源码

🔖请使用源码的注意,自己申请免费的API接口,不要占用我的密钥,免得找出数据访问拥挤导致获取数据失败。

链接:https://pan.baidu.com/s/1h8IlAGmscO5xiBC61P2-GA 
提取码:357u
  • 5
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值