本篇记录一个案例,功能为:连接Wi-Fi,网络授时,开启定时器(1s),每分钟(整分钟)串口输出一次时间,每5分钟输出一次实时天气信息。
1、请求天气
请求天气是通过“心知天气”站点,需要使用者自行注册并获取api_key。相关注册和使用过程,这里就不啰嗦了,不清楚的朋友可以自己到官网上查看(https://www.seniverse.com/)。
本例仅测试实时天气数据获取,天气相关数据只有“状态(晴朗之类)”和“气温”,请求接口地址如下:
https://api.seniverse.com/v3/weather/now.json?key=your_api_key&location=beijing&language=zh-Hans&unit=c
请求天气使用ESP32-Arduino的HTTPClient实例,获取的天气数据为JSON格式,因此案例加载了ArduinoJson库,装得比较早版本是6.18.5,看更新提示最新版是6.19.4了。
图7-1 库安装
图7-2 心知天气返回的JSON格式
2、天气案例代码
- #include <Arduino.h>
- #include <WiFi.h>
- #include <WiFiMulti.h>
- #include <HTTPClient.h>
- #include <ArduinoJson.h>
-
-
- const char *ssid = "yourssid";
- const char *password = "yourpsw";
-
-
- const char *ntpServer = "pool.ntp.org";
- const long gmtOffset_sec = 14400;
- const int daylightOffset_sec = 14400;
- struct tm t;
- void printLocalTime(void);
-
-
- #define INMIN 0x60
- #define ONEMIN 0x61
- hw_timer_t *timer = NULL;
- volatile SemaphoreHandle_t timersem;
- void IRAM_ATTR onTimer(void);
- void initTimer(void);
- static uint8_t timestate = INMIN;
-
-
- DynamicJsonDocument doc(1024);
- const char *url = "https://api.thinkpage.cn/v3/weather/now.json?key=your_api_key&location=tianjin&language=en&unit=c";
- void getWeather(void);
-
- void setup() {
- Serial.begin(115200);
-
- WiFi.begin(ssid, password);
- while (WiFi.status() != WL_CONNECTED) {
- delay(500);
- Serial.print(".");
- }
-
- Serial.println(" CONNECTED");
- Serial.print("IP address: ");
- Serial.println(WiFi.localIP());
-
- configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
- if(!getLocalTime(&t)){
- Serial.println("Failed to obtain time");
- return;
- } else {
- Serial.println(&t, "%A, %B %d %Y %H:%M:%S");
- initTimer();
- }
- }
-
- void loop() {
-
- if(xSemaphoreTake(timersem, 0) == pdTRUE) {
- if((t.tm_sec)++ >= 59) timestate = ONEMIN;
- }
-
- if(timestate == ONEMIN) {
- timestate = INMIN;
- if(WiFi.status() == WL_CONNECTED) {
- printLocalTime();
- if(t.tm_min%5 == 0) getWeather();
- }
- }
- }
-
-
- void printLocalTime() {
- if(!getLocalTime(&t)) {
- Serial.println("Failed to obtain time");
- return;
- }
- Serial.println(&t, "%F %T %A");
- }
-
- void IRAM_ATTR onTimer() {
- xSemaphoreGiveFromISR(timersem, NULL);
- }
-
- void initTimer() {
- timersem = xSemaphoreCreateBinary();
-
-
-
- timer = timerBegin(0, 80, true);
- timerAttachInterrupt(timer, &onTimer, true);
- timerAlarmWrite(timer, 1000000, true);
- timerAlarmEnable(timer);
- }
-
- void getWeather() {
- if((WiFi.status() == WL_CONNECTED)) {
- HTTPClient http;
- http.begin(url);
- int httpCode = http.GET();
- if(httpCode > 0) {
- Serial.printf("[HTTP] GET... code: %d\n", httpCode);
- if(httpCode == HTTP_CODE_OK) {
- String payload = http.getString();
- Serial.println(payload);
-
- deserializeJson(doc, payload);
-
- JsonObject obj = doc.as<JsonObject>();
-
- JsonVariant resultsvar = obj["results"];
- JsonArray resultsarr = resultsvar.as<JsonArray>();
-
- JsonVariant resultselementvar = resultsarr[0];
- JsonObject resultselementobj = resultselementvar.as<JsonObject>();
-
- JsonVariant namevar = resultselementobj["location"]["name"];
- String namestr = namevar.as<String>();
- Serial.println(namestr);
-
- JsonVariant temperaturevar = resultselementobj["now"]["temperature"];
- String temperaturestr = temperaturevar.as<String>();
- Serial.println(temperaturestr);
-
- JsonVariant last_updatevar = resultselementobj["last_update"];
- String last_updatestr = last_updatevar.as<String>();
- Serial.println(last_updatestr);
- }
- } else {
- Serial.printf("[HTTP] GET... failed, error: %s\n",
- http.errorToString(httpCode).c_str());
- }
- http.end();
- }
- }
-
-