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

Posted perseverance52

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了开源天气时钟项目删减和更新相关的知识,希望对你有一定的参考价值。

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


  • 📌原项目开源地址: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以上是关于开源天气时钟项目删减和更新的主要内容,如果未能解决你的问题,请参考以下文章

基于Lua框架下的合宙ESP32C3+1.54‘’Eink墨水屏天气时钟项目

基于STM32与ESP8266的太空人WiFi天气时钟(代码开源)

0.96“OLED+ESP8266天气时钟+古诗农历显示

手把手教你做一个天气时钟,推荐收藏

手把手教你做一个天气时钟,推荐收藏

天气APP之桌面时钟witget组件