From 4932b00f12b7e9429ad79f57eb1cec52fe45b89f Mon Sep 17 00:00:00 2001 From: proddy Date: Wed, 22 Jul 2020 16:11:13 +0200 Subject: [PATCH] automate migration from 1.9.x to 2.0 (in progress) --- src/emsesp.cpp | 45 +++++++++------ src/system.cpp | 148 ++++++++++++++++++++++++++++++++++++++++++++++++- src/system.h | 11 +++- 3 files changed, 183 insertions(+), 21 deletions(-) diff --git a/src/emsesp.cpp b/src/emsesp.cpp index e34700f04..a927dc573 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -720,27 +720,37 @@ void EMSESP::start() { LittleFS.begin(); #endif - esp8266React.begin(); // starts wifi, ap, ota, security, mqtt services - emsespSettingsService.begin(); // load EMS-ESP specific settings from LittleFS - console_.start(); // telnet and serial console - system_.start(); // starts syslog, uart, sets version, initializes LED. Requires pre-loaded settings. - mqtt_.start(EMSESP::esp8266React.getMqttClient()); // mqtt init - sensors_.start(); // dallas external sensors - shower_.start(); // initialize shower timer and shower alert - txservice_.start(); // sets bus ID, sends out request for EMS devices - webServer.begin(); // start web server + esp8266React.begin(); // loads system settings (wifi, mqtt, etc) + emsespSettingsService.begin(); // load EMS-ESP specific settings + + // system_.check_upgrade(); // see if we need to migrate from previous versions + + console_.start(); // telnet and serial console + system_.start(); // starts syslog, uart, sets version, initializes LED. Requires pre-loaded settings. + mqtt_.start(); // mqtt init + shower_.start(); // initialize shower timer and shower alert + txservice_.start(); // sets bus ID, sends out request for EMS devices + sensors_.start(); // dallas external sensors + + webServer.begin(); // start web server } -// loop de loop +// main loop calling all services void EMSESP::loop() { esp8266React.loop(); // web - system_.loop(); // does LED and checks system health, and syslog service - mqtt_.loop(); // starts mqtt, and sends out anything in the queue - rxservice_.loop(); // process what ever is in the rx queue - txservice_.loop(); // check that the Tx is all ok - shower_.loop(); // check for shower on/off - sensors_.loop(); // this will also send out via MQTT - console_.loop(); // telnet/serial console + + // if we're doing an OTA upload, skip MQTT and EMS + if (system_.upload_status()) { + return; + } + + system_.loop(); // does LED and checks system health, and syslog service + mqtt_.loop(); // starts mqtt, and sends out anything in the queue + rxservice_.loop(); // process what ever is in the rx queue + txservice_.loop(); // check that the Tx is all ok + shower_.loop(); // check for shower on/off + sensors_.loop(); // this will also send out via MQTT + console_.loop(); // telnet/serial console // force a query on the EMS devices to fetch latest data at a set interval (1 min) if ((uuid::get_uptime() - last_fetch_ > EMS_FETCH_FREQUENCY)) { @@ -749,7 +759,6 @@ void EMSESP::loop() { } delay(1); - } } // namespace emsesp diff --git a/src/system.cpp b/src/system.cpp index 530e3f88f..b21db535f 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -43,8 +43,10 @@ uuid::log::Logger System::logger_{F_(logger_name), uuid::log::Facility::KERN}; uuid::syslog::SyslogService System::syslog_; #endif -uint32_t System::heap_start_ = 0; -int System::reset_counter_; +// init statics +uint32_t System::heap_start_ = 0; +int System::reset_counter_ = 0; +bool System::upload_status_ = false; // handle generic system related MQTT commands void System::mqtt_commands(const char * message) { @@ -241,6 +243,19 @@ void System::start() { #endif } +// returns true if OTA is uploading +bool System::upload_status() { + return upload_status_ || Update.isRunning(); +} + +void System::upload_status(bool in_progress) { + // if we've just started an upload + if ((!upload_status_) && (in_progress)) { + EMSuart::stop(); + } + upload_status_ = in_progress; +} + // checks system health and handles LED flashing wizardry void System::loop() { #ifndef EMSESP_STANDALONE @@ -602,5 +617,134 @@ void System::console_commands(Shell & shell, unsigned int context) { Console::enter_custom_context(shell, context); } +// upgrade from previous versions of EMS-ESP +void System::check_upgrade() { +// check for v1.9. It uses SPIFFS and only on the ESP8266 +#if defined(ESP8266) + + Serial.begin(115200); // TODO remove + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + + LittleFS.end(); + SPIFFS.begin(); + + // first file + File file = SPIFFS.open("/myesp.json", "r"); + if (!file) { + Serial.println(F("Old config doesn't exist.")); + SPIFFS.end(); + LittleFS.begin(); + return; + } + + DeserializationError error; + StaticJsonDocument<1024> doc; // for myESP settings + error = deserializeJson(doc, file); + if (error) { + Serial.printf("Error. Failed to deserialize json, error %s", error.c_str()); + file.close(); + SPIFFS.end(); + LittleFS.begin(); + return; + } + + file.close(); + + // second file + file = SPIFFS.open("/customconfig.json", "r"); + if (!file) { + Serial.println(F("Old custom config file doesn't exist")); + SPIFFS.end(); + LittleFS.begin(); + return; + } + + StaticJsonDocument<1024> doc2; // for custom EMS-ESP settings + error = deserializeJson(doc2, file); + if (error) { + Serial.printf("Error. Failed to deserialize json, error %s", error.c_str()); + file.close(); + SPIFFS.end(); + LittleFS.begin(); + return; + } + + file.close(); + + // close SPIFFS and open LittleFS + SPIFFS.end(); + LittleFS.begin(); + +#pragma GCC diagnostic pop + + Serial.println(F("Migrating settings from EMS-ESP 1.9.x...")); + + // get the json objects + JsonObject network = doc["network"]; + JsonObject general = doc["general"]; + JsonObject mqtt = doc["mqtt"]; + JsonObject custom_settings = doc2["settings"]; // from 2nd file + + EMSESP::esp8266React.getWiFiSettingsService()->update( + [&](WiFiSettings & wifiSettings) { + wifiSettings.hostname = general["hostname"] | FACTORY_WIFI_HOSTNAME; + wifiSettings.ssid = network["ssid"] | FACTORY_WIFI_SSID; + wifiSettings.password = network["password"] | FACTORY_WIFI_PASSWORD; + + wifiSettings.staticIPConfig = false; + JsonUtils::readIP(network, "staticip", wifiSettings.localIP); + JsonUtils::readIP(network, "dnsip", wifiSettings.dnsIP1); + JsonUtils::readIP(network, "gatewayip", wifiSettings.gatewayIP); + JsonUtils::readIP(network, "nmask", wifiSettings.subnetMask); + + return StateUpdateResult::CHANGED; + }, + "local"); + + EMSESP::esp8266React.getMqttSettingsService()->update( + [&](MqttSettings & mqttSettings) { + mqttSettings.host = mqtt["ip"] | FACTORY_MQTT_HOST; + mqttSettings.mqtt_format = (mqtt["nestedjson"] ? 2 : 1); + mqttSettings.mqtt_qos = mqtt["qos"] | 0; + mqttSettings.username = mqtt["user"] | ""; + mqttSettings.password = mqtt["password"] | ""; + mqttSettings.port = mqtt["port"] | FACTORY_MQTT_PORT; + mqttSettings.clientId = FACTORY_MQTT_CLIENT_ID; + mqttSettings.enabled = mqtt["enabled"]; + mqttSettings.system_heartbeat = mqtt["heartbeat"]; + mqttSettings.keepAlive = FACTORY_MQTT_KEEP_ALIVE; + mqttSettings.cleanSession = FACTORY_MQTT_CLEAN_SESSION; + mqttSettings.maxTopicLength = FACTORY_MQTT_MAX_TOPIC_LENGTH; + + return StateUpdateResult::CHANGED; + }, + "local"); + + EMSESP::esp8266React.getSecuritySettingsService()->update( + [&](SecuritySettings & securitySettings) { + securitySettings.jwtSecret = general["password"] | FACTORY_JWT_SECRET; + + return StateUpdateResult::CHANGED; + }, + "local"); + + EMSESP::emsespSettingsService.update( + [&](EMSESPSettings & settings) { + settings.tx_mode = custom_settings["tx_mode"] | EMSESP_DEFAULT_TX_MODE; + settings.shower_alert = custom_settings["shower_alert"] | EMSESP_DEFAULT_SHOWER_ALERT; + settings.shower_timer = custom_settings["shower_timer"] | EMSESP_DEFAULT_SHOWER_TIMER; + settings.master_thermostat = custom_settings["master_thermostat"] | EMSESP_DEFAULT_MASTER_THERMOSTAT; + settings.ems_bus_id = custom_settings["bus_id"] | EMSESP_DEFAULT_EMS_BUS_ID; + settings.syslog_host = EMSESP_DEFAULT_SYSLOG_HOST; + settings.syslog_level = EMSESP_DEFAULT_SYSLOG_LEVEL; + settings.syslog_mark_interval = EMSESP_DEFAULT_SYSLOG_MARK_INTERVAL; + + return StateUpdateResult::CHANGED; + }, + "local"); +#endif +} } // namespace emsesp diff --git a/src/system.h b/src/system.h index d986c1acb..3b3cd0d52 100644 --- a/src/system.h +++ b/src/system.h @@ -45,16 +45,22 @@ class System { // commands static void restart(); static void format(uuid::console::Shell & shell); + static void console_commands(Shell & shell, unsigned int context); static void mqtt_commands(const char * message); static uint8_t free_mem(); - void syslog_init(); + static void upload_status(bool in_progress); + static bool upload_status(); + + void syslog_init(); // heartbeat void set_heartbeat(bool system_heartbeat); void send_heartbeat(); + void check_upgrade(); + private: static uuid::log::Logger logger_; @@ -99,6 +105,9 @@ class System { static int reset_counter_; uint32_t last_heartbeat_ = 0; + // OTA + static bool upload_status_; // true if we're in the middle of a OTA firmware upload + // settings uint8_t tx_mode_; bool system_heartbeat_;