TCP server separated

This commit is contained in:
andreas 2021-10-17 21:55:34 +02:00
parent 920177fada
commit 0360044ef3
7 changed files with 152 additions and 70 deletions

View File

@ -97,13 +97,18 @@ bool GwConfigHandler::reset(bool save){
if (!save) return true; if (!save) return true;
return saveConfig(); return saveConfig();
} }
String GwConfigHandler::getString(const String name){ String GwConfigHandler::getString(const String name) const{
GwConfigItem *i=findConfig(name); GwConfigInterface *i=getConfigItem(name,false);
if (!i) return String(); if (!i) return String();
return i->asString(); return i->asString();
} }
bool GwConfigHandler::getBool(const String name){ bool GwConfigHandler::getBool(const String name) const{
GwConfigItem *i=findConfig(name); GwConfigInterface *i=getConfigItem(name,false);
if (!i) return false; if (!i) return false;
return i->asBoolean(); return i->asBoolean();
} }
int GwConfigHandler::getInt(const String name) const{
GwConfigInterface *i=getConfigItem(name,false);
if (!i) return 0;
return i->asInt();
}

View File

@ -9,6 +9,7 @@ class GwConfigInterface{
virtual String asString() const=0; virtual String asString() const=0;
virtual const char * asCString() const =0; virtual const char * asCString() const =0;
virtual bool asBoolean() const = 0; virtual bool asBoolean() const = 0;
virtual int asInt() const = 0;
}; };
class GwConfigItem: public GwConfigInterface{ class GwConfigItem: public GwConfigInterface{
private: private:
@ -33,6 +34,9 @@ class GwConfigItem: public GwConfigInterface{
virtual bool asBoolean() const{ virtual bool asBoolean() const{
return strcasecmp(value.c_str(),"true") == 0; return strcasecmp(value.c_str(),"true") == 0;
} }
virtual int asInt() const{
return (int)value.toInt();
}
String getName() const{ String getName() const{
return name; return name;
} }
@ -59,6 +63,8 @@ class GwConfigHandler{
const String wifiClient="wifiClient"; const String wifiClient="wifiClient";
const String wifiPass="wifiPass"; const String wifiPass="wifiPass";
const String wifiSSID="wifiSSID"; const String wifiSSID="wifiSSID";
const String serverPort="serverPort";
const String maxClients="maxClients";
GwConfigHandler(GwLog *logger); GwConfigHandler(GwLog *logger);
bool loadConfig(); bool loadConfig();
bool saveConfig(); bool saveConfig();
@ -67,20 +73,24 @@ class GwConfigHandler{
bool reset(bool save); bool reset(bool save);
String toString() const; String toString() const;
String toJson() const; String toJson() const;
String getString(const String name); String getString(const String name) const;
bool getBool(const String name); bool getBool(const String name) const ;
int getInt(const String name) const;
GwConfigItem * findConfig(const String name, bool dummy=false); GwConfigItem * findConfig(const String name, bool dummy=false);
GwConfigInterface * getConfigItem(const String name, bool dummy=false) const; GwConfigInterface * getConfigItem(const String name, bool dummy=false) const;
private: private:
GwConfigItem* configs[5]={ GwConfigItem* configs[7]={
new GwConfigItem(sendUsb,"true"), new GwConfigItem(sendUsb,"true"),
new GwConfigItem (receiveUsb,"false"), new GwConfigItem (receiveUsb,"false"),
new GwConfigItem (wifiClient,"false"), new GwConfigItem (wifiClient,"false"),
new GwConfigItem (wifiSSID,""), new GwConfigItem (wifiSSID,""),
new GwConfigItem (wifiPass,"") new GwConfigItem (wifiPass,""),
new GwConfigItem (serverPort,"2222"),
new GwConfigItem (maxClients, "10")
}; };
int getNumConfig() const{ int getNumConfig() const{
return 5; return 7;
} }
}; };
#endif #endif

View File

@ -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();
}

View File

@ -0,0 +1,23 @@
#ifndef _GWSOCKETSERVER_H
#define _GWSOCKETSERVER_H
#include "GWConfig.h"
#include "GwLog.h"
#include <list>
#include <memory>
#include <WiFi.h>
using wiFiClientPtr = std::shared_ptr<WiFiClient>;
class GwSocketServer{
private:
const GwConfigHandler *config;
GwLog *logger;
std::list<wiFiClientPtr> clients;
WiFiServer *server=NULL;
public:
GwSocketServer(const GwConfigHandler *config,GwLog *logger);
void begin();
void loop();
void sendToClients(const char *buf);
int numClients();
};
#endif

25
src/GwHardware.h Normal file
View File

@ -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

View File

@ -12,16 +12,8 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#define VERSION "0.0.3" #define VERSION "0.0.4"
#include "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
#define LOG_SERIAL true #define LOG_SERIAL true
@ -41,6 +33,7 @@
#include "GwLog.h" #include "GwLog.h"
#include "GWConfig.h" #include "GWConfig.h"
#include "GWWifi.h" #include "GWWifi.h"
#include "GwSocketServer.h"
@ -55,6 +48,7 @@
GwLog logger(LOG_SERIAL); GwLog logger(LOG_SERIAL);
GwConfigHandler config(&logger); GwConfigHandler config(&logger);
GwWifi gwWifi(&config,&logger); GwWifi gwWifi(&config,&logger);
GwSocketServer socketServer(&config,&logger);
//counter //counter
@ -84,11 +78,8 @@ const size_t MaxClients = 10;
bool SendNMEA0183Conversion = true; // Do we send NMEA2000 -> NMEA0183 conversion bool SendNMEA0183Conversion = true; // Do we send NMEA2000 -> NMEA0183 conversion
bool SendSeaSmart = false; // Do we send NMEA2000 messages in SeaSmart format bool SendSeaSmart = false; // Do we send NMEA2000 messages in SeaSmart format
WiFiServer server(ServerPort, MaxClients);
WiFiServer json(90); WiFiServer json(90);
using tWiFiClientPtr = std::shared_ptr<WiFiClient>;
LinkedList<tWiFiClientPtr> clients;
tN2kDataToNMEA0183 nmea0183Converter(&NMEA2000, 0); tN2kDataToNMEA0183 nmea0183Converter(&NMEA2000, 0);
@ -167,6 +158,7 @@ void js_status(){
status["version"]=VERSION; status["version"]=VERSION;
status["wifiConnected"]=gwWifi.clientConnected(); status["wifiConnected"]=gwWifi.clientConnected();
status["clientIP"]=WiFi.localIP().toString(); status["clientIP"]=WiFi.localIP().toString();
status["numClients"]=socketServer.numClients();
String buf; String buf;
serializeJson(status,buf); serializeJson(status,buf);
webserver.send(200,F("application/json"),buf); webserver.send(200,F("application/json"),buf);
@ -241,7 +233,7 @@ void setup() {
gwWifi.setup(); gwWifi.setup();
// Start TCP server // Start TCP server
server.begin(); socketServer.begin();
// Start JSON server // Start JSON server
json.begin(); 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 #define MAX_NMEA2000_MESSAGE_SEASMART_SIZE 500
//***************************************************************************** //*****************************************************************************
@ -327,7 +312,7 @@ void HandleNMEA2000Msg(const tN2kMsg &N2kMsg) {
char buf[MAX_NMEA2000_MESSAGE_SEASMART_SIZE]; char buf[MAX_NMEA2000_MESSAGE_SEASMART_SIZE];
if ( N2kToSeasmart(N2kMsg, millis(), buf, MAX_NMEA2000_MESSAGE_SEASMART_SIZE) == 0 ) return; 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]; char buf[MAX_NMEA0183_MESSAGE_SIZE];
if ( !NMEA0183Msg.GetMessage(buf, MAX_NMEA0183_MESSAGE_SIZE) ) return; if ( !NMEA0183Msg.GetMessage(buf, MAX_NMEA0183_MESSAGE_SIZE) ) return;
SendBufToClients(buf); socketServer.sendToClients(buf);
if (sendUsb->asBoolean()){ if (sendUsb->asBoolean()){
Serial.println(buf); 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<tWiFiClientPtr>::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() { void handle_json() {
@ -492,7 +441,7 @@ void loop() {
} }
SendN2kEngine(); SendN2kEngine();
CheckConnections(); socketServer.loop();
NMEA2000.ParseMessages(); NMEA2000.ParseMessages();
int SourceAddress = NMEA2000.GetN2kSource(); int SourceAddress = NMEA2000.GetN2kSource();

View File

@ -130,6 +130,10 @@ span#connected.ok{
<span class="label"># CAN messages</span> <span class="label"># CAN messages</span>
<span class="value" id="numcan">---</span> <span class="value" id="numcan">---</span>
</div> </div>
<div class="row">
<span class="label"># TCP clients</span>
<span class="value" id="numClients">---</span>
</div>
<div class="row"> <div class="row">
<span class="label">wifi client connected</span> <span class="label">wifi client connected</span>
<span class="value" id="wifiConnected">---</span> <span class="value" id="wifiConnected">---</span>
@ -147,6 +151,14 @@ span#connected.ok{
<option value="false" selected="selected">Off</option> <option value="false" selected="selected">Off</option>
</select> </select>
</div> </div>
<div class="row">
<span class="label">TCP Port</span>
<input name="serverPort" type="number">
</div>
<div class="row">
<span class="label">maxTCPClients</span>
<input name="maxClients" type="number">
</div>
<div class="row"> <div class="row">
<span class="label">wifiClient</span> <span class="label">wifiClient</span>
<select name="wifiClient"> <select name="wifiClient">