前篇使用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);
}
发表评论