#include <ESPAsyncWebServer.h>
#include <StreamString.h>
#include <Ticker.h>
+#include "ArduinoJson.h"
+#include "AsyncJson.h"
bool isApEnabled = false;
bool isWebStarted = false;
}
}
+void reportMessage(const __FlashStringHelper* msg) {
+ char buf[256];
+ strcpy_P(buf, (PGM_P)msg);
+ events.send(buf,"message",millis());
+}
+
void sendInitial(AsyncEventSourceClient *client) {
String mac = WiFi.macAddress();
char buf[256];
sprintf(buf,"{\"_mac\":\"%s\",\"_weather\":\"%s\"}", mac.c_str(), weatherData);
- client->send(buf,"keepalive",millis());
+ client->send(buf,"update",millis());
mac = String();
}
void sendWeather() {
char buf[256];
sprintf(buf,"{\"_weather\":\"%s\"}",weatherData);
- events.send(buf,"keepalive",millis());
+ events.send(buf,"update",millis());
}
void sendKeepalive() {
} else {
sprintf(buf,"{\"_uptime\":\"%d м %d с\", \"_date\":\"%02d.%2d.%04d\", \"_time\":\"%02d:%02d\",\"_heap\":\"%d б\", \"_rssi\":\"%d\", \"_last_sync\":\"%s\", \"_changed\":%s}", mins, uptime, dd, mm, yy, hh, mi, heap, rssi, sync, changed?"true":"false");
}
- events.send(buf,"keepalive",millis());
+ events.send(buf,"update",millis());
}
void apply(const char* name) {
isWebStarted = true;
- Serial.println("Setting authentication...");
strncpy(auth_user,cfg.getCharValue(F("auth_user")),31);
strncpy(auth_pwd,cfg.getCharValue(F("auth_pwd")),31);
}
if(request->hasParam("name")) {
const char* action = request->getParam("name")->value().c_str();
- if (strcmp(action,"restart") == 0) {
+ if (strcmp(action,"reset") == 0) {
+ millisScheduled = millis();
+ actionScheduled = "reset";
+ request->send(200,"application/json", "{\"result\":\"OK\",\"message\":\"Сбрасываю настройки и перезагружаюсь\"}");
+ } else if (strcmp(action,"restart") == 0) {
if (pendingWiFi) {
request->send(200,"application/json", "{\"result\":\"FAILED\",\"message\":\"Не применены настройки WiFi\", \"page\":\"wifi\"}");
} else if (pendingAuth) {
millisScheduled = millis();
actionScheduled = "save";
}
+ } else if (strcmp(action,"time") == 0) {
+ if(request->hasParam("timestamp")) {
+ unsigned long timestamp = atoi(request->getParam("timestamp")->value().c_str());
+ if (timestamp) {
+ timeval tv = { timestamp, 0 };
+ settimeofday(&tv, nullptr);
+ if (isRTCEnabled) {
+ Serial.println(F("Время установлено вручную"));
+ RTC.adjust(DateTime(timestamp));
+ }
+ }
+ request->send(200,"application/json", "{\"result\":\"OK\",\"message\":\"Устанавливаю время\"}");
+ } else {
+ request->send(500, "text/plain", "{\"result\":\"FAILED\",\"message\":\"Not all parameters set\"}");
+ }
+ } else {
+ request->send(500, "text/plain", "{\"result\":\"FAILED\",\"message\":\"Unsupported action\"}");
}
+ } else {
+ request->send(500, "text/plain", "{\"result\":\"FAILED\",\"message\":\"Not all parameters set\"}");
}
});
}
});
+ AsyncCallbackJsonWebHandler* configUploadHandler = new AsyncCallbackJsonWebHandler("/config/put", [](AsyncWebServerRequest *request, JsonVariant &json) {
+ cfg.clear();
+ // first - set values
+ for( JsonPair kv : json.as<JsonObject>() ) {
+ const char* name = kv.key().c_str();
+ if (kv.value().is<bool>()) {
+ cfg.setValue(name, kv.value().as<bool>());
+ } else if (kv.value().is<int>()) {
+ cfg.setValue(name, kv.value().as<int>());
+ } else if (kv.value().is<double>()) {
+ cfg.setValue(name, kv.value().as<double>());
+ } else if (kv.value().is<char*>()) {
+ cfg.setValue(name, kv.value().as<char*>());
+ } else {
+ Serial.print(F("Неопознанный тип значения параметра ")); Serial.print(name); Serial.print(": "); Serial.println(kv.value().as<String>().c_str());
+ cfg.clear();
+ setupConfig();
+ request->send(500, "text/plain", "Unknown parameter type");
+ }
+ }
+ // second - handle all changes
+ for( JsonPair kv : json.as<JsonObject>() ) {
+ apply(kv.key().c_str());
+ }
+ pendingWiFi = false;
+ pendingAuth = false;
+ saveConfig();
+ message(F("Применены сохраненные настройки"),5);
+ reportMessage(F("Применены сохраненные настройки"));
+ millisScheduled = millis() + 10000;
+ actionScheduled = "restart";
+ request->send(200,"application/json", "{\"result\":\"OK\",\"message\":\"Настройки восстановлены из резервной копии\"}");
+ });
+
+ server.addHandler(configUploadHandler).setAuthentication(auth_user,auth_pwd);
+
server.serveStatic("ui", LittleFS, "/ui.json").setAuthentication(auth_user,auth_pwd);
server.serveStatic("/", LittleFS, "/web/").setDefaultFile("index.html").setAuthentication(auth_user,auth_pwd);
static bool connectInProgress = false;
static unsigned long connectMillis = 0;
if (actionScheduled && millis()>millisScheduled+300) {
- Serial.print(F("Scheduled action ")); Serial.println(actionScheduled);
+ Serial.print(F("Запланированная операция ")); Serial.println(actionScheduled);
//
- if (strcmp(actionScheduled,"restart") == 0) {
+ if (strcmp(actionScheduled,"reset") == 0) {
+ server.end();
+ reset();
+ } else if (strcmp(actionScheduled,"restart") == 0) {
server.end();
reboot();
} else if (strcmp(actionScheduled,"auth") == 0) {
- Serial.println("New authentication credentials");
+ Serial.println("Логин/пароль изменены");
strncpy(auth_user,cfg.getCharValue(F("auth_user")),31);
strncpy(auth_pwd,cfg.getCharValue(F("auth_pwd")),31);
pendingAuth = false;
} else if (strcmp(actionScheduled,"wifi") == 0) {
- Serial.println("New wifi credentials");
+ Serial.println("Применяю настройки сети");
strcpy(storedSSID,WiFi.SSID().c_str());
strcpy(storedPSK,WiFi.psk().c_str());
WiFi.mode(WIFI_STA);
if (!pendingWiFi && !pendingAuth && cfg.getTimestamp() && cfg.getTimestamp() < now - CFG_AUTOSAVE) {
saveConfig();
+ reportMessage(F("Настройки сохранены"));
Serial.println(F("Настройки сохранены"));
}
}