intermediate: simplify task interfaces
This commit is contained in:
parent
85e1a0e5f0
commit
56518d9309
|
@ -43,11 +43,7 @@ class GwApi{
|
|||
* the core part will not handle this data at all but
|
||||
* this interface ensures that there is a correct locking of the
|
||||
* data to correctly handle multi threading
|
||||
* The user code should not use this intterface directly
|
||||
* but instead it should use the static functions
|
||||
* apiGetXXX(GwApi *,...)
|
||||
* apiSetXXX(GwApi *,...)
|
||||
* that will be created by the macro DECLARE_TASK_INTERFACE
|
||||
* there is no protection - i.e. every task can get and set the data
|
||||
*/
|
||||
class TaskInterfaces
|
||||
{
|
||||
|
@ -61,9 +57,8 @@ class GwApi{
|
|||
};
|
||||
using Ptr = std::shared_ptr<Base>;
|
||||
protected:
|
||||
virtual bool iset(const String &file, const String &name, Ptr v) = 0;
|
||||
virtual bool iset(const String &name, Ptr v) = 0;
|
||||
virtual Ptr iget(const String &name, int &result) = 0;
|
||||
virtual bool iclaim(const String &name, const String &task)=0;
|
||||
public:
|
||||
template <typename T>
|
||||
bool set(const T &v){
|
||||
|
@ -76,7 +71,7 @@ class GwApi{
|
|||
}
|
||||
template <typename T>
|
||||
bool claim(const String &task){
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
class Status{
|
||||
|
@ -255,27 +250,20 @@ static void checkDef(T... args){};
|
|||
* int ival2=99;
|
||||
* String sval="unset";
|
||||
* };
|
||||
* DECLARE_TASKIF(testTask,TestTaskApi);
|
||||
* The macro will generate 2 static funtions:
|
||||
* DECLARE_TASKIF(TestTaskApi);
|
||||
*
|
||||
* bool apiSetTestTaskApi(GwApi *api, const TestTaskApi &v);
|
||||
* TestTaskApi apiGetTestTaskApi(GwApi *api, int &result);
|
||||
*
|
||||
* The setter will return true on success.
|
||||
* It is intended to be used by the task that did declare the api.
|
||||
* The getter will set the result to -1 if no data is available, otherwise
|
||||
* it will return the update count (so you can check if there was a change
|
||||
* compared to the last call).
|
||||
* It is intended to be used by any task.
|
||||
* Be aware that all the apis share a common namespace - so be sure to somehow
|
||||
* make your API names unique.
|
||||
*
|
||||
* To utilize this interface a task can call:
|
||||
* api->taskInterfaces()->get<TestTaskApi>(res) //and check the result in res
|
||||
* api->taskInterfaces()->set<TestTaskApi>(value)
|
||||
*
|
||||
*/
|
||||
#define DECLARE_TASKIF_IMPL(type) \
|
||||
template<> \
|
||||
inline bool GwApi::TaskInterfaces::set(const type & v) {\
|
||||
return iset(__FILE__,#type,GwApi::TaskInterfaces::Ptr(new type(v))); \
|
||||
return iset(#type,GwApi::TaskInterfaces::Ptr(new type(v))); \
|
||||
}\
|
||||
template<> \
|
||||
inline type GwApi::TaskInterfaces::get<type>(int &result) {\
|
||||
|
@ -286,11 +274,7 @@ static void checkDef(T... args){};
|
|||
}\
|
||||
type *tp=(type*)ptr.get(); \
|
||||
return type(*tp); \
|
||||
}\
|
||||
template<> \
|
||||
inline bool GwApi::TaskInterfaces::claim<type>(const String &task) {\
|
||||
return iclaim(#type,task);\
|
||||
}\
|
||||
}
|
||||
|
||||
#ifndef DECLARE_TASKIF
|
||||
#define DECLARE_TASKIF(type) DECLARE_TASKIF_IMPL(type)
|
||||
|
|
|
@ -65,7 +65,7 @@ static void addGroveItems(std::vector<IICSensorBase::Creator> &creators,GwApi *a
|
|||
if (scfg->ok)
|
||||
{
|
||||
LOG_DEBUG(GwLog::LOG, "adding %s from grove config", prfx.c_str());
|
||||
sensors.add(api, scfg);
|
||||
sensors.add(api, SensorBase::Ptr(scfg));
|
||||
found=true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
#ifndef _GWIICTASK_H
|
||||
#define _GWIICTASK_H
|
||||
#include "GwApi.h"
|
||||
#include "GwSensor.h"
|
||||
void initIicTask(GwApi *api);
|
||||
DECLARE_INITFUNCTION(initIicTask);
|
||||
class IICSensors : public GwApi::TaskInterfaces::Base{
|
||||
public:
|
||||
SensorList sensors;
|
||||
};
|
||||
DECLARE_TASKIF(IICSensors);
|
||||
#endif
|
|
@ -16,6 +16,7 @@
|
|||
#define _GWSENSORS_H
|
||||
#include "GwApi.h"
|
||||
#include "GwLog.h"
|
||||
#include <memory>
|
||||
class SensorBase{
|
||||
public:
|
||||
using BusType=enum{
|
||||
|
@ -23,6 +24,7 @@ class SensorBase{
|
|||
SPI=1,
|
||||
UNKNOWN=-1
|
||||
};
|
||||
using Ptr=std::shared_ptr<SensorBase>;
|
||||
BusType busType=BusType::UNKNOWN;
|
||||
int busId=0;
|
||||
int iid=99; //N2K instanceId
|
||||
|
@ -59,14 +61,14 @@ class SensorTemplate : public SensorBase{
|
|||
};
|
||||
|
||||
|
||||
class SensorList : public std::vector<SensorBase*>{
|
||||
class SensorList : public std::vector<SensorBase::Ptr>{
|
||||
public:
|
||||
void add(GwApi *api, SensorBase *sensor){
|
||||
void add(GwApi *api, SensorBase::Ptr sensor){
|
||||
sensor->readConfig(api->getConfig());
|
||||
api->getLogger()->logDebug(GwLog::LOG,"configured sensor %s, status %d",sensor->prefix.c_str(),(int)sensor->ok);
|
||||
this->push_back(sensor);
|
||||
}
|
||||
using std::vector<SensorBase*>::vector;
|
||||
using std::vector<SensorBase::Ptr>::vector;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#define DECLARE_STRING_CAPABILITY(name,value) GwUserCapability __CAP##name##__(#name,value);
|
||||
#define DECLARE_TASKIF(type) \
|
||||
DECLARE_TASKIF_IMPL(type) \
|
||||
GwIreg __register##type(__FILE__,#type)
|
||||
static int __taskInterface##type=0; //avoid duplicate declarations
|
||||
|
||||
#include "GwUserCode.h"
|
||||
#include "GwSynchronized.h"
|
||||
|
@ -28,45 +28,6 @@ bool taskExists(V &list, const String &name){
|
|||
}
|
||||
return false;
|
||||
}
|
||||
class RegEntry{
|
||||
public:
|
||||
String file;
|
||||
String task;
|
||||
RegEntry(const String &t, const String &f):file(f),task(t){}
|
||||
RegEntry(){}
|
||||
};
|
||||
using RegMap=std::map<String,RegEntry>;
|
||||
static RegMap ®istrations(){
|
||||
static RegMap *regMap=new RegMap();
|
||||
return *regMap;
|
||||
}
|
||||
|
||||
static void registerInterface(const String &task,const String &file, const String &name){
|
||||
auto it=registrations().find(name);
|
||||
if (it != registrations().end()){
|
||||
if (it->second.file != file){
|
||||
ESP_LOGE("Assert","type %s redefined in %s original in %s",name,file,it->second.file);
|
||||
std::abort();
|
||||
};
|
||||
if (it->second.task != task){
|
||||
ESP_LOGE("Assert","type %s registered for multiple tasks %s and %s",name,task,it->second.task);
|
||||
std::abort();
|
||||
};
|
||||
}
|
||||
else{
|
||||
registrations()[name]=RegEntry(task,file);
|
||||
}
|
||||
}
|
||||
|
||||
class GwIreg{
|
||||
public:
|
||||
GwIreg(const String &file, const String &name){
|
||||
registerInterface("",file,name);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class GwUserTaskDef{
|
||||
public:
|
||||
GwUserTaskDef(TaskFunction_t task,String name, int stackSize=2000){
|
||||
|
@ -112,21 +73,8 @@ class TaskInterfacesStorage{
|
|||
logger(l){
|
||||
lock=xSemaphoreCreateMutex();
|
||||
}
|
||||
bool set(const String &file, const String &name, const String &task,GwApi::TaskInterfaces::Ptr v){
|
||||
bool set(const String &name, GwApi::TaskInterfaces::Ptr v){
|
||||
GWSYNCHRONIZED(&lock);
|
||||
auto it=registrations().find(name);
|
||||
if (it == registrations().end()){
|
||||
LOG_DEBUG(GwLog::ERROR,"TaskInterfaces: invalid set %s not known",name.c_str());
|
||||
return false;
|
||||
}
|
||||
if (it->second.file != file){
|
||||
LOG_DEBUG(GwLog::ERROR,"TaskInterfaces: invalid set %s wrong file, expected %s , got %s",name.c_str(),it->second.file.c_str(),file.c_str());
|
||||
return false;
|
||||
}
|
||||
if (it->second.task != task){
|
||||
LOG_DEBUG(GwLog::ERROR,"TaskInterfaces: invalid set %s wrong task, expected %s , got %s",name.c_str(),it->second.task.c_str(),task.c_str());
|
||||
return false;
|
||||
}
|
||||
auto vit=values.find(name);
|
||||
if (vit != values.end()){
|
||||
vit->second.updates++;
|
||||
|
@ -153,34 +101,20 @@ class TaskInterfacesStorage{
|
|||
}
|
||||
};
|
||||
class TaskInterfacesImpl : public GwApi::TaskInterfaces{
|
||||
String task;
|
||||
|
||||
TaskInterfacesStorage *storage;
|
||||
GwLog *logger;
|
||||
bool isInit=false;
|
||||
public:
|
||||
TaskInterfacesImpl(const String &n,TaskInterfacesStorage *s, GwLog *l,bool i):
|
||||
task(n),storage(s),isInit(i),logger(l){}
|
||||
virtual bool iset(const String &file, const String &name, Ptr v){
|
||||
return storage->set(file,name,task,v);
|
||||
TaskInterfacesImpl(TaskInterfacesStorage *s, GwLog *l,bool i):
|
||||
storage(s),isInit(i),logger(l){}
|
||||
protected:
|
||||
virtual bool iset(const String &name, Ptr v){
|
||||
return storage->set(name,v);
|
||||
}
|
||||
virtual Ptr iget(const String &name, int &result){
|
||||
return storage->get(name,result);
|
||||
}
|
||||
virtual bool iclaim(const String &name, const String &task){
|
||||
if (! isInit) return false;
|
||||
auto it=registrations().find(name);
|
||||
if (it == registrations().end()){
|
||||
LOG_DEBUG(GwLog::ERROR,"unable to claim interface %s for task %s, not registered",name.c_str(),task.c_str());
|
||||
return false;
|
||||
}
|
||||
if (!it->second.task.isEmpty()){
|
||||
LOG_DEBUG(GwLog::ERROR,"unable to claim interface %s for task %s, already claimed by %s",name.c_str(),task.c_str(),it->second.task.c_str());
|
||||
return false;
|
||||
}
|
||||
it->second.task=task;
|
||||
LOG_DEBUG(GwLog::LOG,"claimed interface %s for task %s",name.c_str(),task.c_str());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -210,7 +144,7 @@ public:
|
|||
this->mainLock=mainLock;
|
||||
this->name=name;
|
||||
localLock=xSemaphoreCreateMutex();
|
||||
interfaces=new TaskInterfacesImpl(name,s,api->getLogger(),init);
|
||||
interfaces=new TaskInterfacesImpl(s,api->getLogger(),init);
|
||||
isInit=init;
|
||||
}
|
||||
virtual GwRequestQueue *getQueue()
|
||||
|
|
|
@ -849,7 +849,7 @@ void setup() {
|
|||
buffer[29]=0;
|
||||
request->send(200,"text/plain",buffer);
|
||||
});
|
||||
webserver.registerHandler((USERPREFIX+"*").c_str(),[&USERPREFIX](AsyncWebServerRequest *req){
|
||||
webserver.registerHandler((USERPREFIX+"*").c_str(),[](AsyncWebServerRequest *req){
|
||||
String turl=req->url().substring(USERPREFIX.length());
|
||||
logger.logDebug(GwLog::DEBUG,"user web request for %s",turl.c_str());
|
||||
userCodeHandler.handleWebRequest(turl,req);
|
||||
|
|
Loading…
Reference in New Issue