diff --git a/README.md b/README.md index 2ead2bf0..15c07991 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,9 @@ ESPurna ("spark" in Catalan) is a custom firmware for ESP8285/ESP8266 based smar It uses the Arduino Core for ESP8266 framework and a number of 3rd party libraries. [![version](https://img.shields.io/badge/version-1.13.4--dev-brightgreen.svg)](CHANGELOG.md) -[![branch](https://img.shields.io/badge/branch-dev-orange.svg)](https://github.com/xoseperez/espurna/tree/dev/) +[![branch](https://img.shields.io/badge/branch-refactor--terminal-orange.svg)](https://github.com/xoseperez/espurna/tree/refactor-terminal/) [![license](https://img.shields.io/github/license/xoseperez/espurna.svg)](LICENSE) -[![travis](https://travis-ci.org/xoseperez/espurna.svg?branch=dev)](https://travis-ci.org/xoseperez/espurna) +[![travis](https://travis-ci.org/xoseperez/espurna.svg?branch=refactor-terminal)](https://travis-ci.org/xoseperez/espurna) [![codacy](https://api.codacy.com/project/badge/Grade/c9496e25cf07434cba786b462cb15f49)](https://www.codacy.com/app/xoseperez/espurna/dashboard) [![downloads](https://img.shields.io/github/downloads/xoseperez/espurna/total.svg)](https://github.com/xoseperez/espurna/releases)
diff --git a/code/espurna/config/arduino.h b/code/espurna/config/arduino.h index 8d2a95af..040ac3b9 100644 --- a/code/espurna/config/arduino.h +++ b/code/espurna/config/arduino.h @@ -146,7 +146,7 @@ //#define SPIFFS_SUPPORT 1 //#define SSDP_SUPPORT 1 //#define TELNET_SUPPORT 0 -//#define TERMINAL_SUPPORT 0 +#define TERMINAL_SUPPORT 0 //#define THINGSPEAK_SUPPORT 0 //#define UART_MQTT_SUPPORT 1 //#define WEB_SUPPORT 0 diff --git a/code/espurna/config/prototypes.h b/code/espurna/config/prototypes.h index 6ceb1cf8..693ad4a8 100644 --- a/code/espurna/config/prototypes.h +++ b/code/espurna/config/prototypes.h @@ -142,9 +142,15 @@ template String getSetting(const String& key, T defaultValue); template String getSetting(const String& key, unsigned int index, T defaultValue); void settingsGetJson(JsonObject& data); bool settingsRestoreJson(JsonObject& data); -void settingsRegisterCommand(const String& name, void (*call)(Embedis*)); -void settingsInject(void *data, size_t len); -Stream & settingsSerial(); + +// ----------------------------------------------------------------------------- +// Terminal +// ----------------------------------------------------------------------------- +#if TERMINAL_SUPPORT + void terminalRegisterCommand(const String& name, void (*call)(Embedis*)); + void terminalInject(void *data, size_t len); + Stream & terminalSerial(); +#endif // ----------------------------------------------------------------------------- // Utils diff --git a/code/espurna/debug.ino b/code/espurna/debug.ino index 65fbd796..b4cd80a2 100644 --- a/code/espurna/debug.ino +++ b/code/espurna/debug.ino @@ -128,12 +128,16 @@ void debugWebSetup() { }); wsOnActionRegister([](uint32_t client_id, const char * action, JsonObject& data) { - if (strcmp(action, "dbgcmd") == 0) { - const char* command = data.get("command"); - char buffer[strlen(command) + 2]; - snprintf(buffer, sizeof(buffer), "%s\n", command); - settingsInject((void*) buffer, strlen(buffer)); - } + + #if TERMINAL_SUPPORT + if (strcmp(action, "dbgcmd") == 0) { + const char* command = data.get("command"); + char buffer[strlen(command) + 2]; + snprintf(buffer, sizeof(buffer), "%s\n", command); + terminalInject((void*) buffer, strlen(buffer)); + } + #endif + }); #if DEBUG_UDP_SUPPORT diff --git a/code/espurna/eeprom.ino b/code/espurna/eeprom.ino index ed1ad2b6..36853e30 100644 --- a/code/espurna/eeprom.ino +++ b/code/espurna/eeprom.ino @@ -58,7 +58,7 @@ void eepromCommit() { void _eepromInitCommands() { - settingsRegisterCommand(F("EEPROM"), [](Embedis* e) { + terminalRegisterCommand(F("EEPROM"), [](Embedis* e) { infoMemory("EEPROM", SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE - settingsSize()); eepromSectorsDebug(); if (_eeprom_commit_count > 0) { @@ -68,7 +68,7 @@ void _eepromInitCommands() { DEBUG_MSG_P(PSTR("+OK\n")); }); - settingsRegisterCommand(F("EEPROM.COMMIT"), [](Embedis* e) { + terminalRegisterCommand(F("EEPROM.COMMIT"), [](Embedis* e) { const bool res = _eepromCommit(); if (res) { DEBUG_MSG_P(PSTR("+OK\n")); @@ -77,12 +77,12 @@ void _eepromInitCommands() { } }); - settingsRegisterCommand(F("EEPROM.DUMP"), [](Embedis* e) { - EEPROMr.dump(settingsSerial()); + terminalRegisterCommand(F("EEPROM.DUMP"), [](Embedis* e) { + EEPROMr.dump(terminalSerial()); DEBUG_MSG_P(PSTR("\n+OK\n")); }); - settingsRegisterCommand(F("FLASH.DUMP"), [](Embedis* e) { + terminalRegisterCommand(F("FLASH.DUMP"), [](Embedis* e) { if (e->argc < 2) { DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n")); return; @@ -93,7 +93,7 @@ void _eepromInitCommands() { DEBUG_MSG_P(PSTR("-ERROR: Sector out of range\n")); return; } - EEPROMr.dump(settingsSerial(), sector); + EEPROMr.dump(terminalSerial(), sector); DEBUG_MSG_P(PSTR("\n+OK\n")); }); diff --git a/code/espurna/espurna.ino b/code/espurna/espurna.ino index 82575539..21a87a88 100644 --- a/code/espurna/espurna.ino +++ b/code/espurna/espurna.ino @@ -67,9 +67,14 @@ void setup() { // Init Serial, SPIFFS and system check systemSetup(); - // Init persistance and terminal features + // Init persistance settingsSetup(); + // Init terminal features + #if TERMINAL_SUPPORT + terminalSetup(); + #endif + // Hostname & board name initialization if (getSetting("hostname").length() == 0) { setDefaultHostname(); diff --git a/code/espurna/homeassistant.ino b/code/espurna/homeassistant.ino index 43f47ac3..300f237b 100644 --- a/code/espurna/homeassistant.ino +++ b/code/espurna/homeassistant.ino @@ -267,12 +267,12 @@ void _haWebSocketOnAction(uint32_t client_id, const char * action, JsonObject& d void _haInitCommands() { - settingsRegisterCommand(F("HA.CONFIG"), [](Embedis* e) { + terminalRegisterCommand(F("HA.CONFIG"), [](Embedis* e) { DEBUG_MSG(_haGetConfig().c_str()); DEBUG_MSG_P(PSTR("+OK\n")); }); - settingsRegisterCommand(F("HA.SEND"), [](Embedis* e) { + terminalRegisterCommand(F("HA.SEND"), [](Embedis* e) { setSetting("haEnabled", "1"); _haConfigure(); #if WEB_SUPPORT @@ -281,7 +281,7 @@ void _haInitCommands() { DEBUG_MSG_P(PSTR("+OK\n")); }); - settingsRegisterCommand(F("HA.CLEAR"), [](Embedis* e) { + terminalRegisterCommand(F("HA.CLEAR"), [](Embedis* e) { setSetting("haEnabled", "0"); _haConfigure(); #if WEB_SUPPORT diff --git a/code/espurna/i2c.ino b/code/espurna/i2c.ino index b614c691..b9e6a84b 100644 --- a/code/espurna/i2c.ino +++ b/code/espurna/i2c.ino @@ -351,6 +351,20 @@ void i2cScan() { if (nDevices == 0) DEBUG_MSG_P(PSTR("[I2C] No devices found\n")); } +void i2cCommands() { + + terminalRegisterCommand(F("I2C.SCAN"), [](Embedis* e) { + i2cScan(); + DEBUG_MSG_P(PSTR("+OK\n")); + }); + + terminalRegisterCommand(F("I2C.CLEAR"), [](Embedis* e) { + i2cClearBus(); + DEBUG_MSG_P(PSTR("+OK\n")); + }); + +} + void i2cSetup() { unsigned char sda = getSetting("i2cSDA", I2C_SDA_PIN).toInt(); @@ -366,6 +380,10 @@ void i2cSetup() { DEBUG_MSG_P(PSTR("[I2C] Using GPIO%u for SDA and GPIO%u for SCL\n"), sda, scl); + #if TERMINAL_SUPPORT + i2cCommands(); + #endif + #if I2C_CLEAR_BUS i2cClearBus(); #endif diff --git a/code/espurna/light.ino b/code/espurna/light.ino index 3269ed8d..738d1d12 100644 --- a/code/espurna/light.ino +++ b/code/espurna/light.ino @@ -972,7 +972,7 @@ void _lightAPISetup() { void _lightInitCommands() { - settingsRegisterCommand(F("BRIGHTNESS"), [](Embedis* e) { + terminalRegisterCommand(F("BRIGHTNESS"), [](Embedis* e) { if (e->argc > 1) { lightBrightness(String(e->argv[1]).toInt()); lightUpdate(true, true); @@ -981,7 +981,7 @@ void _lightInitCommands() { DEBUG_MSG_P(PSTR("+OK\n")); }); - settingsRegisterCommand(F("CHANNEL"), [](Embedis* e) { + terminalRegisterCommand(F("CHANNEL"), [](Embedis* e) { if (e->argc < 2) { DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n")); } @@ -995,7 +995,7 @@ void _lightInitCommands() { DEBUG_MSG_P(PSTR("+OK\n")); }); - settingsRegisterCommand(F("COLOR"), [](Embedis* e) { + terminalRegisterCommand(F("COLOR"), [](Embedis* e) { if (e->argc > 1) { String color = String(e->argv[1]); lightColor(color.c_str()); @@ -1005,7 +1005,7 @@ void _lightInitCommands() { DEBUG_MSG_P(PSTR("+OK\n")); }); - settingsRegisterCommand(F("KELVIN"), [](Embedis* e) { + terminalRegisterCommand(F("KELVIN"), [](Embedis* e) { if (e->argc > 1) { String color = String("K") + String(e->argv[1]); lightColor(color.c_str()); @@ -1015,7 +1015,7 @@ void _lightInitCommands() { DEBUG_MSG_P(PSTR("+OK\n")); }); - settingsRegisterCommand(F("MIRED"), [](Embedis* e) { + terminalRegisterCommand(F("MIRED"), [](Embedis* e) { if (e->argc > 1) { String color = String("M") + String(e->argv[1]); lightColor(color.c_str()); diff --git a/code/espurna/mqtt.ino b/code/espurna/mqtt.ino index 882f32fa..12e8b99e 100644 --- a/code/espurna/mqtt.ino +++ b/code/espurna/mqtt.ino @@ -350,7 +350,7 @@ void _mqttWebSocketOnSend(JsonObject& root) { void _mqttInitCommands() { - settingsRegisterCommand(F("MQTT.RESET"), [](Embedis* e) { + terminalRegisterCommand(F("MQTT.RESET"), [](Embedis* e) { _mqttConfigure(); mqttDisconnect(); DEBUG_MSG_P(PSTR("+OK\n")); diff --git a/code/espurna/nofuss.ino b/code/espurna/nofuss.ino index f170ed7d..ad9fd4d2 100644 --- a/code/espurna/nofuss.ino +++ b/code/espurna/nofuss.ino @@ -74,7 +74,7 @@ void _nofussConfigure() { void _nofussInitCommands() { - settingsRegisterCommand(F("NOFUSS"), [](Embedis* e) { + terminalRegisterCommand(F("NOFUSS"), [](Embedis* e) { DEBUG_MSG_P(PSTR("+OK\n")); nofussRun(); }); diff --git a/code/espurna/ota.ino b/code/espurna/ota.ino index a6dcaeb5..bf366f8c 100644 --- a/code/espurna/ota.ino +++ b/code/espurna/ota.ino @@ -188,7 +188,7 @@ void _otaFrom(String url) { void _otaInitCommands() { - settingsRegisterCommand(F("OTA"), [](Embedis* e) { + terminalRegisterCommand(F("OTA"), [](Embedis* e) { if (e->argc < 2) { DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n")); } else { diff --git a/code/espurna/relay.ino b/code/espurna/relay.ino index 897b19d6..338ecbba 100644 --- a/code/espurna/relay.ino +++ b/code/espurna/relay.ino @@ -983,7 +983,7 @@ void relaySetupMQTT() { void _relayInitCommands() { - settingsRegisterCommand(F("RELAY"), [](Embedis* e) { + terminalRegisterCommand(F("RELAY"), [](Embedis* e) { if (e->argc < 2) { DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n")); return; diff --git a/code/espurna/rfbridge.ino b/code/espurna/rfbridge.ino index 818280dc..3524fb06 100644 --- a/code/espurna/rfbridge.ino +++ b/code/espurna/rfbridge.ino @@ -605,7 +605,7 @@ void _rfbAPISetup() { void _rfbInitCommands() { - settingsRegisterCommand(F("LEARN"), [](Embedis* e) { + terminalRegisterCommand(F("LEARN"), [](Embedis* e) { if (e->argc < 3) { DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n")); @@ -626,7 +626,7 @@ void _rfbInitCommands() { }); - settingsRegisterCommand(F("FORGET"), [](Embedis* e) { + terminalRegisterCommand(F("FORGET"), [](Embedis* e) { if (e->argc < 3) { DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n")); diff --git a/code/espurna/sensor.ino b/code/espurna/sensor.ino index 8e9e99a7..cce02dda 100644 --- a/code/espurna/sensor.ino +++ b/code/espurna/sensor.ino @@ -271,7 +271,7 @@ void _sensorAPISetup() { #if TERMINAL_SUPPORT void _sensorInitCommands() { - settingsRegisterCommand(F("MAGNITUDES"), [](Embedis* e) { + terminalRegisterCommand(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"), @@ -285,7 +285,7 @@ void _sensorInitCommands() { DEBUG_MSG_P(PSTR("+OK\n")); }); #if PZEM004T_SUPPORT - settingsRegisterCommand(F("PZ.ADDRESS"), [](Embedis* e) { + terminalRegisterCommand(F("PZ.ADDRESS"), [](Embedis* e) { if (e->argc == 1) { DEBUG_MSG_P(PSTR("[SENSOR] PZEM004T\n")); unsigned char dev_count = pzem004t_sensor->getAddressesCount(); @@ -306,7 +306,7 @@ void _sensorInitCommands() { DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n")); } }); - settingsRegisterCommand(F("PZ.RESET"), [](Embedis* e) { + terminalRegisterCommand(F("PZ.RESET"), [](Embedis* e) { if(e->argc > 2) { DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n")); } else { @@ -321,7 +321,7 @@ void _sensorInitCommands() { DEBUG_MSG_P(PSTR("+OK\n")); } }); - settingsRegisterCommand(F("PZ.VALUE"), [](Embedis* e) { + terminalRegisterCommand(F("PZ.VALUE"), [](Embedis* e) { if(e->argc > 2) { DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n")); } else { diff --git a/code/espurna/settings.ino b/code/espurna/settings.ino index 1678017d..8d323d02 100644 --- a/code/espurna/settings.ino +++ b/code/espurna/settings.ino @@ -2,25 +2,12 @@ SETTINGS MODULE -Copyright (C) 2016-2018 by Xose Pérez +Copyright (C) 2016-2019 by Xose Pérez */ -#include #include #include "libs/EmbedisWrap.h" -#include -#include "libs/StreamInjector.h" - -StreamInjector _serial = StreamInjector(TERMINAL_BUFFER_SIZE); -EmbedisWrap embedis(_serial, TERMINAL_BUFFER_SIZE); - -#if TERMINAL_SUPPORT -#if SERIAL_RX_ENABLED - char _serial_rx_buffer[TERMINAL_BUFFER_SIZE]; - static unsigned char _serial_rx_pointer = 0; -#endif // SERIAL_RX_ENABLED -#endif // TERMINAL_SUPPORT // ----------------------------------------------------------------------------- // Reverse engineering EEPROM storage format @@ -106,214 +93,6 @@ std::vector _settingsKeys() { return keys; } -// ----------------------------------------------------------------------------- -// Commands -// ----------------------------------------------------------------------------- - -void _settingsHelpCommand() { - - // Get sorted list of commands - std::vector commands; - unsigned char size = embedis.getCommandCount(); - for (unsigned int i=0; i 0) { - commands.insert(commands.begin() + j, command); - inserted = true; - break; - } - - } - - // If we could not insert it, just push it at the end - if (!inserted) commands.push_back(command); - - } - - // Output the list - DEBUG_MSG_P(PSTR("Available commands:\n")); - for (unsigned char i=0; i %s\n"), (commands[i]).c_str()); - } - -} - -void _settingsKeysCommand() { - - // Get sorted list of keys - std::vector keys = _settingsKeys(); - - // Write key-values - DEBUG_MSG_P(PSTR("Current settings:\n")); - for (unsigned int i=0; i %s => \"%s\"\n"), (keys[i]).c_str(), value.c_str()); - } - - unsigned long freeEEPROM = SPI_FLASH_SEC_SIZE - settingsSize(); - DEBUG_MSG_P(PSTR("Number of keys: %d\n"), keys.size()); - DEBUG_MSG_P(PSTR("Current EEPROM sector: %u\n"), EEPROMr.current()); - DEBUG_MSG_P(PSTR("Free EEPROM: %d bytes (%d%%)\n"), freeEEPROM, 100 * freeEEPROM / SPI_FLASH_SEC_SIZE); - -} - -void _settingsFactoryResetCommand() { - for (unsigned int i = 0; i < SPI_FLASH_SEC_SIZE; i++) { - EEPROMr.write(i, 0xFF); - } - EEPROMr.commit(); -} - -void _settingsInitCommands() { - - #if DEBUG_SUPPORT - settingsRegisterCommand(F("CRASH"), [](Embedis* e) { - crashDump(); - crashClear(); - DEBUG_MSG_P(PSTR("+OK\n")); - }); - #endif - - settingsRegisterCommand(F("COMMANDS"), [](Embedis* e) { - _settingsHelpCommand(); - DEBUG_MSG_P(PSTR("+OK\n")); - }); - - settingsRegisterCommand(F("ERASE.CONFIG"), [](Embedis* e) { - DEBUG_MSG_P(PSTR("+OK\n")); - resetReason(CUSTOM_RESET_TERMINAL); - _eepromCommit(); - ESP.eraseConfig(); - *((int*) 0) = 0; // see https://github.com/esp8266/Arduino/issues/1494 - }); - - #if I2C_SUPPORT - - settingsRegisterCommand(F("I2C.SCAN"), [](Embedis* e) { - i2cScan(); - DEBUG_MSG_P(PSTR("+OK\n")); - }); - - settingsRegisterCommand(F("I2C.CLEAR"), [](Embedis* e) { - i2cClearBus(); - DEBUG_MSG_P(PSTR("+OK\n")); - }); - - #endif - - settingsRegisterCommand(F("FACTORY.RESET"), [](Embedis* e) { - _settingsFactoryResetCommand(); - DEBUG_MSG_P(PSTR("+OK\n")); - }); - - settingsRegisterCommand(F("GPIO"), [](Embedis* e) { - if (e->argc < 2) { - DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n")); - return; - } - int pin = String(e->argv[1]).toInt(); - //if (!gpioValid(pin)) { - // DEBUG_MSG_P(PSTR("-ERROR: Invalid GPIO\n")); - // return; - //} - if (e->argc > 2) { - bool state = String(e->argv[2]).toInt() == 1; - digitalWrite(pin, state); - } - DEBUG_MSG_P(PSTR("GPIO %d is %s\n"), pin, digitalRead(pin) == HIGH ? "HIGH" : "LOW"); - DEBUG_MSG_P(PSTR("+OK\n")); - }); - - settingsRegisterCommand(F("HEAP"), [](Embedis* e) { - infoMemory("Heap", getInitialFreeHeap(), getFreeHeap()); - DEBUG_MSG_P(PSTR("+OK\n")); - }); - - settingsRegisterCommand(F("STACK"), [](Embedis* e) { - infoMemory("Stack", 4096, getFreeStack()); - DEBUG_MSG_P(PSTR("+OK\n")); - }); - - settingsRegisterCommand(F("HELP"), [](Embedis* e) { - _settingsHelpCommand(); - DEBUG_MSG_P(PSTR("+OK\n")); - }); - - settingsRegisterCommand(F("INFO"), [](Embedis* e) { - info(); - DEBUG_MSG_P(PSTR("+OK\n")); - }); - - settingsRegisterCommand(F("KEYS"), [](Embedis* e) { - _settingsKeysCommand(); - DEBUG_MSG_P(PSTR("+OK\n")); - }); - - settingsRegisterCommand(F("GET"), [](Embedis* e) { - if (e->argc < 2) { - DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n")); - return; - } - - for (unsigned char i = 1; i < e->argc; i++) { - String key = String(e->argv[i]); - String value; - if (!Embedis::get(key, value)) { - DEBUG_MSG_P(PSTR("> %s =>\n"), key.c_str()); - continue; - } - - DEBUG_MSG_P(PSTR("> %s => \"%s\"\n"), key.c_str(), value.c_str()); - } - - DEBUG_MSG_P(PSTR("+OK\n")); - }); - - settingsRegisterCommand(F("RELOAD"), [](Embedis* e) { - espurnaReload(); - DEBUG_MSG_P(PSTR("+OK\n")); - }); - - settingsRegisterCommand(F("RESET"), [](Embedis* e) { - DEBUG_MSG_P(PSTR("+OK\n")); - deferredReset(100, CUSTOM_RESET_TERMINAL); - }); - - settingsRegisterCommand(F("RESET.SAFE"), [](Embedis* e) { - EEPROMr.write(EEPROM_CRASH_COUNTER, SYSTEM_CHECK_MAX); - DEBUG_MSG_P(PSTR("+OK\n")); - deferredReset(100, CUSTOM_RESET_TERMINAL); - }); - - settingsRegisterCommand(F("UPTIME"), [](Embedis* e) { - DEBUG_MSG_P(PSTR("Uptime: %d seconds\n"), getUptime()); - DEBUG_MSG_P(PSTR("+OK\n")); - }); - - settingsRegisterCommand(F("CONFIG"), [](Embedis* e) { - DynamicJsonBuffer jsonBuffer; - JsonObject& root = jsonBuffer.createObject(); - settingsGetJson(root); - String output; - root.printTo(output); - DEBUG_MSG(output.c_str()); - DEBUG_MSG_P(PSTR("\n+OK\n")); - }); - - #if not SETTINGS_AUTOSAVE - settingsRegisterCommand(F("SAVE"), [](Embedis* e) { - eepromCommit(); - DEBUG_MSG_P(PSTR("\n+OK\n")); - }); - #endif - -} - // ----------------------------------------------------------------------------- // Key-value API // ----------------------------------------------------------------------------- @@ -369,21 +148,16 @@ void saveSettings() { } void resetSettings() { - _settingsFactoryResetCommand(); + for (unsigned int i = 0; i < SPI_FLASH_SEC_SIZE; i++) { + EEPROMr.write(i, 0xFF); + } + EEPROMr.commit(); } // ----------------------------------------------------------------------------- -// Settings +// API // ----------------------------------------------------------------------------- -void settingsInject(void *data, size_t len) { - _serial.inject((char *) data, len); -} - -Stream & settingsSerial() { - return (Stream &) _serial; -} - size_t settingsMaxSize() { size_t size = EEPROM_SIZE; if (size > SPI_FLASH_SEC_SIZE) size = SPI_FLASH_SEC_SIZE; @@ -437,25 +211,12 @@ void settingsGetJson(JsonObject& root) { } -void settingsRegisterCommand(const String& name, void (*call)(Embedis*)) { - Embedis::command(name, call); -}; - // ----------------------------------------------------------------------------- // Initialization // ----------------------------------------------------------------------------- void settingsSetup() { - _serial.callback([](uint8_t ch) { - #if TELNET_SUPPORT - telnetWrite(ch); - #endif - #if DEBUG_SERIAL_SUPPORT - DEBUG_PORT.write(ch); - #endif - }); - Embedis::dictionary( F("EEPROM"), SPI_FLASH_SEC_SIZE, [](size_t pos) -> char { return EEPROMr.read(pos); }, @@ -467,44 +228,4 @@ void settingsSetup() { #endif ); - _settingsInitCommands(); - - #if TERMINAL_SUPPORT - #if SERIAL_RX_ENABLED - SERIAL_RX_PORT.begin(SERIAL_RX_BAUDRATE); - #endif // SERIAL_RX_ENABLED - #endif // TERMINAL_SUPPORT - - // Register loop - espurnaRegisterLoop(settingsLoop); - -} - -void settingsLoop() { - - #if TERMINAL_SUPPORT - - #if DEBUG_SERIAL_SUPPORT - while (DEBUG_PORT.available()) { - _serial.inject(DEBUG_PORT.read()); - } - #endif - - embedis.process(); - - #if SERIAL_RX_ENABLED - - while (SERIAL_RX_PORT.available() > 0) { - char rc = Serial.read(); - _serial_rx_buffer[_serial_rx_pointer++] = rc; - if ((_serial_rx_pointer == TERMINAL_BUFFER_SIZE) || (rc == 10)) { - settingsInject(_serial_rx_buffer, (size_t) _serial_rx_pointer); - _serial_rx_pointer = 0; - } - } - - #endif // SERIAL_RX_ENABLED - - #endif // TERMINAL_SUPPORT - -} +} \ No newline at end of file diff --git a/code/espurna/telnet.ino b/code/espurna/telnet.ino index 00b009b1..b4b53c7c 100644 --- a/code/espurna/telnet.ino +++ b/code/espurna/telnet.ino @@ -113,7 +113,9 @@ void _telnetData(unsigned char clientId, void *data, size_t len) { } // Inject command - settingsInject(data, len); + #if TERMINAL_SUPPORT + terminalInject(data, len); + #endif } diff --git a/code/espurna/terminal.ino b/code/espurna/terminal.ino new file mode 100644 index 00000000..6164f38c --- /dev/null +++ b/code/espurna/terminal.ino @@ -0,0 +1,275 @@ +/* + +TERMINAL MODULE + +Copyright (C) 2016-2019 by Xose Pérez + +*/ + +#if TERMINAL_SUPPORT + +#include +#include "libs/EmbedisWrap.h" +#include +#include "libs/StreamInjector.h" + +StreamInjector _serial = StreamInjector(TERMINAL_BUFFER_SIZE); +EmbedisWrap embedis(_serial, TERMINAL_BUFFER_SIZE); + +#if SERIAL_RX_ENABLED + char _serial_rx_buffer[TERMINAL_BUFFER_SIZE]; + static unsigned char _serial_rx_pointer = 0; +#endif // SERIAL_RX_ENABLED + +// ----------------------------------------------------------------------------- +// Commands +// ----------------------------------------------------------------------------- + +void _terminalHelpCommand() { + + // Get sorted list of commands + std::vector commands; + unsigned char size = embedis.getCommandCount(); + for (unsigned int i=0; i 0) { + commands.insert(commands.begin() + j, command); + inserted = true; + break; + } + + } + + // If we could not insert it, just push it at the end + if (!inserted) commands.push_back(command); + + } + + // Output the list + DEBUG_MSG_P(PSTR("Available commands:\n")); + for (unsigned char i=0; i %s\n"), (commands[i]).c_str()); + } + +} + +void _terminalKeysCommand() { + + // Get sorted list of keys + std::vector keys = _settingsKeys(); + + // Write key-values + DEBUG_MSG_P(PSTR("Current settings:\n")); + for (unsigned int i=0; i %s => \"%s\"\n"), (keys[i]).c_str(), value.c_str()); + } + + unsigned long freeEEPROM = SPI_FLASH_SEC_SIZE - settingsSize(); + DEBUG_MSG_P(PSTR("Number of keys: %d\n"), keys.size()); + DEBUG_MSG_P(PSTR("Current EEPROM sector: %u\n"), EEPROMr.current()); + DEBUG_MSG_P(PSTR("Free EEPROM: %d bytes (%d%%)\n"), freeEEPROM, 100 * freeEEPROM / SPI_FLASH_SEC_SIZE); + +} + +void _terminalInitCommand() { + + #if DEBUG_SUPPORT + terminalRegisterCommand(F("CRASH"), [](Embedis* e) { + crashDump(); + crashClear(); + DEBUG_MSG_P(PSTR("+OK\n")); + }); + #endif + + terminalRegisterCommand(F("COMMANDS"), [](Embedis* e) { + _terminalHelpCommand(); + DEBUG_MSG_P(PSTR("+OK\n")); + }); + + terminalRegisterCommand(F("ERASE.CONFIG"), [](Embedis* e) { + DEBUG_MSG_P(PSTR("+OK\n")); + resetReason(CUSTOM_RESET_TERMINAL); + _eepromCommit(); + ESP.eraseConfig(); + *((int*) 0) = 0; // see https://github.com/esp8266/Arduino/issues/1494 + }); + + terminalRegisterCommand(F("FACTORY.RESET"), [](Embedis* e) { + resetSettings(); + DEBUG_MSG_P(PSTR("+OK\n")); + }); + + terminalRegisterCommand(F("GPIO"), [](Embedis* e) { + if (e->argc < 2) { + DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n")); + return; + } + int pin = String(e->argv[1]).toInt(); + //if (!gpioValid(pin)) { + // DEBUG_MSG_P(PSTR("-ERROR: Invalid GPIO\n")); + // return; + //} + if (e->argc > 2) { + bool state = String(e->argv[2]).toInt() == 1; + digitalWrite(pin, state); + } + DEBUG_MSG_P(PSTR("GPIO %d is %s\n"), pin, digitalRead(pin) == HIGH ? "HIGH" : "LOW"); + DEBUG_MSG_P(PSTR("+OK\n")); + }); + + terminalRegisterCommand(F("HEAP"), [](Embedis* e) { + infoMemory("Heap", getInitialFreeHeap(), getFreeHeap()); + DEBUG_MSG_P(PSTR("+OK\n")); + }); + + terminalRegisterCommand(F("STACK"), [](Embedis* e) { + infoMemory("Stack", 4096, getFreeStack()); + DEBUG_MSG_P(PSTR("+OK\n")); + }); + + terminalRegisterCommand(F("HELP"), [](Embedis* e) { + _terminalHelpCommand(); + DEBUG_MSG_P(PSTR("+OK\n")); + }); + + terminalRegisterCommand(F("INFO"), [](Embedis* e) { + info(); + DEBUG_MSG_P(PSTR("+OK\n")); + }); + + terminalRegisterCommand(F("KEYS"), [](Embedis* e) { + _terminalKeysCommand(); + DEBUG_MSG_P(PSTR("+OK\n")); + }); + + terminalRegisterCommand(F("GET"), [](Embedis* e) { + if (e->argc < 2) { + DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n")); + return; + } + + for (unsigned char i = 1; i < e->argc; i++) { + String key = String(e->argv[i]); + String value; + if (!Embedis::get(key, value)) { + DEBUG_MSG_P(PSTR("> %s =>\n"), key.c_str()); + continue; + } + + DEBUG_MSG_P(PSTR("> %s => \"%s\"\n"), key.c_str(), value.c_str()); + } + + DEBUG_MSG_P(PSTR("+OK\n")); + }); + + terminalRegisterCommand(F("RELOAD"), [](Embedis* e) { + espurnaReload(); + DEBUG_MSG_P(PSTR("+OK\n")); + }); + + terminalRegisterCommand(F("RESET"), [](Embedis* e) { + DEBUG_MSG_P(PSTR("+OK\n")); + deferredReset(100, CUSTOM_RESET_TERMINAL); + }); + + terminalRegisterCommand(F("RESET.SAFE"), [](Embedis* e) { + EEPROMr.write(EEPROM_CRASH_COUNTER, SYSTEM_CHECK_MAX); + DEBUG_MSG_P(PSTR("+OK\n")); + deferredReset(100, CUSTOM_RESET_TERMINAL); + }); + + terminalRegisterCommand(F("UPTIME"), [](Embedis* e) { + DEBUG_MSG_P(PSTR("Uptime: %d seconds\n"), getUptime()); + DEBUG_MSG_P(PSTR("+OK\n")); + }); + + terminalRegisterCommand(F("CONFIG"), [](Embedis* e) { + DynamicJsonBuffer jsonBuffer; + JsonObject& root = jsonBuffer.createObject(); + settingsGetJson(root); + String output; + root.printTo(output); + DEBUG_MSG(output.c_str()); + DEBUG_MSG_P(PSTR("\n+OK\n")); + }); + + #if not SETTINGS_AUTOSAVE + terminalRegisterCommand(F("SAVE"), [](Embedis* e) { + eepromCommit(); + DEBUG_MSG_P(PSTR("\n+OK\n")); + }); + #endif + +} + +void _terminalLoop() { + + #if DEBUG_SERIAL_SUPPORT + while (DEBUG_PORT.available()) { + _serial.inject(DEBUG_PORT.read()); + } + #endif + + embedis.process(); + + #if SERIAL_RX_ENABLED + + while (SERIAL_RX_PORT.available() > 0) { + char rc = Serial.read(); + _serial_rx_buffer[_serial_rx_pointer++] = rc; + if ((_serial_rx_pointer == TERMINAL_BUFFER_SIZE) || (rc == 10)) { + terminalInject(_serial_rx_buffer, (size_t) _serial_rx_pointer); + _serial_rx_pointer = 0; + } + } + + #endif // SERIAL_RX_ENABLED + +} + +// ----------------------------------------------------------------------------- +// Pubic API +// ----------------------------------------------------------------------------- + +void terminalInject(void *data, size_t len) { + _serial.inject((char *) data, len); +} + +Stream & terminalSerial() { + return (Stream &) _serial; +} + +void terminalRegisterCommand(const String& name, void (*call)(Embedis*)) { + Embedis::command(name, call); +}; + +void terminalSetup() { + + _serial.callback([](uint8_t ch) { + #if TELNET_SUPPORT + telnetWrite(ch); + #endif + #if DEBUG_SERIAL_SUPPORT + DEBUG_PORT.write(ch); + #endif + }); + + _terminalInitCommand(); + + #if SERIAL_RX_ENABLED + SERIAL_RX_PORT.begin(SERIAL_RX_BAUDRATE); + #endif // SERIAL_RX_ENABLED + + // Register loop + espurnaRegisterLoop(_terminalLoop); + +} + +#endif // TERMINAL_SUPPORT + diff --git a/code/espurna/wifi.ino b/code/espurna/wifi.ino index 7ce93208..78dd79ab 100644 --- a/code/espurna/wifi.ino +++ b/code/espurna/wifi.ino @@ -385,37 +385,37 @@ void _wifiDebugCallback(justwifi_messages_t code, char * parameter) { void _wifiInitCommands() { - settingsRegisterCommand(F("WIFI"), [](Embedis* e) { + terminalRegisterCommand(F("WIFI"), [](Embedis* e) { wifiDebug(); DEBUG_MSG_P(PSTR("+OK\n")); }); - settingsRegisterCommand(F("WIFI.RESET"), [](Embedis* e) { + terminalRegisterCommand(F("WIFI.RESET"), [](Embedis* e) { _wifiConfigure(); wifiDisconnect(); DEBUG_MSG_P(PSTR("+OK\n")); }); - settingsRegisterCommand(F("WIFI.AP"), [](Embedis* e) { + terminalRegisterCommand(F("WIFI.AP"), [](Embedis* e) { wifiStartAP(); DEBUG_MSG_P(PSTR("+OK\n")); }); #if defined(JUSTWIFI_ENABLE_WPS) - settingsRegisterCommand(F("WIFI.WPS"), [](Embedis* e) { + terminalRegisterCommand(F("WIFI.WPS"), [](Embedis* e) { wifiStartWPS(); DEBUG_MSG_P(PSTR("+OK\n")); }); #endif // defined(JUSTWIFI_ENABLE_WPS) #if defined(JUSTWIFI_ENABLE_SMARTCONFIG) - settingsRegisterCommand(F("WIFI.SMARTCONFIG"), [](Embedis* e) { + terminalRegisterCommand(F("WIFI.SMARTCONFIG"), [](Embedis* e) { wifiStartSmartConfig(); DEBUG_MSG_P(PSTR("+OK\n")); }); #endif // defined(JUSTWIFI_ENABLE_SMARTCONFIG) - settingsRegisterCommand(F("WIFI.SCAN"), [](Embedis* e) { + terminalRegisterCommand(F("WIFI.SCAN"), [](Embedis* e) { _wifiScan(); DEBUG_MSG_P(PSTR("+OK\n")); });