1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-11-26 17:46:14 +01:00

ESP32 websockets

This commit is contained in:
Asbelos 2023-12-06 17:12:49 +00:00
parent 2426538e61
commit 48604bf622
4 changed files with 35 additions and 19 deletions

View File

@ -63,8 +63,6 @@ template<typename... Targs> void CommandDistributor::broadcastReply(clientType t
// Parse is called by Withrottle or Ethernet interface to determine which // Parse is called by Withrottle or Ethernet interface to determine which
// protocol the client is using and call the appropriate part of dcc++Ex // protocol the client is using and call the appropriate part of dcc++Ex
void CommandDistributor::parse(byte clientId,byte * buffer, RingStream * stream) { void CommandDistributor::parse(byte clientId,byte * buffer, RingStream * stream) {
if (Diag::WIFI && Diag::CMD)
DIAG(F("Parse C=%d T=%d B=%s"),clientId, clients[clientId], buffer);
ring=stream; ring=stream;
// First check if the client is not known // First check if the client is not known
@ -206,7 +204,9 @@ void CommandDistributor::setClockTime(int16_t clocktime, int8_t clockrate, byte
// CAH. DIAG removed because LCD does it anyway. // CAH. DIAG removed because LCD does it anyway.
LCD(6,F("Clk Time:%d Sp %d"), clocktime, clockrate); LCD(6,F("Clk Time:%d Sp %d"), clocktime, clockrate);
// look for an event for this time // look for an event for this time
#ifdef EXRAIL_ACTIVE
RMFT2::clockEvent(clocktime,1); RMFT2::clockEvent(clocktime,1);
#endif
// Now tell everyone else what the time is. // Now tell everyone else what the time is.
CommandDistributor::broadcastClockTime(clocktime, clockrate); CommandDistributor::broadcastClockTime(clocktime, clockrate);
lastclocktime = clocktime; lastclocktime = clocktime;

View File

@ -51,6 +51,10 @@
#include "libsha1.h" #include "libsha1.h"
#include "Websockets.h" #include "Websockets.h"
#include "DIAG.h" #include "DIAG.h"
#ifdef ARDUINO_ARCH_ESP32
// ESP32 runtime or definitions has strlcat_P missing
#define strlcat_P strlcat
#endif
static const char b64_table[] = { static const char b64_table[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
@ -179,20 +183,23 @@ byte * Websockets::unmask(byte clientId,RingStream *ring, byte * buffer) {
return (dataLength>=126)? 4:2; return (dataLength>=126)? 4:2;
} }
void Websockets::writeOutboundHeader(Print * stream,uint16_t dataLength) { int Websockets::fillOutboundHeader(uint16_t dataLength, byte * buffer) {
// write the outbound header
// length patched if necessary.
// text opcode, flag(126= use 2 length bytes, no mask bit) , length // text opcode, flag(126= use 2 length bytes, no mask bit) , length
if (dataLength>=126) { buffer[0]=0x81;
const byte prefix[]={0x81,126, if (dataLength<126) {
(byte)(dataLength & 0xFF), (byte)(dataLength>>8)}; buffer[1]=(byte)dataLength;
stream->write(prefix,sizeof(prefix)); return 2;
} }
else { buffer[1]=126;
const byte prefix[]={0x81,(byte)dataLength}; buffer[2]=(byte)(dataLength & 0xFF);
stream->write(prefix,sizeof(prefix)); buffer[3]= (byte)(dataLength>>8);
return 4;
} }
void Websockets::writeOutboundHeader(Print * stream,uint16_t dataLength) {
byte prefix[4];
int headerlen=fillOutboundHeader(dataLength,prefix);
stream->write(prefix,sizeof(headerlen));
} }

View File

@ -26,6 +26,7 @@ class Websockets {
static bool checkConnectionString(byte clientId,byte * cmd, RingStream * outbound ); static bool checkConnectionString(byte clientId,byte * cmd, RingStream * outbound );
static byte * unmask(byte clientId,RingStream *ring, byte * buffer); static byte * unmask(byte clientId,RingStream *ring, byte * buffer);
static int16_t getOutboundHeaderSize(uint16_t dataLength); static int16_t getOutboundHeaderSize(uint16_t dataLength);
static int fillOutboundHeader(uint16_t dataLength, byte * buffer);
static void writeOutboundHeader(Print * stream,uint16_t dataLength); static void writeOutboundHeader(Print * stream,uint16_t dataLength);
static const byte WEBSOCK_CLIENT_MARKER=0x80; static const byte WEBSOCK_CLIENT_MARKER=0x80;
}; };

View File

@ -2,6 +2,8 @@
© 2023 Paul M. Antoine © 2023 Paul M. Antoine
© 2021 Harald Barth © 2021 Harald Barth
© 2023 Nathan Kellenicki © 2023 Nathan Kellenicki
© 2023 Chris Harlow
This file is part of CommandStation-EX This file is part of CommandStation-EX
@ -30,6 +32,7 @@
#include "RingStream.h" #include "RingStream.h"
#include "CommandDistributor.h" #include "CommandDistributor.h"
#include "WiThrottle.h" #include "WiThrottle.h"
#include "Websockets.h"
/* /*
#include "soc/rtc_wdt.h" #include "soc/rtc_wdt.h"
#include "esp_task_wdt.h" #include "esp_task_wdt.h"
@ -330,6 +333,8 @@ void WifiESP::loop() {
// something to write out? // something to write out?
clientId=outboundRing->read(); clientId=outboundRing->read();
bool useWebsocket=clientId & Websockets::WEBSOCK_CLIENT_MARKER;
clientId &= ~ Websockets::WEBSOCK_CLIENT_MARKER;
if (clientId >= 0) { if (clientId >= 0) {
// We have data to send in outboundRing // We have data to send in outboundRing
// and we have a valid clientId. // and we have a valid clientId.
@ -337,19 +342,22 @@ void WifiESP::loop() {
// and then look if it can be sent because // and then look if it can be sent because
// we can not leave it in the ring for ever // we can not leave it in the ring for ever
int count=outboundRing->count(); int count=outboundRing->count();
auto wsHeaderLen=useWebsocket? Websockets::getOutboundHeaderSize(count) : 0;
{ {
char buffer[count+1]; // one extra for '\0'
byte buffer[wsHeaderLen+count+1]; // one extra for '\0'
if (useWebsocket) Websockets::fillOutboundHeader(count, buffer);
for(int i=0;i<count;i++) { for(int i=0;i<count;i++) {
int c = outboundRing->read(); int c = outboundRing->read();
if (c >= 0) // Panic check, should never be false if (c >= 0) // Panic check, should never be false
buffer[i] = (char)c; buffer[i+wsHeaderLen] = (char)c;
else { else {
DIAG(F("Ringread fail at %d"),i); DIAG(F("Ringread fail at %d"),i);
break; break;
} }
} }
// buffer filled, end with '\0' so we can use it as C string // buffer filled, end with '\0' so we can use it as C string
buffer[count]='\0'; buffer[wsHeaderLen+count]='\0';
if((unsigned int)clientId <= clients.size() && clients[clientId].ok()) { if((unsigned int)clientId <= clients.size() && clients[clientId].ok()) {
if (Diag::CMD || Diag::WITHROTTLE) if (Diag::CMD || Diag::WITHROTTLE)
DIAG(F("SEND %d:%s"), clientId, buffer); DIAG(F("SEND %d:%s"), clientId, buffer);