【DIY】物联网天气时钟小电视
【DIY】物联网天气时钟小电视
本文最后更新于337 天前,其中的信息可能已经过时,如有错误请发送邮件到273925452@qq.com
Avatar
这个项目是入门Arduino后做的项目,Arduino是跟着太极创客学的,强烈推荐😀

功能介绍

简易WiFi连接

用户可使用手机对本时钟设备设置WiFi连接。简单易用。

实时信息显示

– 可实时显示天气信息(当前天气情况和当前气温)

– 可实时显示天气预报(天气情况、最高气温、最低气温)

– 用户可根据自行需要显示五天天气预报(需要修改代码)

时钟背景可调

– 背景图片定时变化

– 可自行定制背景图片

配合然也物联应用

– 可通过然也物联手机应用对系统进行设置,如设置背景更换时间间隔,LED灯亮灭

– 可使用然也物联手机应用将聊天信息显示在屏幕上(目前只支持英文或拼音,尚无法显示中文)

硬件材料说明

电路模块

ESP8266物联网开发板 – 1块

– ILI9341 TFT彩屏 – 1块

演示视频

Arduino程序

#include <TimeLib.h>
#include <ESP8266WiFi.h>      // 调用ESP8266WiFi功能
#include <WiFiUdp.h>
#include <DNSServer.h>

#define FS_NO_GLOBALS         // 调用ESP8266的SPIFFS FLASH
#include <FS.h>

#include <TFT_eSPI.h>         
#include <TFT_eFEX.h> 
#include <SPI.h> 

#include <WiFiManager.h>       //配网,物联网服务器
#include <ESP8266_BiliBili.h>    
#include <ESP8266_Seniverse.h>
#include <PubSubClient.h>
#define USE_MQTT

//MQTT通讯相关
String controlTopic = WiFi.macAddress() + "-control"; // 设备控制主题
String chatTopic = WiFi.macAddress() + "-chat";       // 用户消息主题
String reportTopic = WiFi.macAddress() + "-report";   // 系统报告主题
String userControlString;                       // 用户通过MQTT协议发来的设置信息
String userChatString;                          // 用户通过MQTT协议发来的聊天信息
bool userChatFlag = false;                   // 告知系统是否有用户聊天信息需要显示
WiFiClient wifiClient;              //建立MQTT协议所需对象
PubSubClient mqttClient(wifiClient);

//中文字库和设置库
#include "chinese.h"  
#include "settings.h" 

//图片解码 
#include <TJpg_Decoder.h>
#include <ArduinoJson.h>

//TFT屏幕显示相关 对象 和 变量
TFT_eSPI tft = TFT_eSPI();
TFT_eFEX  fex = TFT_eFEX(&tft); 
TFT_eSprite clk = TFT_eSprite(&tft);
bool bgChangeFlag;                    // 背景更改显示标识
int bgId = START_BG_NUM;             // 背景序号

// NTP服务
WiFiUDP Udp;
unsigned int localPort = 8888;    // 端口
time_t prevDisplay = 0;           // 上一次显示的时间,打点

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

//Ticker相关
//Ticker ticker;
int bgCounter;   

//b站API相关
FansInfo fansInfo(biliUserId);       // 建立对象用于获取 粉丝信息
VideoInfo videoInfo(biliBV);         // 建立对象用于获取 视频信息
int biliCounter;
bool biliUpdateFlag;
long biliFans;
long biliViews;


// 建立对象和变量用于获取 心知天气信息
WeatherNow weatherNow;
Forecast forecast; 
int weatherUpdateCounter;
bool weatherUpdateFlag;
byte weatherInfoDisplayCounter;
byte weatherInfoId = 1;


//设置图片大小 或者 文字颜色位置
#define BANNER_HEIGHT 20      // 横幅高
#define BANNER_WIDTH 320      // 横幅宽
#define HALF_BANNER_WIDTH 160 // 半横幅宽
#define BANNER_BG  TFT_WHITE  // 横幅背景色
#define BANNER_FG  TFT_NAVY   // 横幅文字色


//字库 动画或者图标
#include "font/ZdyLwFont_20.h"
#include "font/FxLED_32.h"

#include "img/watch_top.h"
#include "img/watch_bottom.h"
#include "img/temperature.h"
#include "img/humidity.h"//湿度

#include "img/pangzi/i0.h"
#include "img/pangzi/i1.h"
#include "img/pangzi/i2.h"
#include "img/pangzi/i3.h"
#include "img/pangzi/i4.h"
#include "img/pangzi/i5.h"
#include "img/pangzi/i6.h"
#include "img/pangzi/i7.h"
#include "img/pangzi/i8.h"
#include "img/pangzi/i9.h"

int led1 = D1;

bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
{
  if ( y >= tft.height() ) return 0;
  tft.pushImage(x, y, w, h, bitmap);
  // Return 1 to decode next block
  return 1;
}


