这里是用ESP32做了从机,一定周期打印 时间,天气数据。
编译环境是 vscode-PlatformIO
#include "Arduino.h"
#include
#include
#include
// WiFi相关
const char *ssid = "233";
const char *password = "12345678";
//心知天气 相关
String API = "SJ3cQqGjCfr2Ej1oS";
String CITY = "luoyang";
// 定时器相关
u32_t cnt = 0;
void Get_Now_Time() ; //NTP 获取当前时间/日期
void Get_Today_Weather(String api, String city) ;//https 获取当日天气
void Get_Rencent_Weather(String api, String city) ;//https 获取 今明后 三日天气
void IRAM_ATTR Tim0_Handle(void) //定时器回调函数
{
++cnt;
if(cnt == 300) //五分钟一个循环
{
cnt =0;
}
}
void setup()
{
Serial.begin(115200);
Serial.println("串口初始化成功");
hw_timer_t *tim0 = timerBegin(0, 8000, true); //建立定时器 //80MHZ 进行 8000预分频后 每秒 计数10000次
timerAlarmWrite(tim0, 10000-1, true);//设置 自动重装载值 10000-1
timerAttachInterrupt(tim0, Tim0_Handle, true);//绑定定时器
timerAlarmEnable(tim0);
}
void loop()
{
switch (cnt)
{
case 3:
if (WiFi.status() != WL_CONNECTED)
{
WiFi.begin(ssid, password);
vTaskDelay(100);
}
Serial.println("WiFi开启");
++cnt;
break;
case 8:
Serial.println("现在的时间是");
Get_Now_Time();
Serial.println("今天的天气是");
Get_Today_Weather(API, CITY);
Serial.println("近三天的天气是");
Get_Rencent_Weather(API, CITY);
++cnt;
break;
case 18:
Serial.println("WiFi关闭");
WiFi.disconnect(true); //关闭wifi ,降低功耗
WiFi.mode(WIFI_OFF);
++cnt;
default:
break;
}
}
void Get_Now_Time()
{
while (WiFi.status() != WL_CONNECTED)
{
WiFi.begin(ssid, password);
vTaskDelay(100);
}
configTime(3600 * 7, 3600, "us.pool.ntp.org");
static struct tm timeinfo;
if (!getLocalTime(&timeinfo))
{
if (!getLocalTime(&timeinfo))
return;
}
Serial.println(&timeinfo, "#T-%Y-%m-%d-%w-%H:%M:%S");//我需要的 时间 年月日 + 星期几 + 时分秒
vTaskDelay(2);
}
void Get_Today_Weather(String api, String city)
{
while (WiFi.status() != WL_CONNECTED)
{
WiFi.begin(ssid, password);
vTaskDelay(100);
}
String url_xinzhi = "";
url_xinzhi = "https://api.seniverse.com/v3/weather/now.json?key=";
url_xinzhi += api;
url_xinzhi += "&location=";
url_xinzhi += city;
url_xinzhi += "&language=en&unit=c";
DynamicJsonDocument doc(2048); //分配内存,动态
HTTPClient http;
char data[100] = {"#w:"};
http.begin(url_xinzhi);
int httpGet = http.GET();
if (httpGet > 0)
{
if (httpGet == HTTP_CODE_OK)
{
String json = http.getString();
//Serial.println(json); //打印接受到的消息
deserializeJson(doc, json);
/* 从doc 中提取出 需要的数据 */
/* code :天气码 temperature:气温 */
strcat(data, doc["results"][0]["now"]["code"].as());
strcat(data, ":");
strcat(data, doc["results"][0]["now"]["temperature"].as());
strcat(data, "$");
Serial.println(data);//我需要的天气数据
}
}
http.end();
}
void Get_Rencent_Weather(String api, String city)
{
while (WiFi.status() != WL_CONNECTED)
{
WiFi.begin(ssid, password);
vTaskDelay(100);
}
String url_xinzhi = "";
url_xinzhi = "https://api.seniverse.com/v3/weather/daily.json?key=";
url_xinzhi += api;
url_xinzhi += "&location=";
url_xinzhi += city;
url_xinzhi += "&language=en&unit=c";
url_xinzhi += "&start=0&days=3";
DynamicJsonDocument doc(2048); //分配内存,动态
HTTPClient http;
char data[100] = {"#W:"};
http.begin(url_xinzhi);
int httpGet = http.GET();
if (httpGet > 0)
{
if (httpGet == HTTP_CODE_OK)
{
String json = http.getString();
//Serial.println(json); //打印接收到的消息
deserializeJson(doc, json);
// JsonObject root = doc.as();
// JsonArray results = root["results"];
// const char *a = results[0]["last_update"];
// const char *b = results[0]["daily"][0]["text_day"];
/* 从doc 中提取出 需要的数据 */
/* code_day白天天气码,code_night晚上天气码 */
strcat(data, doc["results"][0]["daily"][0]["code_day"].as());
strcat(data, ":");
strcat(data, doc["results"][0]["daily"][1]["code_day"].as());
strcat(data, ":");
strcat(data, doc["results"][0]["daily"][2]["code_day"].as());
strcat(data, ":");
strcat(data, doc["results"][0]["daily"][0]["code_night"].as());
strcat(data, ":");
strcat(data, doc["results"][0]["daily"][1]["code_night"].as());
strcat(data, ":");
strcat(data, doc["results"][0]["daily"][2]["code_night"].as());
strcat(data, "$");
Serial.println(data);
}
}
http.end();
}
/*BUG
如果程序编译没有报错, 并且烧录成功后,
不止一次,多次弹出/打印出 下面文本
这个其实就是 ESP32 Reset/复位时 会打印的信息
多次复位, 多为代码逻辑问题,引起了ESP32自动复位
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ets Jun 8 2016 00:22:57
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:1184
load:0x40078000,len:13132
load:0x40080400,len:3036
entry 0x400805e4
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
如果是自带usb串口 的开发板,(烧录超级简单的示例程序 可以正常运行,说明板子一般是没问题的)
那么可以肯定,(坚信不疑)
一定(多数情况下)是: 代码的逻辑问题
包括但不限于 变量生命周期错判,赋值时内存溢出,野指针,形参实参 数据类型错用,.........,
看个人习惯了,这种错误一不留神就找出来了
----------------------------------------------------------
检错步骤(建议):
1.代码最好 功能化,模块化
2.在 setup 函数第一句/最开始就 delay(5000);//延时5s
3.在每一段代码块中,多设置例如
Serial.println("标签 1.1 ##"); 的语句, 设置
4.烧录完成后即刻打开串口,观察串口输出数据
观察 自己设置的标签, 清楚知道程序运行到哪里了
5.这时,突然打印出-上述文本-, 观察相隔最近的标签, 就是这附近出毛病了,
6.修改完成成后,再次烧录运行,观察是否能正常运行到下一个标签处
-------------------------------------------------------------------------
分享下自己找了一天的bug,
正常的
String json = http.getString();
deserializeJson(doc, json);
错误的
deserializeJson(doc, http.getString());
可能原因:
http.getString() 返回类型为 string算是个数组, c++/c 函数 返回 |函数内定义的| 数组类型数据,存不住,生命周期太短了,
https://blog.csdn.net/qq_41989885/article/details/104932634
*/
心知天气返回数据
获取今日天气 url
可以直接在 浏览器上面的访问框内输入这个 url,看看浏览器中显示的内容就是 返回数据
https: //api.seniverse.com/v3/weather/now.json?key=SJ3cQqGjCfr2Ej1oS&location=luoyang&language=en&unit=c&start=0&days=5
返回数据
HTTPGET is 200 //请求成功才返回下面数据
{
"results": [
{
"location": {
"id": "WQPUYY7S4GV2",
"name": "Luoyang",
"country": "CN",
"path": "Luoyang,Luoyang,Henan,China",
"timezone": "Asia/Shanghai",
"timezone_offset": "+08:00"
},
"now": {
"text": "Cloudy",
"code": "4",
"temperature": "29"
},
"last_update": "2022-08-02T12:34:30+08:00"
}
]
}
获取今日起三天天气 url
//非vip用户最多获取近三日天气数据,记得自己注册一个心知天气账号,修改下 API ,也就是?
可以直接在 浏览器上面的访问框内输入这个 url,看看浏览器中显示的内容就是 返回数据
key=SJ3cQqGjCfr2Ej1oS ,这个要改称自己账号的API 私钥
https: //api.seniverse.com/v3/weather/now.json?key=SJ3cQqGjCfr2Ej1oS&location=luoyang&language=en&unit=c&start=0&days=3
返回数据
HTTPGET is 200 //请求成功才返回下面数据
{
"results": [
{
"location": {
"id": "WQPUYY7S4GV2",
"name": "Luoyang",
"country": "CN",
"path": "Luoyang,Luoyang,Henan,China",
"timezone": "Asia/Shanghai",
"timezone_offset": "+08:00"
},
"daily": [
{
"date": "2022-08-02",
"text_day": "Shower",
"code_day": "10",
"text_night": "Cloudy",
"code_night": "4",
"high": "34",
"low": "24",
"rainfall": "5.40",
"precip": "0.96",
"wind_direction": "SE",
"wind_direction_degree": "135",
"wind_speed": "8.4",
"wind_scale": "2",
"humidity": "81"
},
{
"date": "2022-08-03",
"text_day": "Shower",
"code_day": "10",
"text_night": "Cloudy",
"code_night": "4",
"high": "35",
"low": "25",
"rainfall": "5.40",
"precip": "0.96",
"wind_direction": "SE",
"wind_direction_degree": "135",
"wind_speed": "8.4",
"wind_scale": "2",
"humidity": "84"
},
{
"date": "2022-08-04",
"text_day": "Sunny",
"code_day": "0",
"text_night": "Clear",
"code_night": "1",
"high": "36",
"low": "26",
"rainfall": "0.00",
"precip": "0.00",
"wind_direction": "SE",
"wind_direction_degree": "135",
"wind_speed": "3.0",
"wind_scale": "1",
"humidity": "83"
}
],
"last_update": "2022-08-02T08:00:00+08:00"
}
]
}
https: //api.seniverse.com/v3/weather/daily.json?key=SJ3cQqGjCfr2Ej1oS&location=luoyang&language=en&unit=c&start=0&days=5
{
"results": [
{
"location": {
"id": "WQPUYY7S4GV2",
"name": "Luoyang",
"country": "CN",
"path": "Luoyang,Luoyang,Henan,China",
"timezone": "Asia/Shanghai",
"timezone_offset": "+08:00"
},
"now": {
"text": "Cloudy",
"code": "4",
"temperature": "31"
},
"last_update": "2022-08-02T13:24:14+08:00"
}
]
}
{
"results": [
{
"location": {
"id": "WQPUYY7S4GV2",
"name": "Luoyang",
"country": "CN",
"path": "Luoyang,Luoyang,Henan,China",
"timezone": "Asia/Shanghai",
"timezone_offset": "+08:00"
},
"daily": [
{
"date": "2022-08-02",
"text_day": "Shower",
"code_day": "10",
"text_night": "Cloudy",
"code_night": "4",
"high": "34",
"low": "24",
"rainfall": "5.40",
"precip": "0.96",
"wind_direction": "SE",
"wind_direction_degree": "135",
"wind_speed": "8.4",
"wind_scale": "2",
"humidity": "81"
},
{
"date": "2022-08-03",
"text_day": "Shower",
"code_day": "10",
"text_night": "Cloudy",
"code_night": "4",
"high": "35",
"low": "25",
"rainfall": "5.40",
"precip": "0.96",
"wind_direction": "SE",
"wind_direction_degree": "135",
"wind_speed": "8.4",
"wind_scale": "2",
"humidity": "84"
},
{
"date": "2022-08-04",
"text_day": "Sunny",
"code_day": "0",
"text_night": "Clear",
"code_night": "1",
"high": "36",
"low": "26",
"rainfall": "0.00",
"precip": "0.00",
"wind_direction": "SE",
"wind_direction_degree": "135",
"wind_speed": "3.0",
"wind_scale": "1",
"humidity": "83"
}
],
"last_update": "2022-08-02T08:00:00+08:00"
}
]
}
还有一篇和这个有关
vscode Ardunio PlatformIO导入自己写的.c.h文件的正确方法_—=-_-=—的博客-CSDN博客
心知天气 常用接口:
天气实况 · 心知天气获取指定城市的天气实况。付费用户可获取全部数据,免费用...https://seniverse.yuque.com/books/share/e52aa43f-8fe9-4ffa-860d-96c0f3cf1c49/nyiu3t
未来15天逐日天气预报和昨日天气 · 心知天气获取指定城市未来最多 15 天每天的白天和夜间预报,以...https://seniverse.yuque.com/books/share/e52aa43f-8fe9-4ffa-860d-96c0f3cf1c49/sl6gvt
整点实况 · 心知天气获取全国所有市区县(3000+)的天气实况数据更新频率...https://seniverse.yuque.com/books/share/e52aa43f-8fe9-4ffa-860d-96c0f3cf1c49/weather_obs