《项目》 之 ESP8266 在线获取特定省份新型冠状病毒疫情

/**
* 日期:2019/02/09
* 功能:武汉加油 中国加油
* 作者:单片机菜鸟
**/
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
#include <U8g2lib.h>
#include <Wire.h>

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);

#define LED D4
#define DEBUG //是否开启debug功能

#ifdef DEBUG
#define DebugPrintln(message)    Serial.println(message)
#else
#define DebugPrintln(message)
#endif

#ifdef DEBUG
#define DebugPrint(message)    Serial.print(message)
#else
#define DebugPrint(message)
#endif

//声明方法
bool autoConfig();
void smartConfig();
bool sendRequest();
bool skipResponseHeaders();
void readReponseContent(char* content, size_t maxSize);
void stopConnect();
void clrEsp8266ResponseBuffer(void);
bool parseUserData(char* content);
void displayData();
  
const unsigned long BAUD_RATE = 115200;// serial connection speed
const unsigned long HTTP_TIMEOUT = 5000;               // max respone time from server
const size_t MAX_CONTENT_SIZE = 3000;                   // max size of the HTTP response
const char* host = "lab.isaaclin.cn";
const char* provice = "陕西省";

int flag = HIGH;//默认当前灭灯
WiFiClient client;
char response[MAX_CONTENT_SIZE];
char endOfHeaders[] = "\r\n\r\n";

long lastTime = 0;
// 请求服务间隔
long Delay = 5000;
// 疫情数据变量
int confirmedCount;
int suspectedCount;
int curedCount;
int deadCount;

// 西安疫情数据变量
int xian_confirmedCount;
int xian_suspectedCount;
int xian_curedCount;
int xian_deadCount;

// 渭南疫情数据变量
int weinan_confirmedCount;
int weinan__suspectedCount;
int weinan__curedCount;
int weinan__deadCount;

/**
* @Desc 初始化操作
*/
void setup() {
  Serial.begin(BAUD_RATE);
  pinMode(LED,OUTPUT);
  digitalWrite(LED, HIGH);

  // 初始化OLED显示屏
  u8g2.begin();
  u8g2.enableUTF8Print();
  u8g2.setFont(u8g2_font_wqy12_t_gb2312a);
  u8g2.setFontPosTop();
  u8g2.clearDisplay();
  u8g2.firstPage();
  do
  {
  u8g2.setCursor(32, 16);
  u8g2.print("武汉加油!");
  u8g2.setCursor(32, 32);
  u8g2.print("中国加油!");
  }
  while (u8g2.nextPage());
  

  if(!autoConfig()){
    smartConfig();
    DebugPrint("Connecting to WiFi");//写几句提示,哈哈
    while (WiFi.status() != WL_CONNECTED) {
    //这个函数是wifi连接状态,返回wifi链接状态
       delay(500);
       DebugPrint(".");
    }
  }
  
  delay(1000);
  digitalWrite(LED, LOW);
  DebugPrintln("IP address: ");
  DebugPrintln(WiFi.localIP());//WiFi.localIP()返回8266获得的ip地址
  lastTime = millis();
  
  //使能软件看门狗的触发间隔
  ESP.wdtEnable(5000);
}
  
/**
* @Desc  主函数
*/
void loop() {
  while (!client.connected()){
     if (!client.connect(host, 80)){
         flag = !flag;
         digitalWrite(LED, flag);
         delay(500);
         //喂狗
         ESP.wdtFeed();
     }
  }

  digitalWrite(LED, HIGH);

  if(millis()-lastTime>=Delay){
   //每间隔20s左右调用一次
     lastTime = millis();
     if (sendRequest() && skipResponseHeaders()) {
       clrEsp8266ResponseBuffer();
       readReponseContent(response, sizeof(response));
       if (parseUserData(response)) {
          
       }
     }
  }
  
   //喂狗
   ESP.wdtFeed();
}

/**
* 自动连接20s 超过之后自动进入SmartConfig模式
*/
bool autoConfig(){
  WiFi.mode(WIFI_AP_STA);     //设置esp8266 工作模式
  WiFi.begin();
  delay(2000);//刚启动模块的话 延时稳定一下
  DebugPrintln("AutoConfiging ......");
  for(int index=0;index<10;index++){
    int wstatus = WiFi.status();
    if (wstatus == WL_CONNECTED){
      DebugPrintln("AutoConfig Success");
      DebugPrint("SSID:");
      DebugPrintln(WiFi.SSID().c_str());
      DebugPrint("PSW:");
      DebugPrintln(WiFi.psk().c_str());
      return true;
    }else{
      DebugPrint(".");
      delay(500);
      flag = !flag;
      digitalWrite(LED, flag);
    } 
  }
  DebugPrintln("AutoConfig Faild!");
  return false;
}

/**
* 开启SmartConfig功能
*/
void smartConfig()
{
  WiFi.mode(WIFI_STA);
  delay(1000);
  DebugPrintln("Wait for Smartconfig");
  // 等待配网
  WiFi.beginSmartConfig();
  while (1){
    DebugPrint(".");
    delay(200);
    flag = !flag;
    digitalWrite(LED, flag);
    
    if (WiFi.smartConfigDone()){
      //smartconfig配置完毕
      DebugPrintln("SmartConfig Success");
      WiFi.mode(WIFI_AP_STA);     //设置esp8266 工作模式
      WiFi.setAutoConnect(true);  // 设置自动连接
      break;
    }
  }
}

/**
* @发送请求指令
*/
bool sendRequest() {
  // We now create a URI for the request
  //心知天气
  String GetUrl = "/nCoV/api/area";
  GetUrl += "?latest=1";
  GetUrl += "&province=";
  GetUrl += provice;
  
  // This will send the request to the server
  client.print(String("GET ") + GetUrl + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "Connection: close\r\n\r\n");
  delay(1000);
  return true;
}
 