//开机加载动画
byte loadNum = 6;  //加载开始位置
void loading(byte delayTime)
{
   clk.setColorDepth(8);      //颜色深度 4 8 16
  
   clk.createSprite(250, 30);  //创建精灵区域(int16_t width, int16_t height, uint8_t frames = 1)
   clk.fillSprite(TFT_BLACK);  //填充精灵区域的颜色
   //开始在精灵区域画图
   clk.drawRoundRect(0,0,250,16,8,TFT_WHITE);// 绘制圆角矩形(xy为0的时候,自动在区域基准开始)(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color)
   clk.fillRoundRect(3,3,loadNum,10,5,TFT_ORANGE);//填充圆角矩形(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color);
  
  clk.setTextDatum(CC_DATUM);//文字基准位置
  clk.setTextColor(TFT_WHITE, TFT_BLACK); //文字颜色,背景颜色
  clk.drawString("Connecting to WiFi",150,160,2);//(const char *string, int32_t x, int32_t y, uint8_t font(字体)),   
  
  clk.pushSprite(40,180);//(int32_t x, int32_t y);//将精灵的窗口区域推到tx,ty的TFT上
  clk.deleteSprite();
  loadNum += 1;
  if(loadNum>=244){
    loadNum = 244;
  }
}


void setup() 
{
  Serial.begin(9600);

    if (!SPIFFS.begin()) {                              // 检查SPIFFS是否可以正确启动
    Serial.println("SPIFFS initialisation failed!"); // 如果SPIFFS无法启动则输出错误提示
    while (1) yield();                                // 然后程序停在此处
  }
  Serial.println("\r\nSPIFFS initialised.");         // 如果SPIFFS正确启动则输出启动成功信息 
   
   pinMode(D1,OUTPUT);
  // 初始化tft屏幕
     tft.begin();
     tft.setRotation(1);         // 设置屏幕显示方向
     tft.fillScreen(TFT_BLACK);  // 将屏幕填充黑色
  
    // ---WiFi准备工作---  
    // 建立WiFiManager对象    
    WiFiManager wifiManager; 
    //wifiManager.resetSettings();// 清除ESP8266所存储的WiFi连接信息 
    wifiManager.autoConnect("heiweilu"); //手动配网
  
   //开机加载背景与动画
    String bgName1 = "/bg" + String(61) + ".jpg";
    fex.drawJpeg(bgName1, 2, 2); //(数组名字,x,y)
    
    while (WiFi.status() != WL_CONNECTED) {
    for(byte n=0;n<10;n++){ //每500毫秒检测一次状态
      loading(50);
    }
  }
  while(loadNum < 194){ //让动画走完
    loading(1);
  }
    #ifdef USE_MQTT
    // ---MQTT准备工作---
    // 设置MQTT服务器和端口号
    mqttClient.setServer(mqttServer, 1883);
    // 设置MQTT订阅回调函数
    mqttClient.setCallback(receiveCallback);
    // 连接MQTT服务器
    connectMQTTserver();
    Serial.println("Report Topic:");
    Serial.println(reportTopic);
  #endif
  
    //---bili信息初始化---
  biliFans = getBiliFans();
  biliViews = getBiliViews();

  // 天气信息
  weatherNow.config(reqUserKey, reqLocation, reqUnit);
  forecast.config(reqUserKey, reqLocation, reqUnit);
  updateWeatherInfo();  // 启动后获取天气信息  

  // ---NTP初始化---
  ntpInit(); 

  TJpgDec.setJpgScale(1);
  TJpgDec.setSwapBytes(true);
  TJpgDec.setCallback(tft_output);
  

   //设置一个窗口和基准
   tft.setViewport(2, 38, 316, 240);
   tft.fillScreen(TFT_WHITE); 
   tft.resetViewport();//复位基准
   
  //背景设置
  String bgName = "/bg" + String(60) + ".jpg";
  fex.drawJpeg(bgName, 2, 2); //(数组名字,x,y)
  displayBg(bgId); 
   
  //绘制线框
  tft.drawFastHLine(0,238,320,TFT_BLACK);//横线(int32_t x, int32_t y, int32_t w, uint32_t color)
  tft.drawFastHLine(2,40,320,TFT_BLACK);
  tft.drawFastHLine(2,2,320,TFT_BLACK);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
  
  tft.drawFastVLine(2,2,238,TFT_BLACK);//竖线(int32_t x, int32_t y, int32_t h, uint32_t color)
  tft.drawFastVLine(2,2,40,TFT_BLACK);
  tft.drawFastVLine(184,42,179,TFT_BLACK);

  //显示星期二字
  tft.drawBitmap(235,10,xing,20,20,TFT_BLACK); // 显示星字
  tft.drawBitmap(256,10,qi1,20,20,TFT_BLACK);  // 显示期字 
  tft.setTextColor(TFT_MAROON);
  tft.drawString(reqLocation,128,10,4); //显示地区

   //初始化时显示天气信息  
  displayWeatherInfo(1); 

  

  //TJpgDec.drawJpg(7,10,temperature, sizeof(temperature));  //温度图标
  //TJpgDec.drawJpg(65,10,humidity, sizeof(humidity));  //湿度图标
 
}


