2 #include "AsyncHTTPRequest_Generic.h"
4 #include <ArduinoJson.h>
6 Ticker* weatherTicker = nullptr;
7 AsyncHTTPRequest request;
11 void executeWeatherRequest();
13 void IterateJson(JsonVariant json, const String& rootName, Config& lCfg);
15 void IterateJsonObject(JsonObject json, String rootName, Config& lCfg) {
16 for (JsonPair kv : json) {
17 IterateJson(kv.value(), rootName == "" ? String(kv.key().c_str()) : rootName + "." + String(kv.key().c_str()),lCfg);
21 void IterateJsonArray(JsonArray json, const String& rootName, Config& lCfg) {
22 for (int i = 0; i < json.size(); i++) {
23 IterateJson(json[i], rootName == "" ? "[" + String(i) + "]" : rootName + "." + "[" + String(i) + "]", lCfg);
27 void IterateJson(JsonVariant json, const String& rootName, Config& lCfg) {
28 if (json.is<JsonObject>()) {
29 IterateJsonObject(json.as<JsonObject>(), rootName, lCfg);
30 } else if (json.is<JsonArray>()) {
31 IterateJsonArray(json.as<JsonArray>(), rootName, lCfg);
33 lCfg.setValue(rootName.c_str(), json.as<String>().c_str());
37 void processTemplates(char* buf, const char* strTemplate, const Config& cfg, int maxLen) {
40 const char* ptr = strTemplate;
42 char* pos = strchr(ptr, '%');
44 strncat(buf, ptr, maxLen);
48 if (len + strlen(buf) >= maxLen) {
49 len = maxLen - strlen(buf);
51 int bufLen = strlen(buf);
52 strncpy(buf + bufLen, ptr, len);
54 char* endpos = strchr(pos+1, '%');
56 Serial.println(F("Незавершенное имя переменной"));
59 int varLen = (endpos-1) - (pos);
61 Serial.println(F("Имя переменной слишком длинное"));
65 strncpy(varName,pos+1,varLen);
67 const char* value = cfg.getCharValue(varName);
69 strncat(buf, value, maxLen);
71 strncat(buf, "??", maxLen);
74 strncat(buf, "%", maxLen);
80 void requestCB(void* optParm, AsyncHTTPRequest* request, int readyState) {
81 const char* weather_template = cfg.getCharValue(F("weather_template"));
83 if (readyState == readyStateDone) {
84 if (request->responseHTTPcode() == 200) {
85 String weather_json = request->responseText();
86 DynamicJsonDocument* current_weather = new DynamicJsonDocument(2048);
87 DeserializationError error = deserializeJson(*current_weather, weather_json);
89 Serial.print(F("Ошибка разбора ответа: "));
90 Serial.println(error.c_str());
91 Serial.println(weather_json);
92 reportMessage(F("Ошибка обновления погоды"));
96 IterateJson(current_weather->as<JsonObject>(), "", weather);
97 weather_json = String();
98 delete current_weather;
99 processTemplates(weatherData,weather_template,weather,255);
101 reportMessage(F("Погода обновлена"));
102 scroll(weatherData, !isNight());
107 void weatherRequest() {
108 if (!WiFi.isConnected()) { return; }
109 if (WiFi.isConnected() && weatherTicker) {
110 weatherTicker->detach();
111 int weather_min = cfg.getIntValue(F("weather_min"));
112 weather_min = weather_min ? weather_min : 60;
113 weatherTicker->attach(weather_min * 60, executeWeatherRequest); // reschedule to requested interval
115 static bool requestOpenResult;
116 if (request.readyState() == readyStateUnsent || request.readyState() == readyStateDone) {
117 const char* weather_url = cfg.getCharValue(F("weather_url"));
118 requestOpenResult = request.open("GET", weather_url);
120 if (requestOpenResult) {
123 Serial.println(F("Не удалось отправить запрос"));
126 Serial.println(F("Не удалось отправить запрос"));
130 void executeWeatherRequest() {
131 if (cfg.getBoolValue(F("enable_weather"))) {
132 request.onReadyStateChange(requestCB);
137 void setupWeatherRequest() {
139 weatherTicker->detach();
140 delete weatherTicker;
141 weatherTicker = nullptr;
143 if (cfg.getBoolValue(F("enable_weather"))) {
144 weatherTicker = new Ticker;
145 weatherTicker->attach(30, executeWeatherRequest); // before connection - every 30s