esp32-nmea2000-obp60/lib/iictask/GwIicTask.cpp

227 lines
6.5 KiB
C++

#include "GwIicTask.h"
class IICGrove
{
public:
String base;
String grove;
String suffix;
IICGrove(const String &b, const String &g, const String &s) : base(b), grove(g), suffix(s) {}
String item(const String &grove, const String &bus)
{
if (grove == this->grove)
return base + bus + suffix;
return "";
}
};
static std::vector<IICGrove> iicGroveList;
#define GROOVE_IIC(base, grove, suffix) \
static GwInitializer<IICGrove> base##grove##suffix(iicGroveList, IICGrove(#base, #grove, #suffix));
#include "GwIicSensors.h"
#include "GwHardware.h"
#include "GwBME280.h"
#include "GwBMP280.h"
#include "GwQMP6988.h"
#include "GwSHT3X.h"
#include <map>
#include "GwTimer.h"
#ifndef GWIIC_SDA
#define GWIIC_SDA -1
#endif
#ifndef GWIIC_SCL
#define GWIIC_SCL -1
#endif
#ifndef GWIIC_SDA2
#define GWIIC_SDA2 -1
#endif
#ifndef GWIIC_SCL2
#define GWIIC_SCL2 -1
#endif
void runIicTask(GwApi *api);
static void addGroveItems(std::vector<SensorBase::Creator> &creators,GwApi *api, const String &bus,const String &grove, int, int)
{
GwLog *logger=api->getLogger();
for (auto &&init : iicGroveList)
{
LOG_DEBUG(GwLog::DEBUG, "trying grove item %s:%s:%s for grove %s, bus %s",
init.base.c_str(),init.grove.c_str(),
init.suffix.c_str(),grove.c_str(),bus.c_str()
);
String prfx = init.item(grove, bus);
if (!prfx.isEmpty())
{
bool found=false;
for (auto &&creator : creators)
{
if (! creator) continue;
auto *scfg = creator(api, prfx);
if (scfg == nullptr) continue;
scfg->readConfig(api->getConfig());
if (scfg->ok)
{
LOG_DEBUG(GwLog::LOG, "adding %s from grove config", prfx.c_str());
api->addSensor(scfg,false);
found=true;
break;
}
else
{
LOG_DEBUG(GwLog::DEBUG, "unmatched grove sensor config %s", prfx.c_str());
delete scfg;
}
}
if (! found){
LOG_DEBUG(GwLog::ERROR,"no iic sensor found for %s",prfx.c_str());
}
}
}
}
void initIicTask(GwApi *api){
GwLog *logger=api->getLogger();
#ifndef _GWIIC
return;
#else
bool addTask=false;
GwConfigHandler *config=api->getConfig();
std::vector<SensorBase::Creator> creators;
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,"1",_GWI_IIC1);
#endif
#ifdef _GWI_IIC2
addGroveItems(creators,api,"2",_GWI_IIC2);
#endif
//TODO: ensure that we run after other init tasks...
int res=-1;
ConfiguredSensors sensorList=api->taskInterfaces()->get<ConfiguredSensors>(res);
for (auto &&it: sensorList.sensors){
if (it->busType != SensorBase::IIC) continue;
if (it->preinit(api)) {
addTask=true;
api->addCapability(it->prefix,"true");
}
}
if (addTask){
api->addUserTask(runIicTask,"iicTask",4000);
}
#endif
}
#ifndef _GWIIC
void runIicTask(GwApi *api){
GwLog *logger=api->getLogger();
LOG_DEBUG(GwLog::LOG,"no iic defined, iic task stopped");
vTaskDelete(NULL);
return;
}
#else
bool initWireDo(GwLog *logger, TwoWire &wire, int num, const String &dummy, int scl, int sda)
{
if (sda < 0 || scl < 0)
{
LOG_DEBUG(GwLog::ERROR, "IIC %d invalid config sda=%d,scl=%d",
num, sda, scl);
return false;
}
bool rt = Wire.begin(sda, scl);
if (!rt)
{
LOG_DEBUG(GwLog::ERROR, "unable to initialize IIC %d at sad=%d,scl=%d",
num, sda, scl);
return rt;
}
LOG_DEBUG(GwLog::ERROR, "initialized IIC %d at sda=%d,scl=%d",
num,sda,scl);
return true;
}
bool initWire(GwLog *logger, TwoWire &wire, int num){
if (num == 1){
#ifdef _GWI_IIC1
return initWireDo(logger,wire,num,_GWI_IIC1);
#endif
return initWireDo(logger,wire,num,"",GWIIC_SDA,GWIIC_SCL);
}
if (num == 2){
#ifdef _GWI_IIC2
return initWireDo(logger,wire,num,_GWI_IIC2);
#endif
return initWireDo(logger,wire,num,"",GWIIC_SDA2,GWIIC_SCL2);
}
return false;
}
void runIicTask(GwApi *api){
GwLog *logger=api->getLogger();
std::map<int,TwoWire *> buses;
LOG_DEBUG(GwLog::LOG,"iic task started");
int res=-1;
ConfiguredSensors sensorList=api->taskInterfaces()->get<ConfiguredSensors>(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)
{
case 1:
{
if (initWire(logger,Wire,1)){
buses[busId] = &Wire;
}
}
break;
case 2:
{
if (initWire(logger,Wire1,2)){
buses[busId] = &Wire1;
}
}
break;
default:
LOG_DEBUG(GwLog::ERROR, "invalid bus id %d at config %s", busId, it->prefix.c_str());
break;
}
}
}
GwConfigHandler *config=api->getConfig();
bool runLoop=false;
GwIntervalRunner timers;
int counterId=api->addCounter("iicsensors");
for (auto && cfg: sensorList.sensors){
if (cfg->busType != SensorBase::IIC) continue;
auto bus=buses.find(cfg->busId);
if (! cfg->isActive()) continue;
if (bus == buses.end()){
LOG_DEBUG(GwLog::ERROR,"No bus initialized for %s",cfg->prefix.c_str());
continue;
}
TwoWire *wire=bus->second;
bool rt=cfg->initDevice(api,wire);
if (rt){
runLoop=true;
timers.addAction(cfg->intv,[wire,api,cfg,counterId](){
cfg->measure(api,wire,counterId);
});
}
}
if (! runLoop){
LOG_DEBUG(GwLog::LOG,"nothing to do for IIC task, finish");
vTaskDelete(NULL);
return;
}
while(true){
delay(100);
timers.loop();
}
vTaskDelete(NULL);
}
#endif