ESP32 arduino 天气显示 后台可控制 定时消息提示 图片提示

ESP32 arduino 天气显示 后台可控制 定时消息提示 图片提示

后台操作界面

添加图片显示

添加文字轮播

用到的.H库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <WiFi.h>
#include <ESPmDNS.h>
#include <WebServer.h>
#include <WiFiMulti.h>

#include <Arduino.h>
#include <U8g2lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

#include <ArduinoJson.h> //json 序列化库
#include <SimpleTimer.h> //定时库

#include <HTTPClient.h> //HTTP 请求库

ESP32 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
#include <WiFi.h>
#include <ESPmDNS.h>
#include <WebServer.h>
#include <WiFiMulti.h>

#include <Arduino.h>
#include <U8g2lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

#include <ArduinoJson.h> //json 序列化库
#include <SimpleTimer.h> //定时库

 
StaticJsonDocument<6000> doc; //存放HTTP返回数据
//const char *json_o; //声明返回信息
char json_o[6000] =  {0};
float x;//轮播

#include <HTTPClient.h> //HTTP 请求库

String HttpApi = "http://www.tnro.cn/api/esp/esp32?id=fl"; //接口请求地址


SimpleTimer HttpTimer; //定义定时任务 http 请求

int httpCode; //HTTP 请求状态码全局
 unsigned char con_http_image[1024] = {0}; //定义图片解析
  String img_s;
  int img_x = 0;
  int index_i = 0;
  char img_b[5];

const char *type; //leix
 

U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ 22, /* data=*/ 21, /* reset=*/ U8X8_PIN_NONE);   //定义显示器引脚
const char* AP_SSID  = "小刘的天气Tool"; //热点名称
const char* AP_PASS  = "liufeiling";  //密码
 int OLED_STATUS_ACTION = 1; //开机显示状态 1 是默认配置页面 2 是 http链接状态
 int OLED_STATUS_ELSE = 1; //开机显示 配置步骤状态
 int OLED_STATUS_HTTP = 1; //HTTP 显示配置
 
 int OLED_STATUS_HJSON = 0; //解析设置

 const char *type9 = "9"; //HTTP 状态码
 const char *type2 = "2";//HTTP 状态码
 const char *type1 = "1";//HTTP 状态码
 
 unsigned char con[6000] U8X8_PROGMEM= {0};
const unsigned char content[] U8X8_PROGMEM= {这里是矩阵由于太大没有放下};
const unsigned char actionip[] U8X8_PROGMEM= {这里是矩阵由于太大没有放下};
#define ROOT_HTML  "H5页面"
#define ROOT_WAIT  "H5页面"
#define ROOT_LOVE  "H5页面"
WebServer server(80);
WiFiMulti wifiMulti;

