From 166d8d826b98f47166b9130d5d4021fcfb417fd9 Mon Sep 17 00:00:00 2001 From: wellenvogel Date: Wed, 24 Nov 2021 12:47:41 +0100 Subject: [PATCH] intermediate: dynamic boat data for xdr --- lib/boatData/GwBoatData.cpp | 40 ++++++++++--- lib/boatData/GwBoatData.h | 77 ++++++++++++-------------- lib/nmea2kto0183/N2kDataToNMEA0183.cpp | 1 + 3 files changed, 67 insertions(+), 51 deletions(-) diff --git a/lib/boatData/GwBoatData.cpp b/lib/boatData/GwBoatData.cpp index 533f931..f808cd9 100644 --- a/lib/boatData/GwBoatData.cpp +++ b/lib/boatData/GwBoatData.cpp @@ -6,20 +6,42 @@ GwBoatData::GwBoatData(GwLog *logger){ GwBoatData::~GwBoatData(){ GwBoatItemBase::GwBoatItemMap::iterator it; for (it=values.begin() ; it != values.end();it++){ - delete *it; + delete it->second; } } -template GwBoatItem *GwBoatData::getOrCreate(T dummy, String name, String format, - unsigned long invalidTime) +template GwBoatItem *GwBoatData::getOrCreate(T initial, GwBoatItemNameProvider *provider) { - for (auto it=values.begin();it != values.end();it++){ - if ((*it)->getName() == name){ - return *it; + String name=provider->getBoatItemName(); + auto it=values.find(name); + if (it != values.end()) { + int expectedType=GwBoatItemTypes::getType(initial); + if (expectedType != it->second->getCurrentType()){ + return NULL; } + return (GwBoatItem*)(it->second); } - return new GwBoatItem(name,format,invalidTime,&values); + GwBoatItem *rt=new GwBoatItem(GwBoatItemTypes::getType(initial), name, + provider->getBoatItemFormat(), + provider->getInvalidTime(), + &values); + rt->update(initial); + return rt; } +template bool GwBoatData::update(T value,int source,GwBoatItemNameProvider *provider){ + GwBoatItem *item=getOrCreate(value,provider); + if (! item) return false; + return item->update(value,source); +} +template bool GwBoatData::update(double value,int source,GwBoatItemNameProvider *provider); +template T GwBoatData::getDataWithDefault(T defaultv, GwBoatItemNameProvider *provider){ + auto it=values.find(provider->getBoatItemName()); + if (it == values.end()) return defaultv; + int expectedType=GwBoatItemTypes::getType(defaultv); + if (expectedType != it->second->getCurrentType()) return defaultv; + return ((GwBoatItem *)(it->second))->getDataWithDefault(defaultv); +} +template double GwBoatData::getDataWithDefault(double defaultv, GwBoatItemNameProvider *provider); String GwBoatData::toJson() const { unsigned long minTime=millis(); GwBoatItemBase::GwBoatItemMap::const_iterator it; @@ -27,11 +49,11 @@ String GwBoatData::toJson() const { size_t elementSizes=0; for (it=values.begin() ; it != values.end();it++){ count++; - elementSizes+=(*it)->getJsonSize(); + elementSizes+=it->second->getJsonSize(); } DynamicJsonDocument json(JSON_OBJECT_SIZE(count)+elementSizes+10); for (it=values.begin() ; it != values.end();it++){ - (*it)->toJsonDoc(&json,minTime); + it->second->toJsonDoc(&json,minTime); } String buf; serializeJson(json,buf); diff --git a/lib/boatData/GwBoatData.h b/lib/boatData/GwBoatData.h index d2e0db3..cf70dd7 100644 --- a/lib/boatData/GwBoatData.h +++ b/lib/boatData/GwBoatData.h @@ -4,9 +4,21 @@ #include "GwLog.h" #include #include -#include +#include #define GW_BOAT_VALUE_LEN 32 #define GWSC(name) static constexpr const __FlashStringHelper* name=F(#name) +#define GWTYPE_DOUBLE 1 +#define GWTYPE_UINT32 2 +#define GWTYPE_UINT16 3 +#define GWTYPE_INT16 4 +#define GWTYPE_USER 100 +class GwBoatItemTypes{ + public: + static int getType(const uint32_t &x){return GWTYPE_UINT32;} + static int getType(const uint16_t &x){return GWTYPE_UINT16;} + static int getType(const int16_t &x){return GWTYPE_INT16;} + static int getType(const double &x){return GWTYPE_DOUBLE;} +}; class GwBoatItemBase{ public: static const unsigned long INVALID_TIME=60000; @@ -23,8 +35,9 @@ class GwBoatItemBase{ GWSC(mtr2nm); GWSC(formatDop); GWSC(formatRot); - typedef std::vector GwBoatItemMap; + typedef std::map GwBoatItemMap; protected: + int type; unsigned long lastSet=0; unsigned long invalidTime=INVALID_TIME; String name; @@ -34,6 +47,7 @@ class GwBoatItemBase{ else lastSet=millis(); } public: + int getCurrentType(){return type;} unsigned long getLastSet() const {return lastSet;} bool isValid(unsigned long now=0) const { if (lastSet == 0) return false; @@ -46,6 +60,7 @@ class GwBoatItemBase{ this->invalidTime=invalidTime; this->name=name; this->format=format; + this->type=0; } virtual ~GwBoatItemBase(){} void invalidate(){ @@ -63,10 +78,11 @@ template class GwBoatItem : public GwBoatItemBase{ T data; int lastUpdateSource; public: - GwBoatItem(String name,String formatInfo,unsigned long invalidTime=INVALID_TIME,GwBoatItemMap *map=NULL): + GwBoatItem(int type,String name,String formatInfo,unsigned long invalidTime=INVALID_TIME,GwBoatItemMap *map=NULL): GwBoatItemBase(name,formatInfo,invalidTime){ + type=type; if (map){ - map->push_back(this); + (*map)[name]=this; } lastUpdateSource=-1; } @@ -171,7 +187,8 @@ bool convertToJson(const GwSatInfoList &si,JsonVariant &variant); class GwBoatDataSatList : public GwBoatItem { public: - GwBoatDataSatList(String name, String formatInfo, unsigned long invalidTime = INVALID_TIME, GwBoatItemMap *map = NULL) : GwBoatItem(name, formatInfo, invalidTime, map) {} + GwBoatDataSatList(String name, String formatInfo, unsigned long invalidTime = INVALID_TIME, GwBoatItemMap *map = NULL) : + GwBoatItem(GWTYPE_USER+1, name, formatInfo, invalidTime, map) {} bool update(GwSatInfo info, int source) { unsigned long now = millis(); @@ -205,8 +222,16 @@ public: }; +class GwBoatItemNameProvider +{ +public: + virtual String getBoatItemName() = 0; + virtual String getBoatItemFormat() = 0; + virtual unsigned long getInvalidTime(){ return GwBoatItemBase::INVALID_TIME;} + virtual ~GwBoatItemNameProvider() {} +}; #define GWBOATDATA(type,name,time,fmt) \ - GwBoatItem *name=new GwBoatItem(F(#name),GwBoatItemBase::fmt,time,&values) ; + GwBoatItem *name=new GwBoatItem(GwBoatItemTypes::getType((type)0),F(#name),GwBoatItemBase::fmt,time,&values) ; #define GWSPECBOATDATA(clazz,name,time,fmt) \ clazz *name=new clazz(F(#name),GwBoatItemBase::fmt,time,&values) ; class GwBoatData{ @@ -254,43 +279,11 @@ class GwBoatData{ public: GwBoatData(GwLog *logger); ~GwBoatData(); - template GwBoatItem *getOrCreate(T dummy,String name,String format, - unsigned long invalidTime=GwBoatItemBase::INVALID_TIME); + template GwBoatItem *getOrCreate(T initial,GwBoatItemNameProvider *provider); + template bool update(T value,int source,GwBoatItemNameProvider *provider); + template T getDataWithDefault(T defaultv, GwBoatItemNameProvider *provider); String toJson() const; }; -/** - * class for lazy creation of a boat item - * once we have someone that knows the name for it - * and providing fast access without searching all the time trough the map - * xdr mappings implement such a provider - */ -class GwBoatItemNameProvider -{ -public: - virtual String getBoatItemName() = 0; - virtual String getBoatItemFormat() = 0; - virtual ~GwBoatItemNameProvider() {} -}; -template class GwBoatItemHolder{ - private: - GwBoatItem *item=NULL; - GwBoatData *data; - unsigned long invalidTime=GwBoatItemBase::INVALID_TIME; - public: - GwBoatItemHolder(GwBoatData *data,unsigned long invalidTime=GwBoatItemBase::INVALID_TIME){ - this->data=data; - this->invalidTime=invalidTime; - } - GwBoatItem *getItem(GwBoatItemNameProvider *provider){ - if (item) return item; - T dummy; - item=data->getOrCreate(dummy, - provider->getBoatItemName() , - provider->getBoatItemFormat(), - invalidTime); - return item; - } - GwBoatItem *getItem(){return item;} -}; + #endif \ No newline at end of file diff --git a/lib/nmea2kto0183/N2kDataToNMEA0183.cpp b/lib/nmea2kto0183/N2kDataToNMEA0183.cpp index d3253ad..7074ccf 100644 --- a/lib/nmea2kto0183/N2kDataToNMEA0183.cpp +++ b/lib/nmea2kto0183/N2kDataToNMEA0183.cpp @@ -1222,6 +1222,7 @@ private: } GwXDRFoundMapping mapping=xdrMappings->getMapping(XDRPRESSURE,(int)PressureSource,0,PressureInstance); if (mapping.empty) return; + if (! boatData->update(ActualPressure,sourceId,&mapping)) return; LOG_DEBUG(GwLog::DEBUG+1,"found pressure mapping %s",mapping.definition->toString().c_str()); addToXdr(mapping.buildXdrEntry(ActualPressure)); finalizeXdr();