void loop()
{   
  if (timeStatus() != timeNotSet)
  {
    if (now() != prevDisplay)
    {     //仅当时间发生变化时才更新显示
      prevDisplay = now();
      displayTime();
      //digitalClockDisplay();
      #ifdef USE_MQTT
        Serial.println("");
        Serial.println("controlTopic:");
        Serial.println(controlTopic);
        Serial.println("chatTopic:");
        Serial.println(chatTopic);      
        Serial.println("reportTopic:");
        Serial.println(reportTopic);  
        Serial.println("");        
      #endif
      
      tick();  // 计时函数
    }
  }

    if (bgChangeFlag == true)
    {
    bgChangeFlag = false;    
    bgId++;
    if (bgId > END_BG_NUM) 
    bgId = START_BG_NUM;
    displayBg(bgId);   
  }
 
 // 更新bili信息 
  if (biliUpdateFlag == true)
  {
    Serial.println("Update Bili Info");
    
    biliUpdateFlag = false;    
    biliFans = getBiliFans();
    biliViews = getBiliViews();
  }

  // 更新天气信息 
  if (weatherUpdateFlag == true)
  {
    Serial.println("Update Weather Info");
    
    weatherUpdateFlag = false;  
    updateWeatherInfo();   
    displayWeatherInfo(weatherInfoId);
  }
  #ifdef USE_MQTT
  
  if (mqttClient.connected()) // 如果开发板成功连接服务器
  {                          
    mqttClient.loop();          // 处理信息以及心跳
  } else {                      // 如果开发板未能成功连接服务器
    connectMQTTserver();        // 则尝试连接服务器
  } 
  #endif
  imgAnim();//启动太空人
}


//---------时间显示相关函数开始----------
//显示时间子函数
void displayTime()
{
  String timeString;
  String dateString;
  String dateTimeString;
  
  timeString = adjDigit(hour()) + ":" ;//+ adjDigit(minute())+ ":" + adjDigit(second());
  dateString = adjDigit(month()) + "-" + adjDigit(day());
  dateTimeString = dateString + "           " + timeString;

  
  /*// 设置时钟显示位置
  tft.setViewport(0, 0, BANNER_WIDTH, BANNER_HEIGHT);
  tft.setTextDatum(TL_DATUM);
  tft.setTextColor(BANNER_FG, );  //设置文字颜色和背景色
  tft.setTextPadding(10); //设置文字padding,覆盖旧字
  tft.drawString(dateTimeString, 0, 0, 4); */



  //显示星期几(右上角)
  if (weekday() == 1) 
  {
    tft.fillRect(280, 9, 20, 20, TFT_LIGHTGREY);
    tft.drawBitmap(280,9,tian,20,20,TFT_BLACK);  // 星期天显示天字 (中文用Bitmap)
  }
     else 
   {
    tft.fillRect(300, 4, 20, 20, TFT_LIGHTGREY);
    tft.setTextDatum(TR_DATUM);
    tft.setTextColor(TFT_BLACK);
    tft.drawString(String(weekday()-1), 300, 9, 4);    //显示星期几数字
    }
   
  tft.resetViewport();  
  
  /***时间区***/
  //时
  clk.setColorDepth(8);
  clk.createSprite(135, 48);//宽高
  clk.fillSprite(TFT_LIGHTGREY);
 // clk.loadFont(FxLED_32);
  clk.setTextDatum(CC_DATUM);
  clk.setTextColor(TFT_MAROON,TFT_LIGHTGREY);
  clk.drawString(timeString,39,24,7); //绘制时
 // clk.unloadFont();
  clk.setTextColor(TFT_ORANGE,TFT_LIGHTGREY);
  clk.drawString(adjDigit(minute()),105,24,7); //绘制分
  //clk.unloadFont();
  clk.pushSprite(185,42);//完美坐标
  clk.deleteSprite();

  
  
  //秒
  clk.createSprite(40, 32);
  clk.fillSprite(TFT_LIGHTGREY);  
  clk.loadFont(FxLED_32);
  clk.setTextDatum(CC_DATUM);
  clk.setTextColor(TFT_BLACK, TFT_LIGHTGREY); 
  clk.drawString(adjDigit(second()),20,16);  
  clk.unloadFont();
  clk.pushSprite(278,89);
  clk.deleteSprite();
  

  //月日
  clk.loadFont(ZdyLwFont_20);
  clk.createSprite(90, 24);//动态变化必须创建精灵
  clk.fillSprite(TFT_TRANSPARENT);//设置透明背景~~
  
  clk.setTextDatum(CC_DATUM);
  clk.setTextColor(TFT_BLACK, TFT_TRANSPARENT);  
  clk.drawString(monthDay(),45,16);
  clk.pushSprite(13,8,TFT_TRANSPARENT);
  clk.deleteSprite(); 
  clk.unloadFont();    
}


String adjDigit(int number)
{
  if (number >= 10){
    return String(number);
  } else {
    return String("0" + String(number));
  }
}


String monthDay(){
  String s = String(month());
  s = s + "月" + day() + "日";
  return s;
}


