diff --git a/lib/boatData/GwBoatData.h b/lib/boatData/GwBoatData.h index 1a60abc..0c01b3f 100644 --- a/lib/boatData/GwBoatData.h +++ b/lib/boatData/GwBoatData.h @@ -36,6 +36,7 @@ class GwBoatItemBase{ } virtual void toJsonDoc(JsonDocument *doc, unsigned long minTime)=0; virtual size_t getJsonSize(){return JSON_OBJECT_SIZE(4);} + virtual int getLastSource()=0; }; class GwBoatData; template class GwBoatItem : public GwBoatItemBase{ @@ -75,6 +76,7 @@ template class GwBoatItem : public GwBoatItemBase{ o[F("source")]=lastUpdateSource; o[F("valid")]=isValid(minTime); } + virtual int getLastSource(){return lastUpdateSource;} }; static double formatCourse(double cv) diff --git a/lib/converterlist/ConverterList.h b/lib/converterlist/ConverterList.h index cee916f..eb8fb69 100644 --- a/lib/converterlist/ConverterList.h +++ b/lib/converterlist/ConverterList.h @@ -27,53 +27,19 @@ private: pgn = NULL; converter = NULL; } - ConverterEntry(unsigned long pgn, LConverter cv) + ConverterEntry(int num,unsigned long *pgn, LConverter cv) { lconverter = cv; - this->pgn = new unsigned long[1]; - this->pgn[0] = pgn; + numPgn=num; + this->pgn = pgn; } - ConverterEntry(unsigned long pgn, Converter cv = NULL) + ConverterEntry(int num,unsigned long *pgn, Converter cv) { converter = cv; - numPgn = 1; - this->pgn = new unsigned long[1]; - this->pgn[0] = pgn; - } - ConverterEntry(unsigned long pgn1, unsigned long pgn2, Converter cv = NULL) - { - converter = cv; - numPgn = 2; - this->pgn = new unsigned long[2]; - this->pgn[0] = pgn1; - this->pgn[1] = pgn2; - } - ConverterEntry(unsigned long pgn1, unsigned long pgn2, LConverter cv = NULL) - { - lconverter = cv; - numPgn = 2; - this->pgn = new unsigned long[2]; - this->pgn[0] = pgn1; - this->pgn[1] = pgn2; - } - ConverterEntry(unsigned long pgn1, unsigned long pgn2, unsigned long pgn3, Converter cv = NULL) - { - converter = cv; - numPgn = 3; - this->pgn = new unsigned long[3]; - this->pgn[0] = pgn1; - this->pgn[1] = pgn2; - this->pgn[2] = pgn3; - } - ConverterEntry(unsigned long pgn1, unsigned long pgn2, unsigned long pgn3, LConverter cv = NULL) - { - lconverter = cv; - numPgn = 3; - this->pgn = new unsigned long[3]; - this->pgn[0] = pgn1; - this->pgn[1] = pgn2; - this->pgn[2] = pgn3; + numPgn=num; + this->pgn = pgn; } + }; typedef std::map ConverterMap; ConverterMap converters; @@ -85,32 +51,62 @@ public: **/ void registerConverter(unsigned long pgn, Converter converter) { - ConverterEntry e(pgn, converter); + unsigned long *lpgn=new unsigned long[1]{pgn}; + ConverterEntry e(1,lpgn, converter); converters[String(pgn)] = e; } void registerConverter(unsigned long pgn, LConverter converter) { - ConverterEntry e(pgn, converter); + unsigned long *lpgn=new unsigned long[1]{pgn}; + ConverterEntry e(1,lpgn, converter); converters[String(pgn)] = e; } void registerConverter(unsigned long pgn, String sentence, Converter converter) { - ConverterEntry e(pgn, converter); + unsigned long *lpgn=new unsigned long[1]{pgn}; + ConverterEntry e(1,lpgn, converter); converters[sentence] = e; } void registerConverter(unsigned long pgn, String sentence, LConverter converter) { - ConverterEntry e(pgn, converter); + unsigned long *lpgn=new unsigned long[1]{pgn}; + ConverterEntry e(1,lpgn, converter); converters[sentence] = e; } void registerConverter(unsigned long pgn, unsigned long pgn2, String sentence, Converter converter) { - ConverterEntry e(pgn, pgn2, converter); + unsigned long *lpgn=new unsigned long[2]{pgn,pgn2}; + ConverterEntry e(2, lpgn, converter); converters[sentence] = e; } void registerConverter(unsigned long pgn, unsigned long pgn2, String sentence, LConverter converter) { - ConverterEntry e(pgn, pgn2, converter); + unsigned long *lpgn=new unsigned long[2]{pgn,pgn2}; + ConverterEntry e(2, lpgn, converter); + converters[sentence] = e; + } + void registerConverter(unsigned long pgn, unsigned long pgn2, unsigned long pgn3,String sentence, Converter converter) + { + unsigned long *lpgn=new unsigned long[3]{pgn,pgn2,pgn3}; + ConverterEntry e(3, lpgn,converter); + converters[sentence] = e; + } + void registerConverter(unsigned long pgn, unsigned long pgn2, unsigned long pgn3,String sentence, LConverter converter) + { + unsigned long *lpgn=new unsigned long[3]{pgn,pgn2,pgn3}; + ConverterEntry e(3, lpgn,converter); + converters[sentence] = e; + } + void registerConverter(unsigned long pgn, unsigned long pgn2, unsigned long pgn3,unsigned long pgn4,String sentence, Converter converter) + { + unsigned long *lpgn=new unsigned long[4]{pgn,pgn2,pgn3,pgn4}; + ConverterEntry e(4, lpgn,converter); + converters[sentence] = e; + } + void registerConverter(unsigned long pgn, unsigned long pgn2, unsigned long pgn3,unsigned long pgn4,String sentence, LConverter converter) + { + unsigned long *lpgn=new unsigned long[4]{pgn,pgn2,pgn3,pgn4}; + ConverterEntry e(4, lpgn,converter); converters[sentence] = e; } @@ -139,13 +135,13 @@ public: virtual unsigned long *handledPgns() { - //for now max 3 pgns per converter - unsigned long *rt = new unsigned long[converters.size() * 3 + 1]; + //for now max 4 pgns per converter + unsigned long *rt = new unsigned long[converters.size() * 4 + 1]; int idx = 0; for (auto it = converters.begin(); it != converters.end(); it++) { - for (int i = 0; i < it->second.numPgn && i < 3; i++) + for (int i = 0; i < it->second.numPgn && i < 4; i++) { bool found = false; for (int e = 0; e < idx; e++) diff --git a/lib/nmea0183ton2k/NMEA0183DataToN2K.cpp b/lib/nmea0183ton2k/NMEA0183DataToN2K.cpp index 700585c..71aa323 100644 --- a/lib/nmea0183ton2k/NMEA0183DataToN2K.cpp +++ b/lib/nmea0183ton2k/NMEA0183DataToN2K.cpp @@ -1,6 +1,8 @@ #include "NMEA0183DataToN2K.h" #include "NMEA0183Messages.h" +#include "N2kMessages.h" #include "ConverterList.h" +#include NMEA0183DataToN2K::NMEA0183DataToN2K(GwLog *logger, GwBoatData *boatData,N2kSender callback) { this->sender = callback; @@ -14,47 +16,127 @@ bool NMEA0183DataToN2K::parseAndSend(const char *buffer, int sourceId) { return false; } +class SNMEA0183Msg { + public: + int sourceId; + const char *line; + tNMEA0183Msg msg; + }; class NMEA0183DataToN2KFunctions : public NMEA0183DataToN2K { -private: +private: double dummy = 0; - ConverterList converters; - void createBoatData() - { + ConverterList converters; + std::map lastSends; + + bool send(tN2kMsg &msg,unsigned long minDiff=50){ + unsigned long now=millis(); + unsigned long pgn=msg.PGN; + auto it=lastSends.find(pgn); + if (it == lastSends.end()){ + lastSends[pgn]=now; + sender(msg); + return true; + } + if ((it->second + minDiff) < now){ + lastSends[pgn]=now; + sender(msg); + return true; + } + return false; } - void convertRMB(const tNMEA0183Msg &msg) + bool updateDouble(GwBoatItem *target,double v, int sourceId){ + if (v != NMEA0183DoubleNA){ + target->update(v,sourceId); + return true; + } + return false; + } + bool updateUint32(GwBoatItem *target,uint32_t v, int sourceId){ + if (v != NMEA0183UInt32NA){ + target->update(v,sourceId); + return true; + } + return v; + } + uint32_t getUint32(GwBoatItem *src){ + return src->getDataWithDefault(N2kUInt32NA); + } + void convertRMB(const SNMEA0183Msg &msg) { LOG_DEBUG(GwLog::DEBUG + 1, "convert RMB"); } + #define UD(item) updateDouble(boatData->item, item, msg.sourceId) + #define UI(item) updateUint32(boatData->item, item, msg.sourceId) + void convertRMC(const SNMEA0183Msg &msg) + { + double SecondsSinceMidnight=0, Latitude=0, Longitude=0, COG=0, SOG=0, Variation=0; + unsigned long DaysSince1970=0; + time_t DateTime; + char status; + if (!NMEA0183ParseRMC_nc(msg.msg, SecondsSinceMidnight, status, Latitude, Longitude, COG, SOG, DaysSince1970, Variation, &DateTime)) + { + logger->logDebug(GwLog::DEBUG, "failed to parse RMC %s", msg.line); + return; + } + tN2kMsg n2kMsg; + if ( + UD(SecondsSinceMidnight) && + UI(DaysSince1970) + ) + { + + SetN2kSystemTime(n2kMsg, 1, DaysSince1970, SecondsSinceMidnight); + send(n2kMsg); + } + if (UD(Latitude) && + UD(Longitude)){ + SetN2kLatLonRapid(n2kMsg,Latitude,Longitude); + send(n2kMsg); + } + if (UD(COG) && UD(SOG)){ + SetN2kCOGSOGRapid(n2kMsg,1,N2khr_true,COG,SOG); + send(n2kMsg); + } + if (UD(Variation)){ + SetN2kMagneticVariation(n2kMsg,1,N2kmagvar_Calc, + getUint32(boatData->DaysSince1970), Variation); + send(n2kMsg); + } + + } + //shortcut for lambda converters -#define CVL [](const tNMEA0183Msg &msg, NMEA0183DataToN2KFunctions *p) -> void +#define CVL [](const SNMEA0183Msg &msg, NMEA0183DataToN2KFunctions *p) -> void void registerConverters() { converters.registerConverter(129283UL, String(F("RMB")), &NMEA0183DataToN2KFunctions::convertRMB); converters.registerConverter( - 123UL, String(F("RMC")), CVL - { - p->dummy++; - p->logger->logDebug(GwLog::DEBUG, "RMC converter"); - }); + 126992UL,129025UL,129026UL,127258UL, String(F("RMC")), + &NMEA0183DataToN2KFunctions::convertRMC); } public: virtual bool parseAndSend(const char *buffer, int sourceId) { LOG_DEBUG(GwLog::DEBUG + 1, "NMEA0183DataToN2K[%d] parsing %s", sourceId, buffer) - tNMEA0183Msg msg; - if (!msg.SetMessage(buffer)) + SNMEA0183Msg msg; + msg.sourceId=sourceId; + msg.line=buffer; + if (!msg.msg.SetMessage(buffer)) { LOG_DEBUG(GwLog::DEBUG, "NMEA0183DataToN2K[%d] invalid message %s", sourceId, buffer) return false; } - String code = msg.MessageCode(); + String code = msg.msg.MessageCode(); bool rt = converters.handleMessage(code, msg, this); if (!rt) { LOG_DEBUG(GwLog::DEBUG, "NMEA0183DataToN2K[%d] no handler for %s", sourceId, buffer); } + else{ + LOG_DEBUG(GwLog::DEBUG+1, "NMEA0183DataToN2K[%d] handler done ", sourceId); + } return rt; } @@ -66,7 +148,6 @@ public: NMEA0183DataToN2KFunctions(GwLog *logger, GwBoatData *boatData, N2kSender callback) : NMEA0183DataToN2K(logger, boatData, callback) { - createBoatData(); registerConverters(); LOG_DEBUG(GwLog::LOG, "NMEA0183DataToN2KFunctions: registered %d converters", converters.numConverters()); } diff --git a/lib/nmea2kto0183/N2kDataToNMEA0183.cpp b/lib/nmea2kto0183/N2kDataToNMEA0183.cpp index c97b3e6..a7d350e 100644 --- a/lib/nmea2kto0183/N2kDataToNMEA0183.cpp +++ b/lib/nmea2kto0183/N2kDataToNMEA0183.cpp @@ -48,7 +48,6 @@ void N2kDataToNMEA0183::loop() { //***************************************************************************** void N2kDataToNMEA0183::SendMessage(const tNMEA0183Msg &NMEA0183Msg) { - if ( pNMEA0183 != 0 ) pNMEA0183->SendMessage(NMEA0183Msg); if ( SendNMEA0183MessageCallback != 0 ) SendNMEA0183MessageCallback(NMEA0183Msg, sourceId); } @@ -340,7 +339,10 @@ private: void SendRMC() { long now = millis(); - if (NextRMCSend <= millis() && boatData->Latitude->isValid(now)) + if (NextRMCSend <= millis() && + boatData->Latitude->isValid(now) && + boatData->Latitude->getLastSource() == sourceId + ) { tNMEA0183Msg NMEA0183Msg; if (NMEA0183SetRMC(NMEA0183Msg, diff --git a/lib/nmea2kto0183/N2kDataToNMEA0183.h b/lib/nmea2kto0183/N2kDataToNMEA0183.h index 228a8d1..6b2f221 100644 --- a/lib/nmea2kto0183/N2kDataToNMEA0183.h +++ b/lib/nmea2kto0183/N2kDataToNMEA0183.h @@ -38,7 +38,6 @@ public: protected: GwLog *logger; GwBoatData *boatData; - tNMEA0183 *pNMEA0183; int sourceId; tSendNMEA0183MessageCallback SendNMEA0183MessageCallback; void SendMessage(const tNMEA0183Msg &NMEA0183Msg); diff --git a/src/main.cpp b/src/main.cpp index 93e0f03..c77f983 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,7 +12,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#define VERSION "0.2.1" +#define VERSION "0.3.1" + //#define GW_MESSAGE_DEBUG_ENABLED //#define FALLBACK_SERIAL const unsigned long HEAP_REPORT_TIME=2000; //set to 0 to disable heap reporting @@ -292,7 +293,8 @@ void setup() { SendNMEA0183Message, N2K_CHANNEL_ID); toN2KConverter= NMEA0183DataToN2K::create(&logger,&boatData,[](const tN2kMsg &msg)->bool{ - logger.logDebug(GwLog::DEBUG+1,"send N2K"); + logger.logDebug(GwLog::DEBUG+2,"send N2K %ld",msg.PGN); + NMEA2000.SendMsg(msg); return true; }); @@ -328,6 +330,7 @@ void setup() { logger.logDebug(GwLog::LOG,"NodeAddress=%d\n", NodeAddress); NMEA2000.SetMode(tNMEA2000::N2km_ListenAndNode, NodeAddress); + NMEA2000.SetForwardOwnMessages(false); // Set the information for other bus devices, which messages we support NMEA2000.ExtendTransmitMessages(toN2KConverter->handledPgns()); NMEA2000.ExtendReceiveMessages(nmea0183Converter->handledPgns()); @@ -363,9 +366,10 @@ void sendBufferToChannels(const char * buffer, int sourceId){ //***************************************************************************** void SendNMEA0183Message(const tNMEA0183Msg &NMEA0183Msg, int sourceId) { if ( ! sendTCP->asBoolean() && ! sendUsb->asBoolean() ) return; - + logger.logDebug(GwLog::DEBUG+2,"SendNMEA0183(1)"); char buf[MAX_NMEA0183_MESSAGE_SIZE+3]; if ( !NMEA0183Msg.GetMessage(buf, MAX_NMEA0183_MESSAGE_SIZE) ) return; + logger.logDebug(GwLog::DEBUG+2,"SendNMEA0183: %s",buf); size_t len=strlen(buf); buf[len]=0x0d; buf[len+1]=0x0a;