From 0360044ef34492bd522f104a073849213b91ffca Mon Sep 17 00:00:00 2001 From: andreas Date: Sun, 17 Oct 2021 21:55:34 +0200 Subject: [PATCH] TCP server separated --- lib/config/GWConfig.cpp | 13 ++++-- lib/config/GWConfig.h | 20 ++++++-- lib/socketserver/GwSocketServer.cpp | 58 +++++++++++++++++++++++ lib/socketserver/GwSocketServer.h | 23 ++++++++++ src/GwHardware.h | 25 ++++++++++ src/main.cpp | 71 ++++------------------------- web/index.html | 12 +++++ 7 files changed, 152 insertions(+), 70 deletions(-) create mode 100644 lib/socketserver/GwSocketServer.cpp create mode 100644 lib/socketserver/GwSocketServer.h create mode 100644 src/GwHardware.h diff --git a/lib/config/GWConfig.cpp b/lib/config/GWConfig.cpp index 2047258..151904f 100644 --- a/lib/config/GWConfig.cpp +++ b/lib/config/GWConfig.cpp @@ -97,13 +97,18 @@ bool GwConfigHandler::reset(bool save){ if (!save) return true; return saveConfig(); } -String GwConfigHandler::getString(const String name){ - GwConfigItem *i=findConfig(name); +String GwConfigHandler::getString(const String name) const{ + GwConfigInterface *i=getConfigItem(name,false); if (!i) return String(); return i->asString(); } -bool GwConfigHandler::getBool(const String name){ - GwConfigItem *i=findConfig(name); +bool GwConfigHandler::getBool(const String name) const{ + GwConfigInterface *i=getConfigItem(name,false); if (!i) return false; return i->asBoolean(); +} +int GwConfigHandler::getInt(const String name) const{ + GwConfigInterface *i=getConfigItem(name,false); + if (!i) return 0; + return i->asInt(); } \ No newline at end of file diff --git a/lib/config/GWConfig.h b/lib/config/GWConfig.h index c649863..70b4f1e 100644 --- a/lib/config/GWConfig.h +++ b/lib/config/GWConfig.h @@ -9,6 +9,7 @@ class GwConfigInterface{ virtual String asString() const=0; virtual const char * asCString() const =0; virtual bool asBoolean() const = 0; + virtual int asInt() const = 0; }; class GwConfigItem: public GwConfigInterface{ private: @@ -33,6 +34,9 @@ class GwConfigItem: public GwConfigInterface{ virtual bool asBoolean() const{ return strcasecmp(value.c_str(),"true") == 0; } + virtual int asInt() const{ + return (int)value.toInt(); + } String getName() const{ return name; } @@ -59,6 +63,8 @@ class GwConfigHandler{ const String wifiClient="wifiClient"; const String wifiPass="wifiPass"; const String wifiSSID="wifiSSID"; + const String serverPort="serverPort"; + const String maxClients="maxClients"; GwConfigHandler(GwLog *logger); bool loadConfig(); bool saveConfig(); @@ -67,20 +73,24 @@ class GwConfigHandler{ bool reset(bool save); String toString() const; String toJson() const; - String getString(const String name); - bool getBool(const String name); + String getString(const String name) const; + bool getBool(const String name) const ; + int getInt(const String name) const; GwConfigItem * findConfig(const String name, bool dummy=false); GwConfigInterface * getConfigItem(const String name, bool dummy=false) const; private: - GwConfigItem* configs[5]={ + GwConfigItem* configs[7]={ new GwConfigItem(sendUsb,"true"), new GwConfigItem (receiveUsb,"false"), new GwConfigItem (wifiClient,"false"), new GwConfigItem (wifiSSID,""), - new GwConfigItem (wifiPass,"") + new GwConfigItem (wifiPass,""), + new GwConfigItem (serverPort,"2222"), + new GwConfigItem (maxClients, "10") + }; int getNumConfig() const{ - return 5; + return 7; } }; #endif \ No newline at end of file diff --git a/lib/socketserver/GwSocketServer.cpp b/lib/socketserver/GwSocketServer.cpp new file mode 100644 index 0000000..9ee480a --- /dev/null +++ b/lib/socketserver/GwSocketServer.cpp @@ -0,0 +1,58 @@ +#include "GwSocketServer.h" + +GwSocketServer::GwSocketServer(const GwConfigHandler *config,GwLog *logger){ + this->config=config; + this->logger=logger; +} +void GwSocketServer::begin(){ + server=new WiFiServer(config->getInt(config->serverPort),config->getInt(config->maxClients)); + server->begin(); + logger->logString("Socket server created, port=%d", + config->getInt(config->serverPort)); + +} +void GwSocketServer::loop() +{ + WiFiClient client = server->available(); // listen for incoming clients + + if (client){ + logger->logString("new client connected from %s", + client.remoteIP().toString().c_str()); + clients.push_back(wiFiClientPtr(new WiFiClient(client))); + } + for (auto it = clients.begin(); it != clients.end();it++) + { + if ((*it) != NULL) + { + if (!(*it)->connected()) + { + logger->logString("client disconnect "); + (*it)->stop(); + clients.erase(it); + } + else + { + while ((*it)->available()) + { + char c = (*it)->read(); + //TODO: read data + } + } + } + else + { + it = clients.erase(it); // Should have been erased by StopClient + } + } +} +void GwSocketServer::sendToClients(const char *buf){ + for (auto it = clients.begin() ; it != clients.end(); it++) { + if ( (*it) != NULL && (*it)->connected() ) { + (*it)->println(buf); + } + } +} + +int GwSocketServer::numClients(){ + return clients.size(); +} \ No newline at end of file diff --git a/lib/socketserver/GwSocketServer.h b/lib/socketserver/GwSocketServer.h new file mode 100644 index 0000000..9ad946b --- /dev/null +++ b/lib/socketserver/GwSocketServer.h @@ -0,0 +1,23 @@ +#ifndef _GWSOCKETSERVER_H +#define _GWSOCKETSERVER_H +#include "GWConfig.h" +#include "GwLog.h" +#include +#include +#include + +using wiFiClientPtr = std::shared_ptr; +class GwSocketServer{ + private: + const GwConfigHandler *config; + GwLog *logger; + std::list clients; + WiFiServer *server=NULL; + public: + GwSocketServer(const GwConfigHandler *config,GwLog *logger); + void begin(); + void loop(); + void sendToClients(const char *buf); + int numClients(); +}; +#endif \ No newline at end of file diff --git a/src/GwHardware.h b/src/GwHardware.h new file mode 100644 index 0000000..483afd1 --- /dev/null +++ b/src/GwHardware.h @@ -0,0 +1,25 @@ +/* + This code is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + This code 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 + Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef _GWHARDWARE_H +#define _GWHARDWARE_H +//board specific pins +#ifdef BOARD_M5ATOM +#define ESP32_CAN_TX_PIN GPIO_NUM_22 +#define ESP32_CAN_RX_PIN GPIO_NUM_19 +#else +#define ESP32_CAN_TX_PIN GPIO_NUM_5 // Set CAN TX port to 5 (Caution!!! Pin 2 before) +#define ESP32_CAN_RX_PIN GPIO_NUM_4 // Set CAN RX port to 4 +#endif + +#endif diff --git a/src/main.cpp b/src/main.cpp index 562c985..49b4f27 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,16 +12,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#define VERSION "0.0.3" - -//board specific pins -#ifdef BOARD_M5ATOM -#define ESP32_CAN_TX_PIN GPIO_NUM_22 -#define ESP32_CAN_RX_PIN GPIO_NUM_19 -#else -#define ESP32_CAN_TX_PIN GPIO_NUM_5 // Set CAN TX port to 5 (Caution!!! Pin 2 before) -#define ESP32_CAN_RX_PIN GPIO_NUM_4 // Set CAN RX port to 4 -#endif +#define VERSION "0.0.4" +#include "GwHardware.h" #define LOG_SERIAL true @@ -41,6 +33,7 @@ #include "GwLog.h" #include "GWConfig.h" #include "GWWifi.h" +#include "GwSocketServer.h" @@ -55,6 +48,7 @@ GwLog logger(LOG_SERIAL); GwConfigHandler config(&logger); GwWifi gwWifi(&config,&logger); +GwSocketServer socketServer(&config,&logger); //counter @@ -84,11 +78,8 @@ const size_t MaxClients = 10; bool SendNMEA0183Conversion = true; // Do we send NMEA2000 -> NMEA0183 conversion bool SendSeaSmart = false; // Do we send NMEA2000 messages in SeaSmart format -WiFiServer server(ServerPort, MaxClients); WiFiServer json(90); -using tWiFiClientPtr = std::shared_ptr; -LinkedList clients; tN2kDataToNMEA0183 nmea0183Converter(&NMEA2000, 0); @@ -167,6 +158,7 @@ void js_status(){ status["version"]=VERSION; status["wifiConnected"]=gwWifi.clientConnected(); status["clientIP"]=WiFi.localIP().toString(); + status["numClients"]=socketServer.numClients(); String buf; serializeJson(status,buf); webserver.send(200,F("application/json"),buf); @@ -241,7 +233,7 @@ void setup() { gwWifi.setup(); // Start TCP server - server.begin(); + socketServer.begin(); // Start JSON server json.begin(); @@ -308,14 +300,7 @@ void setup() { -//***************************************************************************** -void SendBufToClients(const char *buf) { - for (auto it = clients.begin() ; it != clients.end(); it++) { - if ( (*it) != NULL && (*it)->connected() ) { - (*it)->println(buf); - } - } -} + #define MAX_NMEA2000_MESSAGE_SEASMART_SIZE 500 //***************************************************************************** @@ -327,7 +312,7 @@ void HandleNMEA2000Msg(const tN2kMsg &N2kMsg) { char buf[MAX_NMEA2000_MESSAGE_SEASMART_SIZE]; if ( N2kToSeasmart(N2kMsg, millis(), buf, MAX_NMEA2000_MESSAGE_SEASMART_SIZE) == 0 ) return; - SendBufToClients(buf); + socketServer.sendToClients(buf); } @@ -337,7 +322,7 @@ void SendNMEA0183Message(const tNMEA0183Msg &NMEA0183Msg) { char buf[MAX_NMEA0183_MESSAGE_SIZE]; if ( !NMEA0183Msg.GetMessage(buf, MAX_NMEA0183_MESSAGE_SIZE) ) return; - SendBufToClients(buf); + socketServer.sendToClients(buf); if (sendUsb->asBoolean()){ Serial.println(buf); } @@ -369,42 +354,6 @@ void SendN2kEngine() { } -//***************************************************************************** -void AddClient(WiFiClient &client) { - Serial.println("New Client."); - clients.push_back(tWiFiClientPtr(new WiFiClient(client))); -} - -//***************************************************************************** -void StopClient(LinkedList::iterator &it) { - Serial.println("Client Disconnected."); - (*it)->stop(); - it = clients.erase(it); -} - -//***************************************************************************** -void CheckConnections() { - WiFiClient client = server.available(); // listen for incoming clients - - if ( client ) AddClient(client); - - for (auto it = clients.begin(); it != clients.end(); it++) { - if ( (*it) != NULL ) { - if ( !(*it)->connected() ) { - StopClient(it); - } else { - if ( (*it)->available() ) { - char c = (*it)->read(); - if ( c == 0x03 ) StopClient(it); // Close connection by ctrl-c - } - } - } else { - it = clients.erase(it); // Should have been erased by StopClient - } - } -} - - void handle_json() { @@ -492,7 +441,7 @@ void loop() { } SendN2kEngine(); - CheckConnections(); + socketServer.loop(); NMEA2000.ParseMessages(); int SourceAddress = NMEA2000.GetN2kSource(); diff --git a/web/index.html b/web/index.html index 7b0ba50..f9a772e 100644 --- a/web/index.html +++ b/web/index.html @@ -130,6 +130,10 @@ span#connected.ok{ # CAN messages --- +
+ # TCP clients + --- +
wifi client connected --- @@ -147,6 +151,14 @@ span#connected.ok{
+
+ TCP Port + +
+
+ maxTCPClients + +
wifiClient