|
@ -9,6 +9,7 @@ Copyright (C) 2016-2018 by Xose Pérez <xose dot perez at gmail dot com> |
|
|
#include <EEPROM.h>
|
|
|
#include <EEPROM.h>
|
|
|
#include "spi_flash.h"
|
|
|
#include "spi_flash.h"
|
|
|
#include "libs/EmbedisWrap.h"
|
|
|
#include "libs/EmbedisWrap.h"
|
|
|
|
|
|
#include <vector>
|
|
|
#include <StreamString.h>
|
|
|
#include <StreamString.h>
|
|
|
|
|
|
|
|
|
#if TELNET_SUPPORT
|
|
|
#if TELNET_SUPPORT
|
|
@ -30,23 +31,10 @@ Copyright (C) 2016-2018 by Xose Pérez <xose dot perez at gmail dot com> |
|
|
bool _settings_save = false; |
|
|
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; |
|
|
unsigned pos = SPI_FLASH_SEC_SIZE - 1; |
|
|
while (size_t len = EEPROM.read(pos)) { |
|
|
while (size_t len = EEPROM.read(pos)) { |
|
|
pos = pos - len - 2; |
|
|
pos = pos - len - 2; |
|
@ -54,7 +42,7 @@ unsigned long settingsSize() { |
|
|
return SPI_FLASH_SEC_SIZE - pos; |
|
|
return SPI_FLASH_SEC_SIZE - pos; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
unsigned int settingsKeyCount() { |
|
|
|
|
|
|
|
|
unsigned int _settingsKeyCount() { |
|
|
unsigned count = 0; |
|
|
unsigned count = 0; |
|
|
unsigned pos = SPI_FLASH_SEC_SIZE - 1; |
|
|
unsigned pos = SPI_FLASH_SEC_SIZE - 1; |
|
|
while (size_t len = EEPROM.read(pos)) { |
|
|
while (size_t len = EEPROM.read(pos)) { |
|
@ -66,7 +54,7 @@ unsigned int settingsKeyCount() { |
|
|
return count; |
|
|
return count; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
String settingsKeyName(unsigned int index) { |
|
|
|
|
|
|
|
|
String _settingsKeyName(unsigned int index) { |
|
|
|
|
|
|
|
|
String s; |
|
|
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<String> commands; |
|
|
|
|
|
unsigned char size = embedis.getCommandCount(); |
|
|
|
|
|
for (unsigned int i=0; i<size; i++) { |
|
|
|
|
|
|
|
|
for (auto element : data) { |
|
|
|
|
|
if (strcmp(element.key, "app") == 0) continue; |
|
|
|
|
|
if (strcmp(element.key, "version") == 0) continue; |
|
|
|
|
|
setSetting(element.key, element.value.as<char*>()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
String command = embedis.getCommandName(i); |
|
|
|
|
|
bool inserted = false; |
|
|
|
|
|
for (unsigned char j=0; j<commands.size(); j++) { |
|
|
|
|
|
|
|
|
saveSettings(); |
|
|
|
|
|
|
|
|
// Check if we have to insert it before the current element
|
|
|
|
|
|
if (commands[j].compareTo(command) > 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")); |
|
|
DEBUG_MSG_P(PSTR("\nAvailable commands:\n\n")); |
|
|
for (unsigned char i=0; i<len; i++) { |
|
|
|
|
|
DEBUG_MSG_P(PSTR("* %s\n"), embedis.getCommandName(i).c_str()); |
|
|
|
|
|
if (embedis.getCommandName(i).equals("WRITE")) { |
|
|
|
|
|
DEBUG_MSG_P(PSTR("\n")); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
for (unsigned char i=0; i<commands.size(); i++) { |
|
|
|
|
|
DEBUG_MSG_P(PSTR("* %s\n"), (commands[i]).c_str()); |
|
|
} |
|
|
} |
|
|
DEBUG_MSG_P(PSTR("\n")); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void settingsSetup() { |
|
|
|
|
|
|
|
|
void _settingsKeys() { |
|
|
|
|
|
|
|
|
EEPROM.begin(SPI_FLASH_SEC_SIZE); |
|
|
|
|
|
|
|
|
// Get sorted list of keys
|
|
|
|
|
|
std::vector<String> keys; |
|
|
|
|
|
//unsigned int size = settingsKeyCount();
|
|
|
|
|
|
unsigned int size = _settingsKeyCount(); |
|
|
|
|
|
for (unsigned int i=0; i<size; i++) { |
|
|
|
|
|
|
|
|
#if TELNET_SUPPORT
|
|
|
|
|
|
_serial.callback([](uint8_t ch) { |
|
|
|
|
|
telnetWrite(ch); |
|
|
|
|
|
}); |
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
//String key = settingsKeyName(i);
|
|
|
|
|
|
String key = _settingsKeyName(i); |
|
|
|
|
|
bool inserted = false; |
|
|
|
|
|
for (unsigned char j=0; j<keys.size(); j++) { |
|
|
|
|
|
|
|
|
Embedis::dictionary( F("EEPROM"), |
|
|
|
|
|
SPI_FLASH_SEC_SIZE, |
|
|
|
|
|
[](size_t pos) -> 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<keys.size(); i++) { |
|
|
|
|
|
String value = getSetting(keys[i]); |
|
|
|
|
|
DEBUG_MSG_P(PSTR("+%s => %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
|
|
|
#if DEBUG_SUPPORT
|
|
|
Embedis::command( F("CRASH"), [](Embedis* e) { |
|
|
|
|
|
|
|
|
settingsRegisterCommand(F("CRASH"), [](Embedis* e) { |
|
|
debugDumpCrashInfo(); |
|
|
debugDumpCrashInfo(); |
|
|
DEBUG_MSG_P(PSTR("+OK\n")); |
|
|
DEBUG_MSG_P(PSTR("+OK\n")); |
|
|
}); |
|
|
}); |
|
|
#endif
|
|
|
#endif
|
|
|
|
|
|
|
|
|
Embedis::command( F("DUMP"), [](Embedis* e) { |
|
|
|
|
|
unsigned int size = settingsKeyCount(); |
|
|
|
|
|
for (unsigned int i=0; i<size; i++) { |
|
|
|
|
|
String key = settingsKeyName(i); |
|
|
|
|
|
String value = getSetting(key); |
|
|
|
|
|
DEBUG_MSG_P(PSTR("+%s => %s\n"), key.c_str(), value.c_str()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
settingsRegisterCommand(F("COMMANDS"), [](Embedis* e) { |
|
|
|
|
|
_settingsHelp(); |
|
|
DEBUG_MSG_P(PSTR("+OK\n")); |
|
|
DEBUG_MSG_P(PSTR("+OK\n")); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
Embedis::command( F("DUMP.RAW"), [](Embedis* e) { |
|
|
|
|
|
|
|
|
settingsRegisterCommand(F("EEPROM.DUMP"), [](Embedis* e) { |
|
|
bool ascii = false; |
|
|
bool ascii = false; |
|
|
if (e->argc == 2) ascii = String(e->argv[1]).toInt() == 1; |
|
|
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")); |
|
|
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")); |
|
|
DEBUG_MSG_P(PSTR("+OK\n")); |
|
|
resetReason(CUSTOM_RESET_TERMINAL); |
|
|
resetReason(CUSTOM_RESET_TERMINAL); |
|
|
ESP.eraseConfig(); |
|
|
ESP.eraseConfig(); |
|
|
*((int*) 0) = 0; // see https://github.com/esp8266/Arduino/issues/1494
|
|
|
*((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")); |
|
|
DEBUG_MSG_P(PSTR("+OK\n")); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
Embedis::command( F("GPIO"), [](Embedis* e) { |
|
|
|
|
|
|
|
|
settingsRegisterCommand(F("GPIO"), [](Embedis* e) { |
|
|
if (e->argc < 2) { |
|
|
if (e->argc < 2) { |
|
|
DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n")); |
|
|
DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n")); |
|
|
return; |
|
|
return; |
|
@ -268,132 +226,44 @@ void settingsSetup() { |
|
|
DEBUG_MSG_P(PSTR("+OK\n")); |
|
|
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("Free HEAP: %d bytes\n"), getFreeHeap()); |
|
|
DEBUG_MSG_P(PSTR("+OK\n")); |
|
|
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")); |
|
|
DEBUG_MSG_P(PSTR("+OK\n")); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
Embedis::command( F("INFO"), [](Embedis* e) { |
|
|
|
|
|
|
|
|
settingsRegisterCommand(F("INFO"), [](Embedis* e) { |
|
|
welcome(); |
|
|
welcome(); |
|
|
wifiStatus(); |
|
|
wifiStatus(); |
|
|
|
|
|
//StreamString s;
|
|
|
|
|
|
//WiFi.printDiag(s);
|
|
|
|
|
|
//DEBUG_MSG(s.c_str());
|
|
|
DEBUG_MSG_P(PSTR("+OK\n")); |
|
|
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")); |
|
|
DEBUG_MSG_P(PSTR("+OK\n")); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
Embedis::command( F("RESET"), [](Embedis* e) { |
|
|
|
|
|
|
|
|
settingsRegisterCommand(F("RESET"), [](Embedis* e) { |
|
|
DEBUG_MSG_P(PSTR("+OK\n")); |
|
|
DEBUG_MSG_P(PSTR("+OK\n")); |
|
|
deferredReset(100, CUSTOM_RESET_TERMINAL); |
|
|
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("Uptime: %d seconds\n"), getUptime()); |
|
|
DEBUG_MSG_P(PSTR("+OK\n")); |
|
|
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<size; i++) { |
|
|
|
|
|
String key = settingsKeyName(i); |
|
|
|
|
|
String value = getSetting(key); |
|
|
|
|
|
DEBUG_MSG_P(PSTR("%s => %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) { |
|
|
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) { |
|
|
bool hasSetting(const String& key, unsigned int index) { |
|
|
return getSetting(key, index, "").length() != 0; |
|
|
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<char*>()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
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<size; i++) { |
|
|
|
|
|
String key = _settingsKeyName(i); |
|
|
|
|
|
String value = getSetting(key); |
|
|
|
|
|
root[key] = value; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void settingsRegisterCommand(const String& name, void (*call)(Embedis*)) { |
|
|
|
|
|
Embedis::command(name, call); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
// Initialization
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
void settingsSetup() { |
|
|
|
|
|
|
|
|
|
|
|
EEPROM.begin(SPI_FLASH_SEC_SIZE); |
|
|
|
|
|
|
|
|
|
|
|
#if TELNET_SUPPORT
|
|
|
|
|
|
_serial.callback([](uint8_t ch) { |
|
|
|
|
|
telnetWrite(ch); |
|
|
|
|
|
}); |
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
Embedis::dictionary( F("EEPROM"), |
|
|
|
|
|
SPI_FLASH_SEC_SIZE, |
|
|
|
|
|
[](size_t pos) -> 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
|
|
|
|
|
|
} |