convert RMC from 0183 to 2k, avoid cores

This commit is contained in:
andreas 2021-10-31 21:20:27 +01:00
parent c14ed4cfe9
commit 470dec92ad
6 changed files with 155 additions and 71 deletions

View File

@ -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 T> class GwBoatItem : public GwBoatItemBase{
@ -75,6 +76,7 @@ template<class T> class GwBoatItem : public GwBoatItemBase{
o[F("source")]=lastUpdateSource;
o[F("valid")]=isValid(minTime);
}
virtual int getLastSource(){return lastUpdateSource;}
};
static double formatCourse(double cv)

View File

@ -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<String, ConverterEntry> 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++)

View File

@ -1,6 +1,8 @@
#include "NMEA0183DataToN2K.h"
#include "NMEA0183Messages.h"
#include "N2kMessages.h"
#include "ConverterList.h"
#include <map>
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<NMEA0183DataToN2KFunctions, tNMEA0183Msg> converters;
void createBoatData()
{
ConverterList<NMEA0183DataToN2KFunctions, SNMEA0183Msg> converters;
std::map<unsigned long,unsigned long> 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<double> *target,double v, int sourceId){
if (v != NMEA0183DoubleNA){
target->update(v,sourceId);
return true;
}
return false;
}
bool updateUint32(GwBoatItem<uint32_t> *target,uint32_t v, int sourceId){
if (v != NMEA0183UInt32NA){
target->update(v,sourceId);
return true;
}
return v;
}
uint32_t getUint32(GwBoatItem<uint32_t> *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());
}

View File

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

View File

@ -38,7 +38,6 @@ public:
protected:
GwLog *logger;
GwBoatData *boatData;
tNMEA0183 *pNMEA0183;
int sourceId;
tSendNMEA0183MessageCallback SendNMEA0183MessageCallback;
void SendMessage(const tNMEA0183Msg &NMEA0183Msg);

View File

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