uint8_t resr_count_down = 120;//重启倒计时s
TimerHandle_t xTimer_rest;
void restCallback(TimerHandle_t xTimer );
void HttpTimerService(); //声明方法
void tq_init();
void text_init(); //文字显示
void image_init(); //图片显示
void setup() {
  Serial.begin(115200);
  u8g2.begin(); //初始化
  u8g2.enableUTF8Print();  

  WiFi.mode(WIFI_AP);//配置为AP模式
 
  boolean result = WiFi.softAP(AP_SSID, AP_PASS);//开启WIFI热点
  if (result)
  {
    IPAddress myIP = WiFi.softAPIP();

    //打印相关信息
//    Serial.println("");
    Serial.print("Soft-AP IP address = ");
    Serial.println(myIP);
    Serial.println(String("MAC address = ")  + WiFi.softAPmacAddress().c_str());
    Serial.println("waiting ...");

    xTimer_rest = xTimerCreate("xTimer_rest", 1000 / portTICK_PERIOD_MS, pdTRUE, ( void * ) 0, restCallback);
    xTimerStart( xTimer_rest, 0 );  //开启定时器

  } else {  //开启热点失败
    Serial.println("WiFiAP Failed");
    delay(3000);
    ESP.restart();  //复位esp32
  }

  if (MDNS.begin("esp32")) {
    Serial.println("MDNS responder started");
  }

  //首页
  server.on("/", []() {
    OLED_STATUS_ELSE = 2;// 配置模式显示
    u8g2_prepare(); //屏幕重置
    init_2(); //显示连接状态
    Serial.print("当前状态:CDN连接");
    server.send(200, "text/html", ROOT_HTML);
  });
    //彩蛋
  server.on("/love", []() {
    server.send(200, "text/html",ROOT_LOVE);
  });

  //连接
  server.on("/connect", []() {

    server.send(200, "text/html",ROOT_WAIT);
    delay(1000);
    WiFi.softAPdisconnect(true);
    //获取输入的WIFI账户和密码
    String ssid = server.arg("ssid");
    String pass = server.arg("pass");
    Serial.println("WiFi Connect SSID:" + ssid + "  PASS:" + pass);
    //设置为STA模式并连接WIFI
    WiFi.mode(WIFI_STA);
//    WiFi.hostname("esp8266_test");
    WiFi.begin(ssid.c_str(), pass.c_str());

    resr_count_down = 120;
    xTimerStop(xTimer_rest, 0);

    uint8_t Connect_time = 0; //用于连接计时,如果长时间连接不成功,复位设备
    uint8_t Connect_num = 1; //用于连接计时, 等待时间;
    char str[20] = "";
    u8g2.setFont(u8g2_font_6x10_tf); //设置字体
//    u8g2_init_dis();// 强行重置渲染

    while (WiFi.status() != WL_CONNECTED  ) {  //等待WIFI连接成功
      delay(500);
//       init_2(); //显示连接中信息
      Serial.print(".");
//      sprintf(str,"%d",Connect_num);//int 转字符串显示

      u8g2.setCursor( 100,55); //显示尝试次数位置
      u8g2.print(Connect_num);
      u8g2.nextPage();
      Connect_num ++;
      Connect_time ++;
      if (Connect_time > 80) {  //长时间连接不上,复位设备
        Serial.println("Connection timeout, check input is correct or try again later!");
        delay(3000);
        ESP.restart();
      }
    }
    OLED_STATUS_ACTION =2;
  });
  server.begin();
  //设置定时任务HttpTimer ,Xtime
  HttpTimer.setInterval(8000, HttpTimerService); //HTTP 请求 8秒一次心跳包
}

void loop() {
  ////轮播重置/////
  if(x<-1000)
  {
    x= 0;
  }
  server.handleClient();
//  Serial.print("系统循环");
  u8g2.firstPage();
  do {
    //这里初始化显示图标
    draw(); //动态选择当前屏幕显示内容

  } while ( u8g2.nextPage());
 
//  while (WiFi.status() == WL_CONNECTED) {
//    //WIFI已连接
//    //进行网络请求
//    u8g2_http();
//    
//  }
   
}
///显示屏初始化
void u8g2_prepare(void) {
  u8g2.setFont(u8g2_font_6x10_tf);
  u8g2.setFontMode(0); //设置字体透明格式显示
  u8g2.setFontRefHeightExtendedText();
  u8g2.setDrawColor(0);
  u8g2.setFontPosTop();
  u8g2.setFontDirection(0);
}
//////显示屏显示模式选择
void draw()
{

  switch(OLED_STATUS_ACTION){
    case 1:u8g2_init();break;
    case 2:u8g2_http();break;
//    default:  break;
  }
}
//// 显示屏初始化
void u8g2_init()
{
  u8g2_prepare(); //屏幕重置
   switch(OLED_STATUS_ELSE){
    case 1:init_1();break; //开机显示配置画面
    case 2:init_2();break; //显示正在连接画面 //由于连接需要循环终端//迁移到 连接中去显示
  }
 
}
//显示屏重置显示 强行重置渲染
void u8g2_init_dis()
{
  for (int i=1; i<=100; ++i)
    {
       u8g2.nextPage();
    }
}
//初始化完毕进入http
////////////////HTTP////初始化状态/////////