//*********************动画****************
//太空人
void imgAnim()
{
  int x=230,y=125,dt=30;//瘦子版dt=10毫秒 胖子30较为合适
  TJpgDec.drawJpg(x,y,i0, sizeof(i0));
  delay(dt);
  TJpgDec.drawJpg(x,y,i1, sizeof(i1));
  delay(dt);
  TJpgDec.drawJpg(x,y,i2, sizeof(i2));
  delay(dt);
  TJpgDec.drawJpg(x,y,i3, sizeof(i3));
  delay(dt);  
  TJpgDec.drawJpg(x,y,i4, sizeof(i4));
  delay(dt);  
  TJpgDec.drawJpg(x,y,i5, sizeof(i5));
  delay(dt); 
  TJpgDec.drawJpg(x,y,i6, sizeof(i6));
  delay(dt);  
  TJpgDec.drawJpg(x,y,i7, sizeof(i7));
  delay(dt);  
  TJpgDec.drawJpg(x,y,i8, sizeof(i8));
  delay(dt);  
  TJpgDec.drawJpg(x,y,i9, sizeof(i9));
  delay(dt);
}
//*********************动画****************




//背景图片展示子函数
void displayBg(int bgId){
  String bgName = "/bg" + String(bgId) + ".jpg";
  fex.drawJpeg(bgName, 4, 42); 
  if (userChatFlag == true)
  {
    Serial.print("userChatFlag = ");Serial.println(userChatFlag);
    showChatMessage(userChatString);
  }
  Serial.println(bgName);
}


//--- NTP(Network Time Protocol,网络时间协议)相关函数开始 ---
// ntp初始化
void ntpInit()
{
  Serial.println("Starting UDP");
  Udp.begin(localPort);
  Serial.print("Local UDP port: ");
  Serial.println(Udp.localPort());
  Serial.println("-------------");
  setSyncProvider(getNtpTime);// 设置对时函数
  setSyncInterval(timeCheckInterval);        // 每隔10秒钟对时一次
}

//获取NTP时间
time_t getNtpTime()
{
  IPAddress ntpServerIP; // NTP server's ip address

  while (Udp.parsePacket() > 0) ; // discard any previously received packets
  Serial.println("Transmit NTP Request");
  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 :-(");
  return 0; // return 0 if unable to get the time
}

// 向指定地址的时间服务器发送NTP请求子函数
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();
}
//--- NTP相关函数结束 ---



//--- 定时调用计时器函数 --- 
void tick()
{
  displayTime(); // 每秒更新时钟显示
  
  bgCounter++;//背景更换
  // 哔哩哔哩更新计时器
  biliCounter++;

  //天气更新计时器
  weatherUpdateCounter++;
  weatherInfoDisplayCounter++;
  
  // 达到背景变换时间
  if (bgCounter > bgChgInterval)
  {
    bgCounter = 0;
    bgChangeFlag = true;//更换背景变换状态标志
  }

  // 达到bili信息更新时间
  if (biliCounter > biliUpdateInterval){
    biliCounter = 0;
    biliUpdateFlag = true;
  }  

  // 达到天气信息更新时间
  if (weatherUpdateCounter > weatherUpdateInterval){
    weatherUpdateCounter = 0;
    weatherUpdateFlag = true;
  }   

 // 达到天气信息变化时间
  if (weatherInfoDisplayCounter > weatherDisplayInterval){
    weatherInfoDisplayCounter = 1;
    weatherInfoId++;
    if(weatherInfoId > MAX_INFO_ID) {
      weatherInfoId = 1;
    }
    displayWeatherInfo(weatherInfoId);
  }    
}
//--- 定时调用计时器函数结束 --- 



//--- b站API相关函数 ---
long getBiliFans(){
  if(fansInfo.update()){  // 更新信息成功   
    return fansInfo.getFansNumber();       
  } else {     // 更新失败
    Serial.println("Update Fail...");  
    return -1;  
  }
}

long getBiliViews(){
  if(videoInfo.update()){  // 更新信息成功       
   return videoInfo.getPlay();        
  } else {     // 更新失败
    Serial.println("Update Fail...");  
    return -1;        
  }    
}
//--- b站API相关函数结束 ---


//--- 心知天气相关函数 ---
void updateWeatherInfo(){

  weatherUpdateCounter = 0;
  if(weatherNow.update()){  // 更新天气信息
    Serial.println("Weather Now Updated: "); 
    Serial.println(weatherNow.getLastUpdate()); // 获取服务器更新天气信息时间 
  } else {    // 更新失败
    Serial.println("Weather Now Update Fail.");   
    Serial.print("Server Response: ");          // 输出服务器响应状态码供用户查找问题
    Serial.println(weatherNow.getServerCode()); // 心知天气服务器错误代码说明可通过以下网址获取
  } 
  
  if(forecast.update()){  // 更新天气信息  
      Serial.println("Weather Forecast Updated: "); 
      Serial.println(forecast.getLastUpdate());                
  } else {    // 更新失败
    Serial.println("Weather Forecast Update Fail.");   
    Serial.print("Server Response: ");          // 输出服务器响应状态码供用户查找问题
    Serial.println(weatherNow.getServerCode()); // 心知天气服务器错误代码说明可通过以下网址获取
  } 
}

