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