Browse Source

Move terminal methods to own module

refactor-terminal
Xose Pérez 5 years ago
parent
commit
27e7b9ae89
19 changed files with 361 additions and 330 deletions
  1. +2
    -2
      README.md
  2. +1
    -1
      code/espurna/config/arduino.h
  3. +9
    -3
      code/espurna/config/prototypes.h
  4. +10
    -6
      code/espurna/debug.ino
  5. +6
    -6
      code/espurna/eeprom.ino
  6. +6
    -1
      code/espurna/espurna.ino
  7. +3
    -3
      code/espurna/homeassistant.ino
  8. +18
    -0
      code/espurna/i2c.ino
  9. +5
    -5
      code/espurna/light.ino
  10. +1
    -1
      code/espurna/mqtt.ino
  11. +1
    -1
      code/espurna/nofuss.ino
  12. +1
    -1
      code/espurna/ota.ino
  13. +1
    -1
      code/espurna/relay.ino
  14. +2
    -2
      code/espurna/rfbridge.ino
  15. +4
    -4
      code/espurna/sensor.ino
  16. +7
    -286
      code/espurna/settings.ino
  17. +3
    -1
      code/espurna/telnet.ino
  18. +275
    -0
      code/espurna/terminal.ino
  19. +6
    -6
      code/espurna/wifi.ino

+ 2
- 2
README.md View File

@ -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)
<br />


+ 1
- 1
code/espurna/config/arduino.h View File

@ -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


+ 9
- 3
code/espurna/config/prototypes.h View File

@ -142,9 +142,15 @@ template<typename T> String getSetting(const String& key, T defaultValue);
template<typename T> 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


+ 10
- 6
code/espurna/debug.ino View File

@ -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<const char*>("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<const char*>("command");
char buffer[strlen(command) + 2];
snprintf(buffer, sizeof(buffer), "%s\n", command);
terminalInject((void*) buffer, strlen(buffer));
}
#endif
});
#if DEBUG_UDP_SUPPORT


+ 6
- 6
code/espurna/eeprom.ino View File

@ -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"));
});


+ 6
- 1
code/espurna/espurna.ino View File

@ -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();


+ 3
- 3
code/espurna/homeassistant.ino View File

@ -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


+ 18
- 0
code/espurna/i2c.ino View File

@ -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


+ 5
- 5
code/espurna/light.ino View File

@ -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());


+ 1
- 1
code/espurna/mqtt.ino View File

@ -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"));


+ 1
- 1
code/espurna/nofuss.ino View File

@ -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();
});


+ 1
- 1
code/espurna/ota.ino View File

@ -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 {


+ 1
- 1
code/espurna/relay.ino View File

@ -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;


+ 2
- 2
code/espurna/rfbridge.ino View File

@ -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"));


+ 4
- 4
code/espurna/sensor.ino View File

@ -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 {


+ 7
- 286
code/espurna/settings.ino View File

@ -2,25 +2,12 @@
SETTINGS MODULE
Copyright (C) 2016-2018 by Xose Pérez <xose dot perez at gmail dot com>
Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
*/
#include <EEPROM_Rotate.h>
#include <vector>
#include "libs/EmbedisWrap.h"
#include <Stream.h>
#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<String> _settingsKeys() {
return keys;
}
// -----------------------------------------------------------------------------
// Commands
// -----------------------------------------------------------------------------
void _settingsHelpCommand() {
// Get sorted list of commands
std::vector<String> commands;
unsigned char size = embedis.getCommandCount();
for (unsigned int i=0; i<size; i++) {
String command = embedis.getCommandName(i);
bool inserted = false;
for (unsigned char j=0; j<commands.size(); j++) {
// 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;
}
}
// 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<commands.size(); i++) {
DEBUG_MSG_P(PSTR("> %s\n"), (commands[i]).c_str());
}
}
void _settingsKeysCommand() {
// Get sorted list of keys
std::vector<String> keys = _settingsKeys();
// Write key-values
DEBUG_MSG_P(PSTR("Current settings:\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());
}
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
}
}

+ 3
- 1
code/espurna/telnet.ino View File

@ -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
}


+ 275
- 0
code/espurna/terminal.ino View File

@ -0,0 +1,275 @@
/*
TERMINAL MODULE
Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
*/
#if TERMINAL_SUPPORT
#include <vector>
#include "libs/EmbedisWrap.h"
#include <Stream.h>
#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<String> commands;
unsigned char size = embedis.getCommandCount();
for (unsigned int i=0; i<size; i++) {
String command = embedis.getCommandName(i);
bool inserted = false;
for (unsigned char j=0; j<commands.size(); j++) {
// 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;
}
}
// 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<commands.size(); i++) {
DEBUG_MSG_P(PSTR("> %s\n"), (commands[i]).c_str());
}
}
void _terminalKeysCommand() {
// Get sorted list of keys
std::vector<String> keys = _settingsKeys();
// Write key-values
DEBUG_MSG_P(PSTR("Current settings:\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());
}
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

+ 6
- 6
code/espurna/wifi.ino View File

@ -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"));
});


Loading…
Cancel
Save