From 301783ae40c8401ff55f1ff78f9cd89dcb31ce9a Mon Sep 17 00:00:00 2001 From: andreas Date: Tue, 2 Nov 2021 21:18:11 +0100 Subject: [PATCH] handle and configure a serial device --- lib/config/GWConfig.cpp | 17 +++--- lib/config/GWConfig.h | 6 +-- src/GwHardware.h | 8 +++ src/main.cpp | 101 ++++++++++++++++++++++++++++-------- web/config.json | 46 ++++++++++++++++- web/index.html | 112 +++++++++++++++++++++++----------------- 6 files changed, 209 insertions(+), 81 deletions(-) diff --git a/lib/config/GWConfig.cpp b/lib/config/GWConfig.cpp index 44078d6..2fd4801 100644 --- a/lib/config/GWConfig.cpp +++ b/lib/config/GWConfig.cpp @@ -31,8 +31,9 @@ String GwConfigHandler::toString() const{ String GwConfigHandler::toJson() const{ String rt; - DynamicJsonDocument jdoc(400); - for (int i=0;igetName()]=configs[i]->asCString(); } serializeJson(jdoc,rt); @@ -98,18 +99,18 @@ bool GwConfigHandler::reset(bool save){ if (!save) return true; return saveConfig(); } -String GwConfigHandler::getString(const String name) const{ +String GwConfigHandler::getString(const String name, String defaultv) const{ GwConfigInterface *i=getConfigItem(name,false); - if (!i) return String(); + if (!i) return defaultv; return i->asString(); } -bool GwConfigHandler::getBool(const String name) const{ +bool GwConfigHandler::getBool(const String name, bool defaultv) const{ GwConfigInterface *i=getConfigItem(name,false); - if (!i) return false; + if (!i) return defaultv; return i->asBoolean(); } -int GwConfigHandler::getInt(const String name) const{ +int GwConfigHandler::getInt(const String name,int defaultv) const{ GwConfigInterface *i=getConfigItem(name,false); - if (!i) return 0; + if (!i) return defaultv; return i->asInt(); } \ No newline at end of file diff --git a/lib/config/GWConfig.h b/lib/config/GWConfig.h index 8f8137f..2f10d49 100644 --- a/lib/config/GWConfig.h +++ b/lib/config/GWConfig.h @@ -21,9 +21,9 @@ class GwConfigHandler: public GwConfigDefinitions{ bool reset(bool save); String toString() const; String toJson() const; - String getString(const String name) const; - bool getBool(const String name) const ; - int getInt(const String name) const; + String getString(const String name,const String defaultv="") const; + bool getBool(const String name,bool defaultv=false) const ; + int getInt(const String name,int defaultv=0) const; GwConfigItem * findConfig(const String name, bool dummy=false); GwConfigInterface * getConfigItem(const String name, bool dummy=false) const; private: diff --git a/src/GwHardware.h b/src/GwHardware.h index 8e0fd9a..95cb161 100644 --- a/src/GwHardware.h +++ b/src/GwHardware.h @@ -13,10 +13,16 @@ */ #ifndef _GWHARDWARE_H #define _GWHARDWARE_H + +//SERIAL_MODE can be: UNI (RX or TX only), BI (both), RX, TX //board specific pins #ifdef BOARD_M5ATOM #define ESP32_CAN_TX_PIN GPIO_NUM_22 #define ESP32_CAN_RX_PIN GPIO_NUM_19 +//if using tail485 +#define GWSERIAL_TX 26 +#define GWSERIAL_RX 32 +#define GWSERIAL_MODE "UNI" #elif BOARD_M5ATOM_CANUNIT #define ESP32_CAN_TX_PIN GPIO_NUM_26 #define ESP32_CAN_RX_PIN GPIO_NUM_32 @@ -26,6 +32,8 @@ #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 +#define GWSERIAL_RX GPIO_NUM_16 +#define GWSERIAL_MODE "RX" #endif #endif diff --git a/src/main.cpp b/src/main.cpp index d40c638..414ba6f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,7 +12,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#define VERSION "0.3.1" +#define VERSION "0.4.0" // #define GW_MESSAGE_DEBUG_ENABLED // #define FALLBACK_SERIAL @@ -81,19 +81,26 @@ GwRequestQueue mainQueue(&logger,20); GwWebServer webserver(&logger,&mainQueue,80); //configs that we need in main -GwConfigInterface *sendUsb=NULL; -GwConfigInterface *sendTCP=NULL; -GwConfigInterface *sendSeasmart=NULL; -GwConfigInterface *systemName=NULL; -GwConfigInterface *n2kFromUSB=NULL; -GwConfigInterface *n2kFromTCP=NULL; -GwSerial usbSerial(NULL, UART_NUM_0, USB_CHANNEL_ID); +GwConfigInterface *sendUsb=config.getConfigItem(config.sendUsb,true); +GwConfigInterface *sendTCP=config.getConfigItem(config.sendTCP,true); +GwConfigInterface *sendSeasmart=config.getConfigItem(config.sendSeasmart,true); +GwConfigInterface *systemName=config.getConfigItem(config.systemName,true); +GwConfigInterface *n2kFromTCP=config.getConfigItem(config.tcpToN2k,true); +GwConfigInterface *n2kFromUSB=config.getConfigItem(config.usbToN2k,true); +GwConfigInterface *receiveSerial=config.getConfigItem(config.receiveSerial,true); +GwConfigInterface *sendSerial=config.getConfigItem(config.sendSerial,true); +GwConfigInterface *n2kFromSerial=config.getConfigItem(config.serialToN2k,true); + +GwSerial *usbSerial = new GwSerial(NULL, UART_NUM_0, USB_CHANNEL_ID); +GwSerial *serial1=NULL; + + class GwSerialLog : public GwLogWriter{ public: virtual ~GwSerialLog(){} virtual void write(const char *data){ - usbSerial.sendToClients(data,-1); //ignore any errors + usbSerial->sendToClients(data,-1); //ignore any errors } }; @@ -145,6 +152,22 @@ protected: serializeJson(status, result); } }; + +class CapabilitiesRequest : public GwRequestMessage{ + public: + CapabilitiesRequest() : GwRequestMessage(F("application/json"),F("capabilities")){}; + protected: + virtual void processRequest(){ + DynamicJsonDocument json(JSON_OBJECT_SIZE(2)); + #ifdef GWSERIAL_MODE + String serial(F(GWSERIAL_MODE)); + #else + String serial(F("NONE")); + #endif + json["serialmode"]=serial; + serializeJson(json,result); + } +}; class ConfigRequest : public GwRequestMessage { public: @@ -236,7 +259,7 @@ void setup() { #ifdef FALLBACK_SERIAL int st=-1; #else - int st=usbSerial.setup(baud,3,1); //TODO: PIN defines + int st=usbSerial->setup(baud,3,1); //TODO: PIN defines #endif if (st < 0){ //falling back to old style serial for logging @@ -251,21 +274,48 @@ void setup() { logger.logDebug(GwLog::LOG,"created GwSerial for USB port"); } logger.logDebug(GwLog::LOG,"config: %s", config.toString().c_str()); - sendUsb=config.getConfigItem(config.sendUsb,true); - sendTCP=config.getConfigItem(config.sendTCP,true); - sendSeasmart=config.getConfigItem(config.sendSeasmart,true); - systemName=config.getConfigItem(config.systemName,true); - n2kFromTCP=config.getConfigItem(config.tcpToN2k,true); - n2kFromUSB=config.getConfigItem(config.usbToN2k,true); + #ifdef GWSERIAL_MODE + int serialrx=UART_PIN_NO_CHANGE; + int serialtx=UART_PIN_NO_CHANGE; + #ifdef GWSERIAL_TX + serialtx=GWSERIAL_TX; + #endif + #ifdef GWSERIAL_RX + serialrx=GWSERIAL_RX; + #endif + String serialDirection=config.getString(config.serialDirection); + //we only consider the direction if mode is UNI + String serialMode(F(GWSERIAL_MODE)); + if (serialMode != String("UNI")){ + serialDirection=String(""); + } + if (serialDirection == "receive" || serialDirection == "off") serialtx=UART_PIN_NO_CHANGE; + if (serialDirection == "send" || serialDirection == "off") serialrx=UART_PIN_NO_CHANGE; + logger.logDebug(GwLog::DEBUG,"serial set up: mode=%s,direction=%s,rx=%d,tx=%d", + serialMode.c_str(),serialDirection.c_str(),serialrx,serialtx + ); + if (serialtx != UART_PIN_NO_CHANGE || serialrx != UART_PIN_NO_CHANGE){ + logger.logDebug(GwLog::LOG,"creating serial interface rx=%d, tx=%d",serialrx,serialtx); + serial1=new GwSerial(&logger,UART_NUM_1,SERIAL1_CHANNEL_ID,true); + } + if (serial1){ + serial1->setup(config.getInt(config.serialBaud,115200),serialrx,serialtx); + } + #endif + MDNS.begin(config.getConfigItem(config.systemName)->asCString()); gwWifi.setup(); // Start TCP server socketServer.begin(); + usbSerial->flush(); webserver.registerMainHandler("/api/reset", [](AsyncWebServerRequest *request)->GwRequestMessage *{ return new ResetRequest(); }); + webserver.registerMainHandler("/api/capabilities", [](AsyncWebServerRequest *request)->GwRequestMessage *{ + return new CapabilitiesRequest(); + }); webserver.registerMainHandler("/api/status", [](AsyncWebServerRequest *request)->GwRequestMessage * { return new StatusRequest(); }); webserver.registerMainHandler("/api/config", [](AsyncWebServerRequest *request)->GwRequestMessage * @@ -328,7 +378,7 @@ void setup() { preferences.end(); logger.logDebug(GwLog::LOG,"NodeAddress=%d", NodeAddress); - usbSerial.flush(); + usbSerial->flush(); NMEA2000.SetMode(tNMEA2000::N2km_ListenAndNode, NodeAddress); NMEA2000.SetForwardOwnMessages(false); // Set the information for other bus devices, which messages we support @@ -337,7 +387,7 @@ void setup() { unsigned long *op=pgns; while (*op != 0){ logger.logDebug(GwLog::DEBUG,"add transmit pgn %ld",(long)(*op)); - usbSerial.flush(); + usbSerial->flush(); op++; } } @@ -368,7 +418,10 @@ void sendBufferToChannels(const char * buffer, int sourceId){ socketServer.sendToClients(buffer,sourceId); } if (sendUsb->asBoolean()){ - usbSerial.sendToClients(buffer,sourceId); + usbSerial->sendToClients(buffer,sourceId); + } + if (sendSerial->asBoolean() && serial1){ + serial1->sendToClients(buffer,sourceId); } } @@ -388,7 +441,8 @@ void SendNMEA0183Message(const tNMEA0183Msg &NMEA0183Msg, int sourceId) { void handleReceivedNmeaMessage(const char *buf, int sourceId){ if ((sourceId == USB_CHANNEL_ID && n2kFromUSB->asBoolean())|| - (sourceId >= MIN_TCP_CHANNEL_ID && n2kFromTCP->asBoolean()) + (sourceId >= MIN_TCP_CHANNEL_ID && n2kFromTCP->asBoolean())|| + (sourceId == SERIAL1_CHANNEL_ID && n2kFromSerial) ) toN2KConverter->parseAndSend(buf,sourceId); sendBufferToChannels(buf,sourceId); @@ -396,7 +450,8 @@ void handleReceivedNmeaMessage(const char *buf, int sourceId){ void handleSendAndRead(bool handleRead){ socketServer.loop(handleRead); - usbSerial.loop(handleRead); + usbSerial->loop(handleRead); + if (serial1) serial1->loop(handleRead); } class NMEAMessageReceiver : public GwBufferWriter{ uint8_t buffer[GwBuffer::RX_BUFFER_SIZE+4]; @@ -468,7 +523,9 @@ void loop() { //read channels socketServer.readMessages(&receiver); receiver.id=USB_CHANNEL_ID; - usbSerial.readMessages(&receiver); + usbSerial->readMessages(&receiver); + receiver.id=SERIAL1_CHANNEL_ID; + if (serial1) serial1->readMessages(&receiver); //handle message requests GwMessage *msg=mainQueue.fetchMessage(0); diff --git a/web/config.json b/web/config.json index 2b22d56..906ff2d 100644 --- a/web/config.json +++ b/web/config.json @@ -36,6 +36,48 @@ "default": "true", "description": "convert NMEA0183 from the USB port to NMEA2000" }, + { + "name": "serialDirection", + "label": "serial direction", + "type": "list", + "default": "receive", + "list": ["send","receive","off"], + "description": "use the serial port to send or receive data", + "capabilities":{"serialmode":["UNI"]} + }, + { + "name": "serialBaud", + "label": "serial baud rate", + "type": "list", + "default": "115200", + "description": "baud rate for the serial port", + "list": [1200,2400,4800,9600,14400,19200,28800,38400,57600,115200,230400,460800], + "capabilities":{"serialmode":["RX","TX","UNI","BI"]} + }, + { + "name": "sendSerial", + "label": "NMEA to Serial", + "type": "boolean", + "default": "true", + "description": "send out NMEA data on the serial port", + "capabilities":{"serialmode":["TX","BI"]} + }, + { + "name": "receiveSerial", + "label": "NMEA from Serial", + "type": "boolean", + "default": "true", + "description": "receive NMEA data on the serial port", + "capabilities":{"serialmode":["RX","BI"]} + }, + { + "name": "serialToN2k", + "label": "serial to NMEA2000", + "type": "boolean", + "default": "true", + "description": "convert NMEA0183 from the serial port to NMEA2000", + "capabilities":{"serialmode":["RX","BI","UNI"]} + }, { "name": "serverPort", "label": "TCP port", @@ -60,14 +102,14 @@ }, { "name": "readTCP", - "label": "TCP to NMEA2000", + "label": "NMEA from TCP", "type": "boolean", "default": "true", "description": "receive NMEA data from connected TCP clients" }, { "name": "tcpToN2k", - "label": "NMEA from TCP", + "label": "TCP to NMEA2000", "type": "boolean", "default": "true", "description": "convert NMEA0183 from TCP clients to NMEA2000" diff --git a/web/index.html b/web/index.html index e8fd795..6b7b4d1 100644 --- a/web/index.html +++ b/web/index.html @@ -7,7 +7,9 @@