2782|5

155

帖子

1

TA的资源

一粒金砂(高级)

楼主
 

【Beetle ESP32-C3】七、网络授时和请求天气(Arduino) [复制链接]

       本篇记录一个案例,功能为:连接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>
  • //-----SSID & password
  • const char *ssid = "yourssid"; //WIFI名称
  • const char *password = "yourpsw"; //密码
  • //-----NTP server & timezone offset
  • const char *ntpServer = "pool.ntp.org";
  • const long gmtOffset_sec = 14400; //3600*4 for UTC+8
  • const int daylightOffset_sec = 14400;
  • struct tm t; //time struct
  • void printLocalTime(void);
  • //-----timer HW per second
  • #define INMIN 0x60 //in 60s flag
  • #define ONEMIN 0x61 //one minute flag
  • hw_timer_t *timer = NULL; //timer variable
  • volatile SemaphoreHandle_t timersem; //timer fire sem
  • void IRAM_ATTR onTimer(void); //callback func
  • void initTimer(void);
  • static uint8_t timestate = INMIN; //flag variable
  • //-----weather server URL & instance for json parsing
  • DynamicJsonDocument doc(1024); //json doc instance
  • const char *url = "https://api.thinkpage.cn/v3/weather/now.json?key=your_api_key&location=tianjin&language=en&unit=c";
  • void getWeather(void); //request now weather func
  • void setup() {
  • Serial.begin(115200);
  • //-----connect AP
  • WiFi.begin(ssid, password);
  • while (WiFi.status() != WL_CONNECTED) {
  • delay(500);
  • Serial.print(".");
  • }
  • //-----print IP address
  • Serial.println(" CONNECTED");
  • Serial.print("IP address: ");
  • Serial.println(WiFi.localIP());
  • //-----initialize and get the time then initialize timer(per sec)
  • 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(); //timer init
  • }
  • }
  • void loop() {
  • //-----update time state per second
  • if(xSemaphoreTake(timersem, 0) == pdTRUE) {
  • if((t.tm_sec)++ >= 59) timestate = ONEMIN;
  • }
  • //-----print localtime per minute & weather info per 5 minutes
  • if(timestate == ONEMIN) {
  • timestate = INMIN;
  • if(WiFi.status() == WL_CONNECTED) {
  • printLocalTime();
  • if(t.tm_min%5 == 0) getWeather();
  • }
  • }
  • }
  • //-----print local time function
  • void printLocalTime() {
  • if(!getLocalTime(&t)) {
  • Serial.println("Failed to obtain time");
  • return;
  • }
  • Serial.println(&t, "%F %T %A");
  • }
  • //-----second timer callback function
  • void IRAM_ATTR onTimer() {
  • xSemaphoreGiveFromISR(timersem, NULL);
  • }
  • //-----intialize timer function
  • void initTimer() {
  • timersem = xSemaphoreCreateBinary();
  • //ESP32 sysclk is 80MHz.
  • //frequency division factor to 80,
  • //then timer clock is 1MHz.
  • timer = timerBegin(0, 80, true);
  • timerAttachInterrupt(timer, &onTimer, true);
  • timerAlarmWrite(timer, 1000000, true); //1000000us timer
  • timerAlarmEnable(timer);
  • }
  • //-----request now weather function
  • void getWeather() {
  • if((WiFi.status() == WL_CONNECTED)) {
  • HTTPClient http; //create HTTPClient instance
  • http.begin(url); //begin HTTP request
  • int httpCode = http.GET(); //get response code - normal:200
  • if(httpCode > 0) {
  • Serial.printf("[HTTP] GET... code: %d\n", httpCode);
  • if(httpCode == HTTP_CODE_OK) {
  • String payload = http.getString();
  • Serial.println(payload);
  • //parse response string to DynamicJsonDocument instance
  • deserializeJson(doc, payload);
  • //get top level Json-Object
  • JsonObject obj = doc.as<JsonObject>();
  • //get "results" property then parse the value to Json-Array
  • JsonVariant resultsvar = obj["results"];
  • JsonArray resultsarr = resultsvar.as<JsonArray>();
  • //get array index 0 which is now weather info
  • JsonVariant resultselementvar = resultsarr[0];
  • JsonObject resultselementobj = resultselementvar.as<JsonObject>();
  • //get city, temp, last_update time
  • 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(); //end http connectiong
  • }
  • }

 

查看本帖全部内容,请登录或者注册
此帖出自无线连接论坛

最新回复

看到了,我看用的是拼音,如果有重名的是不是会出问题。   详情 回复 发表于 2022-8-30 13:09
点赞 关注
 

回复
举报

7020

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

网络授时和请求天气功能测评的不错,期待后续

此帖出自无线连接论坛
 
 

回复

7515

帖子

2

TA的资源

版主

板凳
 

如何获取地区?自己输入地区信息吗?

此帖出自无线连接论坛

点评

地址信息在请求的url里面  详情 回复 发表于 2022-8-29 19:13
 
 
 

回复

6041

帖子

198

TA的资源

版主

4
 
wangerxian 发表于 2022-8-29 10:35 如何获取地区?自己输入地区信息吗?

地址信息在请求的url里面

此帖出自无线连接论坛

点评

看到了,我看用的是拼音,如果有重名的是不是会出问题。  详情 回复 发表于 2022-8-30 13:09
 
 
 

回复

7515

帖子

2

TA的资源

版主

5
 
lcofjp 发表于 2022-8-29 19:13 地址信息在请求的url里面

看到了,我看用的是拼音,如果有重名的是不是会出问题。

此帖出自无线连接论坛

点评

就是url请求参数,相关参数可以在心知天气网站查找,网站应该自己解决了重名问题吧(个人猜想)  详情 回复 发表于 2022-9-3 11:24
 
 
 

回复

155

帖子

1

TA的资源

一粒金砂(高级)

6
 
wangerxian 发表于 2022-8-30 13:09 看到了,我看用的是拼音,如果有重名的是不是会出问题。

就是url请求参数,相关参数可以在心知天气网站查找,网站应该自己解决了重名问题吧(个人猜想)

此帖出自无线连接论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
快速回复 返回顶部 返回列表