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);
95 IterateJson(current_weather->as<JsonObject>(), "", weather);
96 weather_json = String();
97 delete current_weather;
98 processTemplates(weatherData,weather_template,weather,255);
100 scroll(weatherData, !isNight());
105 void weatherRequest() {
106 if (!WiFi.isConnected()) { return; }
107 if (WiFi.isConnected() && weatherTicker) {
108 weatherTicker->detach();
109 int weather_min = cfg.getIntValue(F("weather_min"));
110 weather_min = weather_min ? weather_min : 60;
111 weatherTicker->attach(weather_min * 60, executeWeatherRequest); // reschedule to requested interval
113 static bool requestOpenResult;
114 if (request.readyState() == readyStateUnsent || request.readyState() == readyStateDone) {
115 const char* weather_url = cfg.getCharValue(F("weather_url"));
116 requestOpenResult = request.open("GET", weather_url);
118 if (requestOpenResult) {
121 Serial.println(F("Не удалось отправить запрос"));
124 Serial.println(F("Не удалось отправить запрос"));
128 void executeWeatherRequest() {
129 if (cfg.getBoolValue(F("enable_weather"))) {
130 request.onReadyStateChange(requestCB);
135 void setupWeatherRequest() {
137 weatherTicker->detach();
138 delete weatherTicker;
139 weatherTicker = nullptr;
141 if (cfg.getBoolValue(F("enable_weather"))) {
142 weatherTicker = new Ticker;
143 weatherTicker->attach(30, executeWeatherRequest); // before connection - every 30s