// 显示天气的文字信息
void displayWeatherInfo(int infoId)
{
  const uint8_t* chn1;
  const uint8_t* chn2;
  const uint8_t* chn3;
  const uint8_t* chn4;
  int weatherCode;    // 天气或温度代码信息
  bool chineseFlag;   // 中文显示标识
  
  if (infoId == 1){
    chn1 = dang;
    chn2 = qian;
    chn3 = tian;
    chn4 = qi;
    weatherCode = weatherNow.getWeatherCode();
    chineseFlag = true;
    
  } else if (infoId == 2){
    chn1 = dang;
    chn2 = qian;
    chn3 = qi;
    chn4 = wen;
    weatherCode = weatherNow.getDegree();
    chineseFlag = false;
    
  } else if (infoId == 3){
    chn1 = jin;
    chn2 = tian;
    chn3 = zui;
    chn4 = gao;
    weatherCode = forecast.getHigh(0);
    chineseFlag = false;
    
  } else if (infoId == 4){
    chn1 = jin;
    chn2 = tian;
    chn3 = zui;
    chn4 = di;
    weatherCode = forecast.getLow(0);   
    chineseFlag = false;
    
  } else if (infoId == 5){
    chn1 = ming;
    chn2 = tian;
    chn3 = tian;
    chn4 = qi;
    weatherCode = forecast.getDayCode(1);  
    chineseFlag = true;  
    
  } else if (infoId == 6){
    chn1 = ming;
    chn2 = wan;
    chn3 = tian;
    chn4 = qi;
    weatherCode = forecast.getNightCode(1);
    chineseFlag = true;
    
  } else if (infoId == 7){
    chn1 = ming;
    chn2 = tian;
    chn3 = zui;
    chn4 = gao;
    weatherCode = forecast.getHigh(1); 
    chineseFlag = false;
    
  } else if (infoId == 8){
    chn1 = ming;
    chn2 = tian;
    chn3 = zui;
    chn4 = di;
    weatherCode = forecast.getLow(1); 
    chineseFlag = false;

  } else if (infoId == 9){
    chn1 = bi;
    chn2 = li;
    chn3 = fen;
    chn4 = si;
    weatherCode = biliFans; 
    chineseFlag = false;
    
  } else if (infoId == 10){
    chn1 = bo;
    chn2 = fang;
    chn3 = shu;
    chn4 = liang;
    weatherCode = biliViews; 
    chineseFlag = false;
    
  }
  
  showWeatherDetail(weatherCode, chineseFlag);//天气代码,变换标志
  showWeatherChnDesc(chn1, chn2, chn3, chn4);//显示天气文字的函数调用
}

