mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-23 08:06:13 +01:00
Compare commits
4 Commits
277431e84c
...
4aa353edbc
Author | SHA1 | Date | |
---|---|---|---|
|
4aa353edbc | ||
|
c1d6ee2804 | ||
|
14360b4198 | ||
|
dd898d3c16 |
|
@ -117,6 +117,9 @@ Once a new OPCODE is decided upon, update this list.
|
||||||
#include "Turntables.h"
|
#include "Turntables.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "KeywordHasher.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
|
// This macro can't be created easily as a portable function because the
|
||||||
// flashlist requires a far pointer for high flash access.
|
// 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.
|
// 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 state = 1;
|
||||||
byte parameterCount = 0;
|
byte parameterCount = 0;
|
||||||
int16_t runningValue = 0;
|
int16_t runningValue = 0;
|
||||||
const byte *remainingCmd = cmd + 1; // skips the opcode
|
byte *remainingCmd = cmd + 1; // skips the opcode
|
||||||
bool signNegative = false;
|
bool signNegative = false;
|
||||||
|
|
||||||
// clear all parameters in case not enough found
|
// 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)
|
while (parameterCount < MAX_COMMAND_PARAMS)
|
||||||
{
|
{
|
||||||
byte hot = *remainingCmd;
|
byte hot = *remainingCmd;
|
||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -169,7 +171,22 @@ int16_t DCCEXParser::splitValues(int16_t result[MAX_COMMAND_PARAMS], const byte
|
||||||
state = 2;
|
state = 2;
|
||||||
continue;
|
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;
|
signNegative = false;
|
||||||
runningValue = 0;
|
runningValue = 0;
|
||||||
state = 3;
|
state = 3;
|
||||||
|
@ -200,6 +217,16 @@ int16_t DCCEXParser::splitValues(int16_t result[MAX_COMMAND_PARAMS], const byte
|
||||||
parameterCount++;
|
parameterCount++;
|
||||||
state = 1;
|
state = 1;
|
||||||
continue;
|
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++;
|
remainingCmd++;
|
||||||
}
|
}
|
||||||
|
@ -645,6 +672,19 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
|
||||||
StringFormatter::send(stream, F("\n"));
|
StringFormatter::send(stream, F("\n"));
|
||||||
return;
|
return;
|
||||||
case 'C': // CONFIG <C [params]>
|
case 'C': // CONFIG <C [params]>
|
||||||
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
|
// currently this only works on ESP32
|
||||||
|
#if defined(HAS_ENOUGH_MEMORY)
|
||||||
|
if (p[0] == "WIFI"_hk) { // <C WIFI SSID PASSWORD>
|
||||||
|
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))
|
if (parseC(stream, params, p))
|
||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
|
@ -1140,8 +1180,7 @@ bool DCCEXParser::parseC(Print *stream, int16_t params, int16_t p[]) {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
|
default: // invalid/unknown
|
||||||
default: // invalid/unknown
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -43,7 +43,7 @@ struct DCCEXParser
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static const int16_t MAX_BUFFER=50; // longest command sent in
|
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 parseT(Print * stream, int16_t params, int16_t p[]);
|
||||||
static bool parseZ(Print * stream, int16_t params, int16_t p[]);
|
static bool parseZ(Print * stream, int16_t params, int16_t p[]);
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
#define GITHUB_SHA "devel-202409121220Z"
|
#define GITHUB_SHA "devel-202409221903Z"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* © 2022 Paul M. Antoine
|
* © 2022 Paul M. Antoine
|
||||||
* © 2021 Chris Harlow
|
* © 2021 Chris Harlow
|
||||||
* © 2022 Harald Barth
|
* © 2022 2024 Harald Barth
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This file is part of DCC++EX
|
* This file is part of DCC++EX
|
||||||
|
@ -23,6 +23,7 @@
|
||||||
#include "SerialManager.h"
|
#include "SerialManager.h"
|
||||||
#include "DCCEXParser.h"
|
#include "DCCEXParser.h"
|
||||||
#include "StringFormatter.h"
|
#include "StringFormatter.h"
|
||||||
|
#include "DIAG.h"
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
#ifdef SERIAL_BT_COMMANDS
|
#ifdef SERIAL_BT_COMMANDS
|
||||||
|
@ -36,6 +37,10 @@ BluetoothSerial SerialBT;
|
||||||
#endif //COMMANDS
|
#endif //COMMANDS
|
||||||
#endif //ESP32
|
#endif //ESP32
|
||||||
|
|
||||||
|
static const byte PAYLOAD_FALSE = 0;
|
||||||
|
static const byte PAYLOAD_NORMAL = 1;
|
||||||
|
static const byte PAYLOAD_STRING = 2;
|
||||||
|
|
||||||
SerialManager * SerialManager::first=NULL;
|
SerialManager * SerialManager::first=NULL;
|
||||||
|
|
||||||
SerialManager::SerialManager(Stream * myserial) {
|
SerialManager::SerialManager(Stream * myserial) {
|
||||||
|
@ -43,7 +48,7 @@ SerialManager::SerialManager(Stream * myserial) {
|
||||||
next=first;
|
next=first;
|
||||||
first=this;
|
first=this;
|
||||||
bufferLength=0;
|
bufferLength=0;
|
||||||
inCommandPayload=false;
|
inCommandPayload=PAYLOAD_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SerialManager::init() {
|
void SerialManager::init() {
|
||||||
|
@ -114,21 +119,37 @@ void SerialManager::loop() {
|
||||||
void SerialManager::loop2() {
|
void SerialManager::loop2() {
|
||||||
while (serial->available()) {
|
while (serial->available()) {
|
||||||
char ch = serial->read();
|
char ch = serial->read();
|
||||||
|
if (!inCommandPayload) {
|
||||||
if (ch == '<') {
|
if (ch == '<') {
|
||||||
inCommandPayload = true;
|
inCommandPayload = PAYLOAD_NORMAL;
|
||||||
bufferLength = 0;
|
bufferLength = 0;
|
||||||
buffer[0] = '\0';
|
buffer[0] = '\0';
|
||||||
}
|
}
|
||||||
else if (inCommandPayload) {
|
} else { // if (inCommandPayload)
|
||||||
if (bufferLength < (COMMAND_BUFFER_SIZE-1))
|
if (bufferLength < (COMMAND_BUFFER_SIZE-1))
|
||||||
buffer[bufferLength++] = ch;
|
buffer[bufferLength++] = ch;
|
||||||
|
if (inCommandPayload > PAYLOAD_NORMAL) {
|
||||||
|
if (inCommandPayload > 32 + 2) { // String way too long
|
||||||
|
ch = '>'; // we end this nonsense
|
||||||
|
inCommandPayload = PAYLOAD_NORMAL;
|
||||||
|
DIAG(F("Parse error: Unbalanced string"));
|
||||||
|
// fall through to ending parsing below
|
||||||
|
} else if (ch == '"') { // String end
|
||||||
|
inCommandPayload = PAYLOAD_NORMAL;
|
||||||
|
continue; // do not fall through
|
||||||
|
} else
|
||||||
|
inCommandPayload++;
|
||||||
|
}
|
||||||
|
if (inCommandPayload == PAYLOAD_NORMAL) {
|
||||||
if (ch == '>') {
|
if (ch == '>') {
|
||||||
buffer[bufferLength] = '\0';
|
buffer[bufferLength] = '\0';
|
||||||
DCCEXParser::parse(serial, buffer, NULL);
|
DCCEXParser::parse(serial, buffer, NULL);
|
||||||
inCommandPayload = false;
|
inCommandPayload = PAYLOAD_FALSE;
|
||||||
break;
|
break;
|
||||||
|
} else if (ch == '"') {
|
||||||
|
inCommandPayload = PAYLOAD_STRING;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,6 @@ private:
|
||||||
SerialManager * next;
|
SerialManager * next;
|
||||||
byte bufferLength;
|
byte bufferLength;
|
||||||
byte buffer[COMMAND_BUFFER_SIZE];
|
byte buffer[COMMAND_BUFFER_SIZE];
|
||||||
bool inCommandPayload;
|
byte inCommandPayload;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -23,13 +23,13 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
#include "ESPmDNS.h"
|
#include "ESPmDNS.h"
|
||||||
#include <WiFi.h>
|
|
||||||
#include "esp_wifi.h"
|
#include "esp_wifi.h"
|
||||||
#include "WifiESP32.h"
|
#include "WifiESP32.h"
|
||||||
#include "DIAG.h"
|
#include "DIAG.h"
|
||||||
#include "RingStream.h"
|
#include "RingStream.h"
|
||||||
#include "CommandDistributor.h"
|
#include "CommandDistributor.h"
|
||||||
#include "WiThrottle.h"
|
#include "WiThrottle.h"
|
||||||
|
#include "DCC.h"
|
||||||
/*
|
/*
|
||||||
#include "soc/rtc_wdt.h"
|
#include "soc/rtc_wdt.h"
|
||||||
#include "esp_task_wdt.h"
|
#include "esp_task_wdt.h"
|
||||||
|
@ -109,10 +109,13 @@ private:
|
||||||
bool inUse;
|
bool inUse;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// file scope variables
|
||||||
static std::vector<NetworkClient> clients; // a list to hold all clients
|
static std::vector<NetworkClient> clients; // a list to hold all clients
|
||||||
static WiFiServer *server = NULL;
|
|
||||||
static RingStream *outboundRing = new RingStream(10240);
|
static RingStream *outboundRing = new RingStream(10240);
|
||||||
static bool APmode = false;
|
static bool APmode = false;
|
||||||
|
// init of static class scope variables
|
||||||
|
bool WifiESP::wifiUp = false;
|
||||||
|
WiFiServer *WifiESP::server = NULL;
|
||||||
|
|
||||||
#ifdef WIFI_TASK_ON_CORE0
|
#ifdef WIFI_TASK_ON_CORE0
|
||||||
void wifiLoop(void *){
|
void wifiLoop(void *){
|
||||||
|
@ -128,6 +131,30 @@ char asciitolower(char in) {
|
||||||
return 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,
|
bool WifiESP::setup(const char *SSid,
|
||||||
const char *password,
|
const char *password,
|
||||||
const char *hostname,
|
const char *hostname,
|
||||||
|
@ -136,8 +163,10 @@ bool WifiESP::setup(const char *SSid,
|
||||||
const bool forceAP) {
|
const bool forceAP) {
|
||||||
bool havePassword = true;
|
bool havePassword = true;
|
||||||
bool haveSSID = true;
|
bool haveSSID = true;
|
||||||
bool wifiUp = false;
|
// bool wifiUp = false;
|
||||||
uint8_t tries = 40;
|
uint8_t tries = 40;
|
||||||
|
if (wifiUp)
|
||||||
|
teardown();
|
||||||
|
|
||||||
//#ifdef SERIAL_BT_COMMANDS
|
//#ifdef SERIAL_BT_COMMANDS
|
||||||
//return false;
|
//return false;
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#ifndef WifiESP32_h
|
#ifndef WifiESP32_h
|
||||||
#define WifiESP32_h
|
#define WifiESP32_h
|
||||||
|
|
||||||
|
#include <WiFi.h>
|
||||||
#include "FSH.h"
|
#include "FSH.h"
|
||||||
|
|
||||||
class WifiESP
|
class WifiESP
|
||||||
|
@ -36,6 +37,9 @@ public:
|
||||||
const bool forceAP);
|
const bool forceAP);
|
||||||
static void loop();
|
static void loop();
|
||||||
private:
|
private:
|
||||||
|
static void teardown();
|
||||||
|
static bool wifiUp;
|
||||||
|
static WiFiServer *server;
|
||||||
};
|
};
|
||||||
#endif //WifiESP8266_h
|
#endif //WifiESP8266_h
|
||||||
#endif //ESP8266
|
#endif //ESP8266
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
|
|
||||||
#include "StringFormatter.h"
|
#include "StringFormatter.h"
|
||||||
|
|
||||||
#define VERSION "5.2.78"
|
#define VERSION "5.2.79"
|
||||||
|
// 5.2.79 - serial manager loop that handles quoted strings
|
||||||
|
// - WiFiESP32 reconfig
|
||||||
// 5.2.78 - NeoPixel support.
|
// 5.2.78 - NeoPixel support.
|
||||||
// - <o command
|
// - <o command
|
||||||
// - HAL driver
|
// - HAL driver
|
||||||
|
|
Loading…
Reference in New Issue
Block a user