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:
parent
2426538e61
commit
48604bf622
|
@ -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;
|
||||||
|
|
|
@ -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,21 +183,24 @@ 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user