store all values in boatData
This commit is contained in:
parent
e421fe0722
commit
9fa577c768
|
@ -1,54 +1,29 @@
|
||||||
#include "GwBoatData.h"
|
#include "GwBoatData.h"
|
||||||
|
|
||||||
GwBoatItem *GwBoatData::find(String name,bool doCreate){
|
|
||||||
GwBoatItemMap::iterator it;
|
|
||||||
if ((it=values.find(name)) != values.end()){
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
if (! doCreate) return NULL;
|
|
||||||
GwBoatItem *ni=new GwBoatItem();
|
|
||||||
values[name]=ni;
|
|
||||||
return ni;
|
|
||||||
}
|
|
||||||
GwBoatData::GwBoatData(GwLog *logger){
|
GwBoatData::GwBoatData(GwLog *logger){
|
||||||
|
|
||||||
}
|
}
|
||||||
GwBoatData::~GwBoatData(){
|
GwBoatData::~GwBoatData(){
|
||||||
GwBoatItemMap::iterator it;
|
GwBoatItemBase::GwBoatItemMap::iterator it;
|
||||||
for (it=values.begin() ; it != values.end();it++){
|
for (it=values.begin() ; it != values.end();it++){
|
||||||
delete it->second;
|
delete it->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void GwBoatData::update(String name,const char *value){
|
|
||||||
GwBoatItem *i=find(name);
|
|
||||||
i->update(value);
|
|
||||||
}
|
|
||||||
void GwBoatData::update(String name, String value){
|
|
||||||
GwBoatItem *i=find(name);
|
|
||||||
i->update(value);
|
|
||||||
}
|
|
||||||
void GwBoatData::update(String name, long value){
|
|
||||||
GwBoatItem *i=find(name);
|
|
||||||
i->update(value);
|
|
||||||
}
|
|
||||||
void GwBoatData::update(String name, double value){
|
|
||||||
GwBoatItem *i=find(name);
|
|
||||||
i->update(value);
|
|
||||||
}
|
|
||||||
void GwBoatData::update(String name, bool value){
|
|
||||||
GwBoatItem *i=find(name);
|
|
||||||
i->update(value);
|
|
||||||
}
|
|
||||||
String GwBoatData::toJson() const {
|
String GwBoatData::toJson() const {
|
||||||
long minTime=millis() - maxAge;
|
long minTime=millis();
|
||||||
DynamicJsonDocument json(800);
|
DynamicJsonDocument json(800);
|
||||||
GwBoatItemMap::const_iterator it;
|
GwBoatItemBase::GwBoatItemMap::const_iterator it;
|
||||||
for (it=values.begin() ; it != values.end();it++){
|
for (it=values.begin() ; it != values.end();it++){
|
||||||
if (it->second->isValid(minTime)){
|
if (it->second->isValid(minTime)){
|
||||||
json[it->first]=it->second->getValue();
|
it->second->toJsonDoc(&json,it->first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String buf;
|
String buf;
|
||||||
serializeJson(json,buf);
|
serializeJson(json,buf);
|
||||||
return buf;
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
GwBoatItemBase::GwBoatItemMap * GwBoatData::getValues(){
|
||||||
|
return &values;
|
||||||
}
|
}
|
|
@ -6,62 +6,70 @@
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#define GW_BOAT_VALUE_LEN 32
|
#define GW_BOAT_VALUE_LEN 32
|
||||||
class GwBoatItem{
|
class GwBoatItemBase{
|
||||||
private:
|
public:
|
||||||
char value[GW_BOAT_VALUE_LEN];
|
static const long INVALID_TIME=60000;
|
||||||
|
typedef std::map<String,GwBoatItemBase*> GwBoatItemMap;
|
||||||
|
protected:
|
||||||
long lastSet;
|
long lastSet;
|
||||||
|
long invalidTime=INVALID_TIME;
|
||||||
void uls(){
|
void uls(){
|
||||||
lastSet=millis();
|
lastSet=millis();
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
const char * getValue() const{return value;}
|
|
||||||
long getLastSet() const {return lastSet;}
|
long getLastSet() const {return lastSet;}
|
||||||
bool isValid(long minTime) const {return lastSet > minTime;}
|
bool isValid(long now) const {
|
||||||
GwBoatItem(){
|
return (lastSet + invalidTime) >= now;
|
||||||
value[0]=0;
|
}
|
||||||
|
GwBoatItemBase(long invalidTime=INVALID_TIME){
|
||||||
lastSet=-1;
|
lastSet=-1;
|
||||||
|
this->invalidTime=invalidTime;
|
||||||
}
|
}
|
||||||
void update(String nv){
|
virtual ~GwBoatItemBase(){}
|
||||||
strncpy(value,nv.c_str(),GW_BOAT_VALUE_LEN-1);
|
|
||||||
uls();
|
|
||||||
}
|
|
||||||
void update(const char * nv){
|
|
||||||
strncpy(value,nv,GW_BOAT_VALUE_LEN-1);
|
|
||||||
}
|
|
||||||
void update(long nv){
|
|
||||||
ltoa(nv,value,10);
|
|
||||||
uls();
|
|
||||||
}
|
|
||||||
void update(bool nv){
|
|
||||||
if (nv) strcpy_P(value,PSTR("true"));
|
|
||||||
else strcpy_P(value,PSTR("false"));
|
|
||||||
uls();
|
|
||||||
}
|
|
||||||
void update(double nv){
|
|
||||||
dtostrf(nv,3,7,value);
|
|
||||||
uls();
|
|
||||||
}
|
|
||||||
void invalidate(){
|
void invalidate(){
|
||||||
lastSet=0;
|
lastSet=0;
|
||||||
}
|
}
|
||||||
|
virtual void toJsonDoc(DynamicJsonDocument *doc,String name)=0;
|
||||||
};
|
};
|
||||||
class GwBoatData{
|
class GwBoatData{
|
||||||
typedef std::map<String,GwBoatItem*> GwBoatItemMap;
|
|
||||||
private:
|
private:
|
||||||
const long maxAge=60000; //max age for valid data in ms
|
|
||||||
GwLog *logger;
|
GwLog *logger;
|
||||||
GwBoatItemMap values;
|
GwBoatItemBase::GwBoatItemMap values;
|
||||||
GwBoatItem *find(String name, bool doCreate=true);
|
|
||||||
public:
|
public:
|
||||||
GwBoatData(GwLog *logger);
|
GwBoatData(GwLog *logger);
|
||||||
~GwBoatData();
|
~GwBoatData();
|
||||||
void update(String name,const char *value);
|
GwBoatItemBase::GwBoatItemMap * getValues();
|
||||||
void update(String name, String value);
|
|
||||||
void update(String name, long value);
|
|
||||||
void update(String name, bool value);
|
|
||||||
void update(String name, double value);
|
|
||||||
String toJson() const;
|
String toJson() const;
|
||||||
|
friend class GwBoatItemBase;
|
||||||
};
|
};
|
||||||
|
template<class T> class GwBoatItem : public GwBoatItemBase{
|
||||||
|
private:
|
||||||
|
T data;
|
||||||
|
public:
|
||||||
|
GwBoatItem(long invalidTime=INVALID_TIME): GwBoatItemBase(invalidTime){}
|
||||||
|
virtual ~GwBoatItem(){}
|
||||||
|
void update(T nv){
|
||||||
|
data=nv;
|
||||||
|
uls();
|
||||||
|
}
|
||||||
|
T getData(){
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
virtual void toJsonDoc(DynamicJsonDocument *doc,String name){
|
||||||
|
(*doc)[name]=data;
|
||||||
|
}
|
||||||
|
static GwBoatItem<T> *findOrCreate(GwBoatData *handler, String name,bool doCreate=true,
|
||||||
|
long invalidTime=GwBoatItemBase::INVALID_TIME){
|
||||||
|
GwBoatItemMap *values=handler->getValues();
|
||||||
|
GwBoatItemMap::iterator it;
|
||||||
|
if ((it=values->find(name)) != values->end()){
|
||||||
|
return (GwBoatItem<T> *)it->second;
|
||||||
|
}
|
||||||
|
if (! doCreate) return NULL;
|
||||||
|
GwBoatItem<T> *ni=new GwBoatItem<T>(invalidTime);
|
||||||
|
(*values)[name]=ni;
|
||||||
|
return ni;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -29,6 +29,30 @@
|
||||||
|
|
||||||
const double radToDeg = 180.0 / M_PI;
|
const double radToDeg = 180.0 / M_PI;
|
||||||
|
|
||||||
|
static void updateDouble(GwBoatItem<double> *item,double value){
|
||||||
|
if (value == N2kDoubleNA) return;
|
||||||
|
item->update(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
N2kDataToNMEA0183::N2kDataToNMEA0183(GwLog * logger, GwBoatData *boatData, tNMEA2000 *NMEA2000, tNMEA0183 *NMEA0183) : tNMEA2000::tMsgHandler(0,NMEA2000){
|
||||||
|
SendNMEA0183MessageCallback=0;
|
||||||
|
pNMEA0183=NMEA0183;
|
||||||
|
Variation=N2kDoubleNA; COG=N2kDoubleNA; SOG=N2kDoubleNA;
|
||||||
|
SecondsSinceMidnight=N2kDoubleNA; DaysSince1970=N2kUInt16NA;
|
||||||
|
LastPosSend=0;
|
||||||
|
lastLoopTime=0;
|
||||||
|
NextRMCSend=millis()+RMCPeriod;
|
||||||
|
LastHeadingTime=0;
|
||||||
|
LastCOGSOGTime=0;
|
||||||
|
LastWindTime=0;
|
||||||
|
this->logger=logger;
|
||||||
|
this->boatData=boatData;
|
||||||
|
heading=GwBoatItem<double>::findOrCreate(boatData,F("Heading"),true,2000);
|
||||||
|
latitude=GwBoatItem<double>::findOrCreate(boatData,F("Latitude"),true,4000);
|
||||||
|
longitude=GwBoatItem<double>::findOrCreate(boatData,F("Longitude"),true,4000);
|
||||||
|
altitude=GwBoatItem<double>::findOrCreate(boatData,F("Altitude"),true,4000);
|
||||||
|
}
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
void N2kDataToNMEA0183::HandleMsg(const tN2kMsg &N2kMsg) {
|
void N2kDataToNMEA0183::HandleMsg(const tN2kMsg &N2kMsg) {
|
||||||
switch (N2kMsg.PGN) {
|
switch (N2kMsg.PGN) {
|
||||||
|
@ -52,15 +76,10 @@ void N2kDataToNMEA0183::loop() {
|
||||||
if ( now < (lastLoopTime + 100)) return;
|
if ( now < (lastLoopTime + 100)) return;
|
||||||
lastLoopTime=now;
|
lastLoopTime=now;
|
||||||
SendRMC();
|
SendRMC();
|
||||||
if ( (LastHeadingTime + 2000) < now ) Heading = N2kDoubleNA;
|
|
||||||
if ( (LastCOGSOGTime + 2000) < now ) {
|
if ( (LastCOGSOGTime + 2000) < now ) {
|
||||||
COG = N2kDoubleNA;
|
COG = N2kDoubleNA;
|
||||||
SOG = N2kDoubleNA;
|
SOG = N2kDoubleNA;
|
||||||
}
|
}
|
||||||
if ( (LastPositionTime + 4000) < now ) {
|
|
||||||
Latitude = N2kDoubleNA;
|
|
||||||
Longitude = N2kDoubleNA;
|
|
||||||
}
|
|
||||||
if ( ( LastWindTime + 2000) < now ) {
|
if ( ( LastWindTime + 2000) < now ) {
|
||||||
AWS = N2kDoubleNA;
|
AWS = N2kDoubleNA;
|
||||||
AWA = N2kDoubleNA;
|
AWA = N2kDoubleNA;
|
||||||
|
@ -68,7 +87,7 @@ void N2kDataToNMEA0183::loop() {
|
||||||
TWA = N2kDoubleNA;
|
TWA = N2kDoubleNA;
|
||||||
TWD = N2kDoubleNA;
|
TWD = N2kDoubleNA;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
boatData->update(F("Latitude"),Latitude);
|
boatData->update(F("Latitude"),Latitude);
|
||||||
boatData->update(F("Longitude"),Longitude);
|
boatData->update(F("Longitude"),Longitude);
|
||||||
boatData->update(F("Altitude"),Altitude);
|
boatData->update(F("Altitude"),Altitude);
|
||||||
|
@ -91,7 +110,7 @@ void N2kDataToNMEA0183::loop() {
|
||||||
boatData->update(F("Variation"),Variation *radToDeg);
|
boatData->update(F("Variation"),Variation *radToDeg);
|
||||||
boatData->update(F("GPSTime"),SecondsSinceMidnight);
|
boatData->update(F("GPSTime"),SecondsSinceMidnight);
|
||||||
boatData->update(F("DaysSince1970"),(long)DaysSince1970);
|
boatData->update(F("DaysSince1970"),(long)DaysSince1970);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
|
@ -107,13 +126,13 @@ void N2kDataToNMEA0183::HandleHeading(const tN2kMsg &N2kMsg) {
|
||||||
double _Deviation = 0;
|
double _Deviation = 0;
|
||||||
double _Variation;
|
double _Variation;
|
||||||
tNMEA0183Msg NMEA0183Msg;
|
tNMEA0183Msg NMEA0183Msg;
|
||||||
|
double Heading;
|
||||||
if ( ParseN2kHeading(N2kMsg, SID, Heading, _Deviation, _Variation, ref) ) {
|
if ( ParseN2kHeading(N2kMsg, SID, Heading, _Deviation, _Variation, ref) ) {
|
||||||
if ( ref == N2khr_magnetic ) {
|
if ( ref == N2khr_magnetic ) {
|
||||||
if ( !N2kIsNA(_Variation) ) Variation = _Variation; // Update Variation
|
if ( !N2kIsNA(_Variation) ) Variation = _Variation; // Update Variation
|
||||||
if ( !N2kIsNA(Heading) && !N2kIsNA(Variation) ) Heading -= Variation;
|
if ( !N2kIsNA(Heading) && !N2kIsNA(Variation) ) Heading -= Variation;
|
||||||
}
|
}
|
||||||
LastHeadingTime = millis();
|
updateDouble(heading,Heading);
|
||||||
if ( NMEA0183SetHDG(NMEA0183Msg, Heading, _Deviation, Variation) ) {
|
if ( NMEA0183SetHDG(NMEA0183Msg, Heading, _Deviation, Variation) ) {
|
||||||
SendMessage(NMEA0183Msg);
|
SendMessage(NMEA0183Msg);
|
||||||
}
|
}
|
||||||
|
@ -139,8 +158,8 @@ void N2kDataToNMEA0183::HandleBoatSpeed(const tN2kMsg &N2kMsg) {
|
||||||
if ( ParseN2kBoatSpeed(N2kMsg, SID, WaterReferenced, GroundReferenced, SWRT) ) {
|
if ( ParseN2kBoatSpeed(N2kMsg, SID, WaterReferenced, GroundReferenced, SWRT) ) {
|
||||||
tNMEA0183Msg NMEA0183Msg;
|
tNMEA0183Msg NMEA0183Msg;
|
||||||
STW=WaterReferenced;
|
STW=WaterReferenced;
|
||||||
double MagneticHeading = ( !N2kIsNA(Heading) && !N2kIsNA(Variation) ? Heading + Variation : NMEA0183DoubleNA);
|
double MagneticHeading = ( heading->isValid(millis()) && !N2kIsNA(Variation) ? heading->getData() + Variation : NMEA0183DoubleNA);
|
||||||
if ( NMEA0183SetVHW(NMEA0183Msg, Heading, MagneticHeading, WaterReferenced) ) {
|
if ( NMEA0183SetVHW(NMEA0183Msg, heading->getData(), MagneticHeading, WaterReferenced) ) {
|
||||||
SendMessage(NMEA0183Msg);
|
SendMessage(NMEA0183Msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -169,9 +188,11 @@ void N2kDataToNMEA0183::HandleDepth(const tN2kMsg &N2kMsg) {
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
void N2kDataToNMEA0183::HandlePosition(const tN2kMsg &N2kMsg) {
|
void N2kDataToNMEA0183::HandlePosition(const tN2kMsg &N2kMsg) {
|
||||||
|
double Latitude;
|
||||||
|
double Longitude;
|
||||||
if ( ParseN2kPGN129025(N2kMsg, Latitude, Longitude) ) {
|
if ( ParseN2kPGN129025(N2kMsg, Latitude, Longitude) ) {
|
||||||
LastPositionTime = millis();
|
updateDouble(latitude,Latitude);
|
||||||
|
updateDouble(longitude,Longitude);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,11 +228,15 @@ void N2kDataToNMEA0183::HandleGNSS(const tN2kMsg &N2kMsg) {
|
||||||
tN2kGNSStype ReferenceStationType;
|
tN2kGNSStype ReferenceStationType;
|
||||||
uint16_t ReferenceSationID;
|
uint16_t ReferenceSationID;
|
||||||
double AgeOfCorrection;
|
double AgeOfCorrection;
|
||||||
|
double Latitude;
|
||||||
|
double Longitude;
|
||||||
|
double Altitude;
|
||||||
if ( ParseN2kGNSS(N2kMsg, SID, DaysSince1970, SecondsSinceMidnight, Latitude, Longitude, Altitude, GNSStype, GNSSmethod,
|
if ( ParseN2kGNSS(N2kMsg, SID, DaysSince1970, SecondsSinceMidnight, Latitude, Longitude, Altitude, GNSStype, GNSSmethod,
|
||||||
nSatellites, HDOP, PDOP, GeoidalSeparation,
|
nSatellites, HDOP, PDOP, GeoidalSeparation,
|
||||||
nReferenceStations, ReferenceStationType, ReferenceSationID, AgeOfCorrection) ) {
|
nReferenceStations, ReferenceStationType, ReferenceSationID, AgeOfCorrection) ) {
|
||||||
LastPositionTime = millis();
|
updateDouble(latitude,Latitude);
|
||||||
|
updateDouble(longitude,Longitude);
|
||||||
|
updateDouble(altitude,Altitude);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,7 +266,7 @@ void N2kDataToNMEA0183::HandleWind(const tN2kMsg &N2kMsg) {
|
||||||
|
|
||||||
if (WindReference == N2kWind_Apparent && SOG != N2kDoubleNA) { // Lets calculate and send TWS/TWA if SOG is available
|
if (WindReference == N2kWind_Apparent && SOG != N2kDoubleNA) { // Lets calculate and send TWS/TWA if SOG is available
|
||||||
|
|
||||||
AWD=WindAngle*radToDeg + Heading*radToDeg;
|
AWD=WindAngle*radToDeg + heading->getData()*radToDeg;
|
||||||
if (AWD>360) AWD=AWD-360;
|
if (AWD>360) AWD=AWD-360;
|
||||||
if (AWD<0) AWD=AWD+360;
|
if (AWD<0) AWD=AWD+360;
|
||||||
|
|
||||||
|
@ -280,9 +305,10 @@ void N2kDataToNMEA0183::HandleWind(const tN2kMsg &N2kMsg) {
|
||||||
}
|
}
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
void N2kDataToNMEA0183::SendRMC() {
|
void N2kDataToNMEA0183::SendRMC() {
|
||||||
if ( NextRMCSend <= millis() && !N2kIsNA(Latitude) ) {
|
long now=millis();
|
||||||
|
if ( NextRMCSend <= millis() && latitude->isValid(now) ) {
|
||||||
tNMEA0183Msg NMEA0183Msg;
|
tNMEA0183Msg NMEA0183Msg;
|
||||||
if ( NMEA0183SetRMC(NMEA0183Msg, SecondsSinceMidnight, Latitude, Longitude, COG, SOG, DaysSince1970, Variation) ) {
|
if ( NMEA0183SetRMC(NMEA0183Msg, SecondsSinceMidnight, latitude->getData(), longitude->getData(), COG, SOG, DaysSince1970, Variation) ) {
|
||||||
SendMessage(NMEA0183Msg);
|
SendMessage(NMEA0183Msg);
|
||||||
}
|
}
|
||||||
SetNextRMCSend();
|
SetNextRMCSend();
|
||||||
|
|
|
@ -36,11 +36,11 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static const unsigned long RMCPeriod=500;
|
static const unsigned long RMCPeriod=500;
|
||||||
double Latitude;
|
GwBoatItem<double> *latitude;
|
||||||
double Longitude;
|
GwBoatItem<double> *longitude;
|
||||||
double Altitude;
|
GwBoatItem<double> * altitude;
|
||||||
double Variation;
|
double Variation;
|
||||||
double Heading;
|
GwBoatItem<double> *heading;
|
||||||
double COG;
|
double COG;
|
||||||
double SOG;
|
double SOG;
|
||||||
double STW;
|
double STW;
|
||||||
|
@ -68,7 +68,6 @@ protected:
|
||||||
|
|
||||||
unsigned long LastHeadingTime;
|
unsigned long LastHeadingTime;
|
||||||
unsigned long LastCOGSOGTime;
|
unsigned long LastCOGSOGTime;
|
||||||
unsigned long LastPositionTime;
|
|
||||||
unsigned long LastPosSend;
|
unsigned long LastPosSend;
|
||||||
unsigned long LastWindTime;
|
unsigned long LastWindTime;
|
||||||
unsigned long NextRMCSend;
|
unsigned long NextRMCSend;
|
||||||
|
@ -99,22 +98,7 @@ protected:
|
||||||
void SendMessage(const tNMEA0183Msg &NMEA0183Msg);
|
void SendMessage(const tNMEA0183Msg &NMEA0183Msg);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
N2kDataToNMEA0183(GwLog * logger, GwBoatData *boatData, tNMEA2000 *NMEA2000, tNMEA0183 *NMEA0183) : tNMEA2000::tMsgHandler(0,NMEA2000) {
|
N2kDataToNMEA0183(GwLog * logger, GwBoatData *boatData, tNMEA2000 *NMEA2000, tNMEA0183 *NMEA0183) ;
|
||||||
SendNMEA0183MessageCallback=0;
|
|
||||||
pNMEA0183=NMEA0183;
|
|
||||||
Latitude=N2kDoubleNA; Longitude=N2kDoubleNA; Altitude=N2kDoubleNA;
|
|
||||||
Variation=N2kDoubleNA; Heading=N2kDoubleNA; COG=N2kDoubleNA; SOG=N2kDoubleNA;
|
|
||||||
SecondsSinceMidnight=N2kDoubleNA; DaysSince1970=N2kUInt16NA;
|
|
||||||
LastPosSend=0;
|
|
||||||
lastLoopTime=0;
|
|
||||||
NextRMCSend=millis()+RMCPeriod;
|
|
||||||
LastHeadingTime=0;
|
|
||||||
LastCOGSOGTime=0;
|
|
||||||
LastPositionTime=0;
|
|
||||||
LastWindTime=0;
|
|
||||||
this->logger=logger;
|
|
||||||
this->boatData=boatData;
|
|
||||||
}
|
|
||||||
void HandleMsg(const tN2kMsg &N2kMsg);
|
void HandleMsg(const tN2kMsg &N2kMsg);
|
||||||
void SetSendNMEA0183MessageCallback(tSendNMEA0183MessageCallback _SendNMEA0183MessageCallback) {
|
void SetSendNMEA0183MessageCallback(tSendNMEA0183MessageCallback _SendNMEA0183MessageCallback) {
|
||||||
SendNMEA0183MessageCallback=_SendNMEA0183MessageCallback;
|
SendNMEA0183MessageCallback=_SendNMEA0183MessageCallback;
|
||||||
|
|
Loading…
Reference in New Issue