/**
* 日期: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);
}