allow a counter for user tasks, reorganize generated config handling
This commit is contained in:
parent
f52428366f
commit
6cdaab4d60
108
extra_script.py
108
extra_script.py
|
@ -14,6 +14,7 @@ GEN_DIR='lib/generated'
|
||||||
CFG_FILE='web/config.json'
|
CFG_FILE='web/config.json'
|
||||||
XDR_FILE='web/xdrconfig.json'
|
XDR_FILE='web/xdrconfig.json'
|
||||||
CFG_INCLUDE='GwConfigDefinitions.h'
|
CFG_INCLUDE='GwConfigDefinitions.h'
|
||||||
|
CFG_INCLUDE_IMPL='GwConfigDefImpl.h'
|
||||||
XDR_INCLUDE='GwXdrTypeMappings.h'
|
XDR_INCLUDE='GwXdrTypeMappings.h'
|
||||||
TASK_INCLUDE='GwUserTasks.h'
|
TASK_INCLUDE='GwUserTasks.h'
|
||||||
EMBEDDED_INCLUDE="GwEmbeddedFiles.h"
|
EMBEDDED_INCLUDE="GwEmbeddedFiles.h"
|
||||||
|
@ -112,66 +113,62 @@ def generateMergedConfig(inFile,outFile,addDirs=[]):
|
||||||
data=json.dumps(config,indent=2)
|
data=json.dumps(config,indent=2)
|
||||||
writeFileIfChanged(outFile,data)
|
writeFileIfChanged(outFile,data)
|
||||||
|
|
||||||
def generateCfg(inFile,outFile,addDirs=[]):
|
def generateCfg(inFile,outFile,impl):
|
||||||
if not os.path.exists(inFile):
|
if not os.path.exists(inFile):
|
||||||
raise Exception("unable to read cfg file %s"%inFile)
|
raise Exception("unable to read cfg file %s"%inFile)
|
||||||
data=""
|
data=""
|
||||||
with open(inFile,'rb') as ch:
|
with open(inFile,'rb') as ch:
|
||||||
config=json.load(ch)
|
config=json.load(ch)
|
||||||
config=mergeConfig(config,addDirs)
|
|
||||||
data+="//generated from %s\n"%inFile
|
data+="//generated from %s\n"%inFile
|
||||||
data+='#include "GwConfigItem.h"\n'
|
|
||||||
l=len(config)
|
l=len(config)
|
||||||
data+='class GwConfigDefinitions{\n'
|
idx=0
|
||||||
data+=' public:\n'
|
if not impl:
|
||||||
data+=' int getNumConfig() const{return %d;}\n'%(l)
|
data+='#include "GwConfigItem.h"\n'
|
||||||
for item in config:
|
data+='class GwConfigDefinitions{\n'
|
||||||
n=item.get('name')
|
data+=' public:\n'
|
||||||
if n is None:
|
data+=' int getNumConfig() const{return %d;}\n'%(l)
|
||||||
continue
|
for item in config:
|
||||||
if len(n) > 15:
|
n=item.get('name')
|
||||||
raise Exception("%s: config names must be max 15 caracters"%n)
|
if n is None:
|
||||||
data+=' static constexpr const char* %s="%s";\n'%(n,n)
|
continue
|
||||||
data+=' protected:\n'
|
if len(n) > 15:
|
||||||
data+=' GwConfigInterface *configs[%d]={\n'%(l)
|
raise Exception("%s: config names must be max 15 caracters"%n)
|
||||||
first=True
|
data+=' static constexpr const char* %s="%s";\n'%(n,n)
|
||||||
for item in config:
|
data+="};\n"
|
||||||
name=item.get('name')
|
else:
|
||||||
if name is None:
|
data+='void GwConfigHandler::populateConfigs(GwConfigInterface **config){\n'
|
||||||
continue
|
for item in config:
|
||||||
if not first:
|
name=item.get('name')
|
||||||
data+=',\n'
|
if name is None:
|
||||||
first=False
|
continue
|
||||||
secret="false";
|
data+=' configs[%d]=\n'%(idx)
|
||||||
if item.get('type') == 'password':
|
idx+=1
|
||||||
secret="true"
|
secret="false";
|
||||||
data+=" #undef __CFGMODE\n"
|
if item.get('type') == 'password':
|
||||||
data+=" #ifdef CFGMODE_%s\n"%(name)
|
secret="true"
|
||||||
data+=" #define __CFGMODE CFGMODE_%s\n"%(name)
|
data+=" #undef __CFGMODE\n"
|
||||||
data+=" #else\n"
|
data+=" #ifdef CFGMODE_%s\n"%(name)
|
||||||
data+=" #define __CFGMODE GwConfigInterface::NORMAL\n"
|
data+=" #define __CFGMODE CFGMODE_%s\n"%(name)
|
||||||
data+=" #endif\n"
|
data+=" #else\n"
|
||||||
data+=" #ifdef CFGDEFAULT_%s\n"%(name)
|
data+=" #define __CFGMODE GwConfigInterface::NORMAL\n"
|
||||||
data+=" new GwConfigInterface(%s,CFGDEFAULT_%s,%s,__CFGMODE)\n"%(name,name,secret)
|
data+=" #endif\n"
|
||||||
data+=" #else\n"
|
data+=" #ifdef CFGDEFAULT_%s\n"%(name)
|
||||||
data+=" new GwConfigInterface(%s,\"%s\",%s,__CFGMODE)\n"%(name,item.get('default'),secret)
|
data+=" new GwConfigInterface(%s,CFGDEFAULT_%s,%s,__CFGMODE)\n"%(name,name,secret)
|
||||||
data+=" #endif\n"
|
data+=" #else\n"
|
||||||
|
data+=" new GwConfigInterface(%s,\"%s\",%s,__CFGMODE)\n"%(name,item.get('default'),secret)
|
||||||
data+='};\n'
|
data+=" #endif\n"
|
||||||
data+='};\n'
|
data+=";\n"
|
||||||
data+="#ifdef CFG_MESSAGES\n"
|
data+='}\n'
|
||||||
for item in config:
|
for item in config:
|
||||||
name=item.get('name')
|
name=item.get('name')
|
||||||
if name is None:
|
if name is None:
|
||||||
continue
|
continue
|
||||||
data+="#ifdef CFGMODE_%s\n"%(name)
|
data+="#ifdef CFGMODE_%s\n"%(name)
|
||||||
data+=" __MSG(\"CFGMODE_%s=\" __XSTR(CFGMODE_%s))\n"%(name,name)
|
data+=" __MSG(\"CFGMODE_%s=\" __XSTR(CFGMODE_%s))\n"%(name,name)
|
||||||
data+="#endif\n"
|
data+="#endif\n"
|
||||||
data+="#ifdef CFGDEFAULT_%s\n"%(name)
|
data+="#ifdef CFGDEFAULT_%s\n"%(name)
|
||||||
data+=" __MSG(\"CFGDEFAULT_%s=\" CFGDEFAULT_%s)\n"%(name,name)
|
data+=" __MSG(\"CFGDEFAULT_%s=\" CFGDEFAULT_%s)\n"%(name,name)
|
||||||
data+="#endif\n"
|
data+="#endif\n"
|
||||||
data+="#endif"
|
|
||||||
|
|
||||||
writeFileIfChanged(outFile,data)
|
writeFileIfChanged(outFile,data)
|
||||||
|
|
||||||
|
|
||||||
|
@ -273,7 +270,8 @@ def prebuild(env):
|
||||||
mergedConfig=os.path.join(outPath(),os.path.basename(CFG_FILE))
|
mergedConfig=os.path.join(outPath(),os.path.basename(CFG_FILE))
|
||||||
generateMergedConfig(os.path.join(basePath(),CFG_FILE),mergedConfig,userTaskDirs)
|
generateMergedConfig(os.path.join(basePath(),CFG_FILE),mergedConfig,userTaskDirs)
|
||||||
compressFile(mergedConfig,mergedConfig+".gz")
|
compressFile(mergedConfig,mergedConfig+".gz")
|
||||||
generateCfg(mergedConfig,os.path.join(outPath(),CFG_INCLUDE))
|
generateCfg(mergedConfig,os.path.join(outPath(),CFG_INCLUDE),False)
|
||||||
|
generateCfg(mergedConfig,os.path.join(outPath(),CFG_INCLUDE_IMPL),True)
|
||||||
embedded=getEmbeddedFiles(env)
|
embedded=getEmbeddedFiles(env)
|
||||||
filedefs=[]
|
filedefs=[]
|
||||||
for ef in embedded:
|
for ef in embedded:
|
||||||
|
|
|
@ -35,6 +35,12 @@ class GwApi{
|
||||||
|
|
||||||
class Status{
|
class Status{
|
||||||
public:
|
public:
|
||||||
|
typedef enum{
|
||||||
|
OFF,
|
||||||
|
PRESSED,
|
||||||
|
PRESSED_5, //5...10s
|
||||||
|
PRESSED_10 //>10s...30s
|
||||||
|
} ButtonState;
|
||||||
bool wifiApOn=false;
|
bool wifiApOn=false;
|
||||||
bool wifiClientOn=false;
|
bool wifiClientOn=false;
|
||||||
bool wifiClientConnected=false;
|
bool wifiClientConnected=false;
|
||||||
|
@ -47,6 +53,8 @@ class GwApi{
|
||||||
unsigned long usbTx=0;
|
unsigned long usbTx=0;
|
||||||
unsigned long serRx=0;
|
unsigned long serRx=0;
|
||||||
unsigned long serTx=0;
|
unsigned long serTx=0;
|
||||||
|
unsigned long ser2Rx=0;
|
||||||
|
unsigned long ser2Tx=0;
|
||||||
unsigned long tcpSerRx=0;
|
unsigned long tcpSerRx=0;
|
||||||
unsigned long tcpSerTx=0;
|
unsigned long tcpSerTx=0;
|
||||||
int tcpClients=0;
|
int tcpClients=0;
|
||||||
|
@ -55,6 +63,8 @@ class GwApi{
|
||||||
bool tcpClientConnected=false;
|
bool tcpClientConnected=false;
|
||||||
unsigned long n2kRx=0;
|
unsigned long n2kRx=0;
|
||||||
unsigned long n2kTx=0;
|
unsigned long n2kTx=0;
|
||||||
|
ButtonState button=OFF;
|
||||||
|
unsigned long buttonPresses=0;
|
||||||
void empty(){
|
void empty(){
|
||||||
wifiApOn=false;
|
wifiApOn=false;
|
||||||
wifiClientOn=false;
|
wifiClientOn=false;
|
||||||
|
@ -68,6 +78,8 @@ class GwApi{
|
||||||
usbTx=0;
|
usbTx=0;
|
||||||
serRx=0;
|
serRx=0;
|
||||||
serTx=0;
|
serTx=0;
|
||||||
|
ser2Rx=0;
|
||||||
|
ser2Tx=0;
|
||||||
tcpSerRx=0;
|
tcpSerRx=0;
|
||||||
tcpSerTx=0;
|
tcpSerTx=0;
|
||||||
tcpClients=0;
|
tcpClients=0;
|
||||||
|
@ -75,7 +87,9 @@ class GwApi{
|
||||||
tcpClTx=0;
|
tcpClTx=0;
|
||||||
tcpClientConnected=false;
|
tcpClientConnected=false;
|
||||||
n2kRx=0;
|
n2kRx=0;
|
||||||
n2kTx=0;
|
n2kTx=0;
|
||||||
|
button=OFF;
|
||||||
|
buttonPresses=0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
|
@ -109,7 +123,14 @@ class GwApi{
|
||||||
/**
|
/**
|
||||||
* fill the status information
|
* fill the status information
|
||||||
*/
|
*/
|
||||||
virtual void getStatus(Status &status);
|
virtual void getStatus(Status &status)=0;
|
||||||
|
/**
|
||||||
|
* access to counters for a task
|
||||||
|
* thread safe
|
||||||
|
*/
|
||||||
|
virtual void setCounterDisplayName(const String &){}
|
||||||
|
virtual void increment(const String &name,bool failed=false){}
|
||||||
|
virtual void reset(){}
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
|
|
|
@ -322,6 +322,11 @@ void GwChannelList::fillStatus(GwApi::Status &status){
|
||||||
status.serRx=channel->countRx();
|
status.serRx=channel->countRx();
|
||||||
status.serTx=channel->countTx();
|
status.serTx=channel->countTx();
|
||||||
}
|
}
|
||||||
|
channel=getChannelById(SERIAL2_CHANNEL_ID);
|
||||||
|
if (channel){
|
||||||
|
status.ser2Rx=channel->countRx();
|
||||||
|
status.ser2Tx=channel->countTx();
|
||||||
|
}
|
||||||
channel=getChannelById(MIN_TCP_CHANNEL_ID);
|
channel=getChannelById(MIN_TCP_CHANNEL_ID);
|
||||||
if (channel){
|
if (channel){
|
||||||
status.tcpSerRx=channel->countRx();
|
status.tcpSerRx=channel->countRx();
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
#define CFG_MESSAGES
|
#define CFG_MESSAGES
|
||||||
|
#include <Preferences.h>
|
||||||
#include "GWConfig.h"
|
#include "GWConfig.h"
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <MD5Builder.h>
|
#include <MD5Builder.h>
|
||||||
|
#include "GwHardware.h"
|
||||||
|
#include "GwConfigDefImpl.h"
|
||||||
|
|
||||||
#define B(v) (v?"true":"false")
|
#define B(v) (v?"true":"false")
|
||||||
|
|
||||||
|
@ -56,14 +59,20 @@ GwConfigInterface * GwConfigHandler::getConfigItem(const String name, bool dummy
|
||||||
GwConfigHandler::GwConfigHandler(GwLog *logger): GwConfigDefinitions(){
|
GwConfigHandler::GwConfigHandler(GwLog *logger): GwConfigDefinitions(){
|
||||||
this->logger=logger;
|
this->logger=logger;
|
||||||
saltBase=esp_random();
|
saltBase=esp_random();
|
||||||
|
configs=new GwConfigInterface*[getNumConfig()];
|
||||||
|
populateConfigs(configs);
|
||||||
|
prefs=new Preferences();
|
||||||
|
}
|
||||||
|
GwConfigHandler::~GwConfigHandler(){
|
||||||
|
delete prefs;
|
||||||
}
|
}
|
||||||
bool GwConfigHandler::loadConfig(){
|
bool GwConfigHandler::loadConfig(){
|
||||||
prefs.begin(PREF_NAME,true);
|
prefs->begin(PREF_NAME,true);
|
||||||
for (int i=0;i<getNumConfig();i++){
|
for (int i=0;i<getNumConfig();i++){
|
||||||
String v=prefs.getString(configs[i]->getName().c_str(),configs[i]->getDefault());
|
String v=prefs->getString(configs[i]->getName().c_str(),configs[i]->getDefault());
|
||||||
configs[i]->value=v;
|
configs[i]->value=v;
|
||||||
}
|
}
|
||||||
prefs.end();
|
prefs->end();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,19 +87,19 @@ bool GwConfigHandler::updateValue(String name, String value){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
LOG_DEBUG(GwLog::LOG,"update config %s=>%s",name.c_str(),i->isSecret()?"***":value.c_str());
|
LOG_DEBUG(GwLog::LOG,"update config %s=>%s",name.c_str(),i->isSecret()?"***":value.c_str());
|
||||||
prefs.begin(PREF_NAME,false);
|
prefs->begin(PREF_NAME,false);
|
||||||
prefs.putString(i->getName().c_str(),value);
|
prefs->putString(i->getName().c_str(),value);
|
||||||
prefs.end();
|
prefs->end();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool GwConfigHandler::reset(){
|
bool GwConfigHandler::reset(){
|
||||||
LOG_DEBUG(GwLog::LOG,"reset config");
|
LOG_DEBUG(GwLog::LOG,"reset config");
|
||||||
prefs.begin(PREF_NAME,false);
|
prefs->begin(PREF_NAME,false);
|
||||||
for (int i=0;i<getNumConfig();i++){
|
for (int i=0;i<getNumConfig();i++){
|
||||||
prefs.putString(configs[i]->getName().c_str(),configs[i]->getDefault());
|
prefs->putString(configs[i]->getName().c_str(),configs[i]->getDefault());
|
||||||
}
|
}
|
||||||
prefs.end();
|
prefs->end();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
String GwConfigHandler::getString(const String name, String defaultv) const{
|
String GwConfigHandler::getString(const String name, String defaultv) const{
|
||||||
|
|
|
@ -1,21 +1,20 @@
|
||||||
#ifndef _GWCONFIG_H
|
#ifndef _GWCONFIG_H
|
||||||
#define _GWCONFIG_H
|
#define _GWCONFIG_H
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <Preferences.h>
|
|
||||||
#include "GwLog.h"
|
#include "GwLog.h"
|
||||||
#include "GwConfigItem.h"
|
#include "GwConfigItem.h"
|
||||||
#include "GwHardware.h"
|
|
||||||
#include "GwConfigDefinitions.h"
|
#include "GwConfigDefinitions.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
class Preferences;
|
||||||
class GwConfigHandler: public GwConfigDefinitions{
|
class GwConfigHandler: public GwConfigDefinitions{
|
||||||
private:
|
private:
|
||||||
Preferences prefs;
|
Preferences *prefs;
|
||||||
GwLog *logger;
|
GwLog *logger;
|
||||||
typedef std::map<String,String> StringMap;
|
typedef std::map<String,String> StringMap;
|
||||||
boolean allowChanges=true;
|
boolean allowChanges=true;
|
||||||
|
GwConfigInterface **configs;
|
||||||
public:
|
public:
|
||||||
public:
|
public:
|
||||||
GwConfigHandler(GwLog *logger);
|
GwConfigHandler(GwLog *logger);
|
||||||
|
@ -40,7 +39,9 @@ class GwConfigHandler: public GwConfigDefinitions{
|
||||||
bool setValue(String name, String value);
|
bool setValue(String name, String value);
|
||||||
static void toHex(unsigned long v,char *buffer,size_t bsize);
|
static void toHex(unsigned long v,char *buffer,size_t bsize);
|
||||||
unsigned long getSaltBase(){return saltBase;}
|
unsigned long getSaltBase(){return saltBase;}
|
||||||
|
~GwConfigHandler();
|
||||||
private:
|
private:
|
||||||
unsigned long saltBase=0;
|
unsigned long saltBase=0;
|
||||||
|
void populateConfigs(GwConfigInterface **);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
|
@ -11,9 +11,12 @@ template<class T> class GwCounter{
|
||||||
unsigned long globalFail=0;
|
unsigned long globalFail=0;
|
||||||
String name;
|
String name;
|
||||||
public:
|
public:
|
||||||
GwCounter(String name){
|
GwCounter(const String &name){
|
||||||
this->name=name;
|
this->name=name;
|
||||||
};
|
};
|
||||||
|
void setName(const String &name){
|
||||||
|
this->name=name;
|
||||||
|
}
|
||||||
void reset(){
|
void reset(){
|
||||||
okCounter.clear();
|
okCounter.clear();
|
||||||
failCounter.clear();
|
failCounter.clear();
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#ifdef BOARD_TEST
|
#ifdef BOARD_TEST
|
||||||
#include "GwExampleTask.h"
|
#include "GwExampleTask.h"
|
||||||
#include "GwApi.h"
|
#include "GwApi.h"
|
||||||
|
#include "GWConfig.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -97,6 +98,7 @@ void exampleTask(GwApi *api){
|
||||||
GwApi::BoatValue *testValue=new GwApi::BoatValue(boatItemName);
|
GwApi::BoatValue *testValue=new GwApi::BoatValue(boatItemName);
|
||||||
GwApi::BoatValue *valueList[]={longitude,latitude,testValue};
|
GwApi::BoatValue *valueList[]={longitude,latitude,testValue};
|
||||||
GwApi::Status status;
|
GwApi::Status status;
|
||||||
|
api->setCounterDisplayName("usertest");
|
||||||
while(true){
|
while(true){
|
||||||
delay(1000);
|
delay(1000);
|
||||||
/*
|
/*
|
||||||
|
@ -193,7 +195,9 @@ void exampleTask(GwApi *api){
|
||||||
status.tcpClRx,
|
status.tcpClRx,
|
||||||
status.tcpClTx,
|
status.tcpClTx,
|
||||||
status.n2kRx,
|
status.n2kRx,
|
||||||
status.n2kTx);
|
status.n2kTx);
|
||||||
|
//increment some counter
|
||||||
|
api->increment("Test");
|
||||||
|
|
||||||
}
|
}
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
|
|
|
@ -2,32 +2,11 @@
|
||||||
#include "GwApi.h"
|
#include "GwApi.h"
|
||||||
//we only compile for some boards
|
//we only compile for some boards
|
||||||
#ifdef BOARD_TEST
|
#ifdef BOARD_TEST
|
||||||
|
//we could add the following defines also in our local platformio.ini
|
||||||
#define ESP32_CAN_TX_PIN GPIO_NUM_22
|
//CAN base
|
||||||
#define ESP32_CAN_RX_PIN GPIO_NUM_19
|
#define M5_CAN_KIT
|
||||||
//if using tail485
|
//RS485 on groove
|
||||||
#define GWSERIAL_TX 26
|
#define SERIAL_GROOVE_485
|
||||||
#define GWSERIAL_RX 32
|
|
||||||
#define GWSERIAL_MODE "UNI"
|
|
||||||
|
|
||||||
#define GWSERIAL2_TX 14
|
|
||||||
#define GWSERIAL2_RX 15
|
|
||||||
#define GWSERIAL2_MODE "BI"
|
|
||||||
|
|
||||||
#define GWBUTTON_PIN GPIO_NUM_39
|
|
||||||
#define GWBUTTON_ACTIVE LOW
|
|
||||||
//if GWBUTTON_PULLUPDOWN we enable a pulup/pulldown
|
|
||||||
#define GWBUTTON_PULLUPDOWN
|
|
||||||
//led handling
|
|
||||||
//if we define GWLED_FASTNET the arduino fastnet lib is used
|
|
||||||
#define GWLED_FASTLED
|
|
||||||
#define GWLED_TYPE SK6812
|
|
||||||
//color schema for fastled
|
|
||||||
#define GWLED_SCHEMA GRB
|
|
||||||
#define GWLED_PIN GPIO_NUM_27
|
|
||||||
//brightness 0...255
|
|
||||||
#define GWLED_BRIGHTNESS 64
|
|
||||||
#define USBSerial Serial
|
|
||||||
|
|
||||||
void exampleTask(GwApi *param);
|
void exampleTask(GwApi *param);
|
||||||
void exampleInit(GwApi *param);
|
void exampleInit(GwApi *param);
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
|
#define DECLARE_USERTASK(task) GwUserTaskDef __##task##__(task,#task);
|
||||||
|
#define DECLARE_USERTASK_PARAM(task,...) GwUserTaskDef __##task##__(task,#task,__VA_ARGS__);
|
||||||
|
#define DECLARE_INITFUNCTION(task) GwInitTask __Init##task##__(task,#task);
|
||||||
|
#define DECLARE_CAPABILITY(name,value) GwUserCapability __CAP##name##__(#name,#value);
|
||||||
|
#define DECLARE_STRING_CAPABILITY(name,value) GwUserCapability __CAP##name##__(#name,value);
|
||||||
|
|
||||||
#include "GwUserCode.h"
|
#include "GwUserCode.h"
|
||||||
#include "GwSynchronized.h"
|
#include "GwSynchronized.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include "GwCounter.h"
|
||||||
//user task handling
|
//user task handling
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,25 +45,24 @@ class GwUserCapability{
|
||||||
userCapabilities[name]=value;
|
userCapabilities[name]=value;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#define DECLARE_USERTASK(task) GwUserTaskDef __##task##__(task,#task);
|
|
||||||
#define DECLARE_USERTASK_PARAM(task,...) GwUserTaskDef __##task##__(task,#task,__VA_ARGS__);
|
|
||||||
#define DECLARE_INITFUNCTION(task) GwInitTask __Init##task##__(task,#task);
|
|
||||||
#define DECLARE_CAPABILITY(name,value) GwUserCapability __CAP##name##__(#name,#value);
|
|
||||||
#define DECLARE_STRING_CAPABILITY(name,value) GwUserCapability __CAP##name##__(#name,value);
|
|
||||||
#include "GwApi.h"
|
|
||||||
#include "GwUserTasks.h"
|
#include "GwUserTasks.h"
|
||||||
class TaskApi : public GwApi
|
class TaskApi : public GwApiInternal
|
||||||
{
|
{
|
||||||
GwApi *api;
|
GwApiInternal *api;
|
||||||
int sourceId;
|
int sourceId;
|
||||||
SemaphoreHandle_t *mainLock;
|
SemaphoreHandle_t *mainLock;
|
||||||
|
SemaphoreHandle_t localLock;
|
||||||
|
GwCounter<String> *counter=NULL;
|
||||||
|
bool counterUsed=false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TaskApi(GwApi *api, int sourceId, SemaphoreHandle_t *mainLock)
|
TaskApi(GwApiInternal *api, int sourceId, SemaphoreHandle_t *mainLock, const String &name)
|
||||||
{
|
{
|
||||||
this->sourceId = sourceId;
|
this->sourceId = sourceId;
|
||||||
this->api = api;
|
this->api = api;
|
||||||
this->mainLock=mainLock;
|
this->mainLock=mainLock;
|
||||||
|
localLock=xSemaphoreCreateMutex();
|
||||||
|
counter=new GwCounter<String>("count"+name);
|
||||||
}
|
}
|
||||||
virtual GwRequestQueue *getQueue()
|
virtual GwRequestQueue *getQueue()
|
||||||
{
|
{
|
||||||
|
@ -104,10 +110,39 @@ public:
|
||||||
GWSYNCHRONIZED(mainLock);
|
GWSYNCHRONIZED(mainLock);
|
||||||
api->getStatus(status);
|
api->getStatus(status);
|
||||||
}
|
}
|
||||||
virtual ~TaskApi(){};
|
virtual ~TaskApi(){
|
||||||
|
vSemaphoreDelete(localLock);
|
||||||
|
delete counter;
|
||||||
|
};
|
||||||
|
virtual void fillStatus(GwJsonDocument &status){
|
||||||
|
GWSYNCHRONIZED(&localLock);
|
||||||
|
if (! counterUsed) return;
|
||||||
|
return counter->toJson(status);
|
||||||
|
};
|
||||||
|
virtual int getJsonSize(){
|
||||||
|
GWSYNCHRONIZED(&localLock);
|
||||||
|
if (! counterUsed) return 0;
|
||||||
|
return counter->getJsonSize();
|
||||||
|
};
|
||||||
|
virtual void increment(const String &name,bool failed=false){
|
||||||
|
GWSYNCHRONIZED(&localLock);
|
||||||
|
counterUsed=true;
|
||||||
|
if (failed) counter->addFail(name);
|
||||||
|
else (counter->add(name));
|
||||||
|
};
|
||||||
|
virtual void reset(){
|
||||||
|
GWSYNCHRONIZED(&localLock);
|
||||||
|
counterUsed=true;
|
||||||
|
counter->reset();
|
||||||
|
};
|
||||||
|
virtual void setCounterDisplayName(const String &name){
|
||||||
|
GWSYNCHRONIZED(&localLock);
|
||||||
|
counterUsed=true;
|
||||||
|
counter->setName("count"+name);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
GwUserCode::GwUserCode(GwApi *api,SemaphoreHandle_t *mainLock){
|
GwUserCode::GwUserCode(GwApiInternal *api,SemaphoreHandle_t *mainLock){
|
||||||
this->logger=api->getLogger();
|
this->logger=api->getLogger();
|
||||||
this->api=api;
|
this->api=api;
|
||||||
this->mainLock=mainLock;
|
this->mainLock=mainLock;
|
||||||
|
@ -123,8 +158,8 @@ void userTaskStart(void *p){
|
||||||
delete task->api;
|
delete task->api;
|
||||||
task->api=NULL;
|
task->api=NULL;
|
||||||
}
|
}
|
||||||
void GwUserCode::startAddOnTask(GwApi *api,GwUserTask *task,int sourceId,String name){
|
void GwUserCode::startAddOnTask(GwApiInternal *api,GwUserTask *task,int sourceId,String name){
|
||||||
task->api=new TaskApi(api,sourceId,mainLock);
|
task->api=new TaskApi(api,sourceId,mainLock,name);
|
||||||
xTaskCreate(userTaskStart,name.c_str(),task->stackSize,task,3,NULL);
|
xTaskCreate(userTaskStart,name.c_str(),task->stackSize,task,3,NULL);
|
||||||
}
|
}
|
||||||
void GwUserCode::startUserTasks(int baseId){
|
void GwUserCode::startUserTasks(int baseId){
|
||||||
|
@ -139,7 +174,7 @@ void GwUserCode::startInitTasks(int baseId){
|
||||||
LOG_DEBUG(GwLog::DEBUG,"starting %d user init tasks",initTasks.size());
|
LOG_DEBUG(GwLog::DEBUG,"starting %d user init tasks",initTasks.size());
|
||||||
for (auto it=initTasks.begin();it != initTasks.end();it++){
|
for (auto it=initTasks.begin();it != initTasks.end();it++){
|
||||||
LOG_DEBUG(GwLog::LOG,"starting user init task %s with id %d",it->name.c_str(),baseId);
|
LOG_DEBUG(GwLog::LOG,"starting user init task %s with id %d",it->name.c_str(),baseId);
|
||||||
it->api=new TaskApi(api,baseId,mainLock);
|
it->api=new TaskApi(api,baseId,mainLock,it->name);
|
||||||
userTaskStart(&(*it));
|
userTaskStart(&(*it));
|
||||||
baseId++;
|
baseId++;
|
||||||
}
|
}
|
||||||
|
@ -152,4 +187,21 @@ void GwUserCode::startAddonTask(String name, TaskFunction_t task, int id){
|
||||||
|
|
||||||
GwUserCode::Capabilities * GwUserCode::getCapabilities(){
|
GwUserCode::Capabilities * GwUserCode::getCapabilities(){
|
||||||
return &userCapabilities;
|
return &userCapabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GwUserCode::fillStatus(GwJsonDocument &status){
|
||||||
|
for (auto it=userTasks.begin();it != userTasks.end();it++){
|
||||||
|
if (it->api){
|
||||||
|
it->api->fillStatus(status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int GwUserCode::getJsonSize(){
|
||||||
|
int rt=0;
|
||||||
|
for (auto it=userTasks.begin();it != userTasks.end();it++){
|
||||||
|
if (it->api){
|
||||||
|
rt+=it->api->getJsonSize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rt;
|
||||||
}
|
}
|
|
@ -2,16 +2,24 @@
|
||||||
#define _GWUSERCODE_H
|
#define _GWUSERCODE_H
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include "GwApi.h"
|
||||||
|
#include "GwJsonDocument.h"
|
||||||
class GwLog;
|
class GwLog;
|
||||||
class GwApi;
|
|
||||||
typedef void (*GwUserTaskFunction)(GwApi *);
|
typedef void (*GwUserTaskFunction)(GwApi *);
|
||||||
|
|
||||||
|
class GwApiInternal : public GwApi{
|
||||||
|
public:
|
||||||
|
~GwApiInternal(){}
|
||||||
|
virtual void fillStatus(GwJsonDocument &status){};
|
||||||
|
virtual int getJsonSize(){return 0;};
|
||||||
|
};
|
||||||
class GwUserTask{
|
class GwUserTask{
|
||||||
public:
|
public:
|
||||||
String name;
|
String name;
|
||||||
TaskFunction_t task=NULL;
|
TaskFunction_t task=NULL;
|
||||||
GwUserTaskFunction usertask=NULL;
|
GwUserTaskFunction usertask=NULL;
|
||||||
bool isUserTask=false;
|
bool isUserTask=false;
|
||||||
GwApi *api=NULL;
|
GwApiInternal *api=NULL;
|
||||||
int stackSize=2000;
|
int stackSize=2000;
|
||||||
GwUserTask(String name,TaskFunction_t task,int stackSize=2000){
|
GwUserTask(String name,TaskFunction_t task,int stackSize=2000){
|
||||||
this->name=name;
|
this->name=name;
|
||||||
|
@ -25,17 +33,21 @@ class GwUserTask{
|
||||||
this->stackSize=stackSize;
|
this->stackSize=stackSize;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class GwUserCode{
|
class GwUserCode{
|
||||||
GwLog *logger;
|
GwLog *logger;
|
||||||
GwApi *api;
|
GwApiInternal *api;
|
||||||
SemaphoreHandle_t *mainLock;
|
SemaphoreHandle_t *mainLock;
|
||||||
void startAddOnTask(GwApi *api,GwUserTask *task,int sourceId,String name);
|
void startAddOnTask(GwApiInternal *api,GwUserTask *task,int sourceId,String name);
|
||||||
public:
|
public:
|
||||||
typedef std::map<String,String> Capabilities;
|
typedef std::map<String,String> Capabilities;
|
||||||
GwUserCode(GwApi *api, SemaphoreHandle_t *mainLock);
|
GwUserCode(GwApiInternal *api, SemaphoreHandle_t *mainLock);
|
||||||
void startUserTasks(int baseId);
|
void startUserTasks(int baseId);
|
||||||
void startInitTasks(int baseId);
|
void startInitTasks(int baseId);
|
||||||
void startAddonTask(String name,TaskFunction_t task, int id);
|
void startAddonTask(String name,TaskFunction_t task, int id);
|
||||||
Capabilities *getCapabilities();
|
Capabilities *getCapabilities();
|
||||||
|
void fillStatus(GwJsonDocument &status);
|
||||||
|
int getJsonSize();
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
|
@ -235,7 +235,7 @@ void SendNMEA0183Message(const tNMEA0183Msg &NMEA0183Msg, int sourceId,bool conv
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class ApiImpl : public GwApi
|
class ApiImpl : public GwApiInternal
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
int sourceId = -1;
|
int sourceId = -1;
|
||||||
|
@ -374,7 +374,8 @@ protected:
|
||||||
GwJsonDocument status(300 +
|
GwJsonDocument status(300 +
|
||||||
countNMEA2KIn.getJsonSize()+
|
countNMEA2KIn.getJsonSize()+
|
||||||
countNMEA2KOut.getJsonSize() +
|
countNMEA2KOut.getJsonSize() +
|
||||||
channels.getJsonSize()
|
channels.getJsonSize()+
|
||||||
|
userCodeHandler.getJsonSize()
|
||||||
);
|
);
|
||||||
status["version"] = VERSION;
|
status["version"] = VERSION;
|
||||||
status["wifiConnected"] = gwWifi.clientConnected();
|
status["wifiConnected"] = gwWifi.clientConnected();
|
||||||
|
@ -406,6 +407,7 @@ protected:
|
||||||
countNMEA2KIn.toJson(status);
|
countNMEA2KIn.toJson(status);
|
||||||
countNMEA2KOut.toJson(status);
|
countNMEA2KOut.toJson(status);
|
||||||
channels.toJson(status);
|
channels.toJson(status);
|
||||||
|
userCodeHandler.fillStatus(status);
|
||||||
serializeJson(status, result);
|
serializeJson(status, result);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue