mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2025-03-14 18:13:09 +01:00
Fixes the main loop over all interfaces
This commit is contained in:
parent
1b624cdfdb
commit
0144ff7ee4
@ -102,9 +102,7 @@ void loop()
|
|||||||
|
|
||||||
|
|
||||||
// (3) Start Loop NetworkInterface
|
// (3) Start Loop NetworkInterface
|
||||||
// wifi.loop();
|
NetworkInterface::loop();
|
||||||
eth1.loop();
|
|
||||||
eth2.loop();
|
|
||||||
// (3) End Loop NetworkInterface
|
// (3) End Loop NetworkInterface
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
* @brief NetworkInterface configuration
|
* @brief NetworkInterface configuration
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
#define MAX_INTERFACES 4 // Consume too much memeory beyond in general not more than 2 should be required
|
||||||
#define MAX_SOCK_NUM 8 // Maximum number of sockets allowed for any WizNet based EthernetShield. The W5100 only supports 4
|
#define MAX_SOCK_NUM 8 // Maximum number of sockets allowed for any WizNet based EthernetShield. The W5100 only supports 4
|
||||||
#define MAX_WIFI_SOCK 5 // ESP8266 doesn't support more than 5 connections
|
#define MAX_WIFI_SOCK 5 // ESP8266 doesn't support more than 5 connections
|
||||||
#define MAX_ETH_BUFFER 64 // maximum length we read in one go from a TCP packet.
|
#define MAX_ETH_BUFFER 64 // maximum length we read in one go from a TCP packet.
|
||||||
|
@ -23,12 +23,54 @@
|
|||||||
#include "EthernetSetup.h"
|
#include "EthernetSetup.h"
|
||||||
#include "WifiSetup.h"
|
#include "WifiSetup.h"
|
||||||
|
|
||||||
Transport<WiFiServer, WiFiClient, WiFiUDP>* wifiTransport;
|
Transport<WiFiServer, WiFiClient, WiFiUDP> *wifiTransport;
|
||||||
Transport<EthernetServer, EthernetClient, EthernetUDP>* ethernetTransport;
|
Transport<EthernetServer, EthernetClient, EthernetUDP> *ethernetTransport;
|
||||||
|
|
||||||
|
DCCNetwork _dccNet;
|
||||||
|
|
||||||
|
void DCCNetwork::loop()
|
||||||
|
{
|
||||||
|
for (byte i = 0; i < _tCounter; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
Transport<EthernetServer, EthernetClient, EthernetUDP> *e;
|
||||||
|
Transport<WiFiServer, WiFiClient, WiFiUDP> *w;
|
||||||
|
|
||||||
|
switch (_t[i])
|
||||||
|
{
|
||||||
|
case ETHERNET:
|
||||||
|
{
|
||||||
|
e = (Transport<EthernetServer, EthernetClient, EthernetUDP> *)transports[i];
|
||||||
|
e->loop();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WIFI:
|
||||||
|
{
|
||||||
|
w = (Transport<WiFiServer, WiFiClient, WiFiUDP> *)transports[i];
|
||||||
|
w->loop();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byte DCCNetwork::add(AbstractTransport *t, transportType transport)
|
||||||
|
{
|
||||||
|
if (_tCounter != MAX_INTERFACES)
|
||||||
|
{
|
||||||
|
_t[_tCounter] = transport;
|
||||||
|
transports[_tCounter] = t; // add to array of network interfaces returns the index + 1 if added
|
||||||
|
_tCounter++; // if max intefaces is reached returns 0 for too many ...
|
||||||
|
return _tCounter; // normally a delete shall not be necessary as all is setup at the beginning and shall not change over a session
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NetworkInterface::setup(transportType transport, protocolType protocol, uint16_t port)
|
void NetworkInterface::setup(transportType transport, protocolType protocol, uint16_t port)
|
||||||
{
|
{
|
||||||
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
|
|
||||||
DIAG(F("\n[%s] Transport Setup In Progress ...\n"), transport ? "Ethernet" : "Wifi");
|
DIAG(F("\n[%s] Transport Setup In Progress ...\n"), transport ? "Ethernet" : "Wifi");
|
||||||
@ -45,25 +87,29 @@ void NetworkInterface::setup(transportType transport, protocolType protocol, uin
|
|||||||
if (ok)
|
if (ok)
|
||||||
{
|
{
|
||||||
wifiTransport = new Transport<WiFiServer, WiFiClient, WiFiUDP>;
|
wifiTransport = new Transport<WiFiServer, WiFiClient, WiFiUDP>;
|
||||||
|
wifiTransport->id = _dccNet.add(wifiTransport, transport);
|
||||||
wifiTransport->server = wSetup.getServer();
|
wifiTransport->server = wSetup.getServer();
|
||||||
wifiTransport->port = port;
|
wifiTransport->port = port;
|
||||||
wifiTransport->protocol = protocol;
|
wifiTransport->protocol = protocol;
|
||||||
wifiTransport->transport = transport;
|
wifiTransport->transport = transport;
|
||||||
wifiTransport->maxConnections = wSetup.maxConnections;
|
wifiTransport->maxConnections = wSetup.maxConnections;
|
||||||
ok = wifiTransport->setup(this);
|
ok = wifiTransport->setup(this);
|
||||||
}
|
DIAG(F("\n\nInterface [%x] bound to transport id [%d:%x]"), this, wifiTransport->id, wifiTransport);
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
};
|
||||||
case ETHERNET:
|
case ETHERNET:
|
||||||
{
|
{
|
||||||
EthernetSetup eSetup(port, protocol);
|
EthernetSetup eSetup(port, protocol);
|
||||||
ethernetTransport = new Transport<EthernetServer, EthernetClient, EthernetUDP>;
|
ethernetTransport = new Transport<EthernetServer, EthernetClient, EthernetUDP>;
|
||||||
|
ethernetTransport->id = _dccNet.add(ethernetTransport, transport);
|
||||||
ethernetTransport->server = eSetup.setup(); // returns (NULL) 0 if we run over UDP; todo: error handling if something goes wrong in the init
|
ethernetTransport->server = eSetup.setup(); // returns (NULL) 0 if we run over UDP; todo: error handling if something goes wrong in the init
|
||||||
ethernetTransport->port = port;
|
ethernetTransport->port = port;
|
||||||
ethernetTransport->protocol = protocol;
|
ethernetTransport->protocol = protocol;
|
||||||
ethernetTransport->transport = transport;
|
ethernetTransport->transport = transport;
|
||||||
ethernetTransport->maxConnections = eSetup.maxConnections; // that has been determined during the ethernet/wifi setup
|
ethernetTransport->maxConnections = eSetup.maxConnections; // that has been determined during the ethernet/wifi setup
|
||||||
ok = ethernetTransport->setup(this); // start the transport i.e. setup all the client connections; We don't need the setup object anymore from here on
|
ok = ethernetTransport->setup(this); // start the transport i.e. setup all the client connections; We don't need the setup object anymore from here on
|
||||||
|
DIAG(F("\n\nInterface [%x] bound to transport id [%d:%x]"), this, ethernetTransport->id, ethernetTransport);
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
@ -72,7 +118,8 @@ void NetworkInterface::setup(transportType transport, protocolType protocol, uin
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DIAG(F("\n\n[%s] Transport %s ..."), transport ? "Ethernet" : "Wifi", ok ? "OK" : "Failed");
|
|
||||||
|
DIAG(F("\n[%s] Transport %s ..."), transport ? "Ethernet" : "Wifi", ok ? "OK" : "Failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkInterface::setup(transportType tt, protocolType pt)
|
void NetworkInterface::setup(transportType tt, protocolType pt)
|
||||||
@ -92,23 +139,9 @@ void NetworkInterface::setup()
|
|||||||
|
|
||||||
void NetworkInterface::loop()
|
void NetworkInterface::loop()
|
||||||
{
|
{
|
||||||
switch (t)
|
// loop over all the transports in
|
||||||
{
|
_dccNet.loop();
|
||||||
case WIFI:
|
|
||||||
{
|
|
||||||
if (wifiTransport->isConnected()){
|
|
||||||
wifiTransport->loop();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ETHERNET:
|
|
||||||
{
|
|
||||||
if (ethernetTransport->isConnected()) {
|
|
||||||
ethernetTransport->loop();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkInterface::setHttpCallback(HttpCallback callback)
|
void NetworkInterface::setHttpCallback(HttpCallback callback)
|
||||||
@ -121,5 +154,5 @@ HttpCallback NetworkInterface::getHttpCallback()
|
|||||||
return this->httpCallback;
|
return this->httpCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkInterface::NetworkInterface(){}
|
NetworkInterface::NetworkInterface() {}
|
||||||
NetworkInterface::~NetworkInterface(){}
|
NetworkInterface::~NetworkInterface() {}
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
// #include "Transport.h"
|
#include "NetworkConfig.h"
|
||||||
#include "HttpRequest.h"
|
#include "HttpRequest.h"
|
||||||
|
|
||||||
typedef enum protocolType {
|
typedef enum protocolType {
|
||||||
@ -36,10 +36,41 @@ typedef enum transportType {
|
|||||||
|
|
||||||
using HttpCallback = void(*)(ParsedRequest *req, Client *client);
|
using HttpCallback = void(*)(ParsedRequest *req, Client *client);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Abstract parent class of the templated ( Ethernet or Wifi ) class
|
||||||
|
* Instances of Transports are hold through this in an array in DCCNetwork which describes and
|
||||||
|
* actually manages the available transports.
|
||||||
|
*/
|
||||||
|
struct AbstractTransport {
|
||||||
|
void loop(){};
|
||||||
|
virtual ~AbstractTransport(){};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Core class holding and running the instantiated Transports
|
||||||
|
* initalized through the NetworkInterface. The number of transports is
|
||||||
|
* limited by MAX_INTERFACES
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class DCCNetwork {
|
||||||
|
private:
|
||||||
|
byte _tCounter = 0;
|
||||||
|
transportType _t[MAX_INTERFACES];
|
||||||
|
public:
|
||||||
|
AbstractTransport *transports[MAX_INTERFACES];
|
||||||
|
|
||||||
|
byte add(AbstractTransport* t, transportType _t);
|
||||||
|
void loop();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Main entry point and provider of callbacks. Sole responsibility is to create
|
||||||
|
* the transport endpoints and loop over them for processing
|
||||||
|
*
|
||||||
|
*/
|
||||||
class NetworkInterface
|
class NetworkInterface
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
HttpCallback httpCallback;
|
HttpCallback httpCallback;
|
||||||
transportType t;
|
transportType t;
|
||||||
|
|
||||||
@ -52,7 +83,7 @@ public:
|
|||||||
void setup(transportType t); // defaults for protocol/port
|
void setup(transportType t); // defaults for protocol/port
|
||||||
|
|
||||||
void setup(); // defaults for all as above plus CABLE (i.e. using EthernetShield ) as default
|
void setup(); // defaults for all as above plus CABLE (i.e. using EthernetShield ) as default
|
||||||
void loop();
|
static void loop();
|
||||||
|
|
||||||
NetworkInterface();
|
NetworkInterface();
|
||||||
~NetworkInterface();
|
~NetworkInterface();
|
||||||
|
@ -62,8 +62,9 @@ void Transport<S, C, U>::connectionPool(S *server)
|
|||||||
for (int i = 0; i < Transport::maxConnections; i++)
|
for (int i = 0; i < Transport::maxConnections; i++)
|
||||||
{
|
{
|
||||||
clients[i] = server->accept();
|
clients[i] = server->accept();
|
||||||
connections[i].client = &clients[i];
|
connections[i].client = &clients[i]; // set the client
|
||||||
connections[i].id = i;
|
memset(connections[i].overflow, 0, MAX_OVERFLOW); // clear overflow buffer
|
||||||
|
connections[i].id = i; // ser the client id
|
||||||
DIAG(F("\nConnection pool: [%d:%x]"), i, connections[i].client);
|
DIAG(F("\nConnection pool: [%d:%x]"), i, connections[i].client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
#include "NetworkInterface.h"
|
#include "NetworkInterface.h"
|
||||||
#include "TransportProcessor.h"
|
#include "TransportProcessor.h"
|
||||||
|
|
||||||
template <class S, class C, class U> class Transport
|
template <class S, class C, class U> class Transport: public AbstractTransport
|
||||||
{
|
{
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -41,6 +41,7 @@ private:
|
|||||||
void connectionPool(S* server); // allocates the Sockets at setup time and creates the Connections
|
void connectionPool(S* server); // allocates the Sockets at setup time and creates the Connections
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
uint8_t id;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
uint8_t protocol; // TCP or UDP
|
uint8_t protocol; // TCP or UDP
|
||||||
uint8_t transport; // WIFI or ETHERNET
|
uint8_t transport; // WIFI or ETHERNET
|
||||||
@ -48,7 +49,7 @@ public:
|
|||||||
U* udp; // UDP socket object
|
U* udp; // UDP socket object
|
||||||
uint8_t maxConnections; // number of supported connections depending on the network equipment use
|
uint8_t maxConnections; // number of supported connections depending on the network equipment use
|
||||||
|
|
||||||
bool setup(NetworkInterface* nwi);
|
bool setup(NetworkInterface* nwi); // we get the callbacks from the NetworkInterface
|
||||||
void loop();
|
void loop();
|
||||||
|
|
||||||
bool isConnected() {
|
bool isConnected() {
|
||||||
|
@ -52,30 +52,25 @@ uint8_t diagNetworkClient = 0;
|
|||||||
|
|
||||||
void sendToDCC(Connection *c, TransportProcessor* t, bool blocking)
|
void sendToDCC(Connection *c, TransportProcessor* t, bool blocking)
|
||||||
{
|
{
|
||||||
char * _command = t->command;
|
static MemStream *streamer = new MemStream((byte *)t->command, MAX_ETH_BUFFER, MAX_ETH_BUFFER, true);
|
||||||
|
|
||||||
static MemStream *streamer = new MemStream((byte *)_command, MAX_ETH_BUFFER, MAX_ETH_BUFFER, true);
|
DIAG(F("DCC parsing: [%e]\n"), t->command);
|
||||||
|
|
||||||
DIAG(F("DCC parsing: [%e]\n"), _command);
|
|
||||||
// as we use buffer for recv and send we have to reset the write position
|
// as we use buffer for recv and send we have to reset the write position
|
||||||
streamer->setBufferContentPosition(0, 0);
|
streamer->setBufferContentPosition(0, 0);
|
||||||
|
|
||||||
ethParser.parse(streamer, (byte *)_command, true); // set to true to that the execution in DCC is sync
|
ethParser.parse(streamer, (byte *)t->command, true); // set to true to that the execution in DCC is sync
|
||||||
|
|
||||||
if (streamer->available() == 0)
|
if (streamer->available() == 0)
|
||||||
{
|
{
|
||||||
if (c->client->connected())
|
DIAG(F("No response\n"));
|
||||||
{
|
|
||||||
c->client->write((byte *)F("No response\n"), streamer->available());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_command[streamer->available()] = '\0'; // mark end of buffer, so it can be used as a string later
|
t->command[streamer->available()] = '\0'; // mark end of buffer, so it can be used as a string later
|
||||||
DIAG(F("Response: %s\n"), _command);
|
DIAG(F("Response: %s\n"), t->command);
|
||||||
if (c->client->connected())
|
if (c->client->connected())
|
||||||
{
|
{
|
||||||
c->client->write((byte *)_command, streamer->available());
|
c->client->write((byte *)t->command, streamer->available());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -257,17 +252,16 @@ appProtocol setAppProtocol(char a, char b, Connection *c)
|
|||||||
void processStream(Connection *c, TransportProcessor *t)
|
void processStream(Connection *c, TransportProcessor *t)
|
||||||
{
|
{
|
||||||
uint8_t i, j, k, l = 0;
|
uint8_t i, j, k, l = 0;
|
||||||
uint8_t* _buffer = t->buffer;
|
uint8_t *_buffer = t->buffer;
|
||||||
char* _command = t->command;
|
|
||||||
|
|
||||||
DIAG(F("\nBuffer: [%e]\n"), _buffer);
|
DIAG(F("\nBuffer: [%e]\n"), _buffer);
|
||||||
memset(_command, 0, MAX_JMRI_CMD); // clear out the command
|
memset(t->command, 0, MAX_JMRI_CMD); // clear out the command
|
||||||
|
|
||||||
// copy overflow into the command
|
// copy overflow into the command
|
||||||
if ((i = strlen(c->overflow)) != 0)
|
if ((i = strlen(c->overflow)) != 0)
|
||||||
{
|
{
|
||||||
// DIAG(F("\nCopy overflow to command: %e"), c->overflow);
|
// DIAG(F("\nCopy overflow to command: %e"), c->overflow);
|
||||||
strncpy(_command, c->overflow, i);
|
strncpy(t->command, c->overflow, i);
|
||||||
k = i;
|
k = i;
|
||||||
}
|
}
|
||||||
// reset the overflow
|
// reset the overflow
|
||||||
@ -296,19 +290,19 @@ void processStream(Connection *c, TransportProcessor *t)
|
|||||||
}
|
}
|
||||||
// breakup the buffer using its changed length
|
// breakup the buffer using its changed length
|
||||||
i = 0;
|
i = 0;
|
||||||
k = strlen(_command); // current length of the command buffer telling us where to start copy in
|
k = strlen(t->command); // current length of the command buffer telling us where to start copy in
|
||||||
l = strlen((char *)_buffer);
|
l = strlen((char *)_buffer);
|
||||||
// DIAG(F("\nCommand buffer: [%s]:[%d:%d:%d]\n"), command, i, l, k );
|
// DIAG(F("\nCommand buffer: [%s]:[%d:%d:%d]\n"), command, i, l, k );
|
||||||
while (i < l)
|
while (i < l)
|
||||||
{
|
{
|
||||||
// DIAG(F("\nl: %d k: %d , i: %d"), l, k, i);
|
// DIAG(F("\nl: %d k: %d , i: %d"), l, k, i);
|
||||||
_command[k] = _buffer[i];
|
t->command[k] = _buffer[i];
|
||||||
if (_buffer[i] == c->delimiter)
|
if (_buffer[i] == c->delimiter)
|
||||||
{ // closing bracket need to fix if there is none before an opening bracket ?
|
{ // closing bracket need to fix if there is none before an opening bracket ?
|
||||||
|
|
||||||
_command[k + 1] = '\0';
|
t->command[k + 1] = '\0';
|
||||||
|
|
||||||
DIAG(F("Command: [%d:%e]\n"), _rseq[c->id], _command);
|
DIAG(F("Command: [%d:%e]\n"), _rseq[c->id], t->command);
|
||||||
#ifdef DCCEX_ENABLED
|
#ifdef DCCEX_ENABLED
|
||||||
sendToDCC(c, t, true);
|
sendToDCC(c, t, true);
|
||||||
#else
|
#else
|
||||||
|
Loading…
Reference in New Issue
Block a user