//显示网络获取的具体天气信息
void showWeatherDetail(int weatherCode, bool chineseFlag){
   
  tft.setViewport(160, 222, 160, BANNER_HEIGHT);//底端文字坐标
  tft.fillScreen(TFT_LIGHTGREY);
  // 设置信息显示位置
  tft.setTextDatum(TL_DATUM);
  tft.setTextColor(BANNER_FG, TFT_LIGHTGREY);  //设置文字颜色和背景色
  tft.setTextPadding(10); //设置文字padding,覆盖旧字  
  
  if (chineseFlag == false)
  { // 如果不是中文  
    tft.drawString(" : " + String(weatherCode) + "  ", 0, 0, 4); 
    tft.drawBitmap(35, 0, du, 20, 20, BANNER_FG);
  } 
  else 
  {                   // 如果是中文
    tft.drawString(" : ", 0, 0, 4);  

    if (weatherCode >= 0 && weatherCode <= 3) 
    {
      tft.drawBitmap(15, 0, qing, 20, 20, BANNER_FG);   
    } 
    else if (weatherCode >= 4 && weatherCode <= 8) 
    {
      tft.drawBitmap(15, 0, duo, 20, 20, BANNER_FG);   
      tft.drawBitmap(35, 0, yun, 20, 20, BANNER_FG);  
    } 
    else if (weatherCode == 9) 
    {
      tft.drawBitmap(15, 0, yin, 20, 20, BANNER_FG); 
    } 
    else if (weatherCode >= 10 && weatherCode <= 12) 
    {
      tft.drawBitmap(15, 0, zhen, 20, 20, BANNER_FG);   
      tft.drawBitmap(35, 0, yu, 20, 20, BANNER_FG);        
    } 
    else if (weatherCode == 13) 
    {
      tft.drawBitmap(15, 0, xiao, 20, 20, BANNER_FG);   
      tft.drawBitmap(35, 0, yu, 20, 20, BANNER_FG);        
    } else if (weatherCode == 14) {
      tft.drawBitmap(15, 0, zhong, 20, 20, BANNER_FG);   
      tft.drawBitmap(35, 0, yu, 20, 20, BANNER_FG);        
    } 
    else if (weatherCode >= 15 && weatherCode <= 18)
    {
      tft.drawBitmap(15, 0, da, 20, 20, BANNER_FG);   
      tft.drawBitmap(35, 0, yu, 20, 20, BANNER_FG);        
    } 
    else if (weatherCode == 19 || weatherCode == 20) 
    {
      tft.drawBitmap(15, 0, dong, 20, 20, BANNER_FG);   
      tft.drawBitmap(35, 0, yu, 20, 20, BANNER_FG);        
    } 
    else if (weatherCode == 21) 
    {
      tft.drawBitmap(15, 0, zhen, 20, 20, BANNER_FG);   
      tft.drawBitmap(35, 0, xue, 20, 20, BANNER_FG);        
    } 
    else if (weatherCode == 22)
    {
      tft.drawBitmap(15, 0, xiao, 20, 20, BANNER_FG);   
      tft.drawBitmap(35, 0, xue, 20, 20, BANNER_FG);        
    } 
    else if (weatherCode == 23) 
    {
      tft.drawBitmap(15, 0, zhong, 20, 20, BANNER_FG);   
      tft.drawBitmap(35, 0, xue, 20, 20, BANNER_FG);        
    } 
    else if (weatherCode == 24 || weatherCode == 25 )
    {
      tft.drawBitmap(15, 0, da, 20, 20, BANNER_FG);   
      tft.drawBitmap(35, 0, xue, 20, 20, BANNER_FG);        
    }
    else if (weatherCode >= 26 && weatherCode <= 29 ) 
    {
      tft.drawBitmap(15, 0, sha, 20, 20, BANNER_FG);   
      tft.drawBitmap(35, 0, chen, 20, 20, BANNER_FG);        
    } 
    else if (weatherCode == 30 || weatherCode == 31 ) 
    {
      tft.drawBitmap(15, 0, wu, 20, 20, BANNER_FG);   
      tft.drawBitmap(35, 0, mai, 20, 20, BANNER_FG);        
    }
    else if (weatherCode >= 32 || weatherCode <= 36 )
    {
      tft.drawBitmap(15, 0, da, 20, 20, BANNER_FG);   
      tft.drawBitmap(35, 0, feng, 20, 20, BANNER_FG);        
    } 
    else {
      tft.drawString(" : Unknown", 0, 0, 4);  
    }
  }
  
  tft.resetViewport();
}


  
void showWeatherChnDesc(const uint8_t chnChar1[], const uint8_t chnChar2[], const uint8_t chnChar3[], const uint8_t chnChar4[] ){
 
  // 设置信息显示位置-底端
  tft.setViewport(4, 222, HALF_BANNER_WIDTH, BANNER_HEIGHT);//设置横幅显示位置(int32_t x, int32_t y, int32_t w, int32_t h, bool vpDatum = true)
  tft.fillScreen(TFT_LIGHTGREY);//横幅填充颜色
  tft.setTextColor(BANNER_FG, TFT_LIGHTGREY);  //设置文字颜色和横幅背景色

  //显示中文说明
  tft.drawBitmap(80,0,chnChar1,20,20,BANNER_FG);//( int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor)
  tft.drawBitmap(100,0,chnChar2,20,20,BANNER_FG);
  tft.drawBitmap(120,0,chnChar3,20,20,BANNER_FG);
  tft.drawBitmap(140,0,chnChar4,20,20,BANNER_FG); 

  tft.resetViewport();   
}
//--- b站API相关函数结束 ---

//--- MQTT相关函数开始 ---
// 连接MQTT服务器并订阅信息
void connectMQTTserver(){
  // 根据ESP8266的MAC地址生成客户端ID(避免与其它ESP8266的客户端ID重名)
  String clientId = "esp8266-" + WiFi.macAddress();

  // 连接MQTT服务器
  if (mqttClient.connect(clientId.c_str())) { 
    Serial.println("MQTT Server Connected.");
    Serial.println("Server Address:");
    Serial.println(mqttServer);
    Serial.println("ClientId: ");
    Serial.println(clientId);
    subscribeTopic(); // 订阅指定主题
  } else {
    Serial.print("MQTT Server Connect Failed. Client State:");
    Serial.println(mqttClient.state());
    delay(5000);
  }   
}

// 订阅指定主题
void subscribeTopic(){
  String topicString = controlTopic;
  char subTopic[topicString.length() + 1];  
  strcpy(subTopic, topicString.c_str());
  
  // 建立订阅主题2
  String topicString2 = chatTopic;
  char subTopic2[topicString2.length() + 1];  
  strcpy(subTopic2, topicString2.c_str());
  
  // 通过串口监视器输出是否成功订阅主题1以及订阅的主题1名称
  if(mqttClient.subscribe(subTopic)){
    Serial.println("Subscribe Control Topic");
    Serial.println(subTopic);
    Serial.println("OK");
  } else {
    Serial.print("Subscribe Fail...");
  }  

  // 通过串口监视器输出是否成功订阅主题2以及订阅的主题2名称
  if(mqttClient.subscribe(subTopic2)){
    Serial.println("Subscribe Chat Topic ");
    Serial.println(subTopic2);
    Serial.println("OK");
  } else {
    Serial.print("Subscribe Fail...");
  }    
}