void u8g2_http()
{
  ////////////开始网络请求//////////////////
  HttpTimer.run();
//  if(httpCode == HTTP_CODE_OK){
//    json_I = json_o;
    if(OLED_STATUS_HJSON == 1)
    {
      deserializeJson(doc, json_o);
      OLED_STATUS_HJSON =0;
      //屏幕重置
 

          u8g2.setFontDirection(0);
          u8g2.firstPage();
          u8g2.setFont(u8g2_font_wqy14_t_gb2312);
       
          type = doc["data"]["type"];
          if(strcmp(type, type1) == 0)
          {
            String AS = doc["data"]["con"];
             for(img_x;img_x<1023;img_x++){
                  img_s = AS.substring(index_i,index_i+4);
                  strcpy(img_b,img_s.c_str());
                  con_http_image[img_x] = strtoul(img_b,0,0);
                  index_i+=5; //下一个解析
//                  Serial.println(con[img_x]); //链接成功输出IP
             }
             img_x = 0; //重置
             index_i = 0; //重置
            u8g2_prepare(); //屏幕重置
           
          };
     
    }
   
   
   
//    Serial.println("进行对比"); //输出
    if(strcmp(type, type9) == 0)
    {
      tq_init();
      Serial.println("天气类型已执行"); //输出
    };
    if(strcmp(type, type2) == 0)
    {
      init_init();
      Serial.println("文字类型已执行"); //输出
    };
    if(strcmp(type, type1) == 0)
    {
      image_init();
      Serial.println("图片类型已执行"); //输出
    };
   
   
 

}
//////////////////////////////HTTP 网络请求API 方法////////////////////////////
void tq_init()
{
   
   
    ///显示第一天
    u8g2.setCursor(0, 1);
    const char *dayTq00 = doc["data"]["v0"][0];
    const char *dayTq01 = doc["data"]["v0"][1];
    u8g2.print(dayTq00);
    u8g2.setCursor(100, 1);
    u8g2.print(dayTq01);
   //第1天 提示语句
    const char *dayTq10 = doc["data"]["v1"][0]; //第一天提示
   
    u8g2.setCursor((int)x, 17);
    u8g2.print(dayTq10);
    u8g2.drawLine(0, 33, 127, 33); //画横线
   
     /////////////第2天/////////////////第二天 天气提示
    const char *dayTq20 = doc["data"]["v2"][0];
    const char *dayTq21 = doc["data"]["v2"][1];
    u8g2.setCursor(0, 36);
    u8g2.print(dayTq20);
   
    u8g2.setCursor(100, 36);
    u8g2.print(dayTq21);
     ///////////////第3天///////////////
    const char *dayTq30 = doc["data"]["v3"][0];
    const char *dayTq31 = doc["data"]["v3"][1];
   
    u8g2.setCursor(0, 50);
    u8g2.print(dayTq30);

    u8g2.setCursor(100, 50);
    u8g2.print(dayTq31);
    x-=0.3;
    Serial.println(x); //输出
   
}
void init_init()
{
      ///显示第一行
    u8g2.setCursor(0, 1);
    const char *dayTq00 = doc["data"]["v0"];
    u8g2.print(dayTq00);
 
   //第2行 提示语句
    const char *dayTq10 = doc["data"]["v1"];  
   
    u8g2.setCursor((int)x, 17);
    u8g2.print(dayTq10);
 
   
     /////////////第3行天///////////////
    const char *dayTq20 = doc["data"]["v2"];
    u8g2.setCursor(0, 36);
    u8g2.print(dayTq20);

     ///////////////第4天///////////////
    const char *dayTq30 = doc["data"]["v3"];
   
    u8g2.setCursor(0, 50);
    u8g2.print(dayTq30);

    x-=0.3;
};
void image_init()
{
   
 
    u8g2.setDrawColor(1);// Black
    u8g2.drawXBMP(0, 0, 128, 64, con_http_image);
};


////////////////显示屏初始化调用方法区域*////////////////
//开机显示连接画面
void init_1()
{
  u8g2.setDrawColor(1);// Black
  u8g2.drawXBMP(0, 0, 128, 64, actionip);
}
//显示正在连接画面
void init_2()
{
  u8g2.setDrawColor(1);// Black
  u8g2.drawXBMP(0, 0, 128, 64, content);
}

////////////////显示屏初始化调用方法区域*////////////////
void restCallback(TimerHandle_t xTimer ) {  //长时间不访问WIFI Config 将复位设备
  resr_count_down --;
  Serial.print("resr_count_down: ");
  Serial.println(resr_count_down);
  if (resr_count_down < 1) {
    ESP.restart();
  }
}
////////////HttpTimerService/////////////
void HttpTimerService(){
  Serial.print("5秒定时请求测试..... ");
   HTTPClient http; //实例化
  http.begin(HttpApi);// 开始请求的地址
  httpCode = http.GET(); //获取请求返回的code 码
  if (httpCode == HTTP_CODE_OK) { // 状态码正常 200
    String results = http.getString(); //获取响应内容
 
     for (int i = 0; i < results.length(); i++) //string类型转char[]类型
        {
            json_o[i]=results[i];
        }

    OLED_STATUS_HJSON =1;
   

  } else {
    //不正常 //异常请求
    Serial.println("请求错误,状态码: yic");
 
  }
  http.end();
 
}

效果图