diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index fd13a41..c1edebe 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -117,6 +117,9 @@ Once a new OPCODE is decided upon, update this list. #include "Turntables.h" #include "version.h" #include "KeywordHasher.h" +#ifdef ARDUINO_ARCH_ESP32 +#include "WifiESP32.h" +#endif // This macro can't be created easily as a portable function because the // flashlist requires a far pointer for high flash access. @@ -140,12 +143,12 @@ byte DCCEXParser::stashTarget=0; // Non-DCC things like turnouts, pins and sensors are handled in additional JMRI interface classes. -int16_t DCCEXParser::splitValues(int16_t result[MAX_COMMAND_PARAMS], const byte *cmd, bool usehex) +int16_t DCCEXParser::splitValues(int16_t result[MAX_COMMAND_PARAMS], byte *cmd, bool usehex) { byte state = 1; byte parameterCount = 0; int16_t runningValue = 0; - const byte *remainingCmd = cmd + 1; // skips the opcode + byte *remainingCmd = cmd + 1; // skips the opcode bool signNegative = false; // clear all parameters in case not enough found @@ -155,7 +158,6 @@ int16_t DCCEXParser::splitValues(int16_t result[MAX_COMMAND_PARAMS], const byte while (parameterCount < MAX_COMMAND_PARAMS) { byte hot = *remainingCmd; - switch (state) { @@ -169,7 +171,22 @@ int16_t DCCEXParser::splitValues(int16_t result[MAX_COMMAND_PARAMS], const byte state = 2; continue; - case 2: // checking sign + case 2: // checking sign or quoted string +#ifdef HAS_ENOUGH_MEMORY + if (hot == '"') { + // this inserts an extra parameter 0x7777 in front + // of each string parameter as a marker that can + // be checked that a string parameter follows + // This clashes of course with the real value + // 0x7777 which we hope is used seldom + result[parameterCount] = (int16_t)0x7777; + parameterCount++; + result[parameterCount] = (int16_t)(remainingCmd - cmd + 1); + parameterCount++; + state = 4; + break; + } +#endif signNegative = false; runningValue = 0; state = 3; @@ -200,6 +217,16 @@ int16_t DCCEXParser::splitValues(int16_t result[MAX_COMMAND_PARAMS], const byte parameterCount++; state = 1; continue; +#ifdef HAS_ENOUGH_MEMORY + case 4: // skipover text + if (hot == '\0') // We did run to end of buffer without finding the " + return -1; + if (hot == '"') { + *remainingCmd = '\0'; // overwrite " in command buffer with the end-of-string + state = 1; + } + break; +#endif } remainingCmd++; } @@ -616,9 +643,22 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) StringFormatter::send(stream, F("\n")); return; case 'C': // CONFIG - if (parseC(stream, params, p)) - return; - break; +#if defined(ARDUINO_ARCH_ESP32) +// currently this only works on ESP32 +#if defined(HAS_ENOUGH_MEMORY) + if (p[0] == "WIFI"_hk) { // + if (params != 5) // the 5 params 0 to 4 are (kinda): WIFI_hk 0x7777 &SSID 0x7777 &PASSWORD + break; + if (p[1] == 0x7777 && p[3] == 0x7777) { + WifiESP::setup((const char*)(com + p[2]), (const char*)(com + p[4]), WIFI_HOSTNAME, IP_PORT, WIFI_CHANNEL, WIFI_FORCE_AP); + } + return; + } +#endif +#endif //ESP32 + if (parseC(stream, params, p)) + return; + break; #ifndef DISABLE_DIAG case 'D': // DIAG if (parseD(stream, params, p)) @@ -1111,8 +1151,7 @@ bool DCCEXParser::parseC(Print *stream, int16_t params, int16_t p[]) { } return true; #endif - -default: // invalid/unknown + default: // invalid/unknown break; } return false; diff --git a/DCCEXParser.h b/DCCEXParser.h index d3b7851..b9d56ea 100644 --- a/DCCEXParser.h +++ b/DCCEXParser.h @@ -43,7 +43,7 @@ struct DCCEXParser private: static const int16_t MAX_BUFFER=50; // longest command sent in - static int16_t splitValues( int16_t result[MAX_COMMAND_PARAMS], const byte * command, bool usehex); + static int16_t splitValues( int16_t result[MAX_COMMAND_PARAMS], byte * command, bool usehex); static bool parseT(Print * stream, int16_t params, int16_t p[]); static bool parseZ(Print * stream, int16_t params, int16_t p[]); diff --git a/WifiESP32.cpp b/WifiESP32.cpp index d44672a..227484c 100644 --- a/WifiESP32.cpp +++ b/WifiESP32.cpp @@ -23,13 +23,13 @@ #include #include "defines.h" #include "ESPmDNS.h" -#include #include "esp_wifi.h" #include "WifiESP32.h" #include "DIAG.h" #include "RingStream.h" #include "CommandDistributor.h" #include "WiThrottle.h" +#include "DCC.h" /* #include "soc/rtc_wdt.h" #include "esp_task_wdt.h" @@ -109,10 +109,13 @@ private: bool inUse; }; +// file scope variables static std::vector clients; // a list to hold all clients -static WiFiServer *server = NULL; static RingStream *outboundRing = new RingStream(10240); static bool APmode = false; +// init of static class scope variables +bool WifiESP::wifiUp = false; +WiFiServer *WifiESP::server = NULL; #ifdef WIFI_TASK_ON_CORE0 void wifiLoop(void *){ @@ -128,6 +131,30 @@ char asciitolower(char in) { return in; } +void WifiESP::teardown() { + // stop all locos + DCC::setThrottle(0,1,1); // this broadcasts speed 1(estop) and sets all reminders to speed 1. + // terminate all clients connections + while (!clients.empty()) { + // pop_back() should invoke destructor which does stop() + // on the underlying TCP connction + clients.pop_back(); + } + // stop server + if (server != NULL) { + server->stop(); + server->close(); + server->end(); + DIAG(F("server stop, close, end")); + } + // terminate MDNS anouncement + mdns_service_remove_all(); + mdns_free(); + // stop WiFi + WiFi.disconnect(true); + wifiUp = false; +} + bool WifiESP::setup(const char *SSid, const char *password, const char *hostname, @@ -136,8 +163,10 @@ bool WifiESP::setup(const char *SSid, const bool forceAP) { bool havePassword = true; bool haveSSID = true; - bool wifiUp = false; +// bool wifiUp = false; uint8_t tries = 40; + if (wifiUp) + teardown(); //#ifdef SERIAL_BT_COMMANDS //return false; diff --git a/WifiESP32.h b/WifiESP32.h index ec2f560..58cceca 100644 --- a/WifiESP32.h +++ b/WifiESP32.h @@ -22,6 +22,7 @@ #ifndef WifiESP32_h #define WifiESP32_h +#include #include "FSH.h" class WifiESP @@ -36,6 +37,9 @@ public: const bool forceAP); static void loop(); private: + static void teardown(); + static bool wifiUp; + static WiFiServer *server; }; #endif //WifiESP8266_h #endif //ESP8266