модуль Погоды owm

This commit is contained in:
Mit4el
2023-10-06 00:21:14 +03:00
parent 428b8f166b
commit dec76ed367
4 changed files with 324 additions and 0 deletions

View File

@@ -15,5 +15,6 @@ extern const String getDateTimeDotFormated();
extern const String getTodayDateDotFormated(); extern const String getTodayDateDotFormated();
extern unsigned long strDateToUnix(String date); extern unsigned long strDateToUnix(String date);
extern const String getDateTimeDotFormatedFromUnix(unsigned long unixTime); extern const String getDateTimeDotFormatedFromUnix(unsigned long unixTime);
extern const String getTimeDotFormatedFromUnix(unsigned long unixTime);
extern unsigned long gmtTimeToLocal(unsigned long gmtTimestamp); extern unsigned long gmtTimeToLocal(unsigned long gmtTimestamp);
extern const String getDateDotFormatedFromUnix(unsigned long unixTime); extern const String getDateDotFormatedFromUnix(unsigned long unixTime);

View File

@@ -184,6 +184,14 @@ const String getDateTimeDotFormatedFromUnix(unsigned long unixTime) {
return String(buf); return String(buf);
} }
const String getTimeDotFormatedFromUnix(unsigned long unixTime) {
Time_t time;
breakEpochToTime(unixTime, time);
char buf[32];
sprintf(buf, "%02d:%02d:%02d", time.hour, time.minute, time.second);
return String(buf);
}
const String getDateDotFormatedFromUnix(unsigned long unixTime) { const String getDateDotFormatedFromUnix(unsigned long unixTime) {
Time_t time; Time_t time;
breakEpochToTime(unixTime, time); breakEpochToTime(unixTime, time);

View File

@@ -0,0 +1,82 @@
{
"menuSection": "virtual_elments",
"configItem": [
{
"global": 0,
"name": "Погода OWM",
"type": "Reading",
"subtype": "owmWeather",
"id": "owm",
"needSave": 0,
"widget": "nil",
"page": "Погода",
"descr": "Температура на улице",
"int": 30,
"API_key": "",
"сity": "Moscow",
"lon": "37.54",
"lat": "57.74",
"lang": "ru",
"param": "",
"round": 1,
"val": "...",
"debug": 0
}
],
"about": {
"authorName": "Serghei Crasnicov, v2.0 Mikhail Bubnov",
"authorContact": "https://t.me/Serghei63",
"authorGit": "https://github.com/Serghei63",
"specialThanks": "AVAKS",
"moduleName": "owmWeather",
"moduleVersion": "2.0",
"usedRam": {
"esp32_4mb": 15,
"esp8266_4mb": 15
},
"subTypes": [
"temp",
"humidity",
"pressure",
"speed",
"deg",
"all",
"main",
"description",
"icon",
"sunrise",
"sunset",
"name"
],
"title": "Погода",
"moduleDesc": "Получение погоды из интернет OpenWeatherMap",
"propInfo": {
"param": "Тип текущего Item: temp - температура, humidity - влажность, pressure - давление, speed - скорость ветра, deg - направление ветра, all - процент облачности, sunrise - рассвет, sunset - закат, description - Погодные условия, icon - код иконки, name - город. Если оставить пустым пудет искать и публиковать при изменении в Items с именами wea_temp и т.д. wea_...",
"int": "Интервал запроса погоды в минутах",
"API_key": "API ключ",
"сity": "Название города, через запятую можно уочнить код страны. Наример Moscow или Moscow,ru или Москва. Если город не задан будут использоваться координаты. OWM рекомендует координаты",
"lon": "Долгота, при использовании координат, будет автоматически выбран ближайший город",
"lat": "Широта, при использовании координат, будет автоматически выбран ближайший город",
"lang": "Язык используемый в ответах OpenWetaherMap",
"debug":"1 - выводить дополнительный лог в сериал"
}
},
"defActive": true,
"usedLibs": {
"esp32_4mb": [],
"esp32s2_4mb": [],
"esp32_16mb": [],
"esp8266_4mb": [],
"esp8266_16mb": [],
"esp8266_1mb": [],
"esp8266_1mb_ota": [],
"esp8285_1mb": [],
"esp8285_1mb_ota": [],
"esp8266_2mb": [],
"esp8266_2mb_ota": []
}
}

View File

@@ -0,0 +1,233 @@
#include "Global.h"
#include "classes/IoTItem.h"
#include <ArduinoJson.h>
#include "NTP.h"
// long prevWeatherMillis = millis() - 60001;
// TODO Зачем так много???
StaticJsonDocument<JSON_BUFFER_SIZE * 2> Weatherdoc1;
extern IoTGpio IoTgpio;
class owmWeather : public IoTItem
{
private:
// описание параметров передаваемых из настроек датчика из веба
String _location;
String _param;
// long interval;
String _API_key;
String _сity = "";
String _lat = "";
String _lon = "";
String _lang = "";
bool _debug = false;
public:
owmWeather(String parameters) : IoTItem(parameters)
{
_API_key = jsonReadStr(parameters, "API_key");
// _ID_sity = jsonReadStr(parameters, "ID_sity");
_сity = jsonReadStr(parameters, "сity");
_lon = jsonReadStr(parameters, "lon");
_lat = jsonReadStr(parameters, "lat");
_lang = jsonReadStr(parameters, "lang");
_param = jsonReadStr(parameters, "param");
jsonRead(parameters, "debug", _debug);
long interval;
jsonRead(parameters, F("int"), interval); // в минутах
setInterval(interval * 60);
}
void getWeather()
{
String ret;
if (isNetworkActive())
{
String urlReq;
if (_сity != "")
{
// Для нового API
// request = "http://api.openweathermap.org/geo/1.0/direct?q=" _сity + "&limit=1&appid=" + _API_key;
// Устарело, но пока работает
urlReq = "http://api.openweathermap.org/data/2.5/weather?q=" + _сity + "&units=metric&lang=" + _lang + "&appid=" + _API_key;
}
else
{
// Получаем название города по координатам. Новый API
// request = "http://api.openweathermap.org/geo/1.0/reverse?lat=" + _lat + "&lon=" + _lon + "&limit=1&appid=" + _API_key;
//[0].local_names:{ru:Москва,...}
urlReq = "http://api.openweathermap.org/data/2.5/weather?lat=" + _lat + "&lon=" + _lon + "&units=metric&lang=" + _lang + "&appid=" + _API_key;
}
WiFiClient client;
HTTPClient http;
String payload;
bool find = false;
http.setTimeout(500);
http.begin(client, urlReq); // urlCurrent
// http.begin(client, "http://api.openweathermap.org/data/2.5/weather?id=" + _ID_sity + "&appid=" + _API_key + "&units=metric");
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
int httpCode = http.GET();
if (httpCode > 0)
{
ret = httpCode;
if (httpCode == HTTP_CODE_OK)
{
payload = http.getString();
deserializeJson(Weatherdoc1, payload);
ret += payload;
}
}
else
{
ret = http.errorToString(httpCode).c_str();
}
if (_debug)
{
SerialPrint("<-", F("getOwmWeather"), urlReq);
SerialPrint("->", F("getOwmWeather"), "server: " + ret);
}
http.end();
}
}
void doByInterval()
{
getWeather();
if (jsonReadStr(Weatherdoc1["main"], "temp", true) != "null")
{
publishNew("main", "temp");
publishNew("main", "pressure");
publishNew("main", "humidity");
publishNew("wind", "speed");
publishNew("wind", "deg");
publishNew("clouds", "all");
publishNew("weather", "main");
publishNew("weather", "description");
publishNew("weather", "icon");
publishNew("sys", "sunrise");
publishNew("sys", "sunset");
publishNew("", "name");
if (_param == "temp")
{
value.valS = jsonReadStr(Weatherdoc1["main"], "temp", true);
}
else if (_param == "pressure")
{
value.valS = jsonReadStr(Weatherdoc1["main"], "pressure", true);
}
else if (_param == "humidity")
{
value.valS = jsonReadStr(Weatherdoc1["main"], "humidity", true);
}
else if (_param == "speed")
{
value.valS = jsonReadStr(Weatherdoc1["wind"], "speed", true);
}
else if (_param == "deg")
{
value.valS = jsonReadStr(Weatherdoc1["wind"], "deg", true);
}
else if (_param == "all")
{
value.valS = jsonReadStr(Weatherdoc1["clouds"], "all", true);
}
else if (_param == "main")
{
value.valS = jsonReadStr(Weatherdoc1["weather"][0], "main", true);
}
else if (_param == "description")
{
value.valS = jsonReadStr(Weatherdoc1["weather"][0], "description", true);
}
else if (_param == "icon")
{
value.valS = jsonReadStr(Weatherdoc1["weather"][0], "icon", true);
}
else if (_param == "sunrise")
{
value.valS = getTimeDotFormatedFromUnix(std::atoll(jsonReadStr(Weatherdoc1["sys"], "sunrise", true).c_str()));
}
else if (_param == "sunset")
{
value.valS = getTimeDotFormatedFromUnix(std::atoll(jsonReadStr(Weatherdoc1["sys"], "sunset", true).c_str()));
}
else if (_param == "sunset")
{
value.valS = Weatherdoc1["name"].as<String>();
}
// value.isDecimal = false;
regEvent(value.valS, "owmWeather");
}
}
IoTValue execute(String command, std::vector<IoTValue> &param)
{
if (command == "get")
{
// getWeather();
doByInterval();
}
return {};
}
// проверяем если пришедшее значение отличается от предыдущего регистрируем событие
static void publishNew(String root, String param)
{
IoTItem *tmp = findIoTItem("wea_" + param);
if (!tmp)
return;
if (root == "weather")
{
if (Weatherdoc1[root][0][param].as<String>() != tmp->value.valS)
{
tmp->setValue(Weatherdoc1[root][0][param].as<String>(), true);
}
}
else if (root == "")
{
if (Weatherdoc1[param].as<String>() != tmp->value.valS)
{
tmp->setValue(Weatherdoc1[param].as<String>(), true);
}
}
else if (root == "sys")
{
if (Weatherdoc1[root][param].as<String>() != tmp->value.valS)
{
tmp->setValue(getTimeDotFormatedFromUnix(std::atoll(jsonReadStr(Weatherdoc1[root], param, true).c_str())), true);
}
}
else
{
if (Weatherdoc1[root][param].as<String>() != tmp->value.valS)
{
tmp->setValue(Weatherdoc1[root][param].as<String>(), true);
}
}
}
~owmWeather(){};
};
void *getAPI_owmWeather(String subtype, String param)
{
if (subtype == F("owmWeather"))
{
return new owmWeather(param);
}
else
{
return nullptr;
}
}