convert RMC from 0183 to 2k, avoid cores
This commit is contained in:
parent
c14ed4cfe9
commit
470dec92ad
|
@ -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)
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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:
|
||||
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());
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -38,7 +38,6 @@ public:
|
|||
protected:
|
||||
GwLog *logger;
|
||||
GwBoatData *boatData;
|
||||
tNMEA0183 *pNMEA0183;
|
||||
int sourceId;
|
||||
tSendNMEA0183MessageCallback SendNMEA0183MessageCallback;
|
||||
void SendMessage(const tNMEA0183Msg &NMEA0183Msg);
|
||||
|
|
10
src/main.cpp
10
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;
|
||||
|
|
Loading…
Reference in New Issue