change api for getBoatDataValues

This commit is contained in:
wellenvogel 2021-12-05 21:25:12 +01:00
parent 461d4924ad
commit 7b4ab178c2
7 changed files with 57 additions and 42 deletions

View File

@ -5,13 +5,28 @@
#include "NMEA0183Msg.h" #include "NMEA0183Msg.h"
#include "GWConfig.h" #include "GWConfig.h"
#include "GwBoatData.h" #include "GwBoatData.h"
#include <map>
#include <vector>
//API to be used for additional tasks //API to be used for additional tasks
class GwApi{ class GwApi{
public: public:
typedef std::map<String,double> ValueMap; class BoatValue{
typedef std::vector<String> StringList; 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 * thread safe methods - can directly be called from a user task
*/ */
@ -31,13 +46,14 @@ class GwApi{
virtual GwLog *getLogger()=0; virtual GwLog *getLogger()=0;
virtual const char* getTalkerId()=0; virtual const char* getTalkerId()=0;
/** /**
* get a set of boat data values by their names * get a set of boat data values
* the returned map will have the keys being the strings in the names list * the provided list of BoatValue must be initialized with
* the values are the boat data values converted to double * empty boatValues (see exampleTask source code)
* invalid values are not returned in the map * the method will fill the valid flag, the value and the format string of
* this method is thread safe and can directly be used from a user task * 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 * not thread safe methods
* accessing boat data must only be executed from within the main thread * accessing boat data must only be executed from within the main thread

View File

@ -334,6 +334,11 @@ bool GwBoatData::isValid(String name){
if (it == values.end()) return false; if (it == values.end()) return false;
return it->second->isValid(); 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){ double GwBoatData::getDoubleValue(String name,double defaultv){
auto it=values.find(name); auto it=values.find(name);
if (it == values.end()) return defaultv; if (it == values.end()) return defaultv;

View File

@ -71,7 +71,7 @@ class GwBoatItemBase{
virtual void refresh(unsigned long ts=0){uls(ts);} virtual void refresh(unsigned long ts=0){uls(ts);}
virtual double getDoubleValue()=0; virtual double getDoubleValue()=0;
String getName(){return name;} String getName(){return name;}
String getFormat(){return format;} const String & getFormat() const{return format;}
}; };
class GwBoatData; class GwBoatData;
template<class T> class GwBoatItem : public GwBoatItemBase{ template<class T> class GwBoatItem : public GwBoatItemBase{
@ -208,6 +208,7 @@ class GwBoatData{
template<class T> T getDataWithDefault(T defaultv, GwBoatItemNameProvider *provider); template<class T> T getDataWithDefault(T defaultv, GwBoatItemNameProvider *provider);
bool isValid(String name); bool isValid(String name);
double getDoubleValue(String name,double defaultv); double getDoubleValue(String name,double defaultv);
GwBoatItemBase *getBase(String name);
String toJson() const; String toJson() const;
String toString(); String toString();
}; };

View File

@ -51,9 +51,9 @@ void exampleTask(GwApi *api){
bool hasPosition=false; bool hasPosition=false;
bool hasPosition2=false; bool hasPosition2=false;
LOG_DEBUG(GwLog::DEBUG,"example switch ist %s",exampleSwitch?"true":"false"); LOG_DEBUG(GwLog::DEBUG,"example switch ist %s",exampleSwitch?"true":"false");
GwApi::StringList itemNames; GwApi::BoatValue *longitude=new GwApi::BoatValue(F("Longitude"));
itemNames.push_back(F("Latitude")); GwApi::BoatValue *latitude=new GwApi::BoatValue(F("Latitude"));
itemNames.push_back(F("Longitude")); GwApi::BoatValue *valueList[]={longitude,latitude};
while(true){ while(true){
delay(1000); delay(1000);
/* /*
@ -96,30 +96,19 @@ void exampleTask(GwApi *api){
r->unref(); //delete the request r->unref(); //delete the request
/** second example with string based functions to access boatData /** second example with string based functions to access boatData
uses STL vector and map - but does not need any request handling This does not need the request handling approach
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).
Finally it only makes sense to use one of the versions - either with the request Finally it only makes sense to use one of the versions - either with the request
or with the ValueMap approach. 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 //fetch the current values of the items that we have in itemNames
GwApi::ValueMap boatItems=api->getBoatDataValues(itemNames); api->getBoatDataValues(2,valueList);
//get the values out of the map //check if the values are valid (i.e. the values we requested have been found in boatData)
//the returned item is a map iterator if (longitude->valid && latitude->valid){
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()){
//both values are there - so we have a valid position //both values are there - so we have a valid position
if (! hasPosition2){ if (! hasPosition2){
//access to the values via iterator->second (iterator->first would be the name) //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", if (exampleSwitch) LOG_DEBUG(GwLog::LOG,"(2)position availale lat=%f, lon=%f",
latitude->second,longitude->second); latitude->value,longitude->value);
hasPosition2=true; hasPosition2=true;
} }
} }

View File

@ -27,10 +27,10 @@ void exampleTask(GwApi *param);
void exampleInit(GwApi *param); void exampleInit(GwApi *param);
//make the task known to the core //make the task known to the core
//the task function should not return (unless you delete the task - see example code) //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(exampleTask)
DECLARE_USERTASK_PARAM(exampleTask,4000) //if your task is not happy with the default 2000 bytes of stack, replace the DECLARE_USERTASK
//if your task is happy with the default 2000 bytes of stack, replace the DECLARE_USERTASK_PARAM //with: DECLARE_USERTASK_PARAM(exampleTask,4000);
//with: DECLARE_USERTASK(exampleTask); //this would create our task with a stack size of 4000 bytes
//let the core call an init function before the //let the core call an init function before the

View File

@ -95,9 +95,9 @@ public:
virtual const char* getTalkerId(){ virtual const char* getTalkerId(){
return api->getTalkerId(); return api->getTalkerId();
} }
virtual ValueMap getBoatDataValues(StringList names){ virtual void getBoatDataValues(int num,BoatValue **list){
GWSYNCHRONIZED(mainLock); GWSYNCHRONIZED(mainLock);
return api->getBoatDataValues(names); api->getBoatDataValues(num,list);
} }
virtual ~TaskApi(){}; virtual ~TaskApi(){};
}; };

View File

@ -340,14 +340,18 @@ public:
virtual GwLog* getLogger(){ virtual GwLog* getLogger(){
return &logger; return &logger;
} }
virtual GwApi::ValueMap getBoatDataValues(GwApi::StringList names){ virtual void getBoatDataValues(int numValues,BoatValue **list){
std::map<String,double> rt; for (int i=0;i<numValues;i++){
for (auto it=names.begin();it!= names.end();it++){ GwBoatItemBase *item=boatData.getBase(list[i]->getName());
if (boatData.isValid(*it)){ if (item){
rt[*it]=boatData.getDoubleValue(*it,0); 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(){ virtual GwBoatData *getBoatData(){
return &boatData; return &boatData;