2576|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
  }
}

 

此帖出自RF/无线论坛

最新回复

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

回复
举报

6802

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

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

此帖出自RF/无线论坛
 
 

回复

7159

帖子

2

TA的资源

版主

板凳
 

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

此帖出自RF/无线论坛

点评

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

回复

6040

帖子

203

TA的资源

版主

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

地址信息在请求的url里面

此帖出自RF/无线论坛

点评

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

回复

7159

帖子

2

TA的资源

版主

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

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

此帖出自RF/无线论坛

点评

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

回复

155

帖子

1

TA的资源

一粒金砂(高级)

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

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

此帖出自RF/无线论坛
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

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