intermediate: generic handling of user tasks
This commit is contained in:
parent
5bf2aeaffe
commit
1e4285fe5d
|
@ -3,4 +3,5 @@
|
||||||
.vscode/c_cpp_properties.json
|
.vscode/c_cpp_properties.json
|
||||||
.vscode/launch.json
|
.vscode/launch.json
|
||||||
.vscode/ipch
|
.vscode/ipch
|
||||||
generated/*
|
generated/*
|
||||||
|
lib/generated
|
|
@ -5,15 +5,17 @@ import os
|
||||||
import sys
|
import sys
|
||||||
import inspect
|
import inspect
|
||||||
import json
|
import json
|
||||||
|
import glob
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
Import("env")
|
Import("env")
|
||||||
#print(env.Dump())
|
#print(env.Dump())
|
||||||
OWN_FILE="extra_script.py"
|
OWN_FILE="extra_script.py"
|
||||||
GEN_DIR='generated'
|
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'
|
||||||
XDR_INCLUDE='GwXdrTypeMappings.h'
|
XDR_INCLUDE='GwXdrTypeMappings.h'
|
||||||
|
TASK_INCLUDE='GwUserTasks.h'
|
||||||
EMBEDDED_INCLUDE="GwEmbeddedFiles.h"
|
EMBEDDED_INCLUDE="GwEmbeddedFiles.h"
|
||||||
|
|
||||||
def getEmbeddedFiles(env):
|
def getEmbeddedFiles(env):
|
||||||
|
@ -155,6 +157,30 @@ def generateXdrMappings(fp,oh,inFile=''):
|
||||||
oh.write("\n")
|
oh.write("\n")
|
||||||
oh.write("};\n")
|
oh.write("};\n")
|
||||||
|
|
||||||
|
def genereateUserTasks(outfile):
|
||||||
|
includes=[]
|
||||||
|
taskdirs=glob.glob(os.path.join('lib','*task*'))
|
||||||
|
for task in taskdirs:
|
||||||
|
#print("##taskdir=%s"%task)
|
||||||
|
base=os.path.basename(task)
|
||||||
|
includeNames=[base.lower()+".h",'gw'+base.lower()+'.h']
|
||||||
|
for f in os.listdir(task):
|
||||||
|
if not f.endswith('.h'):
|
||||||
|
continue
|
||||||
|
match=False
|
||||||
|
for cmp in includeNames:
|
||||||
|
#print("##check %s<->%s"%(f.lower(),cmp))
|
||||||
|
if f.lower() == cmp:
|
||||||
|
match=True
|
||||||
|
if not match:
|
||||||
|
continue
|
||||||
|
includes.append(f)
|
||||||
|
includeData=""
|
||||||
|
for i in includes:
|
||||||
|
print("#task include %s"%i)
|
||||||
|
includeData+="#include <%s>\n"%i
|
||||||
|
writeFileIfChanged(outfile,includeData)
|
||||||
|
|
||||||
def generateEmbedded(elist,outFile):
|
def generateEmbedded(elist,outFile):
|
||||||
content=""
|
content=""
|
||||||
for entry in elist:
|
for entry in elist:
|
||||||
|
@ -196,6 +222,7 @@ def prebuild(env):
|
||||||
else:
|
else:
|
||||||
print("#WARNING: infile %s for %s not found"%(inFile,ef))
|
print("#WARNING: infile %s for %s not found"%(inFile,ef))
|
||||||
generateEmbedded(filedefs,os.path.join(outPath(),EMBEDDED_INCLUDE))
|
generateEmbedded(filedefs,os.path.join(outPath(),EMBEDDED_INCLUDE))
|
||||||
|
genereateUserTasks(os.path.join(outPath(), TASK_INCLUDE))
|
||||||
generateFile(os.path.join(basePath(),CFG_FILE),os.path.join(outPath(),CFG_INCLUDE),generateCfg)
|
generateFile(os.path.join(basePath(),CFG_FILE),os.path.join(outPath(),CFG_INCLUDE),generateCfg)
|
||||||
generateFile(os.path.join(basePath(),XDR_FILE),os.path.join(outPath(),XDR_INCLUDE),generateXdrMappings)
|
generateFile(os.path.join(basePath(),XDR_FILE),os.path.join(outPath(),XDR_INCLUDE),generateXdrMappings)
|
||||||
version="dev"+datetime.now().strftime("%Y%m%d")
|
version="dev"+datetime.now().strftime("%Y%m%d")
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#ifndef _GWAPI_H
|
#ifndef _GWAPI_H
|
||||||
#define _GWAPI_H
|
#define _GWAPI_H
|
||||||
#include "GwMessage.h"
|
#include "GwMessage.h"
|
||||||
#include "N2kMessages.h"
|
#include "N2kMsg.h"
|
||||||
#include "NMEA0183Messages.h"
|
#include "NMEA0183Msg.h"
|
||||||
#include "GWConfig.h"
|
#include "GWConfig.h"
|
||||||
#include "GwBoatData.h"
|
#include "GwBoatData.h"
|
||||||
//API to be used for additional tasks
|
//API to be used for additional tasks
|
||||||
|
@ -16,4 +16,7 @@ class GwApi{
|
||||||
virtual GwLog *getLogger()=0;
|
virtual GwLog *getLogger()=0;
|
||||||
virtual GwBoatData *getBoatData()=0;
|
virtual GwBoatData *getBoatData()=0;
|
||||||
};
|
};
|
||||||
#endif
|
#ifndef DECLARE_USERTASK
|
||||||
|
#define DECLARE_USERTASK(task)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef _GWEXAMPLEHARDWARE_H
|
||||||
|
#define _GWEXAMPLEHARDWARE_H
|
||||||
|
|
||||||
|
#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 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
|
||||||
|
#endif
|
||||||
|
#endif
|
|
@ -1,4 +1,7 @@
|
||||||
|
|
||||||
|
//we only compile for some boards
|
||||||
|
#ifdef BOARD_TEST
|
||||||
|
#include "GwExampleTask.h"
|
||||||
#include "GwApi.h"
|
#include "GwApi.h"
|
||||||
|
|
||||||
#define INVALID_COORD -99999
|
#define INVALID_COORD -99999
|
||||||
|
@ -79,4 +82,6 @@ void exampleTask(void *param){
|
||||||
}
|
}
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,5 +1,11 @@
|
||||||
#ifndef _GWEXAMPLETASK_H
|
#ifndef _GWEXAMPLETASK_H
|
||||||
#define _GWEXAMPLETASK_H
|
#define _GWEXAMPLETASK_H
|
||||||
//task function
|
#include "GwExampleHardware.h"
|
||||||
|
#include "GwApi.h"
|
||||||
|
//we only compile for some boards
|
||||||
|
#ifdef BOARD_TEST
|
||||||
void exampleTask(void *param);
|
void exampleTask(void *param);
|
||||||
|
//make the task known to the core
|
||||||
|
DECLARE_USERTASK(exampleTask);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
|
@ -0,0 +1,31 @@
|
||||||
|
Extending the Core
|
||||||
|
==================
|
||||||
|
This directory contains an example on how you can extend the base functionality of the gateway.
|
||||||
|
Basically you can define own boards here and can add one or more tasks that will be started by the core.
|
||||||
|
You can also add additional libraries that will be used for your task.
|
||||||
|
In this example we define an addtional board (environment) with the name "testboard".
|
||||||
|
When building for this board we add the -DTEST_BOARD to the compilation - see [platformio.ini](platformio.ini).
|
||||||
|
The additional task that we defined will only be compiled and started for this environment (see the #ifdef TEST_BOARD in the code).
|
||||||
|
You can add your own directory below "lib". The name of the directory must contain "task".
|
||||||
|
|
||||||
|
Files
|
||||||
|
-----
|
||||||
|
* [platformio.ini](platformio.ini)
|
||||||
|
extend the base configuration - we add a dummy library here and define our buil environment (board)
|
||||||
|
* [GwExampleTask.h](GwExampleTask.h) the name of this include must match the name of the directory (ignoring case) with a "gw" in front. This file includes our special hardware definitions and registers our task at the core (DECLARE_USERTASK in the code).
|
||||||
|
* [GwExampleTaks.cpp](GwExampleTask.cpp) includes the implementation of our task. This tasks runs in an own thread - see the comments in the code.
|
||||||
|
* [GwExampleHardware.h](GwExampleHardware.h) includes our pin definitions for the board.
|
||||||
|
|
||||||
|
Hints
|
||||||
|
-----
|
||||||
|
Just be careful not to interfere with names from the core - so it is a good practice to prefix your files and class like in the example.
|
||||||
|
|
||||||
|
Developing
|
||||||
|
----------
|
||||||
|
To develop I recommend forking the gateway repository and adding your own directory below lib (with the string task in it's name).
|
||||||
|
As your code goes into a separate directory it should be very easy to fetch upstream changes without the need to adapt your code.
|
||||||
|
|
||||||
|
Future Plans
|
||||||
|
------------
|
||||||
|
If there will be a need we can extend this extension API by means of adding config items and specific java script code and css for the UI.
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
[env:testboard]
|
||||||
|
board = m5stack-atom
|
||||||
|
lib_deps =
|
||||||
|
${env.lib_deps}
|
||||||
|
own_lib
|
||||||
|
build_flags=
|
||||||
|
-D BOARD_TEST
|
||||||
|
${env.build_flags}
|
||||||
|
upload_port = /dev/esp32
|
||||||
|
upload_protocol = esptool
|
|
@ -13,6 +13,7 @@
|
||||||
*/
|
*/
|
||||||
#ifndef _GWHARDWARE_H
|
#ifndef _GWHARDWARE_H
|
||||||
#define _GWHARDWARE_H
|
#define _GWHARDWARE_H
|
||||||
|
#include "GwUserTasks.h"
|
||||||
|
|
||||||
//SERIAL_MODE can be: UNI (RX or TX only), BI (both), RX, TX
|
//SERIAL_MODE can be: UNI (RX or TX only), BI (both), RX, TX
|
||||||
//board specific pins
|
//board specific pins
|
||||||
|
|
|
@ -7,6 +7,9 @@
|
||||||
;
|
;
|
||||||
; Please visit documentation for the other options and examples
|
; Please visit documentation for the other options and examples
|
||||||
; https://docs.platformio.org/page/projectconf.html
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
[platformio]
|
||||||
|
extra_configs=
|
||||||
|
lib/*task*/platformio.ini
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
|
@ -19,16 +22,16 @@ lib_deps =
|
||||||
ottowinter/ESPAsyncWebServer-esphome@^2.0.1
|
ottowinter/ESPAsyncWebServer-esphome@^2.0.1
|
||||||
fastled/FastLED @ ^3.4.0
|
fastled/FastLED @ ^3.4.0
|
||||||
board_build.embed_files =
|
board_build.embed_files =
|
||||||
generated/index.html.gz
|
lib/generated/index.html.gz
|
||||||
generated/index.js.gz
|
lib/generated/index.js.gz
|
||||||
generated/index.css.gz
|
lib/generated/index.css.gz
|
||||||
generated/config.json.gz
|
lib/generated/config.json.gz
|
||||||
generated/xdrconfig.json.gz
|
lib/generated/xdrconfig.json.gz
|
||||||
board_build.partitions = partitions_custom.csv
|
board_build.partitions = partitions_custom.csv
|
||||||
extra_scripts =
|
extra_scripts =
|
||||||
pre:extra_script.py
|
pre:extra_script.py
|
||||||
post:post.py
|
post:post.py
|
||||||
build_flags = -Igenerated
|
lib_ldf_mode = chain+
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
|
||||||
[env:m5stack-atom]
|
[env:m5stack-atom]
|
||||||
|
|
38
src/main.cpp
38
src/main.cpp
|
@ -30,9 +30,25 @@
|
||||||
// #define GW_MESSAGE_DEBUG_ENABLED
|
// #define GW_MESSAGE_DEBUG_ENABLED
|
||||||
// #define FALLBACK_SERIAL
|
// #define FALLBACK_SERIAL
|
||||||
const unsigned long HEAP_REPORT_TIME=2000; //set to 0 to disable heap reporting
|
const unsigned long HEAP_REPORT_TIME=2000; //set to 0 to disable heap reporting
|
||||||
|
#include <Arduino.h>
|
||||||
|
//user task handling
|
||||||
|
std::vector<TaskFunction_t> userTasks;
|
||||||
|
|
||||||
|
void registerUserTask(TaskFunction_t task){
|
||||||
|
//logWriter.write("register user task\n");
|
||||||
|
userTasks.push_back(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
class GwUserTask{
|
||||||
|
public:
|
||||||
|
GwUserTask(TaskFunction_t task){
|
||||||
|
registerUserTask(task);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#define DECLARE_USERTASK(task) GwUserTask __##task##__(task);
|
||||||
|
//#include "GwUserTasks.h"
|
||||||
#include "GwHardware.h"
|
#include "GwHardware.h"
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include <NMEA2000_CAN.h> // This will automatically choose right CAN library and create suitable NMEA2000 object
|
#include <NMEA2000_CAN.h> // This will automatically choose right CAN library and create suitable NMEA2000 object
|
||||||
#include <ActisenseReader.h>
|
#include <ActisenseReader.h>
|
||||||
#include <Seasmart.h>
|
#include <Seasmart.h>
|
||||||
|
@ -43,6 +59,7 @@ const unsigned long HEAP_REPORT_TIME=2000; //set to 0 to disable heap reporting
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <ESPmDNS.h>
|
#include <ESPmDNS.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
|
|
||||||
#include "N2kDataToNMEA0183.h"
|
#include "N2kDataToNMEA0183.h"
|
||||||
|
@ -57,14 +74,14 @@ const unsigned long HEAP_REPORT_TIME=2000; //set to 0 to disable heap reporting
|
||||||
#include "GwSerial.h"
|
#include "GwSerial.h"
|
||||||
#include "GwWebServer.h"
|
#include "GwWebServer.h"
|
||||||
#include "NMEA0183DataToN2K.h"
|
#include "NMEA0183DataToN2K.h"
|
||||||
#include "GwApi.h"
|
|
||||||
#include "GwButtons.h"
|
#include "GwButtons.h"
|
||||||
#include "GwLeds.h"
|
#include "GwLeds.h"
|
||||||
#include "GwCounter.h"
|
#include "GwCounter.h"
|
||||||
#include "GwXDRMappings.h"
|
#include "GwXDRMappings.h"
|
||||||
#include "GwExampleTask.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "GwApi.h"
|
||||||
|
|
||||||
//NMEA message channels
|
//NMEA message channels
|
||||||
#define N2K_CHANNEL_ID 0
|
#define N2K_CHANNEL_ID 0
|
||||||
#define USB_CHANNEL_ID 1
|
#define USB_CHANNEL_ID 1
|
||||||
|
@ -74,6 +91,8 @@ const unsigned long HEAP_REPORT_TIME=2000; //set to 0 to disable heap reporting
|
||||||
#define MAX_NMEA2000_MESSAGE_SEASMART_SIZE 500
|
#define MAX_NMEA2000_MESSAGE_SEASMART_SIZE 500
|
||||||
#define MAX_NMEA0183_MESSAGE_SIZE 150 // For AIS
|
#define MAX_NMEA0183_MESSAGE_SIZE 150 // For AIS
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef std::map<String,String> StringMap;
|
typedef std::map<String,String> StringMap;
|
||||||
|
|
||||||
|
|
||||||
|
@ -211,6 +230,8 @@ class GwSerialLog : public GwLogWriter{
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GwSerialLog logWriter;
|
||||||
|
|
||||||
class ApiImpl : public GwApi
|
class ApiImpl : public GwApi
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -260,6 +281,7 @@ bool delayedRestart(){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void startAddOnTask(TaskFunction_t task,int sourceId){
|
void startAddOnTask(TaskFunction_t task,int sourceId){
|
||||||
ApiImpl* api=new ApiImpl(sourceId);
|
ApiImpl* api=new ApiImpl(sourceId);
|
||||||
xTaskCreate(task,"user",2000,api,3,NULL);
|
xTaskCreate(task,"user",2000,api,3,NULL);
|
||||||
|
@ -522,9 +544,8 @@ void setup() {
|
||||||
logger.prefix="FALLBACK:";
|
logger.prefix="FALLBACK:";
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
GwSerialLog *writer=new GwSerialLog();
|
|
||||||
logger.prefix="GWSERIAL:";
|
logger.prefix="GWSERIAL:";
|
||||||
logger.setWriter(writer);
|
logger.setWriter(&logWriter);
|
||||||
logger.logDebug(GwLog::LOG,"created GwSerial for USB port");
|
logger.logDebug(GwLog::LOG,"created GwSerial for USB port");
|
||||||
}
|
}
|
||||||
logger.logDebug(GwLog::LOG,"config: %s", config.toString().c_str());
|
logger.logDebug(GwLog::LOG,"config: %s", config.toString().c_str());
|
||||||
|
@ -695,7 +716,12 @@ void setup() {
|
||||||
startAddOnTask(handleButtons,100);
|
startAddOnTask(handleButtons,100);
|
||||||
setLedMode(LED_GREEN);
|
setLedMode(LED_GREEN);
|
||||||
startAddOnTask(handleLeds,101);
|
startAddOnTask(handleLeds,101);
|
||||||
startAddOnTask(exampleTask,102);
|
int userTaskId=200;
|
||||||
|
for (auto it=userTasks.begin();it != userTasks.end();it++){
|
||||||
|
logger.logDebug(GwLog::LOG,"starting user task with id %d",userTaskId);
|
||||||
|
startAddOnTask(*it,userTaskId);
|
||||||
|
userTaskId++;
|
||||||
|
}
|
||||||
logger.logDebug(GwLog::LOG,"setup done");
|
logger.logDebug(GwLog::LOG,"setup done");
|
||||||
}
|
}
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
|
|
Loading…
Reference in New Issue