diff --git a/code/espurna/button.ino b/code/espurna/button.ino index 0b25ab0b..40033e11 100644 --- a/code/espurna/button.ino +++ b/code/espurna/button.ino @@ -112,7 +112,7 @@ void buttonEvent(unsigned int id, unsigned char event) { } if (action == BUTTON_MODE_FACTORY) { DEBUG_MSG_P(PSTR("\n\nFACTORY RESET\n\n")); - settingsFactoryReset(); + resetSettings(); deferredReset(100, CUSTOM_RESET_FACTORY); } diff --git a/code/espurna/config/prototypes.h b/code/espurna/config/prototypes.h index 145f324f..5b7bd10c 100644 --- a/code/espurna/config/prototypes.h +++ b/code/espurna/config/prototypes.h @@ -50,11 +50,14 @@ String mqttSubtopic(char * topic); // ----------------------------------------------------------------------------- // Settings // ----------------------------------------------------------------------------- +#include template bool setSetting(const String& key, T value); template bool setSetting(const String& key, unsigned int index, T value); template String getSetting(const String& key, T defaultValue); template String getSetting(const String& key, unsigned int index, T defaultValue); -bool settingsRestore(JsonObject& data); +bool settingsGetJson(JsonObject& data); +bool settingsRestoreJson(JsonObject& data); +void settingsRegisterCommand(const String& name, void (*call)(Embedis*)); // ----------------------------------------------------------------------------- // I2C diff --git a/code/espurna/libs/EmbedisWrap.h b/code/espurna/libs/EmbedisWrap.h index 2b31d323..ff1b5d58 100644 --- a/code/espurna/libs/EmbedisWrap.h +++ b/code/espurna/libs/EmbedisWrap.h @@ -12,11 +12,11 @@ class EmbedisWrap : public Embedis { EmbedisWrap(Stream& stream, size_t buflen = 128, size_t argvlen = 8): Embedis(stream, buflen, argvlen) {} - unsigned char getCommandsCount() { + unsigned char getCommandCount() { return commands.size(); } - String getCommandName(unsigned char i) { + String getCommandName(unsigned int i) { if (i < commands.size()) return commands[i].name; return String(); } diff --git a/code/espurna/light.ino b/code/espurna/light.ino index f558e27b..f259920e 100644 --- a/code/espurna/light.ino +++ b/code/espurna/light.ino @@ -856,6 +856,67 @@ void _lightAPISetup() { #endif // WEB_SUPPORT +#if TERMINAL_SUPPORT + +void _lightInitCommands() { + + settingsRegisterCommand(F("BRIGHTNESS"), [](Embedis* e) { + if (e->argc > 1) { + lightBrightness(String(e->argv[1]).toInt()); + lightUpdate(true, true); + } + DEBUG_MSG_P(PSTR("Brightness: %d\n"), lightBrightness()); + DEBUG_MSG_P(PSTR("+OK\n")); + }); + + settingsRegisterCommand(F("CHANNEL"), [](Embedis* e) { + if (e->argc < 2) { + DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n")); + } + int id = String(e->argv[1]).toInt(); + if (e->argc > 2) { + int value = String(e->argv[2]).toInt(); + lightChannel(id, value); + lightUpdate(true, true); + } + DEBUG_MSG_P(PSTR("Channel #%d: %d\n"), id, lightChannel(id)); + DEBUG_MSG_P(PSTR("+OK\n")); + }); + + settingsRegisterCommand(F("COLOR"), [](Embedis* e) { + if (e->argc > 1) { + String color = String(e->argv[1]); + lightColor(color.c_str()); + lightUpdate(true, true); + } + DEBUG_MSG_P(PSTR("Color: %s\n"), lightColor().c_str()); + DEBUG_MSG_P(PSTR("+OK\n")); + }); + + settingsRegisterCommand(F("KELVIN"), [](Embedis* e) { + if (e->argc > 1) { + String color = String("K") + String(e->argv[1]); + lightColor(color.c_str()); + lightUpdate(true, true); + } + DEBUG_MSG_P(PSTR("Color: %s\n"), lightColor().c_str()); + DEBUG_MSG_P(PSTR("+OK\n")); + }); + + settingsRegisterCommand(F("MIRED"), [](Embedis* e) { + if (e->argc > 1) { + String color = String("M") + String(e->argv[1]); + lightColor(color.c_str()); + lightUpdate(true, true); + } + DEBUG_MSG_P(PSTR("Color: %s\n"), lightColor().c_str()); + DEBUG_MSG_P(PSTR("+OK\n")); + }); + +} + +#endif // TERMINAL_SUPPORT + #if LIGHT_PROVIDER == LIGHT_PROVIDER_DIMMER unsigned long getIOMux(unsigned long gpio) { @@ -974,6 +1035,10 @@ void lightSetup() { mqttRegister(_lightMQTTCallback); #endif + #if TERMINAL_SUPPORT + _lightInitCommands(); + #endif + } void lightLoop(){ diff --git a/code/espurna/mqtt.ino b/code/espurna/mqtt.ino index 2de271e7..98bc7d07 100644 --- a/code/espurna/mqtt.ino +++ b/code/espurna/mqtt.ino @@ -507,6 +507,28 @@ void mqttSetBrokerIfNone(IPAddress ip, unsigned int port) { if (!hasSetting("mqttServer")) mqttSetBroker(ip, port); } +// ----------------------------------------------------------------------------- +// Comands +// ----------------------------------------------------------------------------- + +#if TERMINAL_SUPPORT + +void _mqttInitCommands() { + + settingsRegisterCommand(F("MQTT.RESET"), [](Embedis* e) { + mqttConfigure(); + mqttDisconnect(); + DEBUG_MSG_P(PSTR("+OK\n")); + }); + +} + +#endif // TERMINAL_SUPPORT + +// ----------------------------------------------------------------------------- +// Setup +// ----------------------------------------------------------------------------- + void mqttSetup() { DEBUG_MSG_P(PSTR("[MQTT] Async %s, SSL %s, Autoconnect %s\n"), @@ -569,6 +591,10 @@ void mqttSetup() { wsOnAfterParseRegister(mqttConfigure); #endif + #if TERMINAL_SUPPORT + _mqttInitCommands(); + #endif + } void mqttLoop() { diff --git a/code/espurna/nofuss.ino b/code/espurna/nofuss.ino index 1112131f..dd1db595 100644 --- a/code/espurna/nofuss.ino +++ b/code/espurna/nofuss.ino @@ -62,6 +62,19 @@ void _nofussConfigure() { } +#if TERMINAL_SUPPORT + +void _nofussInitCommands() { + + settingsRegisterCommand(F("NOFUSS"), [](Embedis* e) { + DEBUG_MSG_P(PSTR("+OK\n")); + nofussRun(); + }); + +} + +#endif // TERMINAL_SUPPORT +# // ----------------------------------------------------------------------------- void nofussRun() { @@ -136,6 +149,10 @@ void nofussSetup() { wsOnAfterParseRegister(_nofussConfigure); #endif + #if TERMINAL_SUPPORT + _nofussInitCommands(); + #endif + } void nofussLoop() { diff --git a/code/espurna/relay.ino b/code/espurna/relay.ino index c6d0a581..62212acb 100644 --- a/code/espurna/relay.ino +++ b/code/espurna/relay.ino @@ -642,12 +642,44 @@ void relaySetupMQTT() { //------------------------------------------------------------------------------ #if INFLUXDB_SUPPORT + void relayInfluxDB(unsigned char id) { if (id >= _relays.size()) return; idbSend(MQTT_TOPIC_RELAY, id, relayStatus(id) ? "1" : "0"); } + #endif + +//------------------------------------------------------------------------------ +// Settings +//------------------------------------------------------------------------------ + +#if TERMINAL_SUPPORT + +void _relayInitCommands() { + + settingsRegisterCommand(F("RELAY"), [](Embedis* e) { + if (e->argc < 2) { + DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n")); + } + int id = String(e->argv[1]).toInt(); + if (e->argc > 2) { + int value = String(e->argv[2]).toInt(); + if (value == 2) { + relayToggle(id); + } else { + relayStatus(id, value == 1); + } + } + DEBUG_MSG_P(PSTR("Status: %s\n"), relayStatus(id) ? "true" : "false"); + DEBUG_MSG_P(PSTR("+OK\n")); + }); + +} + +#endif // TERMINAL_SUPPORT + //------------------------------------------------------------------------------ // Setup //------------------------------------------------------------------------------ @@ -700,10 +732,12 @@ void relaySetup() { relaySetupAPI(); relaySetupWS(); #endif - #if MQTT_SUPPORT relaySetupMQTT(); #endif + #if TERMINAL_SUPPORT + _relayInitCommands(); + #endif DEBUG_MSG_P(PSTR("[RELAY] Number of relays: %d\n"), _relays.size()); diff --git a/code/espurna/sensor.ino b/code/espurna/sensor.ino index 4643874e..ac55a5aa 100644 --- a/code/espurna/sensor.ino +++ b/code/espurna/sensor.ino @@ -173,6 +173,26 @@ void _sensorAPISetup() { } #endif +#if TERMINAL_SUPPORT + +void _sensorInitCommands() { + settingsRegisterCommand(F("MAGNITUDES"), [](Embedis* e) { + for (unsigned char i=0; i<_magnitudes.size(); i++) { + sensor_magnitude_t magnitude = _magnitudes[i]; + DEBUG_MSG_P(PSTR("[SENSOR] * %2d: %s @ %s (%s/%d)\n"), + i, + _magnitudeTopic(magnitude.type).c_str(), + magnitude.sensor->slot(magnitude.local).c_str(), + _magnitudeTopic(magnitude.type).c_str(), + magnitude.global + ); + } + DEBUG_MSG_P(PSTR("+OK\n")); + }); +} + +#endif + void _sensorTick() { for (unsigned char i=0; i<_sensors.size(); i++) { _sensors[i]->tick(); @@ -589,6 +609,10 @@ void sensorSetup() { #endif + #if TERMINAL_SUPPORT + _sensorInitCommands(); + #endif + } void sensorLoop() { diff --git a/code/espurna/settings.ino b/code/espurna/settings.ino index 4845fc3a..d1bbbe67 100644 --- a/code/espurna/settings.ino +++ b/code/espurna/settings.ino @@ -9,6 +9,7 @@ Copyright (C) 2016-2018 by Xose Pérez #include #include "spi_flash.h" #include "libs/EmbedisWrap.h" +#include #include #if TELNET_SUPPORT @@ -30,23 +31,10 @@ Copyright (C) 2016-2018 by Xose Pérez bool _settings_save = false; // ----------------------------------------------------------------------------- -// Settings +// Reverse engineering EEPROM storage format // ----------------------------------------------------------------------------- -#if TELNET_SUPPORT - void settingsInject(void *data, size_t len) { - _serial.inject((char *) data, len); - } -#endif - -size_t settingsMaxSize() { - size_t size = EEPROM_SIZE; - if (size > SPI_FLASH_SEC_SIZE) size = SPI_FLASH_SEC_SIZE; - size = (size + 3) & (~3); - return size; -} - -unsigned long settingsSize() { +unsigned long _settingsSize() { unsigned pos = SPI_FLASH_SEC_SIZE - 1; while (size_t len = EEPROM.read(pos)) { pos = pos - len - 2; @@ -54,7 +42,7 @@ unsigned long settingsSize() { return SPI_FLASH_SEC_SIZE - pos; } -unsigned int settingsKeyCount() { +unsigned int _settingsKeyCount() { unsigned count = 0; unsigned pos = SPI_FLASH_SEC_SIZE - 1; while (size_t len = EEPROM.read(pos)) { @@ -66,7 +54,7 @@ unsigned int settingsKeyCount() { return count; } -String settingsKeyName(unsigned int index) { +String _settingsKeyName(unsigned int index) { String s; @@ -90,167 +78,137 @@ String settingsKeyName(unsigned int index) { } -bool settingsRestore(JsonObject& data) { +// ----------------------------------------------------------------------------- +// Commands +// ----------------------------------------------------------------------------- - const char* app = data["app"]; - if (strcmp(app, APP_NAME) != 0) return false; +void _settingsHelp() { - for (unsigned int i = EEPROM_DATA_END; i < SPI_FLASH_SEC_SIZE; i++) { - EEPROM.write(i, 0xFF); - } + // Get sorted list of commands + std::vector commands; + unsigned char size = embedis.getCommandCount(); + for (unsigned int i=0; i()); - } + String command = embedis.getCommandName(i); + bool inserted = false; + for (unsigned char j=0; j 0) { + commands.insert(commands.begin() + j, command); + inserted = true; + break; + } - DEBUG_MSG_P(PSTR("[SETTINGS] Settings restored successfully\n")); - return true; + } -} + // If we could not insert it, just push it at the end + if (!inserted) commands.push_back(command); -void settingsFactoryReset() { - for (unsigned int i = 0; i < SPI_FLASH_SEC_SIZE; i++) { - EEPROM.write(i, 0xFF); } - EEPROM.commit(); -} -void settingsHelp() { - unsigned char len = embedis.getCommandsCount(); + // Output the list DEBUG_MSG_P(PSTR("\nAvailable commands:\n\n")); - for (unsigned char i=0; i keys; + //unsigned int size = settingsKeyCount(); + unsigned int size = _settingsKeyCount(); + for (unsigned int i=0; i char { return EEPROM.read(pos); }, - [](size_t pos, char value) { EEPROM.write(pos, value); }, - #if SETTINGS_AUTOSAVE - []() { _settings_save = true; } - #else - []() {} - #endif - ); + // Check if we have to insert it before the current element + if (keys[j].compareTo(key) > 0) { + keys.insert(keys.begin() + j, key); + inserted = true; + break; + } - Embedis::hardware( F("WIFI"), [](Embedis* e) { - StreamString s; - WiFi.printDiag(s); - DEBUG_MSG(s.c_str()); - }, 0); + } - // ------------------------------------------------------------------------- + // If we could not insert it, just push it at the end + if (!inserted) keys.push_back(key); - #if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE - Embedis::command( F("BRIGHTNESS"), [](Embedis* e) { - if (e->argc > 1) { - lightBrightness(String(e->argv[1]).toInt()); - lightUpdate(true, true); - } - DEBUG_MSG_P(PSTR("Brightness: %d\n"), lightBrightness()); - DEBUG_MSG_P(PSTR("+OK\n")); - }); - #endif + } - #if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE - Embedis::command( F("CHANNEL"), [](Embedis* e) { - if (e->argc < 2) { - DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n")); - } - int id = String(e->argv[1]).toInt(); - if (e->argc > 2) { - int value = String(e->argv[2]).toInt(); - lightChannel(id, value); - lightUpdate(true, true); - } - DEBUG_MSG_P(PSTR("Channel #%d: %d\n"), id, lightChannel(id)); - DEBUG_MSG_P(PSTR("+OK\n")); - }); - #endif + // Write key-values + DEBUG_MSG_P(PSTR("\n")); + for (unsigned int i=0; i %s\n"), (keys[i]).c_str(), value.c_str()); + } + DEBUG_MSG_P(PSTR("\n")); - #if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE - Embedis::command( F("COLOR"), [](Embedis* e) { - if (e->argc > 1) { - String color = String(e->argv[1]); - lightColor(color.c_str()); - lightUpdate(true, true); - } - DEBUG_MSG_P(PSTR("Color: %s\n"), lightColor().c_str()); - DEBUG_MSG_P(PSTR("+OK\n")); - }); - #endif + unsigned long freeEEPROM = SPI_FLASH_SEC_SIZE - _settingsSize(); + DEBUG_MSG_P(PSTR("Number of keys: %d\n"), keys.size()); + DEBUG_MSG_P(PSTR("Free EEPROM: %d bytes (%d%%)\n"), freeEEPROM, 100 * freeEEPROM / SPI_FLASH_SEC_SIZE); + +} + +void _settingsFactoryReset() { + for (unsigned int i = 0; i < SPI_FLASH_SEC_SIZE; i++) { + EEPROM.write(i, 0xFF); + } + EEPROM.commit(); +} + +void _settingsDump(bool ascii) { + for (unsigned int i = 0; i < SPI_FLASH_SEC_SIZE; i++) { + if (i % 16 == 0) DEBUG_MSG_P(PSTR("\n[%04X] "), i); + byte c = EEPROM.read(i); + if (ascii && 32 <= c && c <= 126) { + DEBUG_MSG_P(PSTR(" %c "), c); + } else { + DEBUG_MSG_P(PSTR("%02X "), c); + } + } +} + +void _settingsInitCommands() { #if DEBUG_SUPPORT - Embedis::command( F("CRASH"), [](Embedis* e) { + settingsRegisterCommand(F("CRASH"), [](Embedis* e) { debugDumpCrashInfo(); DEBUG_MSG_P(PSTR("+OK\n")); }); #endif - Embedis::command( F("DUMP"), [](Embedis* e) { - unsigned int size = settingsKeyCount(); - for (unsigned int i=0; i %s\n"), key.c_str(), value.c_str()); - } + settingsRegisterCommand(F("COMMANDS"), [](Embedis* e) { + _settingsHelp(); DEBUG_MSG_P(PSTR("+OK\n")); }); - Embedis::command( F("DUMP.RAW"), [](Embedis* e) { + settingsRegisterCommand(F("EEPROM.DUMP"), [](Embedis* e) { bool ascii = false; if (e->argc == 2) ascii = String(e->argv[1]).toInt() == 1; - for (unsigned int i = 0; i < SPI_FLASH_SEC_SIZE; i++) { - if (i % 16 == 0) DEBUG_MSG_P(PSTR("\n[%04X] "), i); - byte c = EEPROM.read(i); - if (ascii && 32 <= c && c <= 126) { - DEBUG_MSG_P(PSTR(" %c "), c); - } else { - DEBUG_MSG_P(PSTR("%02X "), c); - } - } + _settingsDump(ascii); DEBUG_MSG_P(PSTR("\n+OK\n")); }); - Embedis::command( F("EEPROM"), [](Embedis* e) { - unsigned long freeEEPROM = SPI_FLASH_SEC_SIZE - settingsSize(); - DEBUG_MSG_P(PSTR("Number of keys: %d\n"), settingsKeyCount()); - DEBUG_MSG_P(PSTR("Free EEPROM: %d bytes (%d%%)\n"), freeEEPROM, 100 * freeEEPROM / SPI_FLASH_SEC_SIZE); - DEBUG_MSG_P(PSTR("+OK\n")); - }); - - Embedis::command( F("ERASE.CONFIG"), [](Embedis* e) { + settingsRegisterCommand(F("ERASE.CONFIG"), [](Embedis* e) { DEBUG_MSG_P(PSTR("+OK\n")); resetReason(CUSTOM_RESET_TERMINAL); ESP.eraseConfig(); *((int*) 0) = 0; // see https://github.com/esp8266/Arduino/issues/1494 }); - Embedis::command( F("FACTORY.RESET"), [](Embedis* e) { - settingsFactoryReset(); + settingsRegisterCommand(F("FACTORY.RESET"), [](Embedis* e) { + _settingsFactoryReset(); DEBUG_MSG_P(PSTR("+OK\n")); }); - Embedis::command( F("GPIO"), [](Embedis* e) { + settingsRegisterCommand(F("GPIO"), [](Embedis* e) { if (e->argc < 2) { DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n")); return; @@ -268,132 +226,44 @@ void settingsSetup() { DEBUG_MSG_P(PSTR("+OK\n")); }); - Embedis::command( F("HEAP"), [](Embedis* e) { + settingsRegisterCommand(F("HEAP"), [](Embedis* e) { DEBUG_MSG_P(PSTR("Free HEAP: %d bytes\n"), getFreeHeap()); DEBUG_MSG_P(PSTR("+OK\n")); }); - Embedis::command( F("HELP"), [](Embedis* e) { - settingsHelp(); + settingsRegisterCommand(F("HELP"), [](Embedis* e) { + _settingsHelp(); DEBUG_MSG_P(PSTR("+OK\n")); }); - Embedis::command( F("INFO"), [](Embedis* e) { + settingsRegisterCommand(F("INFO"), [](Embedis* e) { welcome(); wifiStatus(); + //StreamString s; + //WiFi.printDiag(s); + //DEBUG_MSG(s.c_str()); DEBUG_MSG_P(PSTR("+OK\n")); }); - #if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE - Embedis::command( F("KELVIN"), [](Embedis* e) { - if (e->argc > 1) { - String color = String("K") + String(e->argv[1]); - lightColor(color.c_str()); - lightUpdate(true, true); - } - DEBUG_MSG_P(PSTR("Color: %s\n"), lightColor().c_str()); - DEBUG_MSG_P(PSTR("+OK\n")); - }); - #endif - - #if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE - Embedis::command( F("MIRED"), [](Embedis* e) { - if (e->argc > 1) { - String color = String("M") + String(e->argv[1]); - lightColor(color.c_str()); - lightUpdate(true, true); - } - DEBUG_MSG_P(PSTR("Color: %s\n"), lightColor().c_str()); - DEBUG_MSG_P(PSTR("+OK\n")); - }); - #endif - - #if MQTT_SUPPORT - Embedis::command( F("MQTT.RESET"), [](Embedis* e) { - mqttConfigure(); - mqttDisconnect(); - DEBUG_MSG_P(PSTR("+OK\n")); - }); - #endif - - #if NOFUSS_SUPPORT - Embedis::command( F("NOFUSS"), [](Embedis* e) { - DEBUG_MSG_P(PSTR("+OK\n")); - nofussRun(); - }); - #endif - - Embedis::command( F("RELAY"), [](Embedis* e) { - if (e->argc < 2) { - DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n")); - } - int id = String(e->argv[1]).toInt(); - if (e->argc > 2) { - int value = String(e->argv[2]).toInt(); - if (value == 2) { - relayToggle(id); - } else { - relayStatus(id, value == 1); - } - } - DEBUG_MSG_P(PSTR("Status: %s\n"), relayStatus(id) ? "true" : "false"); + settingsRegisterCommand(F("KEYS"), [](Embedis* e) { + _settingsKeys(); DEBUG_MSG_P(PSTR("+OK\n")); }); - Embedis::command( F("RESET"), [](Embedis* e) { + settingsRegisterCommand(F("RESET"), [](Embedis* e) { DEBUG_MSG_P(PSTR("+OK\n")); deferredReset(100, CUSTOM_RESET_TERMINAL); }); - Embedis::command( F("UPTIME"), [](Embedis* e) { + settingsRegisterCommand(F("UPTIME"), [](Embedis* e) { DEBUG_MSG_P(PSTR("Uptime: %d seconds\n"), getUptime()); DEBUG_MSG_P(PSTR("+OK\n")); }); - Embedis::command( F("WIFI.RESET"), [](Embedis* e) { - wifiConfigure(); - wifiDisconnect(); - DEBUG_MSG_P(PSTR("+OK\n")); - }); - - Embedis::command( F("WIFI.SCAN"), [](Embedis* e) { - wifiScan(); - DEBUG_MSG_P(PSTR("+OK\n")); - }); - - - DEBUG_MSG_P(PSTR("[SETTINGS] EEPROM size: %d bytes\n"), SPI_FLASH_SEC_SIZE); - DEBUG_MSG_P(PSTR("[SETTINGS] Settings size: %d bytes\n"), settingsSize()); - -} - -void settingsDump() { - unsigned int size = settingsKeyCount(); - for (unsigned int i=0; i %s\n"), key.c_str(), value.c_str()); - } -} - -void settingsLoop() { - if (_settings_save) { - //DEBUG_MSG_P(PSTR("[SETTINGS] Saving\n")); - EEPROM.commit(); - _settings_save = false; - } - #if TERMINAL_SUPPORT - embedis.process(); - #endif -} - -void saveSettings() { - #if not SETTINGS_AUTOSAVE - _settings_save = true; - #endif - //settingsDump(); } +// ----------------------------------------------------------------------------- +// Key-value API // ----------------------------------------------------------------------------- void moveSetting(const char * from, const char * to) { @@ -439,3 +309,109 @@ bool hasSetting(const String& key) { bool hasSetting(const String& key, unsigned int index) { return getSetting(key, index, "").length() != 0; } + +void saveSettings() { + #if not SETTINGS_AUTOSAVE + _settings_save = true; + #endif +} + +void resetSettings() { + _settingsFactoryReset(); +} + +// ----------------------------------------------------------------------------- +// Settings +// ----------------------------------------------------------------------------- + +#if TELNET_SUPPORT + void settingsInject(void *data, size_t len) { + _serial.inject((char *) data, len); + } +#endif + +size_t settingsMaxSize() { + size_t size = EEPROM_SIZE; + if (size > SPI_FLASH_SEC_SIZE) size = SPI_FLASH_SEC_SIZE; + size = (size + 3) & (~3); + return size; +} + +bool settingsRestoreJson(JsonObject& data) { + + const char* app = data["app"]; + if (strcmp(app, APP_NAME) != 0) return false; + + for (unsigned int i = EEPROM_DATA_END; i < SPI_FLASH_SEC_SIZE; i++) { + EEPROM.write(i, 0xFF); + } + + for (auto element : data) { + if (strcmp(element.key, "app") == 0) continue; + if (strcmp(element.key, "version") == 0) continue; + setSetting(element.key, element.value.as()); + } + + saveSettings(); + + DEBUG_MSG_P(PSTR("[SETTINGS] Settings restored successfully\n")); + return true; + +} + +bool settingsGetJson(JsonObject& root) { + + unsigned int size = _settingsKeyCount(); + for (unsigned int i=0; i char { return EEPROM.read(pos); }, + [](size_t pos, char value) { EEPROM.write(pos, value); }, + #if SETTINGS_AUTOSAVE + []() { _settings_save = true; } + #else + []() {} + #endif + ); + + _settingsInitCommands(); + + DEBUG_MSG_P(PSTR("[SETTINGS] EEPROM size: %d bytes\n"), SPI_FLASH_SEC_SIZE); + DEBUG_MSG_P(PSTR("[SETTINGS] Settings size: %d bytes\n"), _settingsSize()); + +} + +void settingsLoop() { + if (_settings_save) { + EEPROM.commit(); + _settings_save = false; + } + #if TERMINAL_SUPPORT + embedis.process(); + #endif +} diff --git a/code/espurna/web.ino b/code/espurna/web.ino index a628410e..dfb9c75f 100644 --- a/code/espurna/web.ino +++ b/code/espurna/web.ino @@ -50,13 +50,7 @@ void _onGetConfig(AsyncWebServerRequest *request) { root["app"] = APP_NAME; root["version"] = APP_VERSION; - - unsigned int size = settingsKeyCount(); - for (unsigned int i=0; idata()); - if (root.success()) _webConfigSuccess = settingsRestore(root); + if (root.success()) _webConfigSuccess = settingsRestoreJson(root); delete _webConfigBuffer; } diff --git a/code/espurna/wifi.ino b/code/espurna/wifi.ino index c3dce1d2..6506dece 100644 --- a/code/espurna/wifi.ino +++ b/code/espurna/wifi.ino @@ -346,6 +346,25 @@ void _wifiDebug(justwifi_messages_t code, char * parameter) { #endif // DEBUG_SUPPORT +#if TERMINAL_SUPPORT + +void _wifiInitCommands() { + + settingsRegisterCommand(F("WIFI.RESET"), [](Embedis* e) { + wifiConfigure(); + wifiDisconnect(); + DEBUG_MSG_P(PSTR("+OK\n")); + }); + + settingsRegisterCommand(F("WIFI.SCAN"), [](Embedis* e) { + wifiScan(); + DEBUG_MSG_P(PSTR("+OK\n")); + }); + +} + +#endif + void wifiRegister(wifi_callback_f callback) { jw.subscribe(callback); } @@ -369,6 +388,10 @@ void wifiSetup() { wsOnAfterParseRegister(wifiConfigure); #endif + #if TERMINAL_SUPPORT + _wifiInitCommands(); + #endif + } void wifiLoop() { diff --git a/code/espurna/ws.ino b/code/espurna/ws.ino index 0822f66d..0989c4b7 100644 --- a/code/espurna/ws.ino +++ b/code/espurna/ws.ino @@ -106,7 +106,7 @@ void _wsParse(AsyncWebSocketClient *client, uint8_t * payload, size_t length) { // Restore configuration via websockets if (strcmp(action, "restore") == 0) { - if (settingsRestore(data)) { + if (settingsRestoreJson(data)) { wsSend_P(client_id, PSTR("{\"message\": 5}")); } else { wsSend_P(client_id, PSTR("{\"message\": 4}"));