intermediate: dynamic boat data for xdr
This commit is contained in:
		
							parent
							
								
									3ef74581de
								
							
						
					
					
						commit
						166d8d826b
					
				|  | @ -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<class T> GwBoatItem<T> *GwBoatData::getOrCreate(T dummy, String name, String format, | ||||
|                                                   unsigned long invalidTime) | ||||
| template<class T> GwBoatItem<T> *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<T>*)(it->second); | ||||
|     } | ||||
|     return new GwBoatItem<T>(name,format,invalidTime,&values); | ||||
|     GwBoatItem<T> *rt=new GwBoatItem<T>(GwBoatItemTypes::getType(initial), name, | ||||
|         provider->getBoatItemFormat(), | ||||
|         provider->getInvalidTime(), | ||||
|         &values); | ||||
|     rt->update(initial); | ||||
|     return rt; | ||||
| } | ||||
| template<class T> bool GwBoatData::update(T value,int source,GwBoatItemNameProvider *provider){ | ||||
|     GwBoatItem<T> *item=getOrCreate(value,provider); | ||||
|     if (! item) return false; | ||||
|     return item->update(value,source); | ||||
| } | ||||
| template bool GwBoatData::update<double>(double value,int source,GwBoatItemNameProvider *provider); | ||||
| template<class T> 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<T> *)(it->second))->getDataWithDefault(defaultv); | ||||
| } | ||||
| template double GwBoatData::getDataWithDefault<double>(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); | ||||
|  |  | |||
|  | @ -4,9 +4,21 @@ | |||
| #include "GwLog.h" | ||||
| #include <ArduinoJson.h> | ||||
| #include <Arduino.h> | ||||
| #include <vector> | ||||
| #include <map> | ||||
| #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<GwBoatItemBase*> GwBoatItemMap; | ||||
|         typedef std::map<String,GwBoatItemBase*> 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 T> 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<GwSatInfoList> | ||||
| { | ||||
| public: | ||||
|     GwBoatDataSatList(String name, String formatInfo, unsigned long invalidTime = INVALID_TIME, GwBoatItemMap *map = NULL) : GwBoatItem<GwSatInfoList>(name, formatInfo, invalidTime, map) {} | ||||
|     GwBoatDataSatList(String name, String formatInfo, unsigned long invalidTime = INVALID_TIME, GwBoatItemMap *map = NULL) :  | ||||
|         GwBoatItem<GwSatInfoList>(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<type> *name=new GwBoatItem<type>(F(#name),GwBoatItemBase::fmt,time,&values) ; | ||||
|     GwBoatItem<type> *name=new GwBoatItem<type>(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<class T> GwBoatItem<T> *getOrCreate(T dummy,String name,String format, | ||||
|             unsigned long invalidTime=GwBoatItemBase::INVALID_TIME); | ||||
|         template<class T> GwBoatItem<T> *getOrCreate(T initial,GwBoatItemNameProvider *provider); | ||||
|         template<class T> bool update(T value,int source,GwBoatItemNameProvider *provider); | ||||
|         template<class T> 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 T> class GwBoatItemHolder{ | ||||
|     private: | ||||
|         GwBoatItem<T> *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<T> *getItem(GwBoatItemNameProvider *provider){ | ||||
|                 if (item) return item; | ||||
|                 T dummy; | ||||
|                 item=data->getOrCreate(dummy, | ||||
|                     provider->getBoatItemName() , | ||||
|                     provider->getBoatItemFormat(), | ||||
|                     invalidTime); | ||||
|                 return item; | ||||
|             } | ||||
|         GwBoatItem<T> *getItem(){return item;}        | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| #endif | ||||
|  | @ -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(); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 wellenvogel
						wellenvogel