intermediate: generic handling of user tasks
This commit is contained in:
parent
5bf2aeaffe
commit
1e4285fe5d
|
@ -4,3 +4,4 @@
|
|||
.vscode/launch.json
|
||||
.vscode/ipch
|
||||
generated/*
|
||||
lib/generated
|
|
@ -5,15 +5,17 @@ import os
|
|||
import sys
|
||||
import inspect
|
||||
import json
|
||||
import glob
|
||||
from datetime import datetime
|
||||
Import("env")
|
||||
#print(env.Dump())
|
||||
OWN_FILE="extra_script.py"
|
||||
GEN_DIR='generated'
|
||||
GEN_DIR='lib/generated'
|
||||
CFG_FILE='web/config.json'
|
||||
XDR_FILE='web/xdrconfig.json'
|
||||
CFG_INCLUDE='GwConfigDefinitions.h'
|
||||
XDR_INCLUDE='GwXdrTypeMappings.h'
|
||||
TASK_INCLUDE='GwUserTasks.h'
|
||||
EMBEDDED_INCLUDE="GwEmbeddedFiles.h"
|
||||
|
||||
def getEmbeddedFiles(env):
|
||||
|
@ -155,6 +157,30 @@ def generateXdrMappings(fp,oh,inFile=''):
|
|||
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):
|
||||
content=""
|
||||
for entry in elist:
|
||||
|
@ -196,6 +222,7 @@ def prebuild(env):
|
|||
else:
|
||||
print("#WARNING: infile %s for %s not found"%(inFile,ef))
|
||||
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(),XDR_FILE),os.path.join(outPath(),XDR_INCLUDE),generateXdrMappings)
|
||||
version="dev"+datetime.now().strftime("%Y%m%d")
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef _GWAPI_H
|
||||
#define _GWAPI_H
|
||||
#include "GwMessage.h"
|
||||
#include "N2kMessages.h"
|
||||
#include "NMEA0183Messages.h"
|
||||
#include "N2kMsg.h"
|
||||
#include "NMEA0183Msg.h"
|
||||
#include "GWConfig.h"
|
||||
#include "GwBoatData.h"
|
||||
//API to be used for additional tasks
|
||||
|
@ -16,4 +16,7 @@ class GwApi{
|
|||
virtual GwLog *getLogger()=0;
|
||||
virtual GwBoatData *getBoatData()=0;
|
||||
};
|
||||
#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"
|
||||
|
||||
#define INVALID_COORD -99999
|
||||
|
@ -80,3 +83,5 @@ void exampleTask(void *param){
|
|||
vTaskDelete(NULL);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,5 +1,11 @@
|
|||
#ifndef _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);
|
||||
//make the task known to the core
|
||||
DECLARE_USERTASK(exampleTask);
|
||||
#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
|
||||
#define _GWHARDWARE_H
|
||||
#include "GwUserTasks.h"
|
||||
|
||||
//SERIAL_MODE can be: UNI (RX or TX only), BI (both), RX, TX
|
||||
//board specific pins
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
[platformio]
|
||||
extra_configs=
|
||||
lib/*task*/platformio.ini
|
||||
|
||||
[env]
|
||||
platform = espressif32
|
||||
|
@ -19,16 +22,16 @@ lib_deps =
|
|||
ottowinter/ESPAsyncWebServer-esphome@^2.0.1
|
||||
fastled/FastLED @ ^3.4.0
|
||||
board_build.embed_files =
|
||||
generated/index.html.gz
|
||||
generated/index.js.gz
|
||||
generated/index.css.gz
|
||||
generated/config.json.gz
|
||||
generated/xdrconfig.json.gz
|
||||
lib/generated/index.html.gz
|
||||
lib/generated/index.js.gz
|
||||
lib/generated/index.css.gz
|
||||
lib/generated/config.json.gz
|
||||
lib/generated/xdrconfig.json.gz
|
||||
board_build.partitions = partitions_custom.csv
|
||||
extra_scripts =
|
||||
pre:extra_script.py
|
||||
post:post.py
|
||||
build_flags = -Igenerated
|
||||
lib_ldf_mode = chain+
|
||||
monitor_speed = 115200
|
||||
|
||||
[env:m5stack-atom]
|
||||
|
|
38
src/main.cpp
38
src/main.cpp
|
@ -30,9 +30,25 @@
|
|||
// #define GW_MESSAGE_DEBUG_ENABLED
|
||||
// #define FALLBACK_SERIAL
|
||||
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 <Arduino.h>
|
||||
#include <NMEA2000_CAN.h> // This will automatically choose right CAN library and create suitable NMEA2000 object
|
||||
#include <ActisenseReader.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 <ESPmDNS.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "esp_heap_caps.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 "GwWebServer.h"
|
||||
#include "NMEA0183DataToN2K.h"
|
||||
#include "GwApi.h"
|
||||
#include "GwButtons.h"
|
||||
#include "GwLeds.h"
|
||||
#include "GwCounter.h"
|
||||
#include "GwXDRMappings.h"
|
||||
#include "GwExampleTask.h"
|
||||
|
||||
|
||||
#include "GwApi.h"
|
||||
|
||||
//NMEA message channels
|
||||
#define N2K_CHANNEL_ID 0
|
||||
#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_NMEA0183_MESSAGE_SIZE 150 // For AIS
|
||||
|
||||
|
||||
|
||||
typedef std::map<String,String> StringMap;
|
||||
|
||||
|
||||
|
@ -211,6 +230,8 @@ class GwSerialLog : public GwLogWriter{
|
|||
|
||||
};
|
||||
|
||||
GwSerialLog logWriter;
|
||||
|
||||
class ApiImpl : public GwApi
|
||||
{
|
||||
private:
|
||||
|
@ -260,6 +281,7 @@ bool delayedRestart(){
|
|||
}
|
||||
|
||||
|
||||
|
||||
void startAddOnTask(TaskFunction_t task,int sourceId){
|
||||
ApiImpl* api=new ApiImpl(sourceId);
|
||||
xTaskCreate(task,"user",2000,api,3,NULL);
|
||||
|
@ -522,9 +544,8 @@ void setup() {
|
|||
logger.prefix="FALLBACK:";
|
||||
}
|
||||
else{
|
||||
GwSerialLog *writer=new GwSerialLog();
|
||||
logger.prefix="GWSERIAL:";
|
||||
logger.setWriter(writer);
|
||||
logger.setWriter(&logWriter);
|
||||
logger.logDebug(GwLog::LOG,"created GwSerial for USB port");
|
||||
}
|
||||
logger.logDebug(GwLog::LOG,"config: %s", config.toString().c_str());
|
||||
|
@ -695,7 +716,12 @@ void setup() {
|
|||
startAddOnTask(handleButtons,100);
|
||||
setLedMode(LED_GREEN);
|
||||
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");
|
||||
}
|
||||
//*****************************************************************************
|
||||
|
|
Loading…
Reference in New Issue