diff --git a/lib/queue/GwBuffer.cpp b/lib/queue/GwBuffer.cpp index d60a3ee..0f9d676 100644 --- a/lib/queue/GwBuffer.cpp +++ b/lib/queue/GwBuffer.cpp @@ -2,7 +2,7 @@ void GwBuffer::lp(const char *fkt, int p) { - LOG_DEBUG(GwLog::DEBUG + 1, "Buffer[%s]: buf=%p,wp=%d,rp=%d,used=%d,free=%d, p=%d", + LOG_DEBUG(GwLog::DEBUG+2 , "Buffer[%s]: buf=%p,wp=%d,rp=%d,used=%d,free=%d, p=%d", fkt, buffer, offset(writePointer), offset(readPointer), usedSpace(), freeSpace(), p); } @@ -37,6 +37,19 @@ size_t GwBuffer::usedSpace() return writePointer - readPointer; return writePointer+bufferSize-readPointer; } +int GwBuffer::read(){ + if (! usedSpace()) return -1; + int rt=*readPointer; + readPointer++; + if (offset(readPointer) >= bufferSize) + readPointer -= bufferSize; + lp("read"); + return rt; +} +int GwBuffer::peek(){ + if (! usedSpace()) return -1; + return *readPointer; +} size_t GwBuffer::addData(const uint8_t *data, size_t len, bool addPartial) { lp("addDataE", len); diff --git a/lib/queue/GwBuffer.h b/lib/queue/GwBuffer.h index 4218543..9a133d2 100644 --- a/lib/queue/GwBuffer.h +++ b/lib/queue/GwBuffer.h @@ -20,7 +20,7 @@ class GwBufferWriter{ class GwBuffer{ public: static const size_t TX_BUFFER_SIZE=1620; // app. 20 NMEA messages - static const size_t RX_BUFFER_SIZE=200; // enough for 1 NMEA message... + static const size_t RX_BUFFER_SIZE=400; // enough for 1 NMEA message or actisense message typedef enum { OK, ERROR, @@ -47,6 +47,8 @@ class GwBuffer{ size_t freeSpace(); size_t usedSpace(); size_t addData(const uint8_t *data,size_t len,bool addPartial=false); + int read(); + int peek(); /** * write some data to the buffer writer * return an error if the buffer writer returned < 0 diff --git a/lib/serial/GwSerial.cpp b/lib/serial/GwSerial.cpp index de97e67..d9f1a80 100644 --- a/lib/serial/GwSerial.cpp +++ b/lib/serial/GwSerial.cpp @@ -1,4 +1,44 @@ #include "GwSerial.h" + +class GwSerialStream: public Stream{ + private: + GwSerial *serial; + bool partialWrites; + public: + GwSerialStream(GwSerial *serial,bool partialWrites=false){ + this->serial=serial; + this->partialWrites=partialWrites; + } + virtual int available(){ + if (! serial->isInitialized()) return 0; + if (! serial->readBuffer) return 0; + return serial->readBuffer->usedSpace(); + } + virtual int read(){ + if (! serial->isInitialized()) return -1; + if (! serial->readBuffer) return -1; + return serial->readBuffer->read(); + } + virtual int peek(){ + if (! serial->isInitialized()) return -1; + if (! serial->readBuffer) return -1; + return serial->readBuffer->peek(); + } + virtual void flush() {}; + virtual size_t write(uint8_t v){ + if (! serial->isInitialized()) return 0; + size_t rt=serial->buffer->addData(&v,1,partialWrites); + return rt; + } + virtual size_t write(const uint8_t *buffer, size_t size){ + if (! serial->isInitialized()) return 0; + size_t rt=serial->buffer->addData(buffer,size,partialWrites); + return rt; + } + +}; + + class SerialWriter : public GwBufferWriter{ private: HardwareSerial *serial; @@ -90,4 +130,7 @@ void GwSerial::flush(){ while (buffer->fetchData(writer,-1,false) == GwBuffer::AGAIN){ vTaskDelay(1); } -} \ No newline at end of file +} +Stream * GwSerial::getStream(bool partialWrite){ + return new GwSerialStream(this,partialWrite); +} diff --git a/lib/serial/GwSerial.h b/lib/serial/GwSerial.h index 220b501..fe6adfb 100644 --- a/lib/serial/GwSerial.h +++ b/lib/serial/GwSerial.h @@ -4,6 +4,7 @@ #include "GwLog.h" #include "GwBuffer.h" class SerialWriter; +class GwSerialStream; class GwSerial{ private: GwBuffer *buffer; @@ -28,5 +29,7 @@ class GwSerial{ void loop(bool handleRead=true); bool readMessages(GwBufferWriter *writer); void flush(); + Stream *getStream(bool partialWrites); + friend GwSerialStream; }; #endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index b276719..d8d7504 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -34,6 +34,7 @@ const unsigned long HEAP_REPORT_TIME=2000; //set to 0 to disable heap reporting #include #include // This will automatically choose right CAN library and create suitable NMEA2000 object +#include #include #include #include @@ -94,6 +95,8 @@ int NodeAddress; // To store last Node Address Preferences preferences; // Nonvolatile storage on ESP32 - To store LastDeviceAddress N2kDataToNMEA0183 *nmea0183Converter=NULL; NMEA0183DataToN2K *toN2KConverter=NULL; +tActisenseReader *actisenseReader=NULL; + void SendNMEA0183Message(const tNMEA0183Msg &NMEA0183Msg,int id); @@ -140,6 +143,7 @@ void updateNMEACounter(int id,const char *msg,bool incoming,bool fail=false){ GwConfigInterface *sendUsb=config.getConfigItem(config.sendUsb,true); +GwConfigInterface *usbActisense=config.getConfigItem(config.usbActisense,true); GwConfigInterface *sendTCP=config.getConfigItem(config.sendTCP,true); GwConfigInterface *sendSeasmart=config.getConfigItem(config.sendSeasmart,true); GwConfigInterface *systemName=config.getConfigItem(config.systemName,true); @@ -474,6 +478,16 @@ protected: } }; +void handleN2kMessage(const tN2kMsg &n2kMsg){ + if ( sendSeasmart->asBoolean() ) { + char buf[MAX_NMEA2000_MESSAGE_SEASMART_SIZE]; + if ( N2kToSeasmart(n2kMsg, millis(), buf, MAX_NMEA2000_MESSAGE_SEASMART_SIZE) == 0 ) return; + socketServer.sendToClients(buf,N2K_CHANNEL_ID); + } + logger.logDebug(GwLog::DEBUG+1,"handling pgn %d",n2kMsg.PGN); + nmea0183Converter->HandleMsg(n2kMsg); + logger.logDebug(GwLog::DEBUG+1,"done pgn %d",n2kMsg.PGN); + }; void setup() { uint8_t chipid[6]; @@ -649,15 +663,20 @@ void setup() { NMEA2000.ExtendReceiveMessages(nmea0183Converter->handledPgns()); NMEA2000.SetMsgHandler([](const tN2kMsg &n2kMsg){ countNMEA2KIn.add(n2kMsg.PGN); - if ( sendSeasmart->asBoolean() ) { - char buf[MAX_NMEA2000_MESSAGE_SEASMART_SIZE]; - if ( N2kToSeasmart(n2kMsg, millis(), buf, MAX_NMEA2000_MESSAGE_SEASMART_SIZE) == 0 ) return; - socketServer.sendToClients(buf,N2K_CHANNEL_ID); - } - logger.logDebug(GwLog::DEBUG+1,"handling pgn %d",n2kMsg.PGN); - nmea0183Converter->HandleMsg(n2kMsg); - logger.logDebug(GwLog::DEBUG+1,"done pgn %d",n2kMsg.PGN); - }); + handleN2kMessage(n2kMsg); + }); + if (usbActisense->asBoolean()){ + actisenseReader=new tActisenseReader(); + Stream *usbStream=usbSerial->getStream(false); + actisenseReader->SetReadStream(usbStream); + NMEA2000.SetForwardStream(usbStream); + NMEA2000.SetForwardType(tNMEA2000::fwdt_Actisense); + actisenseReader->SetMsgHandler([](const tN2kMsg &msg){ + NMEA2000.SendMsg(msg); + handleN2kMessage(msg); + }); + NMEA2000.SetForwardOwnMessages(true); + } NMEA2000.Open(); logger.logDebug(GwLog::LOG,"starting addon tasks"); logger.flush(); @@ -680,7 +699,7 @@ void sendBufferToChannels(const char * buffer, int sourceId){ socketServer.sendToClients(buffer,sourceId); updateNMEACounter(MIN_TCP_CHANNEL_ID,buffer,false); } - if (sendUsb->asBoolean() && checkFilter(buffer,USB_CHANNEL_ID,false)){ + if (! actisenseReader && sendUsb->asBoolean() && checkFilter(buffer,USB_CHANNEL_ID,false)){ usbSerial->sendToClients(buffer,sourceId); updateNMEACounter(USB_CHANNEL_ID,buffer,false); } @@ -791,9 +810,12 @@ void loop() { //read channels socketServer.readMessages(&receiver); receiver.id=USB_CHANNEL_ID; - usbSerial->readMessages(&receiver); + if (! actisenseReader) usbSerial->readMessages(&receiver); receiver.id=SERIAL1_CHANNEL_ID; if (serial1 && serCanRead ) serial1->readMessages(&receiver); + if (actisenseReader){ + actisenseReader->ParseMessages(); + } //handle message requests GwMessage *msg=mainQueue.fetchMessage(0); diff --git a/web/config.json b/web/config.json index 1b4294d..73643a2 100644 --- a/web/config.json +++ b/web/config.json @@ -123,6 +123,18 @@ ] } }, + { + "name": "usbActisense", + "label": "USB mode", + "type": "list", + "default": "false", + "description": "send/receive NMEA0183 or actisense format on USB", + "list": [ + {"l":"actisense","v":"true"}, + {"l":"nmea0183","v":"false"} + ], + "category": "usb port" + }, { "name": "usbBaud", "label": "USB baud rate", @@ -151,7 +163,8 @@ "type": "boolean", "default": "true", "description": "send out NMEA data on the USB port", - "category": "usb port" + "category": "usb port", + "condition":{"usbActisense":"false"} }, { "name": "receiveUsb", @@ -159,7 +172,8 @@ "type": "boolean", "default": "true", "description": "receive NMEA data on the USB port", - "category": "usb port" + "category": "usb port", + "condition":{"usbActisense":"false"} }, { "name": "usbToN2k", @@ -167,7 +181,8 @@ "type": "boolean", "default": "true", "description": "convert NMEA0183 from the USB port to NMEA2000", - "category": "usb port" + "category": "usb port", + "condition":{"usbActisense":"false"} }, { "name": "usbReadFilter", @@ -175,7 +190,8 @@ "type": "filter", "default": "", "description": "filter for NMEA0183 data when reading from USB\nselect aison|aisoff, set a whitelist or a blacklist with NMEA sentences like RMC,RMB", - "category": "usb port" + "category": "usb port", + "condition":{"usbActisense":"false"} }, { "name": "usbWriteFilter", @@ -183,7 +199,8 @@ "type": "filter", "default": "", "description": "filter for NMEA0183 data when writing to USB\nselect aison|aisoff, set a whitelist or a blacklist with NMEA sentences like RMC,RMB", - "category": "usb port" + "category": "usb port", + "condition":{"usbActisense":"false"} }, { "name": "serialDirection",