From f75f8033d1dc3619d92b993b5219ff44f3db269e Mon Sep 17 00:00:00 2001 From: andreas Date: Sat, 16 Nov 2024 20:15:09 +0100 Subject: [PATCH] intermediate: restructure for sensors via API --- lib/api/GwApi.h | 48 ++++++++++++++++++++++++++++++++-- lib/iictask/GwBME280.cpp | 16 +++++------- lib/iictask/GwBME280.h | 2 +- lib/iictask/GwBMP280.cpp | 20 +++++--------- lib/iictask/GwBMP280.h | 2 +- lib/iictask/GwIicTask.cpp | 36 ++++++++++++++----------- lib/iictask/GwIicTask.h | 5 ---- lib/iictask/GwQMP6988.cpp | 14 ++++------ lib/iictask/GwQMP6988.h | 2 +- lib/iictask/GwSHT3X.cpp | 16 +++++------- lib/iictask/GwSHT3X.h | 2 +- lib/sensors/GwSensor.cpp | 20 ++++++++++++++ lib/sensors/GwSensor.h | 13 +++++----- lib/spitask/GwSpiSensor.h | 2 +- lib/usercode/GwUserCode.cpp | 52 +++++++++++++++++++++++++++++++++++++ 15 files changed, 173 insertions(+), 77 deletions(-) create mode 100644 lib/sensors/GwSensor.cpp diff --git a/lib/api/GwApi.h b/lib/api/GwApi.h index e7b5dad..5156454 100644 --- a/lib/api/GwApi.h +++ b/lib/api/GwApi.h @@ -9,6 +9,9 @@ #include "GwSynchronized.h" #include #include +#include "GwSensor.h" +#include +#include class GwApi; typedef void (*GwUserTaskFunction)(GwApi *); //API to be used for additional tasks @@ -59,6 +62,7 @@ class GwApi{ protected: virtual bool iset(const String &name, Ptr v) = 0; virtual Ptr iget(const String &name, int &result) = 0; + virtual bool iupdate(const String &name,std::function)=0; public: template bool set(const T &v){ @@ -73,6 +77,10 @@ class GwApi{ bool claim(const String &task){ return true; } + template + bool update(std::function){ + return false; + } }; class Status{ public: @@ -201,7 +209,13 @@ class GwApi{ * @param name: the config name this value is used for * @param value: the current value */ - virtual void setCalibrationValue(const String &name, double value); + virtual void setCalibrationValue(const String &name, double value)=0; + /** + * add a sensor + * depending on the type it will be added to the appropriate task + * @param sensor: created sensor config + */ + virtual void addSensor(SensorBase* sensor,bool readConfig=true){}; /** * not thread safe methods @@ -274,9 +288,39 @@ static void checkDef(T... args){}; }\ type *tp=(type*)ptr.get(); \ return type(*tp); \ - } + } \ + template<> \ + inline bool GwApi::TaskInterfaces::update(std::function f) { \ + return iupdate(#type,[f](GwApi::TaskInterfaces::Ptr cp)->GwApi::TaskInterfaces::Ptr{ \ + if (cp) { \ + f((type *)cp.get()); \ + return cp; \ + } \ + type * et=new type(); \ + bool res=f(et); \ + if (! res){ \ + delete et; \ + return GwApi::TaskInterfaces::Ptr(); \ + } \ + return GwApi::TaskInterfaces::Ptr(et); \ + }); \ + } \ + + #ifndef DECLARE_TASKIF #define DECLARE_TASKIF(type) DECLARE_TASKIF_IMPL(type) #endif + +/** + * do not use this interface directly + * instead use the API function addSensor +*/ +class ConfiguredSensors : public GwApi::TaskInterfaces::Base{ + public: + SensorList sensors; +}; +DECLARE_TASKIF(ConfiguredSensors); + + #endif diff --git a/lib/iictask/GwBME280.cpp b/lib/iictask/GwBME280.cpp index 6eb4847..656718c 100644 --- a/lib/iictask/GwBME280.cpp +++ b/lib/iictask/GwBME280.cpp @@ -149,35 +149,31 @@ class BME280Config : public IICSensorBase{ static IICSensorBase::Creator creator([](GwApi *api, const String &prfx){ return new BME280Config(api,prfx); }); -IICSensorBase::Creator registerBME280(GwApi *api,IICSensorList &sensors){ +IICSensorBase::Creator registerBME280(GwApi *api){ #if defined(GWBME280) || defined(GWBME28011) { - auto *cfg=creator(api,PRFX1); - sensors.add(api,cfg); + api->addSensor(creator(api,PRFX1)); CHECK_IIC1(); #pragma message "GWBME28011 defined" } #endif #if defined(GWBME28012) { - auto *cfg=creator(api,PRFX2); - sensors.add(api,cfg); + api->addSensor(creator(api,PRFX2)); CHECK_IIC1(); #pragma message "GWBME28012 defined" } #endif #if defined(GWBME28021) { - auto *cfg=creator(api,PRFX3); - sensors.add(api,cfg); + api->addSensor(creator(api,PRFX3)); CHECK_IIC2(); #pragma message "GWBME28021 defined" } #endif #if defined(GWBME28022) { - auto *cfg=creator(api,PRFX4); - sensors.add(api,cfg); + api->addSensor(creator(api,PRFX4)); CHECK_IIC1(); #pragma message "GWBME28022 defined" } @@ -185,7 +181,7 @@ IICSensorBase::Creator registerBME280(GwApi *api,IICSensorList &sensors){ return creator; } #else -IICSensorBase::Creator registerBME280(GwApi *api,IICSensorList &sensors){ +IICSensorBase::Creator registerBME280(GwApi *api){ return IICSensorBase::Creator(); } diff --git a/lib/iictask/GwBME280.h b/lib/iictask/GwBME280.h index 6da8c44..a9ee4ec 100644 --- a/lib/iictask/GwBME280.h +++ b/lib/iictask/GwBME280.h @@ -1,5 +1,5 @@ #ifndef _GWBME280_H #define _GWBME280_H #include "GwIicSensors.h" -IICSensorBase::Creator registerBME280(GwApi *api,IICSensorList &sensors); +IICSensorBase::Creator registerBME280(GwApi *api); #endif \ No newline at end of file diff --git a/lib/iictask/GwBMP280.cpp b/lib/iictask/GwBMP280.cpp index c295cd9..08c1517 100644 --- a/lib/iictask/GwBMP280.cpp +++ b/lib/iictask/GwBMP280.cpp @@ -133,39 +133,31 @@ class BMP280Config : public IICSensorBase{ static IICSensorBase::Creator creator([](GwApi *api, const String &prfx){ return new BMP280Config(api,prfx); }); -IICSensorBase::Creator registerBMP280(GwApi *api,IICSensorList &sensors){ +IICSensorBase::Creator registerBMP280(GwApi *api){ #if defined(GWBMP280) || defined(GWBMP28011) { - auto *cfg=creator(api,PRFX1); - //BMP280Config *cfg=new BMP280Config(api,PRFX1); - sensors.add(api,cfg); + api->addSensor(creator(api,PRFX1)); CHECK_IIC1(); #pragma message "GWBMP28011 defined" } #endif #if defined(GWBMP28012) { - auto *cfg=creator(api,PRFX2); - //BMP280Config *cfg=new BMP280Config(api,PRFX2); - sensors.add(api,cfg); + api->addSensor(creator(api,PRFX2)); CHECK_IIC1(); #pragma message "GWBMP28012 defined" } #endif #if defined(GWBMP28021) { - auto *cfg=creator(api,PRFX3); - //BMP280Config *cfg=new BMP280Config(api,PRFX3); - sensors.add(api,cfg); + api->addSensor(creator(api,PRFX3)); CHECK_IIC2(); #pragma message "GWBMP28021 defined" } #endif #if defined(GWBMP28022) { - auto *cfg=creator(api,PRFX4); - //BMP280Config *cfg=new BMP280Config(api,PRFX4); - sensors.add(api,cfg); + api->addSensor(creator(api,PRFX4)); CHECK_IIC1(); #pragma message "GWBMP28022 defined" } @@ -173,7 +165,7 @@ IICSensorBase::Creator registerBMP280(GwApi *api,IICSensorList &sensors){ return creator; } #else -IICSensorBase::Creator registerBMP280(GwApi *api,IICSensorList &sensors){ +IICSensorBase::Creator registerBMP280(GwApi *api){ return IICSensorBase::Creator(); } diff --git a/lib/iictask/GwBMP280.h b/lib/iictask/GwBMP280.h index 97fd4fe..b2fd0bc 100644 --- a/lib/iictask/GwBMP280.h +++ b/lib/iictask/GwBMP280.h @@ -1,6 +1,6 @@ #ifndef _GWBMP280_H #define _GWBMP280_H #include "GwIicSensors.h" -IICSensorBase::Creator registerBMP280(GwApi *api,IICSensorList &sensors); +IICSensorBase::Creator registerBMP280(GwApi *api); #endif diff --git a/lib/iictask/GwIicTask.cpp b/lib/iictask/GwIicTask.cpp index def5545..949d18e 100644 --- a/lib/iictask/GwIicTask.cpp +++ b/lib/iictask/GwIicTask.cpp @@ -43,8 +43,7 @@ static std::vector iicGroveList; void runIicTask(GwApi *api); -static IICSensorList sensors; -static void addGroveItems(std::vector &creators,GwApi *api, IICSensorList &sensors, const String &bus,const String &grove, int, int) +static void addGroveItems(std::vector &creators,GwApi *api, const String &bus,const String &grove, int, int) { GwLog *logger=api->getLogger(); for (auto &&init : iicGroveList) @@ -65,7 +64,7 @@ static void addGroveItems(std::vector &creators,GwApi *a if (scfg->ok) { LOG_DEBUG(GwLog::LOG, "adding %s from grove config", prfx.c_str()); - sensors.add(api, SensorBase::Ptr(scfg)); + api->addSensor(scfg,false); found=true; break; } @@ -90,18 +89,22 @@ void initIicTask(GwApi *api){ bool addTask=false; GwConfigHandler *config=api->getConfig(); std::vector creators; - creators.push_back(registerSHT3X(api,sensors)); - creators.push_back(registerQMP6988(api,sensors)); - creators.push_back(registerBME280(api,sensors)); - creators.push_back(registerBMP280(api,sensors)); + creators.push_back(registerSHT3X(api)); + creators.push_back(registerQMP6988(api)); + creators.push_back(registerBME280(api)); + creators.push_back(registerBMP280(api)); #ifdef _GWI_IIC1 - addGroveItems(creators,api,sensors,"1",_GWI_IIC1); + addGroveItems(creators,api,"1",_GWI_IIC1); #endif #ifdef _GWI_IIC2 - addGroveItems(creators,api,sensors,"2",_GWI_IIC2); + addGroveItems(creators,api,"2",_GWI_IIC2); #endif - for (auto it=sensors.begin();it != sensors.end();it++){ - if ((*it)->preinit(api)) addTask=true; + //TODO: ensure that we run after other init tasks... + int res=-1; + ConfiguredSensors sensorList=api->taskInterfaces()->get(res); + for (auto &&it: sensorList.sensors){ + if (it->busType != SensorBase::IIC) continue; + if (it->preinit(api)) addTask=true; } if (addTask){ api->addUserTask(runIicTask,"iicTask",4000); @@ -154,8 +157,11 @@ void runIicTask(GwApi *api){ GwLog *logger=api->getLogger(); std::map buses; LOG_DEBUG(GwLog::LOG,"iic task started"); - for (auto it=sensors.begin();it != sensors.end();it++){ - int busId=(*it)->busId; + int res=-1; + ConfiguredSensors sensorList=api->taskInterfaces()->get(res); + for (auto &&it : sensorList.sensors){ + if (it->busType != SensorBase::IIC) continue; + int busId=it->busId; auto bus=buses.find(busId); if (bus == buses.end()){ switch (busId) @@ -175,7 +181,7 @@ void runIicTask(GwApi *api){ } break; default: - LOG_DEBUG(GwLog::ERROR, "invalid bus id %d at config %s", busId, (*it)->prefix.c_str()); + LOG_DEBUG(GwLog::ERROR, "invalid bus id %d at config %s", busId, it->prefix.c_str()); break; } } @@ -184,7 +190,7 @@ void runIicTask(GwApi *api){ bool runLoop=false; GwIntervalRunner timers; int counterId=api->addCounter("iicsensors"); - for (auto &&cfg:sensors){ + for (auto && cfg: sensorList.sensors){ if (cfg->busType != SensorBase::IIC) continue; auto bus=buses.find(cfg->busId); if (! cfg->isActive()) continue; diff --git a/lib/iictask/GwIicTask.h b/lib/iictask/GwIicTask.h index f2db0e4..608262b 100644 --- a/lib/iictask/GwIicTask.h +++ b/lib/iictask/GwIicTask.h @@ -4,9 +4,4 @@ #include "GwSensor.h" void initIicTask(GwApi *api); DECLARE_INITFUNCTION(initIicTask); -class IICSensors : public GwApi::TaskInterfaces::Base{ - public: - SensorList sensors; -}; -DECLARE_TASKIF(IICSensors); #endif \ No newline at end of file diff --git a/lib/iictask/GwQMP6988.cpp b/lib/iictask/GwQMP6988.cpp index f3a7671..dbcde7d 100644 --- a/lib/iictask/GwQMP6988.cpp +++ b/lib/iictask/GwQMP6988.cpp @@ -86,32 +86,28 @@ IICSensorBase::Creator registerQMP6988(GwApi *api,IICSensorList &sensors){ GwLog *logger=api->getLogger(); #if defined(GWQMP6988) || defined(GWQMP698811) { - QMP6988Config *scfg=new QMP6988Config(api,PRFX1); - sensors.add(api,scfg); + api->addSensor(new QMP6988Config(api,PRFX1)); CHECK_IIC1(); #pragma message "GWQMP698811 defined" } #endif #if defined(GWQMP698812) { - QMP6988Config *scfg=new QMP6988Config(api,PRFX2); - sensors.add(api,scfg); + api->addSensor(new QMP6988Config(api,PRFX2)); CHECK_IIC1(); #pragma message "GWQMP698812 defined" } #endif #if defined(GWQMP698821) { - QMP6988Config *scfg=new QMP6988Config(api,PRFX3); - sensors.add(api,scfg); + api->addSensor(new QMP6988Config(api,PRFX3)); CHECK_IIC2(); #pragma message "GWQMP698821 defined" } #endif #if defined(GWQMP698822) { - QMP6988Config *scfg=new QMP6988Config(api,PRFX4); - sensors.add(api,scfg); + api->addSensor(new QMP6988Config(api,PRFX4)); CHECK_IIC2(); #pragma message "GWQMP698822 defined" } @@ -120,7 +116,7 @@ IICSensorBase::Creator registerQMP6988(GwApi *api,IICSensorList &sensors){ } #else - IICSensorBase::Creator registerQMP6988(GwApi *api,IICSensorList &sensors){ + IICSensorBase::Creator registerQMP6988(GwApi *api){ return IICSensorBase::Creator(); } #endif \ No newline at end of file diff --git a/lib/iictask/GwQMP6988.h b/lib/iictask/GwQMP6988.h index cb6a881..af00616 100644 --- a/lib/iictask/GwQMP6988.h +++ b/lib/iictask/GwQMP6988.h @@ -16,5 +16,5 @@ #ifdef _GWQMP6988 #include "QMP6988.h" #endif -IICSensorBase::Creator registerQMP6988(GwApi *api,IICSensorList &sensors); +IICSensorBase::Creator registerQMP6988(GwApi *api); #endif \ No newline at end of file diff --git a/lib/iictask/GwSHT3X.cpp b/lib/iictask/GwSHT3X.cpp index 40735e1..2de7fd8 100644 --- a/lib/iictask/GwSHT3X.cpp +++ b/lib/iictask/GwSHT3X.cpp @@ -109,36 +109,32 @@ class SHT3XConfig : public IICSensorBase{ IICSensorBase::Creator creator=[](GwApi *api,const String &prfx){ return new SHT3XConfig(api,prfx); }; -IICSensorBase::Creator registerSHT3X(GwApi *api,IICSensorList &sensors){ +IICSensorBase::Creator registerSHT3X(GwApi *api){ GwLog *logger=api->getLogger(); #if defined(GWSHT3X) || defined (GWSHT3X11) { - auto *scfg=creator(api,PRFX1); - sensors.add(api,scfg); + api->addSensor(creator(api,PRFX1)); CHECK_IIC1(); #pragma message "GWSHT3X11 defined" } #endif #if defined(GWSHT3X12) { - auto *scfg=creator(api,PRFX2); - sensors.add(api,scfg); + api->addSensor(creator(api,PRFX2)); CHECK_IIC1(); #pragma message "GWSHT3X12 defined" } #endif #if defined(GWSHT3X21) { - auto *scfg=creator(api,PRFX3); - sensors.add(api,scfg); + api->addSensor(creator(api,PRFX3)); CHECK_IIC2(); #pragma message "GWSHT3X21 defined" } #endif #if defined(GWSHT3X22) { - auto *scfg=creator(api,PRFX4); - sensors.add(api,scfg); + api->addSensor(creator(api,PRFX4)); CHECK_IIC2(); #pragma message "GWSHT3X22 defined" } @@ -147,7 +143,7 @@ IICSensorBase::Creator registerSHT3X(GwApi *api,IICSensorList &sensors){ }; #else -IICSensorBase::Creator registerSHT3X(GwApi *api,IICSensorList &sensors){ +IICSensorBase::Creator registerSHT3X(GwApi *api){ return IICSensorBase::Creator(); } diff --git a/lib/iictask/GwSHT3X.h b/lib/iictask/GwSHT3X.h index f59d51f..b9beb79 100644 --- a/lib/iictask/GwSHT3X.h +++ b/lib/iictask/GwSHT3X.h @@ -16,5 +16,5 @@ #ifdef _GWSHT3X #include "SHT3X.h" #endif -IICSensorBase::Creator registerSHT3X(GwApi *api,IICSensorList &sensors); +IICSensorBase::Creator registerSHT3X(GwApi *api); #endif \ No newline at end of file diff --git a/lib/sensors/GwSensor.cpp b/lib/sensors/GwSensor.cpp new file mode 100644 index 0000000..d0d580b --- /dev/null +++ b/lib/sensors/GwSensor.cpp @@ -0,0 +1,20 @@ +/* + (C) Andreas Vogel andreas@wellenvogel.de + This code is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + This code is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include "GwSensor.h" +#include "GwApi.h" + +void SensorList::add(SensorBase::Ptr sensor){ + this->push_back(sensor); + } \ No newline at end of file diff --git a/lib/sensors/GwSensor.h b/lib/sensors/GwSensor.h index 3f821d4..b133897 100644 --- a/lib/sensors/GwSensor.h +++ b/lib/sensors/GwSensor.h @@ -14,9 +14,11 @@ */ #ifndef _GWSENSORS_H #define _GWSENSORS_H -#include "GwApi.h" -#include "GwLog.h" +#include #include +#include +class GwApi; +class GwConfigHandler; class SensorBase{ public: using BusType=enum{ @@ -63,16 +65,13 @@ class SensorTemplate : public SensorBase{ class SensorList : public std::vector{ public: - 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); - } + void add(SensorBase::Ptr sensor); using std::vector::vector; }; #define CFG_GET(name,prefix) \ cfg->getValue(name, GwConfigDefinitions::prefix ## name) + #endif \ No newline at end of file diff --git a/lib/spitask/GwSpiSensor.h b/lib/spitask/GwSpiSensor.h index 88127c6..1a8ab92 100644 --- a/lib/spitask/GwSpiSensor.h +++ b/lib/spitask/GwSpiSensor.h @@ -16,7 +16,7 @@ #ifndef _GWSPISENSOR_H #define _GWSPISENSOR_H #include -#include "GwSensor.h" +#include "GwApi.h" #include class SPIBus{ diff --git a/lib/usercode/GwUserCode.cpp b/lib/usercode/GwUserCode.cpp index bc2fd54..44af1d4 100644 --- a/lib/usercode/GwUserCode.cpp +++ b/lib/usercode/GwUserCode.cpp @@ -98,6 +98,40 @@ class TaskInterfacesStorage{ } result = it->second.updates; return it->second.ptr; + } + + bool update(const String &name, std::functionf){ + GWSYNCHRONIZED(&lock); + auto vit=values.find(name); + bool rt=false; + int mode=0; + if (vit == values.end()){ + mode=1; + auto np=f(GwApi::TaskInterfaces::Ptr()); + if (np){ + mode=11; + values[name]=TaskDataEntry(np); + rt=true; + } + } + else + { + auto np = f(vit->second.ptr); + mode=2; + if (np) + { + mode=22; + vit->second = np; + vit->second.updates++; + if (vit->second.updates < 0) + { + vit->second.updates = 0; + } + rt=true; + } + } + LOG_DEBUG(GwLog::DEBUG,"TaskApi::update %s (mode %d)returns %d",name.c_str(),mode,(int)rt); + return rt; } }; class TaskInterfacesImpl : public GwApi::TaskInterfaces{ @@ -115,6 +149,9 @@ class TaskInterfacesImpl : public GwApi::TaskInterfaces{ virtual Ptr iget(const String &name, int &result){ return storage->get(name,result); } + virtual bool iupdate(const String &name,std::function f){ + return storage->update(name,f); + } }; @@ -291,6 +328,21 @@ public: handler(req); return true; } + virtual void addSensor(SensorBase *sb,bool readConfig=true) override{ + if (sb == nullptr) return; + SensorBase::Ptr sensor(sb); + if (readConfig) sb->readConfig(this->getConfig()); + if (! sensor->ok){ + api->getLogger()->logDebug(GwLog::ERROR,"sensor %s nok , bustype=%d",sensor->prefix.c_str(),(int)sensor->busType); + return; + } + bool rt=taskInterfaces()->update( [sensor,this](ConfiguredSensors *sensors)->bool{ + api->getLogger()->logDebug(GwLog::LOG,"adding sensor %s, type=%d",sensor->prefix,(int)sensor->busType); + sensors->sensors.add(sensor); + return true; + }); + api->getLogger()->logDebug(GwLog::LOG,"adding sensor %s returns %d",sensor->prefix.c_str(),(int)rt); + } }; GwUserCode::GwUserCode(GwApiInternal *api,SemaphoreHandle_t *mainLock){