mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2025-02-21 08:16:04 +01:00
Multiple NetworkInterface support
This commit is contained in:
parent
c1e4727ee8
commit
5888e21090
@ -17,6 +17,11 @@
|
|||||||
// to be issued from the USB serial console.
|
// to be issued from the USB serial console.
|
||||||
DCCEXParser serialParser;
|
DCCEXParser serialParser;
|
||||||
|
|
||||||
|
// (0) Declare NetworkInterfaces
|
||||||
|
NetworkInterface wifi;
|
||||||
|
NetworkInterface eth;
|
||||||
|
// (0) Declared NetworkInterfaces
|
||||||
|
|
||||||
// (1) Start NetworkInterface - HTTP callback
|
// (1) Start NetworkInterface - HTTP callback
|
||||||
void httpRequestHandler(ParsedRequest *req, Client* client) {
|
void httpRequestHandler(ParsedRequest *req, Client* client) {
|
||||||
DIAG(F("\nParsed Request:"));
|
DIAG(F("\nParsed Request:"));
|
||||||
@ -64,12 +69,10 @@ void setup()
|
|||||||
|
|
||||||
DIAG(F("\nFree RAM before network init: [%d]\n"),freeMemory());
|
DIAG(F("\nFree RAM before network init: [%d]\n"),freeMemory());
|
||||||
DIAG(F("\nNetwork Setup In Progress ...\n"));
|
DIAG(F("\nNetwork Setup In Progress ...\n"));
|
||||||
NetworkInterface::setup(ETHERNET, TCP, 8888); // specify WIFI or ETHERNET depending on if you have Wifi or an EthernetShield; Wifi has to be on Serial1 UDP or TCP for the protocol
|
|
||||||
NetworkInterface::setHttpCallback(httpRequestHandler); // The network interface will provide and HTTP request object which can be used as well to send the reply. cf. example above
|
|
||||||
|
|
||||||
// NetworkInterface::setup(WIFI, UDP, 8888); // Setup without port will use the by default port 2560 :: Wifi+UDP IS NOT YET SUPPORTED
|
wifi.setup(WIFI); // WIFI, TCP on Port 2560
|
||||||
// NetworkInterface::setup(WIFI); // setup without port and protocol will use by default TCP on port 2560
|
eth.setup(ETHERNET, TCP, 8888); // ETHERNET, TCP on Port 8888
|
||||||
// NetworkInterface::setup(); // all defaults ETHERNET, TCP on port 2560
|
eth.setHttpCallback(httpRequestHandler); // HTTP callback
|
||||||
|
|
||||||
DIAG(F("\nNetwork Setup done ..."));
|
DIAG(F("\nNetwork Setup done ..."));
|
||||||
DIAG(F("\nFree RAM after network init: [%d]\n"),freeMemory());
|
DIAG(F("\nFree RAM after network init: [%d]\n"),freeMemory());
|
||||||
@ -94,9 +97,14 @@ void loop()
|
|||||||
#if WIFI_ON
|
#if WIFI_ON
|
||||||
WifiInterface::loop();
|
WifiInterface::loop();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// (3) Start Loop NetworkInterface
|
// (3) Start Loop NetworkInterface
|
||||||
NetworkInterface::loop();
|
wifi.loop();
|
||||||
|
eth.loop();
|
||||||
// (3) End Loop NetworkInterface
|
// (3) End Loop NetworkInterface
|
||||||
|
|
||||||
|
|
||||||
LCDDisplay::loop(); // ignored if LCD not in use
|
LCDDisplay::loop(); // ignored if LCD not in use
|
||||||
|
|
||||||
// Optionally report any decrease in memory (will automatically trigger on first call)
|
// Optionally report any decrease in memory (will automatically trigger on first call)
|
||||||
|
@ -54,7 +54,7 @@ EthernetServer* EthernetSetup::setup()
|
|||||||
}
|
}
|
||||||
else if (Ethernet.hardwareStatus() == EthernetW5500)
|
else if (Ethernet.hardwareStatus() == EthernetW5500)
|
||||||
{
|
{
|
||||||
DIAG(F("\nW5500 Ethernet controller detected."));
|
DIAG(F("W5500 Ethernet controller detected."));
|
||||||
maxConnections = 8;
|
maxConnections = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,6 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// EthernetServer *setup(uint16_t port);
|
|
||||||
EthernetServer *setup();
|
EthernetServer *setup();
|
||||||
|
|
||||||
EthernetSetup();
|
EthernetSetup();
|
||||||
|
47
NetworkConfig.h
Normal file
47
NetworkConfig.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* © 2020, Gregor Baues. All rights reserved.
|
||||||
|
*
|
||||||
|
* This is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* It is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* some generated mac addresses as EthernetShields don't have one by default in HW.
|
||||||
|
* Sometimes they come on a sticker on the EthernetShield then use this address otherwise
|
||||||
|
* just choose one from below or generate one yourself. Only condition is that there is no
|
||||||
|
* other device on your network with the same Mac address.
|
||||||
|
*
|
||||||
|
* 52:b8:8a:8e:ce:21
|
||||||
|
* e3:e9:73:e1:db:0d
|
||||||
|
* 54:2b:13:52:ac:0c
|
||||||
|
* c2:d8:d4:7d:7c:cb
|
||||||
|
* 86:cf:fa:9f:07:79
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Network operational configuration
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define LISTEN_PORT 2560 // default listen port for the server
|
||||||
|
#define MAC_ADDRESS {0x52, 0xB8, 0x8A, 0x8E, 0xCE, 0x21} // MAC address of your networking card found on the sticker on your card or take one from above
|
||||||
|
#define IP_ADDRESS 10, 0, 0, 101 // Just in case we don't get an adress from DHCP try a static one;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief NetworkInterface configuration
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#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_ETH_BUFFER 64 // maximum length we read in one go from a TCP packet.
|
||||||
|
#define MAX_OVERFLOW MAX_ETH_BUFFER / 2 // length of the overflow buffer to be used for a given connection.
|
||||||
|
#define MAX_JMRI_CMD MAX_ETH_BUFFER / 2 // MAX Length of a JMRI Command
|
@ -19,14 +19,12 @@
|
|||||||
|
|
||||||
#include "DIAG.h"
|
#include "DIAG.h"
|
||||||
#include "NetworkInterface.h"
|
#include "NetworkInterface.h"
|
||||||
|
#include "Transport.h"
|
||||||
#include "EthernetSetup.h"
|
#include "EthernetSetup.h"
|
||||||
#include "WifiSetup.h"
|
#include "WifiSetup.h"
|
||||||
|
|
||||||
HttpCallback NetworkInterface::httpCallback = 0;
|
Transport<WiFiServer, WiFiClient, WiFiUDP>* wifiTransport;
|
||||||
|
Transport<EthernetServer, EthernetClient, EthernetUDP>* ethernetTransport;
|
||||||
Transport<WiFiServer, WiFiClient, WiFiUDP> *NetworkInterface::wifiTransport;
|
|
||||||
Transport<EthernetServer, EthernetClient, EthernetUDP> *NetworkInterface::ethernetTransport;
|
|
||||||
transportType t;
|
|
||||||
|
|
||||||
void NetworkInterface::setup(transportType transport, protocolType protocol, uint16_t port)
|
void NetworkInterface::setup(transportType transport, protocolType protocol, uint16_t port)
|
||||||
{
|
{
|
||||||
@ -43,31 +41,29 @@ void NetworkInterface::setup(transportType transport, protocolType protocol, uin
|
|||||||
case WIFI:
|
case WIFI:
|
||||||
{
|
{
|
||||||
WifiSetup wSetup(port, protocol);
|
WifiSetup wSetup(port, protocol);
|
||||||
|
|
||||||
wifiTransport = new Transport<WiFiServer, WiFiClient, WiFiUDP>();
|
|
||||||
ok = wSetup.setup();
|
ok = wSetup.setup();
|
||||||
if (ok)
|
if (ok)
|
||||||
{
|
{
|
||||||
|
wifiTransport = new Transport<WiFiServer, WiFiClient, WiFiUDP>;
|
||||||
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();
|
ok = wifiTransport->setup(this);
|
||||||
}
|
}
|
||||||
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->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
|
|
||||||
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(); // 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
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
@ -117,19 +113,13 @@ void NetworkInterface::loop()
|
|||||||
|
|
||||||
void NetworkInterface::setHttpCallback(HttpCallback callback)
|
void NetworkInterface::setHttpCallback(HttpCallback callback)
|
||||||
{
|
{
|
||||||
httpCallback = callback;
|
this->httpCallback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpCallback NetworkInterface::getHttpCallback()
|
HttpCallback NetworkInterface::getHttpCallback()
|
||||||
{
|
{
|
||||||
return httpCallback;
|
return this->httpCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkInterface::NetworkInterface()
|
NetworkInterface::NetworkInterface(){}
|
||||||
{
|
NetworkInterface::~NetworkInterface(){}
|
||||||
// DIAG(F("NetworkInterface created "));
|
|
||||||
}
|
|
||||||
|
|
||||||
NetworkInterface::~NetworkInterface()
|
|
||||||
{
|
|
||||||
// DIAG(F("NetworkInterface destroyed"));
|
|
||||||
}
|
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
#include "Transport.h"
|
// #include "Transport.h"
|
||||||
#include "HttpRequest.h"
|
#include "HttpRequest.h"
|
||||||
|
|
||||||
typedef enum protocolType {
|
typedef enum protocolType {
|
||||||
@ -32,29 +32,27 @@ typedef enum protocolType {
|
|||||||
typedef enum transportType {
|
typedef enum transportType {
|
||||||
WIFI, // using an AT (Version >= V1.7) command enabled ESP8266 not to be used in conjunction with the WifiInterface though! not tested for conflicts
|
WIFI, // using an AT (Version >= V1.7) command enabled ESP8266 not to be used in conjunction with the WifiInterface though! not tested for conflicts
|
||||||
ETHERNET // using the EthernetShield
|
ETHERNET // using the EthernetShield
|
||||||
} transoprtType;
|
} transportType;
|
||||||
|
|
||||||
// typedef void (*HttpCallback)(ParsedRequest *req, Client *client);
|
|
||||||
using HttpCallback = void(*)(ParsedRequest *req, Client *client);
|
using HttpCallback = void(*)(ParsedRequest *req, Client *client);
|
||||||
|
|
||||||
class NetworkInterface
|
class NetworkInterface
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static Transport<WiFiServer,WiFiClient,WiFiUDP>* wifiTransport;
|
HttpCallback httpCallback;
|
||||||
static Transport<EthernetServer,EthernetClient,EthernetUDP>* ethernetTransport;
|
transportType t;
|
||||||
static HttpCallback httpCallback;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static void setHttpCallback(HttpCallback callback);
|
void setHttpCallback(HttpCallback callback);
|
||||||
static HttpCallback getHttpCallback();
|
HttpCallback getHttpCallback();
|
||||||
static void setup(transportType t, protocolType p, uint16_t port); // specific port nummber
|
void setup(transportType t, protocolType p, uint16_t port); // specific port nummber
|
||||||
static void setup(transportType t, protocolType p); // uses default port number
|
void setup(transportType t, protocolType p); // uses default port number
|
||||||
static void setup(transportType t); // defaults for protocol/port
|
void setup(transportType t); // defaults for protocol/port
|
||||||
|
|
||||||
static 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
|
||||||
static void loop();
|
void loop();
|
||||||
|
|
||||||
NetworkInterface();
|
NetworkInterface();
|
||||||
~NetworkInterface();
|
~NetworkInterface();
|
||||||
|
@ -17,31 +17,11 @@
|
|||||||
#ifndef NetworkSetup_h
|
#ifndef NetworkSetup_h
|
||||||
#define NetworkSetup_h
|
#define NetworkSetup_h
|
||||||
|
|
||||||
#include "Ethernet.h"
|
#include <Ethernet.h>
|
||||||
|
|
||||||
|
#include "NetworkConfig.h"
|
||||||
#include "NetworkInterface.h"
|
#include "NetworkInterface.h"
|
||||||
|
|
||||||
/* some generated mac addresses as EthernetShields don't have one by default in HW.
|
|
||||||
* Sometimes they come on a sticker on the EthernetShield then use this address otherwise
|
|
||||||
* just choose one from below or generate one yourself. Only condition is that there is no
|
|
||||||
* other device on your network with the same Mac address.
|
|
||||||
*
|
|
||||||
* 52:b8:8a:8e:ce:21
|
|
||||||
* e3:e9:73:e1:db:0d
|
|
||||||
* 54:2b:13:52:ac:0c
|
|
||||||
* c2:d8:d4:7d:7c:cb
|
|
||||||
* 86:cf:fa:9f:07:79
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Network Configuration
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#define MAC_ADDRESS \
|
|
||||||
{ \
|
|
||||||
0x52, 0xB8, 0x8A, 0x8E, 0xCE, 0x21 \
|
|
||||||
} // MAC address of your networking card found on the sticker on your card or take one from above
|
|
||||||
#define IP_ADDRESS 10, 0, 0, 101 // Just in case we don't get an adress from DHCP try a static one;
|
|
||||||
|
|
||||||
class NetworkSetup
|
class NetworkSetup
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -179,4 +179,3 @@ void StringFormatter::printPadded(Print* stream, long value, byte width, bool fo
|
|||||||
if (!formatLeft) stream->print(value, DEC);
|
if (!formatLeft) stream->print(value, DEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,8 +54,6 @@ class StringFormatter
|
|||||||
static void printEscapes(char * input);
|
static void printEscapes(char * input);
|
||||||
static void printEscape( char c);
|
static void printEscape( char c);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void setDiagOut(Connection *c) {
|
static void setDiagOut(Connection *c) {
|
||||||
if ( c->client->connected() ) {
|
if ( c->client->connected() ) {
|
||||||
diagSerial = c->client;
|
diagSerial = c->client;
|
||||||
|
@ -25,11 +25,12 @@ extern bool diagNetwork;
|
|||||||
extern uint8_t diagNetworkClient;
|
extern uint8_t diagNetworkClient;
|
||||||
|
|
||||||
template<class S, class C, class U>
|
template<class S, class C, class U>
|
||||||
bool Transport<S,C,U>::setup() {
|
bool Transport<S,C,U>::setup(NetworkInterface *nw) {
|
||||||
if (protocol == TCP) {
|
if (protocol == TCP) {
|
||||||
connectionPool(server); // server should have started here so create the connection pool only for TCP though
|
connectionPool(server); // server should have started here so create the connection pool only for TCP though
|
||||||
}
|
}
|
||||||
t = new TransportProcessor();
|
t = new TransportProcessor();
|
||||||
|
t->nwi = nw; // The TransportProcesor needs to know which Interface he is connected to
|
||||||
connected = true; // server & clients which will recieve/send data have all e setup and are available
|
connected = true; // server & clients which will recieve/send data have all e setup and are available
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -45,8 +46,7 @@ void Transport<S,C,U>::loop() {
|
|||||||
};
|
};
|
||||||
case TCP:
|
case TCP:
|
||||||
{
|
{
|
||||||
tcpSessionHandler(server); // for session oriented coms
|
tcpSessionHandler(server);
|
||||||
break;
|
|
||||||
};
|
};
|
||||||
case MQTT:
|
case MQTT:
|
||||||
{
|
{
|
||||||
@ -64,7 +64,7 @@ void Transport<S, C, U>::connectionPool(S *server)
|
|||||||
clients[i] = server->accept();
|
clients[i] = server->accept();
|
||||||
connections[i].client = &clients[i];
|
connections[i].client = &clients[i];
|
||||||
connections[i].id = i;
|
connections[i].id = i;
|
||||||
DIAG(F("\nConnection pool: [%d:%x]"), i, clients[i]);
|
DIAG(F("\nConnection pool: [%d:%x]"), i, connections[i].client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +114,7 @@ void Transport<S,C,U>::tcpSessionHandler(S* server)
|
|||||||
// check for new client
|
// check for new client
|
||||||
if (client)
|
if (client)
|
||||||
{
|
{
|
||||||
for (byte i = 0; i < Transport<S,C,U>::maxConnections; i++)
|
for (byte i = 0; i < maxConnections; i++)
|
||||||
{
|
{
|
||||||
if (!clients[i])
|
if (!clients[i])
|
||||||
{
|
{
|
||||||
@ -126,23 +126,24 @@ void Transport<S,C,U>::tcpSessionHandler(S* server)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for incoming data from all possible clients
|
// check for incoming data from all possible clients
|
||||||
for (byte i = 0; i < Transport<S,C,U>::maxConnections; i++)
|
for (byte i = 0; i < maxConnections; i++)
|
||||||
{
|
{
|
||||||
if (clients[i] && clients[i].available() > 0)
|
if (clients[i] && clients[i].available() > 0)
|
||||||
{
|
{
|
||||||
// readStream(i);
|
|
||||||
t->readStream(&connections[i]);
|
t->readStream(&connections[i]);
|
||||||
}
|
}
|
||||||
// stop any clients which disconnect
|
// stop any clients which disconnect
|
||||||
for (byte i = 0; i < Transport<S,C,U>::maxConnections; i++)
|
for (byte i = 0; i < maxConnections; i++)
|
||||||
{
|
{
|
||||||
if (clients[i] && !clients[i].connected())
|
if (clients[i] && !clients[i].connected())
|
||||||
{
|
{
|
||||||
DIAG(F("\nDisconnect client #%d"), i);
|
DIAG(F("\nDisconnect client #%d"), i);
|
||||||
clients[i].stop();
|
clients[i].stop();
|
||||||
connections[i].isProtocolDefined = false;
|
connections[i].isProtocolDefined = false;
|
||||||
if (diagNetworkClient == i && diagNetwork) {
|
if (diagNetworkClient == i && diagNetwork)
|
||||||
|
{
|
||||||
diagNetwork = false;
|
diagNetwork = false;
|
||||||
StringFormatter::resetDiagOut();
|
StringFormatter::resetDiagOut();
|
||||||
}
|
}
|
||||||
@ -152,22 +153,10 @@ void Transport<S,C,U>::tcpSessionHandler(S* server)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class S, class C, class U>
|
template<class S, class C, class U>
|
||||||
Transport<S,C,U>::Transport()
|
Transport<S,C,U>::Transport(){}
|
||||||
{
|
|
||||||
// DIAG(F("Transport created "));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class S, class C, class U>
|
template<class S, class C, class U>
|
||||||
Transport<S,C,U>::~Transport()
|
Transport<S,C,U>::~Transport(){}
|
||||||
{
|
|
||||||
// DIAG(F("Transport destroyed"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// explicitly instatiate to get the relevant copies for ethernet / wifi build @compile time
|
// explicitly instatiate to get the relevant copies for ethernet / wifi build @compile time
|
||||||
template class Transport<EthernetServer,EthernetClient,EthernetUDP>;
|
template class Transport<EthernetServer,EthernetClient,EthernetUDP>;
|
||||||
template class Transport<WiFiServer, WiFiClient, WiFiUDP>;
|
template class Transport<WiFiServer, WiFiClient, WiFiUDP>;
|
||||||
|
|
||||||
/*
|
|
||||||
* Scratch pad Section
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
26
Transport.h
26
Transport.h
@ -23,30 +23,10 @@
|
|||||||
#include <Ethernet.h>
|
#include <Ethernet.h>
|
||||||
#include <WiFiEspAT.h>
|
#include <WiFiEspAT.h>
|
||||||
|
|
||||||
|
#include "NetworkConfig.h"
|
||||||
#include "NetworkInterface.h"
|
#include "NetworkInterface.h"
|
||||||
#include "TransportProcessor.h"
|
#include "TransportProcessor.h"
|
||||||
|
|
||||||
|
|
||||||
#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 in //
|
|
||||||
#define LISTEN_PORT 2560 // default listen port for the server
|
|
||||||
|
|
||||||
|
|
||||||
#define MAC_ADDRESS \
|
|
||||||
{ \
|
|
||||||
0x52, 0xB8, 0x8A, 0x8E, 0xCE, 0x21 \
|
|
||||||
} // MAC address of your networking card found on the sticker on your card or take one from above
|
|
||||||
#define IP_ADDRESS 10, 0, 0, 101 // Just in case we don't get an adress from DHCP try a static one;
|
|
||||||
|
|
||||||
// Emulate Serial1 on pins 6/7 if not present
|
|
||||||
#if defined(ARDUINO_ARCH_AVR) && !defined(HAVE_HWSERIAL1)
|
|
||||||
#include <SoftwareSerial.h>
|
|
||||||
SoftwareSerial Serial1(6, 7); // RX, TX
|
|
||||||
#define AT_BAUD_RATE 9600
|
|
||||||
#else
|
|
||||||
#define AT_BAUD_RATE 115200
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template <class S, class C, class U> class Transport
|
template <class S, class C, class U> class Transport
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -66,9 +46,9 @@ public:
|
|||||||
uint8_t transport; // WIFI or ETHERNET
|
uint8_t transport; // WIFI or ETHERNET
|
||||||
S* server; // WiFiServer or EthernetServer
|
S* server; // WiFiServer or EthernetServer
|
||||||
U* udp; // UDP socket object
|
U* udp; // UDP socket object
|
||||||
uint8_t maxConnections; // number of supported connections depending on the network equipment used
|
uint8_t maxConnections; // number of supported connections depending on the network equipment use
|
||||||
|
|
||||||
bool setup();
|
bool setup(NetworkInterface* nwi);
|
||||||
void loop();
|
void loop();
|
||||||
|
|
||||||
bool isConnected() {
|
bool isConnected() {
|
||||||
|
@ -24,17 +24,13 @@
|
|||||||
|
|
||||||
#ifdef DCCEX_ENABLED
|
#ifdef DCCEX_ENABLED
|
||||||
|
|
||||||
#include "DCCEXParser.h"
|
#include "DCCEXParser.h"
|
||||||
#include "MemStream.h"
|
#include "MemStream.h"
|
||||||
|
|
||||||
DCCEXParser ethParser;
|
DCCEXParser ethParser;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static uint8_t buffer[MAX_ETH_BUFFER];
|
|
||||||
static char command[MAX_JMRI_CMD] = {0};
|
|
||||||
static uint8_t reply[MAX_ETH_BUFFER];
|
|
||||||
|
|
||||||
HttpRequest httpReq;
|
HttpRequest httpReq;
|
||||||
uint16_t _rseq[MAX_SOCK_NUM] = {0};
|
uint16_t _rseq[MAX_SOCK_NUM] = {0};
|
||||||
uint16_t _sseq[MAX_SOCK_NUM] = {0};
|
uint16_t _sseq[MAX_SOCK_NUM] = {0};
|
||||||
@ -50,19 +46,19 @@ uint8_t diagNetworkClient = 0;
|
|||||||
* before ending it.
|
* before ending it.
|
||||||
*
|
*
|
||||||
* @param stream Actually the Client to whom to send the reply. As Clients implement Print this is working
|
* @param stream Actually the Client to whom to send the reply. As Clients implement Print this is working
|
||||||
* @param command The reply to be send ( echo as in sendReply() )
|
* @param t TransportProcessor used for accessing the buffers to be send
|
||||||
* @param blocking if set to true will instruct the DCC code to not use the async callback functions
|
* @param blocking if set to true will instruct the DCC code to not use the async callback functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void sendToDCC(Connection* c ,char *command, bool blocking)
|
void sendToDCC(Connection *c, TransportProcessor* t, bool blocking)
|
||||||
{
|
{
|
||||||
static MemStream* streamer = new MemStream((byte *)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"), 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)
|
||||||
{
|
{
|
||||||
@ -71,10 +67,10 @@ void sendToDCC(Connection* c ,char *command, bool blocking)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
command[streamer->available()] = '\0'; // mark end of buffer, so it can be used as a string later
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,29 +81,41 @@ void sendToDCC(Connection* c ,char *command, bool blocking)
|
|||||||
* @param client Client who send the command to which the reply shall be send
|
* @param client Client who send the command to which the reply shall be send
|
||||||
* @param command Command initaliy recieved to be echoed back
|
* @param command Command initaliy recieved to be echoed back
|
||||||
*/
|
*/
|
||||||
void sendReply(Connection* c, char *command)
|
void sendReply(Connection *c, TransportProcessor *t)
|
||||||
{
|
{
|
||||||
|
byte reply[MAX_ETH_BUFFER];
|
||||||
|
byte *response;
|
||||||
char *number;
|
char *number;
|
||||||
|
char *command = t->command;
|
||||||
char seqNumber[6];
|
char seqNumber[6];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
memset(reply, 0, MAX_ETH_BUFFER); // reset reply
|
memset(reply, 0, MAX_ETH_BUFFER); // reset reply
|
||||||
|
|
||||||
number = strrchr(command, ':'); // replace the int after the last ':'
|
// This expects messages to be send with a trailing sequence number <R 1 1 1:0>
|
||||||
while( &command[i] != number ) { // copy command into the reply upto the last ':'
|
// as of my stress test program to verify the arrival of messages
|
||||||
|
|
||||||
|
number = strrchr(command, ':'); // replace the int after the last ':' if number != 0
|
||||||
|
if (number != 0)
|
||||||
|
{
|
||||||
|
while (&command[i] != number)
|
||||||
|
{ // copy command into the reply upto the last ':'
|
||||||
reply[i] = command[i];
|
reply[i] = command[i];
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
strcat((char *)reply, ":");
|
strcat((char *)reply, ":");
|
||||||
itoa(_sseq[c->id], seqNumber, 10);
|
itoa(_sseq[c->id], seqNumber, 10);
|
||||||
strcat((char *)reply, seqNumber);
|
strcat((char *)reply, seqNumber);
|
||||||
strcat((char *)reply, ">");
|
strcat((char *)reply, ">");
|
||||||
|
response = reply;
|
||||||
|
} else {
|
||||||
|
response = (byte *)command;
|
||||||
|
}
|
||||||
|
|
||||||
DIAG(F("Response: [%e]"), (char *)reply);
|
DIAG(F("Response: [%e]"), (char *)response);
|
||||||
if (c->client->connected())
|
if (c->client->connected())
|
||||||
{
|
{
|
||||||
c->client->write(reply, strlen((char *)reply));
|
c->client->write(response, strlen((char *)response));
|
||||||
_sseq[c->id]++;
|
_sseq[c->id]++;
|
||||||
DIAG(F(" send\n"));
|
DIAG(F(" send\n"));
|
||||||
}
|
}
|
||||||
@ -121,20 +129,21 @@ void sendReply(Connection* c, char *command)
|
|||||||
* @param client Client object from whom we receievd the data
|
* @param client Client object from whom we receievd the data
|
||||||
* @param c id of the Client object
|
* @param c id of the Client object
|
||||||
*/
|
*/
|
||||||
void httpProcessor(Connection* c)
|
void httpProcessor(Connection *c, TransportProcessor *t)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (httpReq.callback == 0) return; // no callback i.e. nothing to do
|
if (httpReq.callback == 0)
|
||||||
|
return; // no callback i.e. nothing to do
|
||||||
/**
|
/**
|
||||||
* @todo look for jmri formatted uris and execute those if there is no callback. If no command found ignore and
|
* @todo look for jmri formatted uris and execute those if there is no callback. If no command found ignore and
|
||||||
* ev. send a 401 error back
|
* ev. send a 401 error back
|
||||||
*/
|
*/
|
||||||
uint8_t i, l = 0;
|
uint8_t i, l = 0;
|
||||||
ParsedRequest preq;
|
ParsedRequest preq;
|
||||||
l = strlen((char *)buffer);
|
l = strlen((char *)t->buffer);
|
||||||
for (i = 0; i < l; i++)
|
for (i = 0; i < l; i++)
|
||||||
{
|
{
|
||||||
httpReq.parseRequest((char)buffer[i]);
|
httpReq.parseRequest((char)t->buffer[i]);
|
||||||
}
|
}
|
||||||
if (httpReq.endOfRequest())
|
if (httpReq.endOfRequest())
|
||||||
{
|
{
|
||||||
@ -216,7 +225,8 @@ appProtocol setAppProtocol(char a, char b, Connection *c)
|
|||||||
p = DCCEX;
|
p = DCCEX;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case '#': {
|
case '#':
|
||||||
|
{
|
||||||
p = DCCEX;
|
p = DCCEX;
|
||||||
DIAG(F("\nDiagnostics routed to network client\n"));
|
DIAG(F("\nDiagnostics routed to network client\n"));
|
||||||
StringFormatter::setDiagOut(c);
|
StringFormatter::setDiagOut(c);
|
||||||
@ -239,32 +249,31 @@ appProtocol setAppProtocol(char a, char b, Connection *c)
|
|||||||
* @brief Parses the buffer to extract commands to be executed
|
* @brief Parses the buffer to extract commands to be executed
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
void processStream(Connection *c, TransportProcessor *t)
|
||||||
// void TransportProcessor::processStream(Connection *c)
|
|
||||||
void processStream(Connection *c)
|
|
||||||
{
|
{
|
||||||
uint8_t i, j, k, l = 0;
|
uint8_t i, j, k, l = 0;
|
||||||
|
uint8_t *_buffer = t->buffer;
|
||||||
|
|
||||||
|
DIAG(F("\nBuffer: [%e]\n"), _buffer);
|
||||||
|
memset(t->command, 0, MAX_JMRI_CMD); // clear out the command
|
||||||
|
|
||||||
memset(command, 0, MAX_JMRI_CMD); // clear out the command
|
|
||||||
DIAG(F("\nBuffer: [%e]\n"), buffer);
|
|
||||||
// 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
|
||||||
memset(c->overflow, 0, MAX_OVERFLOW);
|
memset(c->overflow, 0, MAX_OVERFLOW);
|
||||||
|
|
||||||
// check if there is again an overflow and copy if needed
|
// check if there is again an overflow and copy if needed
|
||||||
if ((i = strlen((char *)buffer)) == MAX_ETH_BUFFER - 1)
|
if ((i = strlen((char *)_buffer)) == MAX_ETH_BUFFER - 1)
|
||||||
{ // only then we shall be in an overflow situation
|
{
|
||||||
// DIAG(F("\nPossible overflow situation detected: %d "), i);
|
// DIAG(F("\nPossible overflow situation detected: %d "), i);
|
||||||
j = i;
|
j = i;
|
||||||
while (buffer[i] != c->delimiter)
|
while (_buffer[i] != c->delimiter)
|
||||||
{ // what if there is none: ?
|
{
|
||||||
// DIAG(F("%c"),(char) buffer[i]);
|
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
i++; // start of the buffer to copy
|
i++; // start of the buffer to copy
|
||||||
@ -273,32 +282,31 @@ void processStream(Connection *c)
|
|||||||
|
|
||||||
for (j = 0; j < k; j++, i++)
|
for (j = 0; j < k; j++, i++)
|
||||||
{
|
{
|
||||||
c->overflow[j] = buffer[i];
|
c->overflow[j] = _buffer[i];
|
||||||
// DIAG(F("\n%d %d %d %c"),k,j,i, buffer[i]); // c->overflow[j]);
|
// DIAG(F("\n%d %d %d %c"),k,j,i, buffer[i]); // c->overflow[j]);
|
||||||
}
|
}
|
||||||
buffer[l] = '\0'; // terminate buffer just after the last '>'
|
_buffer[l] = '\0'; // terminate buffer just after the last '>'
|
||||||
// DIAG(F("\nNew buffer: [%s] New overflow: [%s]\n"), (char*) buffer, c->overflow );
|
// DIAG(F("\nNew buffer: [%s] New overflow: [%s]\n"), (char*) buffer, c->overflow );
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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, command, true);
|
sendToDCC(c, command, true);
|
||||||
#else
|
#else
|
||||||
sendReply(c, command);
|
sendReply(c, t);
|
||||||
#endif
|
#endif
|
||||||
_rseq[c->id]++;
|
_rseq[c->id]++;
|
||||||
j = 0;
|
j = 0;
|
||||||
@ -312,24 +320,26 @@ void processStream(Connection *c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void echoProcessor(Connection *c)
|
void echoProcessor(Connection *c, TransportProcessor *t)
|
||||||
{
|
{
|
||||||
|
byte reply[MAX_ETH_BUFFER];
|
||||||
|
|
||||||
memset(reply, 0, MAX_ETH_BUFFER);
|
memset(reply, 0, MAX_ETH_BUFFER);
|
||||||
sprintf((char *)reply, "ERROR: malformed content in [%s]", buffer);
|
sprintf((char *)reply, "ERROR: malformed content in [%s]", t->buffer);
|
||||||
if (c->client->connected())
|
if (c->client->connected())
|
||||||
{
|
{
|
||||||
c->client->write(reply, strlen((char *)reply));
|
c->client->write(reply, strlen((char *)reply));
|
||||||
_sseq[c->id]++;
|
_sseq[c->id]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void jmriProcessor(Connection *c)
|
void jmriProcessor(Connection *c, TransportProcessor *t)
|
||||||
{
|
{
|
||||||
processStream(c);
|
DIAG(F("Processing JMRI ... \n"));
|
||||||
|
processStream(c, t);
|
||||||
}
|
}
|
||||||
void withrottleProcessor(Connection *c)
|
void withrottleProcessor(Connection *c, TransportProcessor *t)
|
||||||
{
|
{
|
||||||
processStream(c);
|
processStream(c, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -340,6 +350,7 @@ void withrottleProcessor(Connection *c)
|
|||||||
|
|
||||||
void TransportProcessor::readStream(Connection *c)
|
void TransportProcessor::readStream(Connection *c)
|
||||||
{
|
{
|
||||||
|
|
||||||
// read bytes from a client
|
// read bytes from a client
|
||||||
int count = c->client->read(buffer, MAX_ETH_BUFFER - 1); // count is the amount of data ready for reading, -1 if there is no data, 0 is the connection has been closed
|
int count = c->client->read(buffer, MAX_ETH_BUFFER - 1); // count is the amount of data ready for reading, -1 if there is no data, 0 is the connection has been closed
|
||||||
buffer[count] = 0;
|
buffer[count] = 0;
|
||||||
@ -368,7 +379,7 @@ void TransportProcessor::readStream(Connection *c)
|
|||||||
case HTTP:
|
case HTTP:
|
||||||
{
|
{
|
||||||
c->appProtocolHandler = (appProtocolCallback)httpProcessor;
|
c->appProtocolHandler = (appProtocolCallback)httpProcessor;
|
||||||
httpReq.callback = NetworkInterface::getHttpCallback();
|
httpReq.callback = nwi->getHttpCallback();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case UNKNOWN_PROTOCOL:
|
case UNKNOWN_PROTOCOL:
|
||||||
@ -380,17 +391,14 @@ void TransportProcessor::readStream(Connection *c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IPAddress remote = c->client->remoteIP(); // only available in my modified Client.h file
|
IPAddress remote = c->client->remoteIP();
|
||||||
|
|
||||||
buffer[count] = '\0'; // terminate the string properly
|
buffer[count] = '\0'; // terminate the string properly
|
||||||
|
DIAG(F("\nReceived packet of size:[%d] from [%d.%d.%d.%d]\n"), count, remote[0], remote[1], remote[2], remote[3]);
|
||||||
// DIAG(F("\nReceived packet of size:[%d] from [%d.%d.%d.%d]\n"), count, remote[0], remote[1], remote[2], remote[3]);
|
|
||||||
DIAG(F("\nReceived packet of size:[%d]\n"), count);
|
|
||||||
DIAG(F("Client #: [%d]\n"), c->id);
|
DIAG(F("Client #: [%d]\n"), c->id);
|
||||||
DIAG(F("Packet: [%e]\n"), buffer);
|
DIAG(F("Packet: [%e]\n"), buffer);
|
||||||
|
|
||||||
// chop the buffer into CS / WiThrottle commands || assemble command across buffer read boundaries
|
// chop the buffer into CS / WiThrottle commands || assemble command across buffer read boundaries
|
||||||
c->appProtocolHandler(c);
|
c->appProtocolHandler(c, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -408,63 +416,3 @@ void parse(Print *stream, byte *command, bool blocking)
|
|||||||
// echo back (as mock parser )
|
// echo back (as mock parser )
|
||||||
StringFormatter::send(stream, F("reply to: %s"), command);
|
StringFormatter::send(stream, F("reply to: %s"), command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
// Alternative reply mechanism using MemStream thus allowing to send all in one go using the parser
|
|
||||||
streamer.setBufferContentPosition(0, 0);
|
|
||||||
|
|
||||||
// Parse via MemBuffer to be replaced by DCCEXparser.parse later
|
|
||||||
|
|
||||||
parse(&streamer, buffer, true); // set to true to that the execution in DCC is sync
|
|
||||||
|
|
||||||
if (streamer.available() == 0)
|
|
||||||
{
|
|
||||||
DIAG(F("No response\n"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
buffer[streamer.available()] = '\0'; // mark end of buffer, so it can be used as a string later
|
|
||||||
DIAG(F("Response: [%s]\n"), (char *)reply);
|
|
||||||
if (clients[i]->connected())
|
|
||||||
{
|
|
||||||
clients[i]->write(reply, streamer.available());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/* This should work but creates a segmentation fault ??
|
|
||||||
|
|
||||||
// check if we have one parameter with name 'jmri' then send the payload directly and don't call the callback
|
|
||||||
preq = httpReq.getParsedRequest();
|
|
||||||
DIAG(F("Check parameter count\n"));
|
|
||||||
if (*preq.paramCount == 1)
|
|
||||||
{
|
|
||||||
Params *p;
|
|
||||||
int cmp;
|
|
||||||
p = httpReq.getParam(1);
|
|
||||||
|
|
||||||
DIAG(F("Parameter name[%s]\n"), p->name);
|
|
||||||
DIAG(F("Parameter value[%s]\n"), p->value);
|
|
||||||
|
|
||||||
cmp = strcmp("jmri", p->name);
|
|
||||||
if ( cmp == 0 ) {
|
|
||||||
memset(buffer, 0, MAX_ETH_BUFFER); // reset PacktBuffer
|
|
||||||
strncpy((char *)buffer, p->value, strlen(p->value));
|
|
||||||
jmriHandler(client, c);
|
|
||||||
} else {
|
|
||||||
DIAG(F("Callback 1\n"));
|
|
||||||
httpReq.callback(&preq, client);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DIAG(F("Callback 2\n"));
|
|
||||||
httpReq.callback(&preq, client);
|
|
||||||
}
|
|
||||||
DIAG(F("ResetRequest\n"));
|
|
||||||
httpReq.resetRequest();
|
|
||||||
|
|
||||||
} // else do nothing and wait for the next packet
|
|
||||||
}
|
|
||||||
*/
|
|
@ -23,12 +23,11 @@
|
|||||||
#include <Ethernet.h>
|
#include <Ethernet.h>
|
||||||
#include <WiFiEspAT.h>
|
#include <WiFiEspAT.h>
|
||||||
|
|
||||||
#define DCCEX_ENABLED
|
#include "NetworkConfig.h"
|
||||||
|
#include "NetworkInterface.h"
|
||||||
|
|
||||||
|
// #define DCCEX_ENABLED
|
||||||
|
|
||||||
#define MAX_ETH_BUFFER 64 // maximum length we read in one go from a TCP packet. Anything longer in one go send to the Arduino may result in unpredictable behaviour.
|
|
||||||
// idealy the windowsize should be set accordingly so that the sender knows to produce only max 250 size packets.
|
|
||||||
#define MAX_OVERFLOW MAX_ETH_BUFFER / 2 // length of the overflow buffer to be used for a given connection.
|
|
||||||
#define MAX_JMRI_CMD 32 // MAX Length of a JMRI Command
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
DCCEX, // if char[0] = < opening bracket the client should be a JMRI / DCC EX client_h
|
DCCEX, // if char[0] = < opening bracket the client should be a JMRI / DCC EX client_h
|
||||||
@ -38,8 +37,11 @@ typedef enum
|
|||||||
UNKNOWN_PROTOCOL
|
UNKNOWN_PROTOCOL
|
||||||
} appProtocol;
|
} appProtocol;
|
||||||
|
|
||||||
|
// Needed forward declarations
|
||||||
struct Connection;
|
struct Connection;
|
||||||
using appProtocolCallback = void (*)(Connection *c);
|
class TransportProcessor;
|
||||||
|
|
||||||
|
using appProtocolCallback = void (*)(Connection* c, TransportProcessor* t);
|
||||||
|
|
||||||
struct Connection
|
struct Connection
|
||||||
{
|
{
|
||||||
@ -56,10 +58,15 @@ class TransportProcessor
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
#ifdef DCCEX_ENABLED
|
#ifdef DCCEX_ENABLED
|
||||||
void sendToDCC(Connection *c, char *command, bool blocking);
|
void sendToDCC(Connection *c, TransportProcessor* t, bool blocking);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
NetworkInterface *nwi;
|
||||||
|
uint8_t buffer[MAX_ETH_BUFFER];
|
||||||
|
char command[MAX_JMRI_CMD];
|
||||||
|
|
||||||
void readStream(Connection *c); // reads incomming packets and hands over to the commandHandle for taking the stream apart for commands
|
void readStream(Connection *c); // reads incomming packets and hands over to the commandHandle for taking the stream apart for commands
|
||||||
|
|
||||||
TransportProcessor(){};
|
TransportProcessor(){};
|
||||||
|
@ -40,13 +40,11 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// WiFiServer *setup(uint16_t port);
|
|
||||||
bool setup();
|
bool setup();
|
||||||
|
|
||||||
WiFiUDP* getUdp() {
|
WiFiUDP* getUdp() {
|
||||||
return udp;
|
return udp;
|
||||||
}
|
}
|
||||||
|
|
||||||
WiFiServer* getServer() {
|
WiFiServer* getServer() {
|
||||||
return server;
|
return server;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user