diff --git a/lib/api/GwApi.h b/lib/api/GwApi.h index c9f2cc5..5de6de5 100644 --- a/lib/api/GwApi.h +++ b/lib/api/GwApi.h @@ -5,13 +5,28 @@ #include "NMEA0183Msg.h" #include "GWConfig.h" #include "GwBoatData.h" -#include -#include //API to be used for additional tasks class GwApi{ public: - typedef std::map ValueMap; - typedef std::vector StringList; + class BoatValue{ + const String name; + String format; + bool formatSet=false; + public: + double value=0; + bool valid=false; + BoatValue(){} + BoatValue(String n):name(n){ + } + void setFormat(const String &format){ + if (formatSet) return; + this->format=format; + formatSet=true; + } + const String & getName() const{ + return name; + } + }; /** * thread safe methods - can directly be called from a user task */ @@ -31,13 +46,14 @@ class GwApi{ virtual GwLog *getLogger()=0; virtual const char* getTalkerId()=0; /** - * get a set of boat data values by their names - * the returned map will have the keys being the strings in the names list - * the values are the boat data values converted to double - * invalid values are not returned in the map - * this method is thread safe and can directly be used from a user task + * get a set of boat data values + * the provided list of BoatValue must be initialized with + * empty boatValues (see exampleTask source code) + * the method will fill the valid flag, the value and the format string of + * each boat value + * just make sure to have the list being of appropriate size (numValues) */ - virtual ValueMap getBoatDataValues(StringList)=0; + virtual void getBoatDataValues(int numValues,BoatValue **list)=0; /** * not thread safe methods * accessing boat data must only be executed from within the main thread diff --git a/lib/boatData/GwBoatData.cpp b/lib/boatData/GwBoatData.cpp index 5e5cb51..80ea23d 100644 --- a/lib/boatData/GwBoatData.cpp +++ b/lib/boatData/GwBoatData.cpp @@ -334,6 +334,11 @@ bool GwBoatData::isValid(String name){ if (it == values.end()) return false; return it->second->isValid(); } +GwBoatItemBase* GwBoatData::getBase(String name){ + auto it=values.find(name); + if (it == values.end()) return NULL; + return it->second; +} double GwBoatData::getDoubleValue(String name,double defaultv){ auto it=values.find(name); if (it == values.end()) return defaultv; diff --git a/lib/boatData/GwBoatData.h b/lib/boatData/GwBoatData.h index 7329e8d..4e9e13e 100644 --- a/lib/boatData/GwBoatData.h +++ b/lib/boatData/GwBoatData.h @@ -71,7 +71,7 @@ class GwBoatItemBase{ virtual void refresh(unsigned long ts=0){uls(ts);} virtual double getDoubleValue()=0; String getName(){return name;} - String getFormat(){return format;} + const String & getFormat() const{return format;} }; class GwBoatData; template class GwBoatItem : public GwBoatItemBase{ @@ -208,6 +208,7 @@ class GwBoatData{ template T getDataWithDefault(T defaultv, GwBoatItemNameProvider *provider); bool isValid(String name); double getDoubleValue(String name,double defaultv); + GwBoatItemBase *getBase(String name); String toJson() const; String toString(); }; diff --git a/lib/exampletask/GwExampleTask.cpp b/lib/exampletask/GwExampleTask.cpp index 5f6a3a2..f82fd9d 100644 --- a/lib/exampletask/GwExampleTask.cpp +++ b/lib/exampletask/GwExampleTask.cpp @@ -51,9 +51,9 @@ void exampleTask(GwApi *api){ bool hasPosition=false; bool hasPosition2=false; LOG_DEBUG(GwLog::DEBUG,"example switch ist %s",exampleSwitch?"true":"false"); - GwApi::StringList itemNames; - itemNames.push_back(F("Latitude")); - itemNames.push_back(F("Longitude")); + GwApi::BoatValue *longitude=new GwApi::BoatValue(F("Longitude")); + GwApi::BoatValue *latitude=new GwApi::BoatValue(F("Latitude")); + GwApi::BoatValue *valueList[]={longitude,latitude}; while(true){ delay(1000); /* @@ -96,30 +96,19 @@ void exampleTask(GwApi *api){ r->unref(); //delete the request /** second example with string based functions to access boatData - uses STL vector and map - but does not need any request handling - this uses a reasonable amount of mmeory on the stack: - up to 2x the size of the list of names and 2x the size of the returned map - the default stack size of 2000 will not fit. - So be sure to use DECLARA_USERTASK_PARAM(taskFuntion,stackSize) and provide - a reasonable stack size (e.g. 4000 in this example). + This does not need the request handling approach Finally it only makes sense to use one of the versions - either with the request or with the ValueMap approach. - The request access to boatData gives you more options on how to access the data - and ueses less ressources and runtime but this one is maybe easier to understand and implement **/ //fetch the current values of the items that we have in itemNames - GwApi::ValueMap boatItems=api->getBoatDataValues(itemNames); - //get the values out of the map - //the returned item is a map iterator - auto longitude=boatItems.find(itemNames[1]); - auto latitude=boatItems.find(itemNames[0]); - //check if the iterators are valid (i.e. the values we requested have been found in boatData) - if (longitude != boatItems.end() && latitude != boatItems.end()){ + api->getBoatDataValues(2,valueList); + //check if the values are valid (i.e. the values we requested have been found in boatData) + if (longitude->valid && latitude->valid){ //both values are there - so we have a valid position if (! hasPosition2){ //access to the values via iterator->second (iterator->first would be the name) if (exampleSwitch) LOG_DEBUG(GwLog::LOG,"(2)position availale lat=%f, lon=%f", - latitude->second,longitude->second); + latitude->value,longitude->value); hasPosition2=true; } } diff --git a/lib/exampletask/GwExampleTask.h b/lib/exampletask/GwExampleTask.h index 28704eb..4200d7a 100644 --- a/lib/exampletask/GwExampleTask.h +++ b/lib/exampletask/GwExampleTask.h @@ -27,10 +27,10 @@ void exampleTask(GwApi *param); void exampleInit(GwApi *param); //make the task known to the core //the task function should not return (unless you delete the task - see example code) -//we create our task with a stack size of 4000 bytes -DECLARE_USERTASK_PARAM(exampleTask,4000) -//if your task is happy with the default 2000 bytes of stack, replace the DECLARE_USERTASK_PARAM -//with: DECLARE_USERTASK(exampleTask); +DECLARE_USERTASK(exampleTask) +//if your task is not happy with the default 2000 bytes of stack, replace the DECLARE_USERTASK +//with: DECLARE_USERTASK_PARAM(exampleTask,4000); +//this would create our task with a stack size of 4000 bytes //let the core call an init function before the diff --git a/lib/usercode/GwUserCode.cpp b/lib/usercode/GwUserCode.cpp index 3c1e07f..6be082d 100644 --- a/lib/usercode/GwUserCode.cpp +++ b/lib/usercode/GwUserCode.cpp @@ -95,9 +95,9 @@ public: virtual const char* getTalkerId(){ return api->getTalkerId(); } - virtual ValueMap getBoatDataValues(StringList names){ + virtual void getBoatDataValues(int num,BoatValue **list){ GWSYNCHRONIZED(mainLock); - return api->getBoatDataValues(names); + api->getBoatDataValues(num,list); } virtual ~TaskApi(){}; }; diff --git a/src/main.cpp b/src/main.cpp index a5953e0..02c2bcb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -340,14 +340,18 @@ public: virtual GwLog* getLogger(){ return &logger; } - virtual GwApi::ValueMap getBoatDataValues(GwApi::StringList names){ - std::map rt; - for (auto it=names.begin();it!= names.end();it++){ - if (boatData.isValid(*it)){ - rt[*it]=boatData.getDoubleValue(*it,0); + virtual void getBoatDataValues(int numValues,BoatValue **list){ + for (int i=0;igetName()); + if (item){ + list[i]->valid=item->isValid(); + if (list[i]->valid) list[i]->value=item->getDoubleValue(); + list[i]->setFormat(item->getFormat()); + } + else{ + list[i]->valid=false; } } - return rt; } virtual GwBoatData *getBoatData(){ return &boatData;