/**
* @Desc 跳过 HTTP 头,使我们在响应正文的开头
*/
bool skipResponseHeaders() {
  // HTTP headers end with an empty line
  bool ok = client.find(endOfHeaders);
  if (!ok) {
    DebugPrintln("No response or invalid response!");
  }
  return ok;
}
 
/**
* @Desc 从HTTP服务器响应中读取正文
*/
void readReponseContent(char* content, size_t maxSize) {
  size_t length = client.readBytes(content, maxSize);
  delay(100);
  content[length] = 0;
  client.flush();//这句代码需要加上  不然会发现每隔一次client.find会失败
}
  
// 关闭与HTTP服务器连接
void stopConnect() {
  client.stop();
}
 
void clrEsp8266ResponseBuffer(void){
    memset(response, 0, MAX_CONTENT_SIZE);      //清空
}

bool parseUserData(char* content) {
//    -- 根据我们需要解析的数据来计算JSON缓冲区最佳大小
//   如果你使用StaticJsonBuffer时才需要
//    const size_t BUFFER_SIZE = 1024;
//   在堆栈上分配一个临时内存池
//    StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;
//    -- 如果堆栈的内存池太大,使用 DynamicJsonBuffer jsonBuffer 代替
  DynamicJsonBuffer jsonBuffer;
  
  JsonObject& root = jsonBuffer.parseObject(content);
  
  if (!root.success()) {
    Serial.println("JSON parsing failed!");
    return false;
  }

  // -------- 对应省数据 -----------
  JsonObject& provinces = root["results"][0];
  const char* country = provinces["country"]; // "中国"
  const char* provinceName = provinces["provinceName"]; // "省份"
  confirmedCount = provinces["confirmedCount"];
  suspectedCount = provinces["suspectedCount"];
  curedCount = provinces["curedCount"];
  deadCount = provinces["deadCount"];
  
  // -------- 串口打印实时疫情信息 -----------
  Serial.printf("%s新型肺炎疫情实时数据",provice);
  Serial.println("-----------------------------------------");

  Serial.printf("确诊:%d | 疑似:%d | 治愈:%d | 死亡:%d",confirmedCount,suspectedCount,curedCount,deadCount);
  Serial.println();
  // -------- cities -----------
  JsonArray& cities = provinces["cities"];

  for( int index = 0; index < cities.size(); index ++){
    JsonObject& ciry = cities[index];
    const char* cityName = ciry["cityName"]; // "宁波"
    confirmedCount = ciry["confirmedCount"];
    suspectedCount = ciry["suspectedCount"];
    curedCount = ciry["curedCount"];
    deadCount = ciry["deadCount"];
    Serial.printf("%s | 确诊:%d | 疑似:%d | 治愈:%d | 死亡:%d",cityName,confirmedCount,suspectedCount,curedCount,deadCount);
    Serial.println();
  }
  Serial.println("-----------------------------------------");
  // -------- 西安数据 -----------
    JsonObject& xian = cities[0];
    const char* hangzhou_cityName = xian["cityName"]; // "西安"
    xian_confirmedCount = xian["confirmedCount"];
    xian_suspectedCount = xian["suspectedCount"];
    xian_curedCount = xian["curedCount"];
    xian_deadCount = xian["deadCount"];

    // -------- 渭南数据 -----------
    JsonObject& weinan = cities[5];
    const char* ningbo_cityName = weinan["cityName"]; // "渭南"
    weinan_confirmedCount = weinan["confirmedCount"];
    weinan__suspectedCount = weinan["suspectedCount"];
    weinan__curedCount = weinan["curedCount"];
    weinan__deadCount = weinan["deadCount"];

  u8g2.firstPage();
  do
  {
    displayData();
  }
  while (u8g2.nextPage());
  return true;
}

// 在OLED上显示实时疫情数据
void displayData() {
  u8g2.clearDisplay();

  // 绘制表格
  u8g2.drawFrame(0, 16, 128, 48);
  u8g2.drawLine(0, 32, 127, 32);
  u8g2.drawLine(0, 48, 127, 48);
  u8g2.drawLine(32, 16, 32, 63);
  u8g2.drawLine(64, 16, 64, 63);
  u8g2.drawLine(96, 16, 96, 63);

  // 标题
  u8g2.setCursor(18, 2);
  u8g2.print("陕西疫情实时信息");

  // 表格类别
  u8g2.setCursor(36, 20);
  u8g2.print("确诊");
  u8g2.setCursor(68, 20);
  u8g2.print("治愈");
  u8g2.setCursor(100, 20);
  u8g2.print("死亡");

  // 西安情况
  u8g2.setCursor(4, 36);
  u8g2.print("西安");
  u8g2.setCursor(38, 36);
  u8g2.print(xian_confirmedCount);
  u8g2.setCursor(72, 36);
  u8g2.print(xian_curedCount);
  u8g2.setCursor(104, 36);
  u8g2.print(xian_deadCount);

  // 渭南情况
  u8g2.setCursor(4, 52);
  u8g2.print("渭南");
  u8g2.setCursor(40, 52);
  u8g2.print(weinan_confirmedCount);
  u8g2.setCursor(72, 52);
  u8g2.print(weinan__curedCount);
  u8g2.setCursor(104, 52);
  u8g2.print(weinan__deadCount);
}
  • 一起来看下效果吧

发布了3 篇原创文章 · 获赞 9 · 访问量 679

猜你喜欢

转载自blog.csdn.net/qq_41868901/article/details/104238286