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 "GWConfig.h"
#include "GwBoatData.h"
#include <map>
#include <vector>
//API to be used for additional tasks
class GwApi{
public:
typedef std::map<String,double> ValueMap;
typedef std::vector<String> 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

View File

@ -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;

View File

@ -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 T> class GwBoatItem : public GwBoatItemBase{
@ -208,6 +208,7 @@ class GwBoatData{
template<class T> 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();
};

View File

@ -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;
}
}

View File

@ -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

View File

@ -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(){};
};

View File

@ -340,14 +340,18 @@ public:
virtual GwLog* getLogger(){
return &logger;
}
virtual GwApi::ValueMap getBoatDataValues(GwApi::StringList names){
std::map<String,double> 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;i<numValues;i++){
GwBoatItemBase *item=boatData.getBase(list[i]->getName());
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;