├── BMP ├── 0.bmp ├── 0@1x.png ├── 10.bmp ├── 10@1x.png ├── 11.bmp ├── 11@1x.png ├── 13.bmp ├── 13@1x.png ├── 14.bmp ├── 14@1x.png ├── 15.bmp ├── 15@1x.png ├── 22@1x.png ├── 23@1x.png ├── 24@1x.png ├── 30.bmp ├── 30@1x.png ├── 31.bmp ├── 31@1x.png ├── 4.bmp ├── 4@1x.png ├── 9.bmp ├── 9@1x.png ├── bilibili12832.bmp ├── bilibili2424.bmp ├── likes.bmp ├── list └── viewer.bmp ├── ESP8266_monitor.ino └── README.md /BMP/0.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/0.bmp -------------------------------------------------------------------------------- /BMP/0@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/0@1x.png -------------------------------------------------------------------------------- /BMP/10.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/10.bmp -------------------------------------------------------------------------------- /BMP/10@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/10@1x.png -------------------------------------------------------------------------------- /BMP/11.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/11.bmp -------------------------------------------------------------------------------- /BMP/11@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/11@1x.png -------------------------------------------------------------------------------- /BMP/13.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/13.bmp -------------------------------------------------------------------------------- /BMP/13@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/13@1x.png -------------------------------------------------------------------------------- /BMP/14.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/14.bmp -------------------------------------------------------------------------------- /BMP/14@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/14@1x.png -------------------------------------------------------------------------------- /BMP/15.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/15.bmp -------------------------------------------------------------------------------- /BMP/15@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/15@1x.png -------------------------------------------------------------------------------- /BMP/22@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/22@1x.png -------------------------------------------------------------------------------- /BMP/23@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/23@1x.png -------------------------------------------------------------------------------- /BMP/24@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/24@1x.png -------------------------------------------------------------------------------- /BMP/30.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/30.bmp -------------------------------------------------------------------------------- /BMP/30@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/30@1x.png -------------------------------------------------------------------------------- /BMP/31.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/31.bmp -------------------------------------------------------------------------------- /BMP/31@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/31@1x.png -------------------------------------------------------------------------------- /BMP/4.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/4.bmp -------------------------------------------------------------------------------- /BMP/4@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/4@1x.png -------------------------------------------------------------------------------- /BMP/9.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/9.bmp -------------------------------------------------------------------------------- /BMP/9@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/9@1x.png -------------------------------------------------------------------------------- /BMP/bilibili12832.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/bilibili12832.bmp -------------------------------------------------------------------------------- /BMP/bilibili2424.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/bilibili2424.bmp -------------------------------------------------------------------------------- /BMP/likes.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/likes.bmp -------------------------------------------------------------------------------- /BMP/list: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /BMP/viewer.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nemo-ssc/Esp8266_monitor/b3417b5ece168ab0d267ba67ff29134893f5cb7b/BMP/viewer.bmp -------------------------------------------------------------------------------- /ESP8266_monitor.ino: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 项目:ESP8266_monitor 3 | * 硬件:适用于NodeMCU ESP8266 + ssd1306 128*32 4 | * 功能:连接WiFi后获取指定用户的哔哩哔哩实时粉丝数+WIFI网络授时时钟+知心天气 5 | * 作者:Nemo_ssc bilibili UID:12772522 6 | * 日期:2020/06/20 7 | **********************************************************************/ 8 | //----------------------调用库头文件--------------------- 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include "DHT.h" 20 | #define DHTTYPE DHT11 21 | #define DHTPIN 2 22 | 23 | DHT dht(DHTPIN, DHTTYPE); 24 | 25 | U8G2_SSD1306_128X32_UNIVISION_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE); 26 | 27 | //---------------wifi连接/API用户名密码信息---------------- 28 | const char *ssid = "********"; //WiFi名 29 | const char *password = "********"; //WiFi密码 30 | 31 | String biliuid = "********"; //bilibili UID 32 | 33 | const char* HOST = "http://api.seniverse.com"; 34 | const char* APIKEY = "********"; //API KEY 知心天气私钥 35 | const char* CITY = "********"; //城市全拼 36 | const char* LANGUAGE = "zh-Hans";//zh-Hans 简体中文 37 | //------------------------------------------------------- 38 | 39 | //-----------------------天气参数------------------------- 40 | typedef struct 41 | { 42 | String date_m; 43 | String date_d; 44 | int code_day; 45 | int high; 46 | int low; 47 | int wind_direction_degree; 48 | int wind_scale; 49 | int humidity; 50 | }weather_date; //天气信息的结构体 51 | 52 | weather_date day0,day1,day2; 53 | //------------------------------------------------------- 54 | 55 | //-----------------------定义常量------------------------- 56 | int Click = 0; //轻触开关引脚 57 | int beep = 13; //蜂鸣器引脚 58 | const unsigned long HTTP_TIMEOUT = 5000; //http访问请求 59 | WiFiClient client; 60 | HTTPClient http; 61 | 62 | String response_bff; //json返回粉丝数 63 | String response_bfv; //json返回观看数、点赞数 64 | int follower = 0; //粉丝数 65 | long viewer = 0; //浏览量 66 | long likes = 0; //点赞数 67 | const int slaveSelect = 5; 68 | const int scanLimit = 7; 69 | 70 | static const char ntpServerName[] = "ntp1.aliyun.com"; //NTP服务器,阿里云 71 | const int timeZone = 8; //时区,北京时间为+8 72 | WiFiUDP Udp; 73 | unsigned int localPort = 8888; // 用于侦听UDP数据包的本地端口 74 | time_t getNtpTime(); 75 | boolean isNTPConnected = false; 76 | 77 | String response_ws; //json返回天气信息 78 | String GetUrl; //心知天气url请求 79 | //------------------------------------------------------------------ 80 | 81 | //---------------------------位图信息-------------------------------- 82 | //24*24小电视 83 | const unsigned char bilibilitv_24u[] U8X8_PROGMEM = { 84 | 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x30, 0x00, 0x01, 0xe0, 0x80, 0x01, 85 | 0x80, 0xc3, 0x00, 0x00, 0xef, 0x00, 0xff, 0xff, 0xff, 0x03, 0x00, 0xc0, 0xf9, 0xff, 0xdf, 0x09, 0x00, 0xd0, 0x09, 0x00, 0xd0, 0x89, 0xc1, 86 | 0xd1, 0xe9, 0x81, 0xd3, 0x69, 0x00, 0xd6, 0x09, 0x91, 0xd0, 0x09, 0xdb, 0xd0, 0x09, 0x7e, 0xd0, 0x0d, 0x00, 0xd0, 0x4d, 0x89, 0xdb, 0xfb, 87 | 0xff, 0xdf, 0x03, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x78, 0x00, 0x1e, 0x30, 0x00, 0x0c}; 88 | //128*32小电视bilibili 89 | const unsigned char bilibilitv_12832[] U8X8_PROGMEM ={ 90 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 91 | 0x00,0x00,0x1C,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 92 | 0x00,0x00,0x1C,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 93 | 0x00,0x00,0x7C,0xC0,0x0F,0x00,0x1E,0x00,0x00,0x00,0xE0,0x03,0x00,0x00,0x00,0x00, 94 | 0x00,0x00,0xF0,0xE0,0x03,0x80,0x1F,0x00,0x00,0x00,0xF8,0x03,0x00,0x00,0x00,0x00, 95 | 0x00,0xF8,0xFF,0xFF,0xFF,0x83,0x1F,0x00,0x00,0x00,0xF8,0x03,0x00,0x00,0x00,0x00, 96 | 0x00,0xFC,0xFF,0xFF,0xFF,0x8F,0x1F,0x00,0x80,0x07,0xF8,0x03,0x00,0x78,0x00,0x00, 97 | 0x00,0xFE,0xFF,0xFF,0xFF,0x9F,0x1F,0x00,0x80,0x0F,0xF8,0x03,0x00,0xF8,0x00,0x00, 98 | 0x00,0xFE,0xFF,0xFF,0xFF,0x9F,0x1F,0x00,0x80,0x0F,0xF8,0x03,0x00,0xF8,0x00,0x00, 99 | 0x00,0x3F,0x00,0x00,0x80,0x9F,0x1F,0x00,0x80,0x0F,0xF0,0x03,0x00,0xF0,0x00,0x00, 100 | 0x00,0x1F,0x00,0x00,0x00,0xBE,0x1F,0x00,0x80,0x0F,0xF0,0x03,0x00,0xF0,0x00,0x00, 101 | 0x00,0x1F,0x00,0x00,0x00,0xBE,0x1F,0x00,0x00,0x0F,0xF0,0x03,0x00,0xF0,0x00,0x00, 102 | 0x00,0x1F,0x00,0x00,0x00,0xBE,0x1F,0x00,0x7C,0xEF,0xF3,0x03,0xC0,0xF7,0x7E,0x00, 103 | 0x00,0x1F,0x7F,0xC0,0x1F,0x3E,0x1F,0x00,0x7C,0xEF,0xF3,0x03,0xC0,0xF7,0x7E,0x00, 104 | 0x00,0xDF,0xFF,0xC0,0x3F,0x3E,0x1F,0x00,0x7C,0xEF,0xE3,0x03,0xC0,0xF7,0x78,0x00, 105 | 0x00,0x1F,0x1F,0x00,0x3E,0x3E,0x1F,0x00,0x18,0xEF,0xE3,0x03,0x80,0xE0,0x78,0x00, 106 | 0x00,0x1F,0x00,0x00,0x00,0x3E,0x1F,0x00,0x78,0x1F,0xE0,0x03,0x80,0xEF,0x00,0x00, 107 | 0x00,0x1F,0x00,0x00,0x00,0x3E,0x1E,0x00,0x78,0xFE,0xE3,0x03,0x80,0xEF,0x79,0x00, 108 | 0x00,0x1F,0xC0,0x4C,0x00,0x3E,0x3E,0x00,0xF8,0xFE,0xE3,0x03,0x80,0xEF,0x79,0x00, 109 | 0x00,0x1F,0xC0,0xFF,0x00,0x3E,0xFE,0x1F,0xF0,0xDE,0xE3,0xFF,0x87,0xEF,0xF9,0x00, 110 | 0x00,0x1F,0xC0,0xFF,0x00,0x3E,0xFE,0xFF,0xF0,0xDE,0xE3,0xFF,0x9F,0xEF,0xF9,0x00, 111 | 0x00,0x1F,0x80,0x3B,0x00,0x3E,0xFE,0xFF,0xF7,0xDE,0xE3,0xFF,0x7F,0xEF,0xF9,0x00, 112 | 0x00,0x1F,0x00,0x00,0x00,0x3E,0xFE,0xFF,0xFF,0xDE,0xE3,0xFF,0xFF,0xCF,0xF9,0x00, 113 | 0x00,0x3F,0x00,0x00,0x80,0x1F,0xFC,0xF8,0xEF,0xDF,0xC3,0x3F,0xFF,0xDF,0xF9,0x00, 114 | 0x00,0xFE,0xFF,0xFF,0xFF,0x1F,0xFC,0xFD,0xEF,0xDD,0xC3,0xBF,0xFF,0xDE,0xF1,0x00, 115 | 0x00,0xFE,0xFF,0xFF,0xFF,0x1F,0xFC,0xFF,0xEF,0xDD,0xC3,0xFF,0xFF,0xDE,0xF1,0x00, 116 | 0x00,0xFC,0xFF,0xFF,0xFF,0x0F,0xFC,0xFF,0xE3,0xDD,0xC3,0xFF,0x3F,0xDE,0xF1,0x00, 117 | 0x00,0xFC,0xFF,0xFF,0xFF,0x0F,0xFC,0xFF,0xE3,0xDD,0xC3,0xFF,0x3F,0xDE,0xF1,0x00, 118 | 0x00,0x00,0x0F,0x00,0x3E,0x00,0xFC,0x1F,0x00,0x00,0xC0,0xFF,0x01,0x00,0x00,0x00, 119 | 0x00,0x00,0x0F,0x00,0x3E,0x00,0xFC,0x1F,0x00,0x00,0xC0,0xFF,0x01,0x00,0x00,0x00, 120 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 121 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 122 | 123 | //下面是天气图标和对应心知天气的天气代码 124 | //Sunny = 0 晴 125 | const unsigned char Sunny[] U8X8_PROGMEM ={ 126 | 0x00,0xC0,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0xC0,0x00,0x00, 127 | 0x30,0xC0,0x00,0x03,0x70,0x00,0x80,0x03,0xE0,0x00,0xC0,0x01,0xC0,0xE0,0xC1,0x00, 128 | 0x00,0xF8,0x07,0x00,0x00,0xFE,0x1F,0x00,0x00,0xFE,0x1F,0x00,0x00,0xFF,0x3F,0x00, 129 | 0x00,0xFF,0x3F,0x00,0x80,0xFF,0x7F,0x00,0x8F,0xFF,0x7F,0x3C,0x8F,0xFF,0x7F,0x3C, 130 | 0x80,0xFF,0x7F,0x00,0x80,0xFF,0x7F,0x00,0x00,0xFF,0x3F,0x00,0x00,0xFE,0x1F,0x00, 131 | 0x00,0xFE,0x1F,0x00,0x00,0xFC,0x0F,0x00,0xC0,0xF0,0xC3,0x00,0xE0,0x00,0xC0,0x01, 132 | 0x70,0x00,0x80,0x03,0x30,0x00,0x00,0x03,0x00,0xC0,0x00,0x00,0x00,0xC0,0x00,0x00, 133 | 0x00,0xC0,0x00,0x00,0x00,0xC0,0x00,0x00 134 | }; 135 | //Cloudy = 4 多云 136 | const unsigned char Cloudy[] U8X8_PROGMEM ={ 137 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00, 138 | 0x00,0x80,0x3F,0x00,0x00,0xE6,0xFF,0x00,0x00,0xFF,0xFF,0x00,0x80,0xFF,0xFF,0x00, 139 | 0x80,0xFF,0xFF,0x01,0xC0,0xFF,0xFF,0x01,0xC0,0xFF,0xFF,0x03,0xE0,0xFF,0xFF,0x07, 140 | 0xF0,0xFF,0xFF,0x0F,0xF8,0xFF,0x07,0x0F,0xF8,0xFF,0x71,0x0F,0xF8,0xFF,0xFE,0x0E, 141 | 0xF8,0x7F,0xFE,0x08,0xF0,0x7F,0xFF,0x07,0xE0,0x1F,0xFF,0x0F,0xC0,0xEF,0xFF,0x1F, 142 | 0x80,0xE7,0xFF,0x1F,0x00,0xF0,0xFF,0x3F,0x1C,0xF0,0xFF,0x3F,0x3C,0xF0,0xFF,0x1F, 143 | 0x7E,0xF0,0xFF,0x1F,0x7F,0xE0,0xFF,0x0F,0x3E,0xC0,0xFF,0x07,0x00,0x00,0x00,0x00, 144 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 145 | }; 146 | //Overcast = 9 阴 147 | const unsigned char Overcast[] U8X8_PROGMEM ={ 148 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 149 | 0x00,0x00,0x00,0x00,0x00,0x80,0x1F,0x00,0x00,0xE0,0x7F,0x00,0x00,0xF3,0xFF,0x00, 150 | 0xC0,0xFF,0xFF,0x01,0xE0,0xFF,0xFF,0x01,0xF0,0xFF,0xFF,0x01,0xF0,0xFF,0xFF,0x03, 151 | 0xF0,0xFF,0xFF,0x03,0xF8,0xFF,0xFF,0x07,0xFC,0xFF,0xFF,0x0F,0xFE,0xFF,0xFF,0x1F, 152 | 0xFF,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF,0xFF,0x3F, 153 | 0xFF,0xFF,0xFF,0x1F,0xFE,0xFF,0xFF,0x1F,0xFE,0xFF,0xFF,0x0F,0xF8,0xFF,0xFF,0x07, 154 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 155 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 156 | }; 157 | //Shower = 10 阵雨 158 | const unsigned char Shower[] U8X8_PROGMEM ={ 159 | 0x00,0x00,0x70,0x00,0x00,0x00,0xFC,0x03,0x00,0x00,0xFE,0x07,0x00,0x00,0xF8,0x0F, 160 | 0x00,0xC0,0xE3,0x1F,0x00,0xF0,0xCF,0x1F,0xC0,0xF9,0x9F,0x3F,0xE0,0xFF,0xBF,0x3F, 161 | 0xF0,0xFF,0x3F,0x3F,0xF0,0xFF,0x7F,0x1F,0xF0,0xFF,0x7F,0x1E,0xF8,0xFF,0xFF,0x1C, 162 | 0xFC,0xFF,0xFF,0x09,0xFE,0xFF,0xFF,0x03,0xFE,0xFF,0xFF,0x03,0xFF,0xFF,0xFF,0x07, 163 | 0xFF,0xFF,0xFF,0x07,0xFF,0xFF,0xFF,0x07,0xFF,0xFF,0xFF,0x03,0xFE,0xFF,0xFF,0x03, 164 | 0xFC,0xFF,0xFF,0x01,0xF0,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x20,0x00, 165 | 0x60,0x60,0x30,0x00,0x60,0x60,0x30,0x00,0x30,0x30,0x18,0x00,0x30,0x30,0x18,0x00, 166 | 0x18,0x18,0x0C,0x00,0x08,0x08,0x04,0x00 167 | }; 168 | //Thundershower = 11 雷阵雨 169 | const unsigned char Thundershower[] U8X8_PROGMEM ={ 170 | 0x00,0x00,0x0E,0x00,0x00,0xC0,0x3F,0x00,0x00,0xE0,0xFF,0x00,0xC0,0xFF,0xFF,0x01, 171 | 0xE0,0xFF,0xFF,0x01,0xF0,0xFF,0xFF,0x01,0xF0,0xFF,0xFF,0x03,0xF0,0xFF,0xFF,0x03, 172 | 0xF0,0xFF,0xFF,0x03,0xF8,0xFF,0xFF,0x07,0xFC,0xFF,0xFF,0x0F,0xFE,0xFF,0xFF,0x1F, 173 | 0xFF,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0x1F, 174 | 0xFE,0xFF,0xFF,0x1F,0xFE,0xFF,0xFF,0x0F,0xFC,0xFF,0xFF,0x07,0xF0,0xFF,0xFF,0x01, 175 | 0x00,0xF0,0x01,0x00,0x60,0xF0,0xC1,0x00,0x60,0xF0,0xC0,0x00,0x60,0x78,0xC0,0x00, 176 | 0x30,0xFC,0x60,0x00,0x30,0x70,0x60,0x00,0x10,0x30,0x20,0x00,0x10,0x18,0x20,0x00, 177 | 0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00 178 | }; 179 | //Rain_L = 13 小雨 180 | const unsigned char Rain_L[] U8X8_PROGMEM ={ 181 | 0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0xC0,0x3F,0x00,0x00,0xE0,0xFF,0x00, 182 | 0xC0,0xFF,0xFF,0x01,0xE0,0xFF,0xFF,0x01,0xF0,0xFF,0xFF,0x01,0xF0,0xFF,0xFF,0x03, 183 | 0xF0,0xFF,0xFF,0x03,0xF0,0xFF,0xFF,0x03,0xF8,0xFF,0xFF,0x0F,0xFC,0xFF,0xFF,0x0F, 184 | 0xFE,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0x1F, 185 | 0xFF,0xFF,0xFF,0x1F,0xFE,0xFF,0xFF,0x1F,0xFE,0xFF,0xFF,0x0F,0xFC,0xFF,0xFF,0x07, 186 | 0xE0,0xFF,0xFF,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 187 | 0x00,0x60,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x10,0x00,0x00, 188 | 0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00 189 | }; 190 | //Rain_M = 14 中雨 191 | const unsigned char Rain_M[] U8X8_PROGMEM ={ 192 | 0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0xC0,0x3F,0x00,0x00,0xE0,0xFF,0x00, 193 | 0xC0,0xFF,0xFF,0x01,0xE0,0xFF,0xFF,0x01,0xF0,0xFF,0xFF,0x01,0xF0,0xFF,0xFF,0x03, 194 | 0xF0,0xFF,0xFF,0x03,0xF0,0xFF,0xFF,0x03,0xF8,0xFF,0xFF,0x0F,0xFC,0xFF,0xFF,0x0F, 195 | 0xFE,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0x1F, 196 | 0xFF,0xFF,0xFF,0x1F,0xFE,0xFF,0xFF,0x1F,0xFE,0xFF,0xFF,0x0F,0xFC,0xFF,0xFF,0x07, 197 | 0xE0,0xFF,0xFF,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 198 | 0x00,0x0C,0x0C,0x00,0x00,0x04,0x04,0x00,0x00,0x06,0x06,0x00,0x00,0x02,0x02,0x00, 199 | 0x00,0x03,0x03,0x00,0x00,0x00,0x00,0x00 200 | }; 201 | //Rain_H = 15 大雨 202 | const unsigned char Rain_H[] U8X8_PROGMEM ={ 203 | 0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0xC0,0x3F,0x00,0x00,0xE0,0xFF,0x00, 204 | 0xC0,0xFF,0xFF,0x01,0xE0,0xFF,0xFF,0x01,0xF0,0xFF,0xFF,0x01,0xF0,0xFF,0xFF,0x03, 205 | 0xF0,0xFF,0xFF,0x03,0xF0,0xFF,0xFF,0x03,0xF8,0xFF,0xFF,0x0F,0xFC,0xFF,0xFF,0x0F, 206 | 0xFE,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0x1F, 207 | 0xFF,0xFF,0xFF,0x1F,0xFE,0xFF,0xFF,0x1F,0xFE,0xFF,0xFF,0x0F,0xFC,0xFF,0xFF,0x07, 208 | 0xE0,0xFF,0xFF,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 209 | 0x60,0x60,0x60,0x00,0x20,0x20,0x20,0x00,0x30,0x30,0x30,0x00,0x10,0x10,0x10,0x00, 210 | 0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00 211 | }; 212 | //Foggy = 30 雾 213 | const unsigned char Foggy[] U8X8_PROGMEM ={ 214 | 0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x00,0xC0,0xFF,0x00,0x00,0xF0,0xFF,0x01,0x00, 215 | 0xF8,0xFF,0x03,0x00,0xFC,0xFF,0x07,0x00,0xFC,0xFF,0x0F,0x00,0xFE,0xFF,0xFF,0x01, 216 | 0xFE,0xFF,0xFF,0x07,0xFE,0xFF,0xFF,0x0F,0xFE,0xFF,0xFF,0x0F,0xFE,0xFF,0xFF,0x1F, 217 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFF,0xFF,0x1F, 218 | 0xFE,0xFF,0xFF,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 219 | 0x00,0x00,0x00,0x00,0xFE,0xFF,0xFF,0x1F,0xFE,0xFF,0xFF,0x1F,0x00,0x00,0x00,0x00, 220 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFF,0xFF,0x1F, 221 | 0xFE,0xFF,0xFF,0x1F,0x00,0x00,0x00,0x00 222 | }; 223 | //Haze = 31 霾 224 | const unsigned char Haze[] U8X8_PROGMEM ={ 225 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0xE0,0x00,0x1C,0x0E,0xE0,0x00,0x1C, 226 | 0x0E,0xE0,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 227 | 0x00,0x00,0x00,0x00,0xF0,0x03,0xF0,0x01,0xF8,0x0F,0xFC,0x07,0x1C,0x1E,0x0E,0x0E, 228 | 0x0E,0x38,0x07,0x1C,0x06,0x30,0x03,0x18,0x07,0xF0,0x03,0x38,0x03,0xE0,0x01,0x30, 229 | 0x03,0xE0,0x01,0x30,0x07,0x30,0x03,0x38,0x06,0x38,0x07,0x18,0x0E,0x1C,0x0E,0x1C, 230 | 0x1C,0x0F,0x1C,0x0F,0xF8,0x07,0xF8,0x03,0xF0,0x03,0xF0,0x01,0x00,0x00,0x00,0x00, 231 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0xE0,0x00,0x1C,0x0E,0xE0,0x00,0x1C, 232 | 0x0E,0xE0,0x00,0x1C,0x00,0x00,0x00,0x00 233 | }; 234 | 235 | //浏览和点赞的图标 236 | //viewer 237 | const unsigned char viewer_bmp[] U8X8_PROGMEM ={ 238 | 0x00,0x00,0x00,0x00,0x80,0x00,0x8C,0x18,0x98,0x0C,0xF0,0x07,0x38,0x0E,0x0C,0x18, 239 | 0xC6,0x31,0x63,0x63,0x23,0x62,0x60,0x03,0xC0,0x01,0x00,0x00,0x00,0x00 240 | }; 241 | //likes 242 | const unsigned char likes_bmp[] U8X8_PROGMEM ={ 243 | 0x00,0x00,0x00,0x00,0xC0,0x00,0xC0,0x00,0xE0,0x00,0xE0,0x00,0xF0,0x7F,0xF7,0x7F, 244 | 0xF7,0x7F,0xF7,0x7F,0xF7,0x3F,0xF7,0x3F,0xF7,0x1F,0xF7,0x1F,0x00,0x00 245 | }; 246 | //------------------------------------------------------------------ 247 | //-------------------------中断执行函数------------------------------- 248 | //------------------------------------------------------------------ 249 | ICACHE_RAM_ATTR void onChange() 250 | { 251 | delay(100); //延时消抖 252 | if(digitalRead(15) == HIGH) 253 | { 254 | Click ++; 255 | Serial.println("Key Down"); 256 | } 257 | 258 | } 259 | //------------------------------------------------------------------ 260 | //---------------------------setup函数------------------------------- 261 | //------------------------------------------------------------------ 262 | void setup() 263 | { 264 | attachInterrupt(15, onChange, RISING); //中断控制 引脚为内部GPIO口号 265 | pinMode(beep, OUTPUT); 266 | u8g2.begin(); //启用u8g2库 267 | u8g2.clearBuffer(); 268 | u8g2.drawXBMP( 0 , 0 , 128 , 32 , bilibilitv_12832 ); //开机画面 269 | u8g2.sendBuffer(); 270 | Serial.begin(115200); //串口通讯波特率 271 | while (!Serial) 272 | continue; 273 | Serial.println("bilibili fans monitor, version v1.2"); 274 | Serial.print("Connecting WiFi..."); 275 | WiFi.mode(WIFI_STA); 276 | WiFi.begin(ssid, password); //连接WIFI 277 | while (WiFi.status() != WL_CONNECTED){ 278 | delay(500); 279 | Serial.print("."); 280 | } 281 | Serial.println(""); 282 | Serial.println("WiFi connected"); 283 | Serial.println("IP address: "); 284 | Serial.println(WiFi.localIP()); 285 | 286 | Serial.println("Starting UDP"); 287 | Udp.begin(localPort); 288 | Serial.print("Local port: "); 289 | Serial.println(Udp.localPort()); 290 | Serial.println("waiting for sync"); 291 | setSyncProvider(getNtpTime); 292 | setSyncInterval(300); //每300秒同步一次时间 293 | isNTPConnected = true; 294 | 295 | dht.begin(); 296 | } 297 | //------------------------------------------------------------------ 298 | //--------------------bilibili_fans_follower------------------------ 299 | //------------------------------------------------------------------ 300 | bool getJson() //同时获得粉丝数和浏览量的json数据 301 | { 302 | bool r = false; 303 | http.setTimeout(HTTP_TIMEOUT); 304 | http.begin("http://api.bilibili.com/x/relation/stat?vmid=" + biliuid); 305 | int httpCode = http.GET(); 306 | if (httpCode > 0){ 307 | if (httpCode == HTTP_CODE_OK){ 308 | response_bff = http.getString(); 309 | Serial.println(response_bff); 310 | r = true; 311 | } 312 | }else{ 313 | Serial.printf("[HTTP] GET JSON failed, error: %s\n", http.errorToString(httpCode).c_str()); 314 | //errorCode(0x2); 315 | r = false;; 316 | } 317 | http.end(); 318 | //return t; 319 | 320 | //view 321 | http.begin("http://api.bilibili.com/x/space/upstat?mid=" + biliuid); 322 | int httpCode_v = http.GET(); 323 | if (httpCode_v > 0){ 324 | if (httpCode_v == HTTP_CODE_OK){ 325 | response_bfv = http.getString(); 326 | //Serial.println(response_bfv); 327 | r = true; 328 | } 329 | }else{ 330 | Serial.printf("[HTTP] GET JSON failed, error: %s\n", http.errorToString(httpCode_v).c_str()); 331 | r = false; 332 | } 333 | http.end(); 334 | 335 | return r; 336 | } 337 | 338 | bool parseJson_bff(String json) //对粉丝数的json解析 339 | { 340 | const size_t capacity = JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(5) + 70;//分配内存大小 341 | DynamicJsonDocument doc(capacity); //解析Json 342 | deserializeJson(doc, json); 343 | 344 | int code = doc["code"]; //返回json 345 | const char *message = doc["message"]; 346 | 347 | if (code != 0){ //根据code判断返回数据状态,并输出错误信息代码 348 | Serial.print("[API]Code:"); 349 | Serial.print(code); 350 | Serial.print(" Message:"); 351 | Serial.println(message); 352 | //errorCode(0x3); 353 | return false; 354 | } 355 | 356 | JsonObject data = doc["data"]; //Json对象 357 | unsigned long data_mid = data["mid"]; 358 | int data_follower = data["follower"]; 359 | if (data_mid == 0){ 360 | Serial.println("[JSON] FORMAT ERROR"); 361 | //errorCode(0x4); 362 | return false; 363 | } 364 | Serial.print("UID: "); 365 | Serial.print(data_mid); 366 | Serial.print(" follower: "); 367 | Serial.println(data_follower); 368 | 369 | follower = data_follower; 370 | return true; 371 | } 372 | 373 | void displayNumber_f(int number) //oled输出粉丝数 374 | { 375 | u8g2.setFont(u8g2_font_freedoomr25_tn); // choose a suitable font 376 | u8g2.setCursor(40, 30); 377 | u8g2.print(number); 378 | u8g2.sendBuffer(); // transfer internal memory to the display 379 | } 380 | 381 | void displayBmp_f() //输出图片 382 | { 383 | u8g2.clearBuffer(); 384 | u8g2.drawXBMP( 4 , 4 , 24 , 24 , bilibilitv_24u ); 385 | } 386 | 387 | void bilibili_fans_follower() //获取json数据并解析成功 388 | { 389 | if (getJson()){ 390 | if (parseJson_bff(response_bff)){ 391 | displayBmp_f(); 392 | displayNumber_f(follower); 393 | delay(10); 394 | } 395 | } 396 | else{ 397 | u8g2.clearBuffer(); 398 | u8g2.setFont(u8g2_font_luBIS08_tr); 399 | u8g2.drawStr(20,20,"Get Data ."); 400 | u8g2.sendBuffer(); 401 | u8g2.clearBuffer(); 402 | u8g2.setFont(u8g2_font_luBIS08_tr); 403 | u8g2.drawStr(20,20,"Get Data .."); 404 | u8g2.sendBuffer(); 405 | u8g2.clearBuffer(); 406 | u8g2.setFont(u8g2_font_luBIS08_tr); 407 | u8g2.drawStr(20,20,"Get Data ..."); 408 | u8g2.sendBuffer(); 409 | } 410 | } 411 | 412 | //------------------------------------------------------------------ 413 | //--------------------bilibili_fans_viewer-------------------------- 414 | //------------------------------------------------------------------ 415 | 416 | bool parseJson_bfv(String json) //对浏览量的json解析 417 | { 418 | const size_t capacity = 2*JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(4) + 70; 419 | DynamicJsonDocument doc(capacity); 420 | deserializeJson(doc, json); 421 | 422 | int code = doc["code"]; // 0 423 | const char* message = doc["message"]; // "0" 424 | int ttl = doc["ttl"]; // 1 425 | 426 | JsonObject data = doc["data"]; 427 | 428 | long data_archive_view = data["archive"]["view"]; // 2974603 429 | int data_article_view = data["article"]["view"]; // 1218 430 | long data_likes = data["likes"]; 431 | viewer = data_archive_view + data_article_view; 432 | likes = data_likes; 433 | } 434 | 435 | void displayBmp_v() //输出图片 436 | { 437 | u8g2.clearBuffer(); 438 | u8g2.drawXBMP( 4 , 4 , 24 , 24 , bilibilitv_24u ); 439 | u8g2.drawXBMP( 100 , 1 , 15 , 15 , viewer_bmp ); 440 | u8g2.drawXBMP( 100 , 17 , 15 , 15 , likes_bmp ); 441 | } 442 | 443 | void displayNumber_v(int vw,int lk) //oled输出浏览量和点赞数 444 | { 445 | u8g2.setFont(u8g2_font_freedoomr10_tu); // choose a suitable font 446 | u8g2.setCursor(40, 15); 447 | u8g2.print(vw); 448 | u8g2.setCursor(40, 31); 449 | u8g2.print(lk); 450 | u8g2.sendBuffer(); 451 | } 452 | 453 | void bilibili_fans_viewer() //获取json数据并解析成功 454 | { 455 | if (getJson()){ 456 | if (parseJson_bfv(response_bfv)){ 457 | displayBmp_v(); 458 | displayNumber_v(viewer,likes); 459 | delay(10); 460 | } 461 | } 462 | } 463 | 464 | 465 | //------------------------------------------------------------------ 466 | //-----------------------NTP_clock---------------------------------- 467 | //------------------------------------------------------------------ 468 | const int NTP_PACKET_SIZE = 48; // NTP时间在消息的前48个字节里 469 | byte packetBuffer[NTP_PACKET_SIZE]; // 输入输出包的缓冲区 470 | 471 | time_t getNtpTime() 472 | { 473 | IPAddress ntpServerIP; // NTP服务器的地址 474 | 475 | while (Udp.parsePacket() > 0); // 丢弃以前接收的任何数据包 476 | Serial.println("Transmit NTP Request"); 477 | // 从池中获取随机服务器 478 | WiFi.hostByName(ntpServerName, ntpServerIP); 479 | Serial.print(ntpServerName); 480 | Serial.print(": "); 481 | Serial.println(ntpServerIP); 482 | sendNTPpacket(ntpServerIP); 483 | uint32_t beginWait = millis(); 484 | while (millis() - beginWait < 1500) 485 | { 486 | int size = Udp.parsePacket(); 487 | if (size >= NTP_PACKET_SIZE) 488 | { 489 | Serial.println("Receive NTP Response"); 490 | isNTPConnected = true; 491 | Udp.read(packetBuffer, NTP_PACKET_SIZE); // 将数据包读取到缓冲区 492 | unsigned long secsSince1900; 493 | // 将从位置40开始的四个字节转换为长整型,只取前32位整数部分 494 | secsSince1900 = (unsigned long)packetBuffer[40] << 24; 495 | secsSince1900 |= (unsigned long)packetBuffer[41] << 16; 496 | secsSince1900 |= (unsigned long)packetBuffer[42] << 8; 497 | secsSince1900 |= (unsigned long)packetBuffer[43]; 498 | Serial.println(secsSince1900); 499 | Serial.println(secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR); 500 | return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR; 501 | } 502 | } 503 | Serial.println("No NTP Response :-("); //无NTP响应 504 | isNTPConnected = false; 505 | return 0; //如果未得到时间则返回0 506 | } 507 | 508 | 509 | // 向给定地址的时间服务器发送NTP请求 510 | void sendNTPpacket(IPAddress& address) 511 | { 512 | memset(packetBuffer, 0, NTP_PACKET_SIZE); 513 | packetBuffer[0] = 0b11100011; // LI, Version, Mode 514 | packetBuffer[1] = 0; // Stratum, or type of clock 515 | packetBuffer[2] = 6; // Polling Interval 516 | packetBuffer[3] = 0xEC; // Peer Clock Precision 517 | // 8 bytes of zero for Root Delay & Root Dispersion 518 | packetBuffer[12] = 49; 519 | packetBuffer[13] = 0x4E; 520 | packetBuffer[14] = 49; 521 | packetBuffer[15] = 52; 522 | Udp.beginPacket(address, 123); //NTP需要使用的UDP端口号为123 523 | Udp.write(packetBuffer, NTP_PACKET_SIZE); 524 | Udp.endPacket(); 525 | } 526 | void NTP_CLOCK() //oled输出时分秒,没有十位的补0 527 | { 528 | int hours, minutes, seconds; 529 | hours = hour(); 530 | minutes = minute(); 531 | seconds = second(); 532 | Serial.printf("%d:%d:%d\n", hours, minutes, seconds); 533 | String currentTime_hm = ""; 534 | String currentTime_s = ""; 535 | if (hours < 10) 536 | currentTime_hm += 0; 537 | currentTime_hm += hours; 538 | currentTime_hm += ":"; 539 | if (minutes < 10) 540 | currentTime_hm += 0; 541 | currentTime_hm += minutes; 542 | //currentTime += ":"; 543 | if (seconds < 10) 544 | currentTime_s += 0; 545 | currentTime_s += seconds; 546 | u8g2.clearBuffer(); 547 | u8g2.setFont(u8g2_font_freedoomr25_tn); // choose a suitable font 548 | u8g2.setCursor(0, 30); 549 | u8g2.print(currentTime_hm); // write something to the internal memory 550 | u8g2.setFont(u8g2_font_freedoomr10_tu); // choose a suitable font 551 | u8g2.setCursor(90, 30); 552 | u8g2.print(currentTime_s); // write something to the internal memory 553 | u8g2.setFont(u8g2_font_freedoomr10_tu); // choose a suitable font 554 | u8g2.setCursor(90, 15); 555 | u8g2.print("UTC+8"); 556 | u8g2.sendBuffer(); 557 | } 558 | void NTP_DAY() //oled输出年月日+星期 559 | { 560 | int years, months, days, weekdays; 561 | years = year(); 562 | months = month(); 563 | days = day(); 564 | weekdays = weekday(); 565 | Serial.printf("%d/%d/%d Weekday:%d\n", years, months, days, weekdays); 566 | String currentDay = ""; 567 | if (months < 10) 568 | currentDay += 0; 569 | currentDay += months; 570 | currentDay += "/"; 571 | if (days < 10) 572 | currentDay += 0; 573 | currentDay += days; 574 | u8g2.clearBuffer(); 575 | u8g2.setFont(u8g2_font_ncenB12_tr); 576 | u8g2.setCursor(0, 15); 577 | u8g2.print(years); 578 | u8g2.setCursor(0, 31); 579 | u8g2.print(currentDay); 580 | u8g2.setFont(u8g2_font_logisoso24_tr); 581 | u8g2.setCursor(60, 31); 582 | if (weekdays == 1) 583 | u8g2.print("SUN"); 584 | else if (weekdays == 2) 585 | u8g2.print("MON"); 586 | else if (weekdays == 3) 587 | u8g2.print("TUS"); 588 | else if (weekdays == 4) 589 | u8g2.print("WED"); 590 | else if (weekdays == 5) 591 | u8g2.print("THU"); 592 | else if (weekdays == 6) 593 | u8g2.print("FRI"); 594 | else if (weekdays == 7) 595 | u8g2.print("SAT"); 596 | u8g2.sendBuffer(); 597 | } 598 | 599 | //------------------------------------------------------------------ 600 | //------------------------weather_station--------------------------- 601 | //----------------------------api test------------------------------ 602 | //https://api.seniverse.com/v3/weather/now.json?key=SuQDmnIsehmcwH7cx&location=beijing&language=zh-Hans&unit=c 603 | //https://api.seniverse.com/v3/weather/daily.json?key=SuQDmnIsehmcwH7cx&location=beijing&language=zh-Hans&unit=c&start=0&days=5 604 | bool getJson_ws() //构建并发出获取天气数据的请求,获得json数据 605 | { 606 | bool s = false; 607 | GetUrl = String(HOST) + "/v3/weather/daily.json?key="; 608 | GetUrl += APIKEY; 609 | GetUrl += "&location="; 610 | GetUrl += CITY; 611 | GetUrl += "&language="; 612 | GetUrl += LANGUAGE; 613 | GetUrl += "&unit=c&start=0&days=3"; 614 | http.setTimeout(HTTP_TIMEOUT); 615 | http.begin(GetUrl); 616 | int httpCode = http.GET(); 617 | if (httpCode > 0){ 618 | if (httpCode == HTTP_CODE_OK){ 619 | response_ws = http.getString(); 620 | //Serial.println(response_ws); 621 | s = true; 622 | } 623 | }else{ 624 | Serial.printf("[HTTP] GET JSON failed, error: %s\n", http.errorToString(httpCode).c_str()); 625 | s = false; 626 | } 627 | http.end(); 628 | return s; 629 | } 630 | 631 | bool parseJson_ws(String json) //对心知天气的json数据解析,采用arduinojson v6库 632 | { 633 | const size_t capacity = JSON_ARRAY_SIZE(1) + JSON_ARRAY_SIZE(3) + JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(6) + 3*JSON_OBJECT_SIZE(14) + 810; 634 | DynamicJsonDocument doc(capacity); //根据json数据结构计算所需要的内存大小 635 | deserializeJson(doc, json); //反序列化json数据 636 | JsonObject results_0 = doc["results"][0]; 637 | JsonArray results_0_daily = results_0["daily"]; 638 | 639 | JsonObject results_0_daily_0 = results_0_daily[0]; //今天的天气数据 640 | const char* results_0_daily_0_date = results_0_daily_0["date"]; // "2020-06-20" 641 | const char* results_0_daily_0_text_day = results_0_daily_0["text_day"]; // "多云" 642 | const char* results_0_daily_0_code_day = results_0_daily_0["code_day"]; // "4" 643 | const char* results_0_daily_0_text_night = results_0_daily_0["text_night"]; // "多云" 644 | const char* results_0_daily_0_code_night = results_0_daily_0["code_night"]; // "4" 645 | const char* results_0_daily_0_high = results_0_daily_0["high"]; // "28" 646 | const char* results_0_daily_0_low = results_0_daily_0["low"]; // "20" 647 | const char* results_0_daily_0_rainfall = results_0_daily_0["rainfall"]; // "0.0" 648 | const char* results_0_daily_0_precip = results_0_daily_0["precip"]; // "" 649 | const char* results_0_daily_0_wind_direction = results_0_daily_0["wind_direction"]; // "东" 650 | const char* results_0_daily_0_wind_direction_degree = results_0_daily_0["wind_direction_degree"]; // "90" 651 | const char* results_0_daily_0_wind_speed = results_0_daily_0["wind_speed"]; // "16.20" 652 | const char* results_0_daily_0_wind_scale = results_0_daily_0["wind_scale"]; // "3" 653 | const char* results_0_daily_0_humidity = results_0_daily_0["humidity"]; // "72" 654 | 655 | JsonObject results_0_daily_1 = results_0_daily[1]; //明天的天气数据 656 | const char* results_0_daily_1_date = results_0_daily_1["date"]; // "2020-06-21" 657 | const char* results_0_daily_1_text_day = results_0_daily_1["text_day"]; // "多云" 658 | const char* results_0_daily_1_code_day = results_0_daily_1["code_day"]; // "4" 659 | const char* results_0_daily_1_text_night = results_0_daily_1["text_night"]; // "阴" 660 | const char* results_0_daily_1_code_night = results_0_daily_1["code_night"]; // "9" 661 | const char* results_0_daily_1_high = results_0_daily_1["high"]; // "27" 662 | const char* results_0_daily_1_low = results_0_daily_1["low"]; // "20" 663 | const char* results_0_daily_1_rainfall = results_0_daily_1["rainfall"]; // "0.0" 664 | const char* results_0_daily_1_precip = results_0_daily_1["precip"]; // "" 665 | const char* results_0_daily_1_wind_direction = results_0_daily_1["wind_direction"]; // "东南" 666 | const char* results_0_daily_1_wind_direction_degree = results_0_daily_1["wind_direction_degree"]; // "135" 667 | const char* results_0_daily_1_wind_speed = results_0_daily_1["wind_speed"]; // "16.20" 668 | const char* results_0_daily_1_wind_scale = results_0_daily_1["wind_scale"]; // "3" 669 | const char* results_0_daily_1_humidity = results_0_daily_1["humidity"]; // "68" 670 | 671 | JsonObject results_0_daily_2 = results_0_daily[2]; //后天的天气数据 672 | const char* results_0_daily_2_date = results_0_daily_2["date"]; // "2020-06-22" 673 | const char* results_0_daily_2_text_day = results_0_daily_2["text_day"]; // "中雨" 674 | const char* results_0_daily_2_code_day = results_0_daily_2["code_day"]; // "14" 675 | const char* results_0_daily_2_text_night = results_0_daily_2["text_night"]; // "小雨" 676 | const char* results_0_daily_2_code_night = results_0_daily_2["code_night"]; // "13" 677 | const char* results_0_daily_2_high = results_0_daily_2["high"]; // "26" 678 | const char* results_0_daily_2_low = results_0_daily_2["low"]; // "23" 679 | const char* results_0_daily_2_rainfall = results_0_daily_2["rainfall"]; // "10.0" 680 | const char* results_0_daily_2_precip = results_0_daily_2["precip"]; // "" 681 | const char* results_0_daily_2_wind_direction = results_0_daily_2["wind_direction"]; // "东南" 682 | const char* results_0_daily_2_wind_direction_degree = results_0_daily_2["wind_direction_degree"]; // "127" 683 | const char* results_0_daily_2_wind_speed = results_0_daily_2["wind_speed"]; // "25.20" 684 | const char* results_0_daily_2_wind_scale = results_0_daily_2["wind_scale"]; // "4" 685 | const char* results_0_daily_2_humidity = results_0_daily_2["humidity"]; // "71" 686 | 687 | const char* results_0_last_update = results_0["last_update"]; //数据更新时间 688 | 689 | String date0 = results_0_daily_0_date; //将日期取出处理 690 | String date1 = results_0_daily_1_date; 691 | String date2 = results_0_daily_2_date; 692 | 693 | day0.date_m = date0.substring(5, 7); //日期字符串切片 694 | day0.date_d = date0.substring(8, 10); 695 | day0.code_day = atoi(results_0_daily_0_code_day);//获取今天天气信息 696 | day0.high = atoi(results_0_daily_0_high); //最高温度 697 | day0.low = atoi(results_0_daily_0_low); //最低温度 698 | day0.wind_direction_degree = atoi(results_0_daily_0_wind_direction_degree); //风向 699 | day0.wind_scale = atoi(results_0_daily_0_wind_scale); //风力等级 700 | day0.humidity = atoi(results_0_daily_0_humidity); //湿度 701 | 702 | day1.date_m = date1.substring(5, 7); 703 | day1.date_d = date1.substring(8, 10); 704 | day1.code_day = atoi(results_0_daily_1_code_day);//获取明天天气信息 705 | day1.high = atoi(results_0_daily_1_high); 706 | day1.low = atoi(results_0_daily_1_low); 707 | day1.wind_direction_degree = atoi(results_0_daily_1_wind_direction_degree); 708 | day1.wind_scale = atoi(results_0_daily_1_wind_scale); 709 | day1.humidity = atoi(results_0_daily_1_humidity); 710 | 711 | day2.date_m = date2.substring(5, 7); 712 | day2.date_d = date2.substring(8, 10); 713 | day2.code_day = atoi(results_0_daily_2_code_day);//获取后天天气信息 714 | day2.high = atoi(results_0_daily_2_high); 715 | day2.low = atoi(results_0_daily_2_low); 716 | day2.wind_direction_degree = atoi(results_0_daily_2_wind_direction_degree); 717 | day2.wind_scale = atoi(results_0_daily_2_wind_scale); 718 | day2.humidity = atoi(results_0_daily_2_humidity); 719 | 720 | return true; 721 | } 722 | 723 | void display_today() //oled显示今天的天气信息 724 | { 725 | u8g2.clearBuffer(); 726 | u8g2.setFont(u8g2_font_lubB08_tr); 727 | u8g2.setCursor(34, 15); 728 | u8g2.print(day0.low); 729 | u8g2.setCursor(49, 15); 730 | u8g2.print("-"); 731 | u8g2.setCursor(54, 15); 732 | u8g2.print(day0.high); 733 | u8g2.setCursor(68, 15); 734 | u8g2.print("C"); 735 | 736 | u8g2.drawLine(87, 5, 87, 31); 737 | 738 | u8g2.setCursor(94, 15); 739 | u8g2.print(day0.humidity); 740 | u8g2.setCursor(110, 15); 741 | u8g2.print("%"); 742 | //u8g2.setCursor(80, 31); 743 | //u8g2.print(day0.wind_direction_degree); 744 | 745 | String Direction; //将风向角度简化为风向文字信息 746 | if (day0.wind_direction_degree == 0) 747 | { 748 | Direction = "N"; 749 | } 750 | else if (day0.wind_direction_degree == 90) 751 | { 752 | Direction = "E"; 753 | } 754 | else if (day0.wind_direction_degree == 180) 755 | { 756 | Direction = "S"; 757 | } 758 | else if (day0.wind_direction_degree == 270) 759 | { 760 | Direction = "W"; 761 | } 762 | else if ((day0.wind_direction_degree>0) && (day0.wind_direction_degree<90)) 763 | { 764 | Direction = "EN"; 765 | } 766 | else if ((day0.wind_direction_degree>90) && (day0.wind_direction_degree<180)) 767 | { 768 | Direction = "ES"; 769 | } 770 | else if ((day0.wind_direction_degree>180) && (day0.wind_direction_degree<270)) 771 | { 772 | Direction = "WS"; 773 | } 774 | else if ((day0.wind_direction_degree>270) && (day0.wind_direction_degree<360)) 775 | { 776 | Direction = "WN"; 777 | } 778 | u8g2.setCursor(94, 31); 779 | u8g2.print(Direction); 780 | 781 | u8g2.setFont(u8g2_font_tenstamps_mn); 782 | u8g2.setCursor(110, 31); 783 | u8g2.print(day0.wind_scale); 784 | 785 | 786 | switch(day0.code_day) //将天气代码转化为天气图标和字符显示 787 | { 788 | case 0: 789 | u8g2.drawXBMP( 1 , 1 , 30 , 30 , Sunny ); 790 | u8g2.setFont(u8g2_font_luBIS08_tr); 791 | u8g2.drawStr(33,30,"Sunny"); 792 | break; 793 | case 4: 794 | u8g2.drawXBMP( 1 , 1 , 30 , 30 , Cloudy ); 795 | u8g2.setFont(u8g2_font_luBIS08_tr); 796 | u8g2.drawStr(33,30,"Cloudy"); 797 | break; 798 | case 9: 799 | u8g2.drawXBMP( 1 , 1 , 30 , 30 , Overcast ); 800 | u8g2.setFont(u8g2_font_luBIS08_tr); 801 | u8g2.drawStr(33,30,"Overcast"); 802 | break; 803 | case 10: 804 | u8g2.drawXBMP( 1 , 1 , 30 , 30 , Shower ); 805 | u8g2.setFont(u8g2_font_luBIS08_tr); 806 | u8g2.drawStr(33,30,"Shower"); 807 | break; 808 | case 11: 809 | u8g2.drawXBMP( 1 , 1 , 30 , 30 , Thundershower ); 810 | u8g2.setFont(u8g2_font_luBIS08_tr); 811 | u8g2.drawStr(33,30,"Thunder"); 812 | break; 813 | case 13: 814 | u8g2.drawXBMP( 1 , 1 , 30 , 30 , Rain_L ); 815 | u8g2.setFont(u8g2_font_luBIS08_tr); 816 | u8g2.drawStr(33,30,"L-Rain"); 817 | break; 818 | case 14: 819 | u8g2.drawXBMP( 1 , 1 , 30 , 30 , Rain_M ); 820 | u8g2.setFont(u8g2_font_luBIS08_tr); 821 | u8g2.drawStr(33,30,"M-Rain"); 822 | break; 823 | case 15: 824 | u8g2.drawXBMP( 1 , 1 , 30 , 30 , Rain_H ); 825 | u8g2.setFont(u8g2_font_luBIS08_tr); 826 | u8g2.drawStr(33,30,"H-Rain"); 827 | break; 828 | case 30: 829 | u8g2.drawXBMP( 1 , 1 , 30 , 30 , Foggy ); 830 | u8g2.setFont(u8g2_font_luBIS08_tr); 831 | u8g2.drawStr(33,30,"Foggy"); 832 | break; 833 | case 31: 834 | u8g2.drawXBMP( 1 , 1 , 30 , 30 , Haze ); 835 | u8g2.setFont(u8g2_font_luBIS08_tr); 836 | u8g2.drawStr(33,30,"Haze"); 837 | break; 838 | } 839 | 840 | u8g2.sendBuffer(); 841 | Serial.println(day0.code_day); 842 | } 843 | 844 | void weather_station0() //获取解析json,显示今天天气 845 | { 846 | if (getJson_ws()){ 847 | if (parseJson_ws(response_ws)){ 848 | display_today(); 849 | } 850 | 851 | } 852 | } 853 | 854 | void weather_station1() //并列显示三天日期和最高/低温度信息 855 | { 856 | u8g2.clearBuffer(); 857 | u8g2.setFont(u8g2_font_lubB08_tr); 858 | u8g2.setCursor(7, 15); 859 | u8g2.print(day0.date_m); 860 | u8g2.setCursor(21, 15); 861 | u8g2.print("/"); 862 | u8g2.setCursor(29, 15); 863 | u8g2.print(day0.date_d); 864 | 865 | u8g2.setCursor(7, 31); 866 | u8g2.print(day0.low); 867 | u8g2.setCursor(22, 31); 868 | u8g2.print("-"); 869 | u8g2.setCursor(27, 31); 870 | u8g2.print(day0.high); 871 | 872 | u8g2.drawLine(45, 5, 45, 31); 873 | 874 | u8g2.setCursor(49, 15); 875 | u8g2.print(day1.date_m); 876 | u8g2.setCursor(63, 15); 877 | u8g2.print("/"); 878 | u8g2.setCursor(71, 15); 879 | u8g2.print(day1.date_d); 880 | 881 | u8g2.setCursor(49, 31); 882 | u8g2.print(day1.low); 883 | u8g2.setCursor(64, 31); 884 | u8g2.print("-"); 885 | u8g2.setCursor(69, 31); 886 | u8g2.print(day1.high); 887 | 888 | u8g2.drawLine(87, 5, 87, 31); 889 | 890 | u8g2.setCursor(91, 15); 891 | u8g2.print(day2.date_m); 892 | u8g2.setCursor(105, 15); 893 | u8g2.print("/"); 894 | u8g2.setCursor(113, 15); 895 | u8g2.print(day2.date_d); 896 | 897 | u8g2.setCursor(91, 31); 898 | u8g2.print(day2.low); 899 | u8g2.setCursor(106, 31); 900 | u8g2.print("-"); 901 | u8g2.setCursor(111, 31); 902 | u8g2.print(day2.high); 903 | 904 | u8g2.sendBuffer(); 905 | } 906 | 907 | void weather_station2() //并列显示三天天气图标 908 | { 909 | u8g2.clearBuffer(); 910 | switch(day0.code_day) 911 | { 912 | case 0: 913 | u8g2.drawXBMP( 7 , 1 , 30 , 30 , Sunny ); 914 | break; 915 | case 4: 916 | u8g2.drawXBMP( 7 , 1 , 30 , 30 , Cloudy ); 917 | break; 918 | case 9: 919 | u8g2.drawXBMP( 7 , 1 , 30 , 30 , Overcast ); 920 | break; 921 | case 10: 922 | u8g2.drawXBMP( 7 , 1 , 30 , 30 , Shower ); 923 | break; 924 | case 11: 925 | u8g2.drawXBMP( 7 , 1 , 30 , 30 , Thundershower ); 926 | break; 927 | case 13: 928 | u8g2.drawXBMP( 7 , 1 , 30 , 30 , Rain_L ); 929 | break; 930 | case 14: 931 | u8g2.drawXBMP( 7 , 1 , 30 , 30 , Rain_M ); 932 | break; 933 | case 15: 934 | u8g2.drawXBMP( 7 , 1 , 30 , 30 , Rain_H ); 935 | break; 936 | case 30: 937 | u8g2.drawXBMP( 7 , 1 , 30 , 30 , Foggy ); 938 | break; 939 | case 31: 940 | u8g2.drawXBMP( 7 , 1 , 30 , 30 , Haze ); 941 | break; 942 | } 943 | switch(day1.code_day) 944 | { 945 | case 0: 946 | u8g2.drawXBMP( 49 , 1 , 30 , 30 , Sunny ); 947 | break; 948 | case 4: 949 | u8g2.drawXBMP( 49 , 1 , 30 , 30 , Cloudy ); 950 | break; 951 | case 9: 952 | u8g2.drawXBMP( 49 , 1 , 30 , 30 , Overcast ); 953 | break; 954 | case 10: 955 | u8g2.drawXBMP( 49 , 1 , 30 , 30 , Shower ); 956 | break; 957 | case 11: 958 | u8g2.drawXBMP( 49 , 1 , 30 , 30 , Thundershower ); 959 | break; 960 | case 13: 961 | u8g2.drawXBMP( 49 , 1 , 30 , 30 , Rain_L ); 962 | break; 963 | case 14: 964 | u8g2.drawXBMP( 49 , 1 , 30 , 30 , Rain_M ); 965 | break; 966 | case 15: 967 | u8g2.drawXBMP( 49 , 1 , 30 , 30 , Rain_H ); 968 | break; 969 | case 30: 970 | u8g2.drawXBMP( 49 , 1 , 30 , 30 , Foggy ); 971 | break; 972 | case 31: 973 | u8g2.drawXBMP( 49 , 1 , 30 , 30 , Haze ); 974 | break; 975 | } 976 | switch(day2.code_day) 977 | { 978 | case 0: 979 | u8g2.drawXBMP( 91 , 1 , 30 , 30 , Sunny ); 980 | break; 981 | case 4: 982 | u8g2.drawXBMP( 91 , 1 , 30 , 30 , Cloudy ); 983 | break; 984 | case 9: 985 | u8g2.drawXBMP( 91 , 1 , 30 , 30 , Overcast ); 986 | break; 987 | case 10: 988 | u8g2.drawXBMP( 91 , 1 , 30 , 30 , Shower ); 989 | break; 990 | case 11: 991 | u8g2.drawXBMP( 91 , 1 , 30 , 30 , Thundershower ); 992 | break; 993 | case 13: 994 | u8g2.drawXBMP( 91 , 1 , 30 , 30 , Rain_L ); 995 | break; 996 | case 14: 997 | u8g2.drawXBMP( 91 , 1 , 30 , 30 , Rain_M ); 998 | break; 999 | case 15: 1000 | u8g2.drawXBMP( 91 , 1 , 30 , 30 , Rain_H ); 1001 | break; 1002 | case 30: 1003 | u8g2.drawXBMP( 91 , 1 , 30 , 30 , Foggy ); 1004 | break; 1005 | case 31: 1006 | u8g2.drawXBMP( 91 , 1 , 30 , 30 , Haze ); 1007 | break; 1008 | } 1009 | u8g2.sendBuffer(); 1010 | 1011 | } 1012 | 1013 | //------------------------------------------------------------------ 1014 | //-------------------------DHT11_SENSOR----------------------------- 1015 | //------------------------------------------------------------------ 1016 | void dht11() //DHT11传感器,精度不行已弃用 1017 | { 1018 | float h = dht.readHumidity(); 1019 | // Read temperature as Celsius (the default) 1020 | float t = dht.readTemperature(); 1021 | // Read temperature as Fahrenheit (isFahrenheit = true) 1022 | float f = dht.readTemperature(true); 1023 | 1024 | //float hif = dht.computeHeatIndex(f, h); 1025 | // Compute heat index in Celsius (isFahreheit = false) 1026 | //float hic = dht.computeHeatIndex(t, h, false); 1027 | //Serial.println(h); 1028 | //Serial.println(t); 1029 | char Humidity[25]; 1030 | char Temperature[25]; 1031 | itoa(h, Humidity, 10); 1032 | itoa(t, Temperature, 10); 1033 | 1034 | // clear the internal memory 1035 | u8g2.clearBuffer(); 1036 | u8g2.setFont(u8g2_font_ncenB12_tr); // choose a suitable font 1037 | u8g2.drawStr(0,15,"Hum:"); // write something to the internal memory 1038 | u8g2.drawStr(0,30,"Tem:"); // write something to the internal memory 1039 | u8g2.setCursor(55, 15); 1040 | u8g2.print(h); 1041 | u8g2.setCursor(55, 30); 1042 | u8g2.print(t); 1043 | u8g2.drawStr(105,15,"%"); // write something to the internal memory 1044 | u8g2.drawStr(105,30,"C"); 1045 | //u8g2.drawStr(30,15,Humidity+"%"); // write something to the internal memory 1046 | //u8g2.drawStr(30,30,Temperature+"°C"); // write something to the internal memory 1047 | u8g2.sendBuffer(); 1048 | delay(500); 1049 | } 1050 | //------------------------------------------------------------------ 1051 | //---------------------------loop函数-------------------------------- 1052 | //------------------------------------------------------------------ 1053 | void loop() //主循环,判断按键次数切换运行程序和显示 1054 | { 1055 | int menu = Click%7; 1056 | if (WiFi.status() == WL_CONNECTED){ 1057 | switch(menu){ 1058 | case 0: 1059 | NTP_CLOCK(); 1060 | break; 1061 | case 1: 1062 | NTP_DAY(); 1063 | break; 1064 | case 2: 1065 | weather_station0(); 1066 | break; 1067 | case 3: 1068 | weather_station1(); 1069 | break; 1070 | case 4: 1071 | weather_station2(); 1072 | break; 1073 | case 5: 1074 | bilibili_fans_follower(); 1075 | break; 1076 | case 6: 1077 | bilibili_fans_viewer(); 1078 | break; 1079 | case 7: 1080 | dht11(); 1081 | break; 1082 | } 1083 | 1084 | Serial.println(Click); 1085 | } 1086 | else{ 1087 | Serial.println("[WiFi] Waiting to reconnect..."); //未联网串口输出 1088 | } 1089 | } 1090 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Esp8266_monitor 2 | NTP time+bilibili_fans monitor+weather station 3 | 4 | * 项目:ESP8266_monitor 5 | * 硬件:适用于NodeMCU ESP8266 + ssd1306 128*32 6 | * 功能:连接WiFi后获取指定用户的哔哩哔哩实时粉丝数+WIFI网络授时时钟+知心天气 7 | * 作者:Nemo_ssc bilibili UID:12772522 8 | * 图像:BMP文件夹存放所有用到的位图文件,可用pctolcd2002取模 9 | * 字模选项:阴码 逐行式 逆向 十六进制数 自定义格式 段前缀{ 段后缀} 数据前缀0x 数据后缀, 行后缀, 10 | * 日期:2020/06/20 11 | 12 | 13 | 需要用到的部分网址: 14 | 15 | 1.ArduinoJson部分 16 | 17 | https://arduinojson.org/v6/assistant/ 18 | 19 | https://blog.csdn.net/dpjcn1990/article/details/92831612 20 | 21 | https://blog.csdn.net/dpjcn1990/article/details/92831648 22 | 23 | 2.u8g2部分 24 | 25 | https://blog.csdn.net/dpjcn1990/article/details/92831760 26 | 27 | 3.心知天气 28 | 29 | https://www.seniverse.com/ 30 | 31 | 32 | 需要用到的材料清单 33 | 34 | 1. NodeMcu D1 Mini 35 | 36 | 2. 0.91' OLED 12832 37 | 38 | 3. CD42 5V2A充放电一体模块 39 | 40 | 4. microusb 母座 41 | 42 | 5. 300mah 3.7v锂电池 43 | 44 | 6. 30#硅胶线若干、ABS板、铜柱 45 | 46 | 47 | 48 | 感谢以下B站UP提供的代码支持: 49 | 50 | 1. 会飞的阿卡林 UID751219 BV1x441187QF BV1eJ411H7LN 51 | 52 | https://github.com/flyAkari/bilibili_fans_monitor 53 | 54 | https://github.com/flyAkari/ESP8266_Network_Clock 55 | 56 | 2. Hans叫泽涵 UID15481541 BV1LE411n7XR 57 | 58 | https://github.com/HansCallZH/bilibili_fans_clock_ESP8266 59 | 60 | 3. 小年轻只爱她 UID389851522 BV1N7411g7Ps BV157411L7Xf 61 | 62 | https://gitee.com/young_people_only_love_her/My_ESP8266/tree/master/%E5%BF%83%E7%9F%A5%E5 63 | --------------------------------------------------------------------------------