Jay
Jay

ESP8266-通过调用天气API以及DHT11输出天气信息

前篇使用ESP8266制作了下雨自动警报器,现在尝试加入天气信息(API和DHT11)

这里用的API来自和风天气,免费版的API勉强够用。天气API接口说明

Arduino IDE库配置

由于API返回的是一个JSON,所以我们需要安装ArduinoJson库

DHT11也需要安装相应的库,我选择的是(图片丢失23333

代码编写

和风天气的API是HTTPS的,所以我们需要引入SSL

#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>
// Fingerprint for demo URL, expires on June 2, 2021, needs to be updated well before this date
const uint8_t fingerprint[20] = {0x40, 0xaf, 0x00, 0x6b, 0xec, 0x90, 0x22, 0x41, 0x8e, 0xa3, 0xad, 0xfa, 0x1a, 0xe8, 0x25, 0x41, 0x1d, 0x1a, 0x54, 0xb3};

很显然,这里的指纹我们是无法使用的,所以这里我们使用不安全的连接(在有敏感信息的环境下不建议使用)

//client->setFingerprint(fingerprint);
client->setInsecure();

JSON的解析使用https://arduinojson.org/v6/assistant/

手动请求一遍API,将返回的JSON复制到这个网站上就能生成对应的代码。

const size_t capacity = JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(8) + JSON_OBJECT_SIZE(13) + 350;
  DynamicJsonDocument doc(capacity);
  deserializeJson(doc, data);
  JsonObject HeWeather6_0 = doc["HeWeather6"][0];
  JsonObject HeWeather6_0_basic = HeWeather6_0["basic"];
  const char *HeWeather6_0_basic_cid = HeWeather6_0_basic["cid"];                 
  const char *HeWeather6_0_basic_location = HeWeather6_0_basic["location"];       
  const char *HeWeather6_0_basic_parent_city = HeWeather6_0_basic["parent_city"];
  const char *HeWeather6_0_basic_admin_area = HeWeather6_0_basic["admin_area"];
  const char *HeWeather6_0_basic_cnty = HeWeather6_0_basic["cnty"];
  const char *HeWeather6_0_basic_lat = HeWeather6_0_basic["lat"];                 
  const char *HeWeather6_0_basic_lon = HeWeather6_0_basic["lon"];                 
  const char *HeWeather6_0_basic_tz = HeWeather6_0_basic["tz"];                   
  const char *HeWeather6_0_update_loc = HeWeather6_0["update"]["loc"];  
  const char *HeWeather6_0_update_utc = HeWeather6_0["update"]["utc"];  
  const char *HeWeather6_0_status = HeWeather6_0["status"]; 
  JsonObject HeWeather6_0_now = HeWeather6_0["now"];
  const char *HeWeather6_0_now_cloud = HeWeather6_0_now["cloud"];
  const char *HeWeather6_0_now_cond_code = HeWeather6_0_now["cond_code"];
  const char *HeWeather6_0_now_cond_txt = HeWeather6_0_now["cond_txt"];
  const char *HeWeather6_0_now_fl = HeWeather6_0_now["fl"];
  const char *HeWeather6_0_now_hum = HeWeather6_0_now["hum"];
  const char *HeWeather6_0_now_pcpn = HeWeather6_0_now["pcpn"];
  const char *HeWeather6_0_now_pres = HeWeather6_0_now["pres"];
  const char *HeWeather6_0_now_tmp = HeWeather6_0_now["tmp"];
  const char *HeWeather6_0_now_vis = HeWeather6_0_now["vis"];
  const char *HeWeather6_0_now_wind_deg = HeWeather6_0_now["wind_deg"];
  const char *HeWeather6_0_now_wind_dir = HeWeather6_0_now["wind_dir"];
  const char *HeWeather6_0_now_wind_sc = HeWeather6_0_now["wind_sc"];
  const char *HeWeather6_0_now_wind_spd = HeWeather6_0_now["wind_spd"];

其中HeWeather6_0_now_cond_code为天气代码,天气代码查阅

HeWeather6_0_now_hum为湿度

HeWeather6_0_now_tmp为温度

DHT11 需要引入"DHTesp.h",下面是官方的实例

#include "DHTesp.h"

#ifdef ESP32
#pragma message(THIS EXAMPLE IS FOR ESP8266 ONLY!)
#error Select ESP8266 board.
#endif

DHTesp dht;

void setup()
{
  Serial.begin(115200);
  Serial.println();
  Serial.println("Status\tHumidity (%)\tTemperature (C)\t(F)\tHeatIndex (C)\t(F)");
  String thisBoard= ARDUINO_BOARD;
  Serial.println(thisBoard);

  // Autodetect is not working reliable, don't use the following line
  // dht.setup(17);
  // use this instead: 
  dht.setup(17, DHTesp::DHT22); // Connect DHT sensor to GPIO 17
}

void loop()
{
  delay(dht.getMinimumSamplingPeriod());

  float humidity = dht.getHumidity();
  float temperature = dht.getTemperature();

  Serial.print(dht.getStatusString());
  Serial.print("\t");
  Serial.print(humidity, 1);
  Serial.print("\t\t");
  Serial.print(temperature, 1);
  Serial.print("\t\t");
  Serial.print(dht.toFahrenheit(temperature), 1);
  Serial.print("\t\t");
  Serial.print(dht.computeHeatIndex(temperature, humidity, false), 1);
  Serial.print("\t\t");
  Serial.println(dht.computeHeatIndex(dht.toFahrenheit(temperature), humidity, true), 1);
  delay(2000);
}

请求JSON函数

void getweather()
{
  std::unique_ptr<BearSSL::WiFiClientSecure> client(new BearSSL::WiFiClientSecure);
  //client->setFingerprint(fingerprint);
  client->setInsecure();
  HTTPClient https;
  https.begin(*client, "https://free-api.heweather.net/s6/weather/now?location=你的城市代码&key=APIKEY");
  int httpCode = https.GET();
  if (httpCode > 0)
  {
    String payload = https.getString();
    handlejson(payload);
  }
  else
  {
    Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
  }
  https.end();
}

处理JSON函数

void handlejson(String data)
{
  const size_t capacity = JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(8) + JSON_OBJECT_SIZE(13) + 350;
  DynamicJsonDocument doc(capacity);
  deserializeJson(doc, data);
  JsonObject HeWeather6_0 = doc["HeWeather6"][0];
  JsonObject HeWeather6_0_basic = HeWeather6_0["basic"];
  const char *HeWeather6_0_basic_cid = HeWeather6_0_basic["cid"];
  const char *HeWeather6_0_basic_location = HeWeather6_0_basic["location"];
  const char *HeWeather6_0_basic_parent_city = HeWeather6_0_basic["parent_city"];
  const char *HeWeather6_0_basic_admin_area = HeWeather6_0_basic["admin_area"];
  const char *HeWeather6_0_basic_cnty = HeWeather6_0_basic["cnty"];
  const char *HeWeather6_0_basic_lat = HeWeather6_0_basic["lat"];
  const char *HeWeather6_0_basic_lon = HeWeather6_0_basic["lon"];
  const char *HeWeather6_0_basic_tz = HeWeather6_0_basic["tz"]; 
  const char *HeWeather6_0_update_loc = HeWeather6_0["update"]["loc"];
  const char *HeWeather6_0_update_utc = HeWeather6_0["update"]["utc"];
  const char *HeWeather6_0_status = HeWeather6_0["status"]; // "ok"
  JsonObject HeWeather6_0_now = HeWeather6_0["now"];
  const char *HeWeather6_0_now_cloud = HeWeather6_0_now["cloud"];
  const char *HeWeather6_0_now_cond_code = HeWeather6_0_now["cond_code"];
  const char *HeWeather6_0_now_cond_txt = HeWeather6_0_now["cond_txt"];
  const char *HeWeather6_0_now_fl = HeWeather6_0_now["fl"];
  const char *HeWeather6_0_now_hum = HeWeather6_0_now["hum"];
  const char *HeWeather6_0_now_pcpn = HeWeather6_0_now["pcpn"];
  const char *HeWeather6_0_now_pres = HeWeather6_0_now["pres"];
  const char *HeWeather6_0_now_tmp = HeWeather6_0_now["tmp"];
  const char *HeWeather6_0_now_vis = HeWeather6_0_now["vis"];
  const char *HeWeather6_0_now_wind_deg = HeWeather6_0_now["wind_deg"];
  const char *HeWeather6_0_now_wind_dir = HeWeather6_0_now["wind_dir"];
  const char *HeWeather6_0_now_wind_sc = HeWeather6_0_now["wind_sc"];
  const char *HeWeather6_0_now_wind_spd = HeWeather6_0_now["wind_spd"];
}

成品:

#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include "DHTesp.h"
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>
//const uint8_t fingerprint[20] = {0x40, 0xaf, 0x00, 0x6b, 0xec, 0x90, 0x22, 0x41, 0x8e, 0xa3, 0xad, 0xfa, 0x1a, 0xe8, 0x25, 0x41, 0x1d, 0x1a, 0x54, 0xb3};
#define LED 2
#ifndef STASSID
#define STASSID "WIFI"
#define STAPSK "KEY"
#endif
int issend=0;
DHTesp dht;
int loopcount=150;
//-----WiFi settings------------
const char *ssid = STASSID;
const char *password = STAPSK;
//------------------------------
String key = "KEY"; 
//String key2 = "KEY";
//sever酱获取的key
//--------天气变量---------
int getweather();
String temp;
String hum;
//------------------------
void setup()
{
  Serial.begin(115200);
  pinMode(LED, OUTPUT);
  digitalWrite(LED, 0);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println("Status\tHumidity (%)\tTemperature (C)\t(F)\tHeatIndex (C)\t(F)");
  dht.setup(14, DHTesp::DHT11); // 连接DHT11到GPIO14
  delay(dht.getMinimumSamplingPeriod());
  float humidity = dht.getHumidity();
  float temperature = dht.getTemperature();
  Serial.print(dht.getStatusString());
  Serial.print("\t");
  Serial.print(humidity, 1);
  Serial.print("\t\t");
  Serial.print(temperature, 1);
  Serial.print("\t\t");
  Serial.print(dht.toFahrenheit(temperature), 1);
  Serial.print("\t\t");
  Serial.print(dht.computeHeatIndex(temperature, humidity, false), 1);
  Serial.print("\t\t");
  Serial.println(dht.computeHeatIndex(dht.toFahrenheit(temperature), humidity, true), 1);
  
}
int handlejson(String data)
{
  const size_t capacity = JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(8) + JSON_OBJECT_SIZE(13) + 350;
  DynamicJsonDocument doc(capacity);
  deserializeJson(doc, data);
  JsonObject HeWeather6_0 = doc["HeWeather6"][0];
  JsonObject HeWeather6_0_basic = HeWeather6_0["basic"];
  const char *HeWeather6_0_basic_cid = HeWeather6_0_basic["cid"];
  const char *HeWeather6_0_basic_location = HeWeather6_0_basic["location"];
  const char *HeWeather6_0_basic_parent_city = HeWeather6_0_basic["parent_city"];
  const char *HeWeather6_0_basic_admin_area = HeWeather6_0_basic["admin_area"];
  const char *HeWeather6_0_basic_cnty = HeWeather6_0_basic["cnty"];
  const char *HeWeather6_0_basic_lat = HeWeather6_0_basic["lat"];
  const char *HeWeather6_0_basic_lon = HeWeather6_0_basic["lon"];
  const char *HeWeather6_0_basic_tz = HeWeather6_0_basic["tz"];
  const char *HeWeather6_0_update_loc = HeWeather6_0["update"]["loc"];
  const char *HeWeather6_0_update_utc = HeWeather6_0["update"]["utc"];
  const char *HeWeather6_0_status = HeWeather6_0["status"];
  JsonObject HeWeather6_0_now = HeWeather6_0["now"];
  const char *HeWeather6_0_now_cloud = HeWeather6_0_now["cloud"];
  const char *HeWeather6_0_now_cond_code = HeWeather6_0_now["cond_code"];
  const char *HeWeather6_0_now_cond_txt = HeWeather6_0_now["cond_txt"];
  const char *HeWeather6_0_now_fl = HeWeather6_0_now["fl"];
  const char *HeWeather6_0_now_hum = HeWeather6_0_now["hum"];
  const char *HeWeather6_0_now_pcpn = HeWeather6_0_now["pcpn"];
  const char *HeWeather6_0_now_pres = HeWeather6_0_now["pres"];
  const char *HeWeather6_0_now_tmp = HeWeather6_0_now["tmp"];
  const char *HeWeather6_0_now_vis = HeWeather6_0_now["vis"];
  const char *HeWeather6_0_now_wind_deg = HeWeather6_0_now["wind_deg"];
  const char *HeWeather6_0_now_wind_dir = HeWeather6_0_now["wind_dir"];
  const char *HeWeather6_0_now_wind_sc = HeWeather6_0_now["wind_sc"];
  const char *HeWeather6_0_now_wind_spd = HeWeather6_0_now["wind_spd"];
  //Serial.print(HeWeather6_0_now_cond_code);
  temp=HeWeather6_0_now_tmp;
  hum=HeWeather6_0_now_hum;
  if((int)HeWeather6_0_now_cond_code>=300&&(int)HeWeather6_0_now_cond_code<400)
    return 1;
  else
    return 0;
}
int getweather()
{
  std::unique_ptr<BearSSL::WiFiClientSecure> client(new BearSSL::WiFiClientSecure);
  //client->setFingerprint(fingerprint);
  client->setInsecure();
  HTTPClient https;
  https.begin(*client, "https://free-api.heweather.net/s6/weather/now?location=&key=KEY");
  int httpCode = https.GET();
  if (httpCode > 0)
  {
    String payload = https.getString();
    return handlejson(payload);
  }
  else
  {
    Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
  }
  https.end();
}
void wechat(String title, String message)
{
  HTTPClient http;
  //发送post请求,把消息发出去
  http.begin("http://sc.ftqq.com/" + key + ".send?text=" + title + "&desp=" + message);
  //http.begin("http://sc.ftqq.com/" + key2 + ".send?text=" + title + "&desp=" + message);
  int httpCode = http.GET();
  http.end();
  Serial.println("done");
  //结束
}

void loop()
{
  digitalWrite(LED, 1);
  int sensorValue = analogRead(A0);
  delay(dht.getMinimumSamplingPeriod());
  float humidity = dht.getHumidity();
  float temperature = dht.getTemperature();
  if (loopcount==150)
  {
    if(getweather()==1)
    {
      Serial.println("天气预报显示有雨,当前气温"+temp+",当前湿度"+hum);
    }
    else
    {
      Serial.println("天气预报显示无雨,当前气温"+temp+",当前湿度"+hum);
    }
    loopcount=0;
  }
  if (sensorValue < 888 && issend==0)
  {
    int tmp = getweather();
    if(getweather()==1&&loopcount==150)
      wechat("可能下雨了", "传感器表面可能有水或者下雨了,请检查%0D%0A%0D%0A天气预报显示有雨,当前气温"+temp+"℃,当前湿度"+hum+"%%0D%0A%0D%0A传感器报告现在温度"+temperature+"℃,当前湿度"+humidity+"%");
    else
      wechat("可能下雨了", "传感器表面可能有水或者下雨了,请检查%0D%0A%0D%0A天气预报显示无雨,当前气温"+temp+"℃,当前湿度"+hum+"%%0D%0A%0D%0A传感器报告现在温度"+temperature+"℃,当前湿度"+humidity+"%");
    issend=1;
  }
  if(loopcount==60)
    issend=0;
  loopcount++;
  delay(2000);
}

没有标签
首页      学习记录      ESP8266-通过调用天气API以及DHT11输出天气信息

发表评论

textsms
account_circle
email

Jay

ESP8266-通过调用天气API以及DHT11输出天气信息
前篇使用ESP8266制作了下雨自动警报器,现在尝试加入天气信息(API和DHT11) 这里用的API来自和风天气,免费版的API勉强够用。天气API接口说明 Arduino IDE库配置 …
扫描二维码继续阅读
2020-06-10