// 收到信息后的回调函数
void receiveCallback(char* topic, byte* payload, unsigned int length) {

  int cmdId;    // 系统控制指令id
  char cmdInfo; // 系统控制信息具体内容
    
  Serial.print("Message Received [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println("");
  Serial.print("Message Length(Bytes) ");
  Serial.println(length);

  if(String(topic) == controlTopic){
    userControlString = "";
    for (int i = 0; i < length; i++) {
      userControlString += (char)payload[i];
    }
    Serial.print("userControlString = ");Serial.println(userControlString); 

    if(payload[0] == 'b' && payload[1] == 'j' ){
      cmdId = 1;            // 修改背景显示间隔
      cmdInfo = payload[2];
      
    } else  if(payload[0] == 's' && payload[1] == 'j' ){
      cmdId = 2;            // 修改时间更新间隔
      cmdInfo = payload[2];
      
    } else  if(payload[0] == 'b' && payload[1] == 'l' ){
      cmdId = 3;            // 修改bili更新间隔
      cmdInfo = payload[2];
      
    } else  if(payload[0] == 't' && payload[1] == 'q' ){
      cmdId = 4;            // 修改bili更新间隔
      cmdInfo = payload[2];
      
    } else  if(payload[0] == 'x' && payload[1] == 's' )
    {
      cmdId = 5;            // 修改信息显示时间间隔
      cmdInfo = payload[2];
      
    } 
    else  if(payload[0] == 'h' && payload[1] == 'b' 
    ){
      cmdId = 6;            // 修改信息显示时间间隔
      cmdInfo = payload[2];
      
    }
    else  if(payload[0] == 'K' && payload[1] == 'D' 
    )
    {
      cmdId = 7;            // 改变led亮
      cmdInfo = payload[2];
      
    }
    else  if(payload[0] == 'G' && payload[1] == 'D' 
    )
    {
      cmdId = 8;            // 改变led关
      cmdInfo = payload[2];
      
    }
    else {
      return;
    }

    changeSettings(cmdId, cmdInfo);
    
  } else if(String(topic) == chatTopic){
    userChatString = "";
    for (int i = 0; i < length; i++) {
      userChatString += (char)payload[i];
    }
    Serial.print("userChatString = ");Serial.println(userChatString); 
  
    showChatMessage(userChatString);  // 屏幕上显示用户聊天消息
    pubReportMsg(userChatString);  // 通过系统报告主题发布用户聊天信息
  } 
}

// 发布信息
void pubReportMsg(String reportMsg){

  String topicString = reportTopic;
  char publishTopic[topicString.length() + 1];  
  strcpy(publishTopic, topicString.c_str());
 
  char publishMsg[reportMsg.length() + 1];   
  strcpy(publishMsg, reportMsg.c_str());
  
  // 实现ESP8266向主题发布信息
  if(mqttClient.publish(publishTopic, publishMsg)){
    Serial.println("Publish Report Topic:");Serial.println(publishTopic);
    Serial.println("Publish Report Message:");Serial.println(publishMsg);    
  } else {
    Serial.println("Report Message Publish Failed."); 
  }
}

//--- MQTT相关函数结束 ---

//--- 显示用户聊天信息相关函数开始 ---
void showChatMessage(String userChatString){
  if (userChatString == NULL){
    userChatFlag = false;  // 告知系统目前没有用户聊天信息
    displayBg(bgId);  
  } else {
    userChatFlag = true;  // 告知系统目前有用户聊天信息
    if(userChatString.length() > 24){
      userChatString = "[MESSAGE TOO LONG!]";
      
    } else {
      displayUserMessage(userChatString);
    }
  }
}


  
void displayUserMessage(String userString){
    tft.setViewport(0, 220, BANNER_WIDTH, BANNER_HEIGHT);
    tft.fillScreen(BANNER_BG);
    // 设置信息显示位置
    tft.setTextDatum(TC_DATUM);
    tft.setTextColor(BANNER_FG, TFT_LIGHTGREY);  //设置文字颜色和背景色
    tft.setTextPadding(10); //设置文字padding,覆盖旧字  
    
    tft.drawString(userString, 160, 0, 4); 
    tft.resetViewport();  
}

//--- 显示用户聊天信息相关函数结束 ---

//--- 设置系统相关函数开始 ---
void changeSettings(int cmdId, char cmdInfo){
  String userSettingMessage;
  Serial.print("cmdId = ");Serial.println(cmdId);
  Serial.print("cmdInfo = ");Serial.println(cmdInfo);

  if(cmdId == 1){       // 收到修改背景变化间隔调整的指令 
    if(cmdInfo == '1'){
      bgChgInterval = 5;
    } else if(cmdInfo == '2'){
      bgChgInterval = 10;
    } else if(cmdInfo == '3'){
      bgChgInterval = 30;
    } else if(cmdInfo == '4'){
      bgChgInterval = 60;
    } else if(cmdInfo == '5'){
      bgChgInterval = 300;
    } else {
      return;
    }
    
    userSettingMessage = "bgChgInterval = " + String(bgChgInterval); 
     
  } else if(cmdId == 2){       // 收到修改更新间隔调整的指令 
    if(cmdInfo == '1'){
      timeCheckInterval = 300;
    } else if(cmdInfo == '2'){
      timeCheckInterval = 600;
    } else if(cmdInfo == '3'){
      timeCheckInterval = 900;
    } else if(cmdInfo == '4'){
      timeCheckInterval = 1200;
    } else if(cmdInfo == '5'){
      timeCheckInterval = 1800;
    } else {
      return;
    }

    userSettingMessage = "timeCheckInterval = " + String(timeCheckInterval);
    
  } else if(cmdId == 3){  // 收到修改哔哩哔哩信息更新时间设置
    if(cmdInfo == '1'){
      biliUpdateInterval = 350;
    } else if(cmdInfo == '2'){
      biliUpdateInterval = 650;
    } else if(cmdInfo == '3'){
      biliUpdateInterval = 950;
    } else if(cmdInfo == '4'){
      biliUpdateInterval = 1250;
    } else if(cmdInfo == '5'){
      biliUpdateInterval = 1850;
    } else {
      return;
    }

    userSettingMessage = "biliUpdateInterval = " + String(biliUpdateInterval);      
    
  } else if(cmdId == 4){  // 收到修改天气信息更新时间设置
    if(cmdInfo == '1'){
      weatherUpdateInterval = 300;
    } else if(cmdInfo == '2'){
      weatherUpdateInterval = 600;
    } else if(cmdInfo == '3'){
      weatherUpdateInterval = 900;
    } else if(cmdInfo == '4'){
      weatherUpdateInterval = 1200;
    } else if(cmdInfo == '5'){
      weatherUpdateInterval = 1800;
    } else {
      return;
    }

    userSettingMessage = "weatherUpdateInterval = " + String(weatherUpdateInterval);      
  } 
  else if(cmdId == 5)
  {  // 收到修改天气信息显示时间设置
    if(cmdInfo == '1'){
      weatherDisplayInterval = 2;
    } else if(cmdInfo == '2'){
      weatherDisplayInterval = 5;
    } else if(cmdInfo == '3'){
      weatherDisplayInterval = 10;
    } else if(cmdInfo == '4'){
      weatherDisplayInterval = 15;
    } else if(cmdInfo == '5'){
      weatherDisplayInterval = 20;
    } else if (cmdId == 6) {
      
    } else {
      return;
    }

    userSettingMessage = "weatherDisplayInterval = " + String(weatherDisplayInterval);      
  } 
  else if(cmdId == 7)
  {
     digitalWrite(D1,HIGH);    
    }
  else if(cmdId == 8)
  {
     digitalWrite(D1,LOW);    
    }  
  else if (cmdId == 6){  // 收到要求系统汇报状态的指令
    String systemReportString;
    systemReportString = "bj:" + String(bgChgInterval) + ", ";
    systemReportString = systemReportString + "sj:" + String(timeCheckInterval) + ", ";
    systemReportString = systemReportString + "bl:" + String(biliUpdateInterval) + ", ";
    systemReportString = systemReportString + "tq:" + String(weatherUpdateInterval) + ", ";    
    systemReportString = systemReportString + "xs:" + String(weatherDisplayInterval); 
    systemReportString = systemReportString + "led:" ; 
    pubReportMsg(systemReportString);
    return;
  } else {
    return;
  }

  displayUserMessage(userSettingMessage);
  pubReportMsg(userSettingMessage);
}

/*
MQTT控制指令说明
bj - 修改背景变换时间间隔
1 - 5秒 / 2 -10秒 / 3 - 30秒 / 4 - 60秒(默认) / 5 - 300秒
sj - 修改系统NTP对时时间间隔
1 - 300秒(默认) / 2 -600秒 / 3 - 900秒 / 4 - 1200秒 / 5 - 1800秒
bl - 修改哔哩哔哩信息更新时间间隔
1 - 350秒(默认) / 2 -650秒 / 3 - 950秒 / 4 - 1250秒 / 5 - 1850秒
tq - 修改天气信息更新时间间隔
1 - 300秒 / 2 -600秒 / 3 - 900秒(默认) / 4 - 1200秒 / 5 - 1800秒
xs - 修改屏幕下方信息显示变换时间间隔
1 - 2秒 / 2 -5秒 / 3 - 10秒 / 4 - 15秒 / 5 - 20秒(默认)
hb - 指示系统汇报运行状态
*/

下载链接

百度网盘链接:https://pan.baidu.com/s/1YyaeFz9Ohmwjabt0inRWkw?pwd=vnnl
提取码:vnnl
💡商业转载请联系作者获得授权,非商业转载请注明出处。
协议(License):署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)。
使用这些免费资源的时候应遵守版权意识,切勿非法利用,售卖,尊重原创内容知识产权。未经允许严禁转载。

评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