Merge branch 'master' of github.com:wellenvogel/esp32-nmea2000
This commit is contained in:
commit
30ade0c07a
|
@ -170,6 +170,12 @@ For details refer to the [example description](lib/exampletask/Readme.md).
|
||||||
|
|
||||||
Changelog
|
Changelog
|
||||||
---------
|
---------
|
||||||
|
[20250305](../../releases/tag/20250305)
|
||||||
|
*********
|
||||||
|
* better handling for reconnect to a raspberry pi after reset [#102](../../issues/102)
|
||||||
|
* introduce _custom_config_, _custom_js_, _custom_css_, refer to [extending the core](lib/exampletask/Readme.md) [#100](../../pull/100)
|
||||||
|
* create VWR [#103](../../issues/103)
|
||||||
|
|
||||||
[20241128](../../releases/tag/20241128)
|
[20241128](../../releases/tag/20241128)
|
||||||
*********
|
*********
|
||||||
* additional correction for: USB connection on S3 stops [#81](../../issues/81)
|
* additional correction for: USB connection on S3 stops [#81](../../issues/81)
|
||||||
|
|
|
@ -104,8 +104,7 @@ def writeFileIfChanged(fileName,data):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def mergeConfig(base,other):
|
def mergeConfig(base,other):
|
||||||
for bdir in other:
|
for cname in other:
|
||||||
cname=os.path.join(bdir,"config.json")
|
|
||||||
if os.path.exists(cname):
|
if os.path.exists(cname):
|
||||||
print("merge config %s"%cname)
|
print("merge config %s"%cname)
|
||||||
with open(cname,'rb') as ah:
|
with open(cname,'rb') as ah:
|
||||||
|
@ -151,13 +150,25 @@ def expandConfig(config):
|
||||||
rt.append(replaceTexts(c,replace))
|
rt.append(replaceTexts(c,replace))
|
||||||
return rt
|
return rt
|
||||||
|
|
||||||
def generateMergedConfig(inFile,outFile,addDirs=[]):
|
def createUserItemList(dirs,itemName,files):
|
||||||
|
rt=[]
|
||||||
|
for d in dirs:
|
||||||
|
iname=os.path.join(d,itemName)
|
||||||
|
if os.path.exists(iname):
|
||||||
|
rt.append(iname)
|
||||||
|
for f in files:
|
||||||
|
if not os.path.exists(f):
|
||||||
|
raise Exception("user item %s not found"%f)
|
||||||
|
rt.append(f)
|
||||||
|
return rt
|
||||||
|
|
||||||
|
def generateMergedConfig(inFile,outFile,addFiles=[]):
|
||||||
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)
|
config=mergeConfig(config,addFiles)
|
||||||
config=expandConfig(config)
|
config=expandConfig(config)
|
||||||
data=json.dumps(config,indent=2)
|
data=json.dumps(config,indent=2)
|
||||||
writeFileIfChanged(outFile,data)
|
writeFileIfChanged(outFile,data)
|
||||||
|
@ -274,9 +285,9 @@ class Grove:
|
||||||
def _ss(self,z=False):
|
def _ss(self,z=False):
|
||||||
if z:
|
if z:
|
||||||
return self.name
|
return self.name
|
||||||
return self.name if self.name is not 'Z' else ''
|
return self.name if self.name != 'Z' else ''
|
||||||
def _suffix(self):
|
def _suffix(self):
|
||||||
return '_'+self.name if self.name is not 'Z' else ''
|
return '_'+self.name if self.name != 'Z' else ''
|
||||||
def replace(self,line):
|
def replace(self,line):
|
||||||
if line is None:
|
if line is None:
|
||||||
return line
|
return line
|
||||||
|
@ -377,12 +388,7 @@ def getLibs():
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def joinFiles(target,pattern,dirlist):
|
def joinFiles(target,flist):
|
||||||
flist=[]
|
|
||||||
for dir in dirlist:
|
|
||||||
fn=os.path.join(dir,pattern)
|
|
||||||
if os.path.exists(fn):
|
|
||||||
flist.append(fn)
|
|
||||||
current=False
|
current=False
|
||||||
if os.path.exists(target):
|
if os.path.exists(target):
|
||||||
current=True
|
current=True
|
||||||
|
@ -453,7 +459,28 @@ def handleDeps(env):
|
||||||
)
|
)
|
||||||
env.AddBuildMiddleware(injectIncludes)
|
env.AddBuildMiddleware(injectIncludes)
|
||||||
|
|
||||||
|
def getOption(env,name,toArray=True):
|
||||||
|
try:
|
||||||
|
opt=env.GetProjectOption(name)
|
||||||
|
if toArray:
|
||||||
|
if opt is None:
|
||||||
|
return []
|
||||||
|
if isinstance(opt,list):
|
||||||
|
return opt
|
||||||
|
return opt.split("\n" if "\n" in opt else ",")
|
||||||
|
return opt
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
if toArray:
|
||||||
|
return []
|
||||||
|
|
||||||
|
def getFileList(files):
|
||||||
|
base=basePath()
|
||||||
|
rt=[]
|
||||||
|
for f in files:
|
||||||
|
if f is not None and f != "":
|
||||||
|
rt.append(os.path.join(base,f))
|
||||||
|
return rt
|
||||||
def prebuild(env):
|
def prebuild(env):
|
||||||
global userTaskDirs
|
global userTaskDirs
|
||||||
print("#prebuild running")
|
print("#prebuild running")
|
||||||
|
@ -463,14 +490,18 @@ def prebuild(env):
|
||||||
if ldf_mode == 'off':
|
if ldf_mode == 'off':
|
||||||
print("##ldf off - own dependency handling")
|
print("##ldf off - own dependency handling")
|
||||||
handleDeps(env)
|
handleDeps(env)
|
||||||
|
extraConfigs=getOption(env,'custom_config',toArray=True)
|
||||||
|
extraJs=getOption(env,'custom_js',toArray=True)
|
||||||
|
extraCss=getOption(env,'custom_css',toArray=True)
|
||||||
|
|
||||||
userTaskDirs=getUserTaskDirs()
|
userTaskDirs=getUserTaskDirs()
|
||||||
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,createUserItemList(userTaskDirs,"config.json", getFileList(extraConfigs)))
|
||||||
compressFile(mergedConfig,mergedConfig+".gz")
|
compressFile(mergedConfig,mergedConfig+".gz")
|
||||||
generateCfg(mergedConfig,os.path.join(outPath(),CFG_INCLUDE),False)
|
generateCfg(mergedConfig,os.path.join(outPath(),CFG_INCLUDE),False)
|
||||||
generateCfg(mergedConfig,os.path.join(outPath(),CFG_INCLUDE_IMPL),True)
|
generateCfg(mergedConfig,os.path.join(outPath(),CFG_INCLUDE_IMPL),True)
|
||||||
joinFiles(os.path.join(outPath(),INDEXJS+".gz"),INDEXJS,["web"]+userTaskDirs)
|
joinFiles(os.path.join(outPath(),INDEXJS+".gz"),createUserItemList(["web"]+userTaskDirs,INDEXJS,getFileList(extraJs)))
|
||||||
joinFiles(os.path.join(outPath(),INDEXCSS+".gz"),INDEXCSS,["web"]+userTaskDirs)
|
joinFiles(os.path.join(outPath(),INDEXCSS+".gz"),createUserItemList(["web"]+userTaskDirs,INDEXCSS,getFileList(extraCss)))
|
||||||
embedded=getEmbeddedFiles(env)
|
embedded=getEmbeddedFiles(env)
|
||||||
filedefs=[]
|
filedefs=[]
|
||||||
for ef in embedded:
|
for ef in embedded:
|
||||||
|
|
|
@ -14,7 +14,7 @@ Files
|
||||||
* [platformio.ini](platformio.ini)<br>
|
* [platformio.ini](platformio.ini)<br>
|
||||||
This file is completely optional.
|
This file is completely optional.
|
||||||
You only need this if you want to
|
You only need this if you want to
|
||||||
extend the base configuration - we add a dummy library here and define one additional build environment (board)
|
extend the base configuration - we add a dummy library here and define additional build environments (boards)
|
||||||
* [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.<br>
|
* [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.<br>
|
||||||
This registration can be done statically using [DECLARE_USERTASK](https://github.com/wellenvogel/esp32-nmea2000/blob/9b955d135d74937a60f2926e8bfb9395585ff8cd/lib/api/GwApi.h#L202) in the header file. <br>
|
This registration can be done statically using [DECLARE_USERTASK](https://github.com/wellenvogel/esp32-nmea2000/blob/9b955d135d74937a60f2926e8bfb9395585ff8cd/lib/api/GwApi.h#L202) in the header file. <br>
|
||||||
As an alternative we just only register an [initialization function](https://github.com/wellenvogel/esp32-nmea2000/blob/9b955d135d74937a60f2926e8bfb9395585ff8cd/lib/exampletask/GwExampleTask.h#L19) using DECLARE_INITFUNCTION and later on register the task function itself via the [API](https://github.com/wellenvogel/esp32-nmea2000/blob/9b955d135d74937a60f2926e8bfb9395585ff8cd/lib/exampletask/GwExampleTask.cpp#L32).<br>
|
As an alternative we just only register an [initialization function](https://github.com/wellenvogel/esp32-nmea2000/blob/9b955d135d74937a60f2926e8bfb9395585ff8cd/lib/exampletask/GwExampleTask.h#L19) using DECLARE_INITFUNCTION and later on register the task function itself via the [API](https://github.com/wellenvogel/esp32-nmea2000/blob/9b955d135d74937a60f2926e8bfb9395585ff8cd/lib/exampletask/GwExampleTask.cpp#L32).<br>
|
||||||
|
@ -28,11 +28,13 @@ Files
|
||||||
|
|
||||||
* [GwExampleTaks.cpp](GwExampleTask.cpp) includes the implementation of our task. This tasks runs in an own thread - see the comments 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.
|
||||||
We can have as many cpp (and header files) as we need to structure our code.
|
We can have as many cpp (and header files) as we need to structure our code.
|
||||||
* [config.json](config.json)<br>
|
* [config.json](exampleConfig.json)<br>
|
||||||
This file allows to add some config definitions that are needed for our task. For the possible options have a look at the global [config.json](../../web/config.json). Be careful not to overwrite config defitions from the global file. A good practice wood be to prefix the names of definitions with parts of the library name. Always put them in a separate category so that they do not interfere with the system ones.
|
This file allows to add some config definitions that are needed for our task. For the possible options have a look at the global [config.json](../../web/config.json). Be careful not to overwrite config defitions from the global file. A good practice wood be to prefix the names of definitions with parts of the library name. Always put them in a separate category so that they do not interfere with the system ones.
|
||||||
The defined config items can later be accessed in the code (see the example in [GwExampleTask.cpp](GwExampleTask.cpp)).
|
The defined config items can later be accessed in the code (see the example in [GwExampleTask.cpp](GwExampleTask.cpp)).<br>
|
||||||
|
|
||||||
* [index.js](index.js)<br>
|
Starting from Version 20250305 you should normally not use this file name any more as those configs would be added for all build environments. Instead define a parameter _custom_config_ in your [platformio.ini](platformio.ini) for the environments you would like to add some configurations for. This parameter accepts a list of file names (relative to the project root, separated by ,).
|
||||||
|
|
||||||
|
* [index.js](example.js)<br>
|
||||||
You can add javascript code that will contribute to the UI of the system. The WebUI provides a small API that allows you to "hook" into some functions to include your own parts of the UI. This includes adding new tabs, modifying/replacing the data display items, modifying the status display or accessing the config items.
|
You can add javascript code that will contribute to the UI of the system. The WebUI provides a small API that allows you to "hook" into some functions to include your own parts of the UI. This includes adding new tabs, modifying/replacing the data display items, modifying the status display or accessing the config items.
|
||||||
For the API refer to [../../web/index.js](../../web/index.js#L2001).
|
For the API refer to [../../web/index.js](../../web/index.js#L2001).
|
||||||
To start interacting just register for some events like api.EVENTS.init. You can check the capabilities you have defined to see if your task is active.
|
To start interacting just register for some events like api.EVENTS.init. You can check the capabilities you have defined to see if your task is active.
|
||||||
|
@ -46,10 +48,14 @@ Files
|
||||||
tools/testServer.py nnn http://x.x.x.x/api
|
tools/testServer.py nnn http://x.x.x.x/api
|
||||||
```
|
```
|
||||||
with nnn being the local port and x.x.x.x the address of a running system. Open `http://localhost:nnn` in your browser.<br>
|
with nnn being the local port and x.x.x.x the address of a running system. Open `http://localhost:nnn` in your browser.<br>
|
||||||
After a change just start the compilation and reload the page.
|
After a change just start the compilation and reload the page.<br>
|
||||||
|
|
||||||
|
Starting from Version 20250305 you should normally not use this file name any more as those js code would be added for all build environments. Instead define a parameter _custom_js_ in your [platformio.ini](platformio.ini) for the environments you would like to add the js code for. This parameter accepts a list of file names (relative to the project root, separated by ,). This will also allow you to skip the check for capabilities in your code.
|
||||||
|
|
||||||
* [index.css](index.css)<br>
|
* [index.css](index.css)<br>
|
||||||
You can add own css to influence the styling of the display.
|
You can add own css to influence the styling of the display.<br>
|
||||||
|
|
||||||
|
Starting from Version 20250305 you should normally not use this file name any more as those styles would be added for all build environments. Instead define a parameter _custom_css_ in your [platformio.ini](platformio.ini) for the environments you would like to add some styles for. This parameter accepts a list of file names (relative to the project root, separated by , or as multi line entry)
|
||||||
|
|
||||||
|
|
||||||
Interfaces
|
Interfaces
|
||||||
|
|
|
@ -10,5 +10,9 @@ lib_deps =
|
||||||
build_flags=
|
build_flags=
|
||||||
-D BOARD_TEST
|
-D BOARD_TEST
|
||||||
${env.build_flags}
|
${env.build_flags}
|
||||||
|
custom_config=
|
||||||
|
lib/exampletask/exampleConfig.json
|
||||||
|
custom_js=lib/exampletask/example.js
|
||||||
|
custom_css=lib/exampletask/example.css
|
||||||
upload_port = /dev/esp32
|
upload_port = /dev/esp32
|
||||||
upload_protocol = esptool
|
upload_protocol = esptool
|
|
@ -351,8 +351,8 @@ private:
|
||||||
rmb.vmg
|
rmb.vmg
|
||||||
);
|
);
|
||||||
send(n2kMsg,msg.sourceId);
|
send(n2kMsg,msg.sourceId);
|
||||||
SetN2kPGN129285(n2kMsg,sourceId,1,1,true,true,"default");
|
SetN2kRouteWPInfo(n2kMsg,sourceId,1,1,N2kdir_forward,"default");
|
||||||
AppendN2kPGN129285(n2kMsg,destinationId,rmb.destID,rmb.latitude,rmb.longitude);
|
AppendN2kRouteWPInfo(n2kMsg,destinationId,rmb.destID,rmb.latitude,rmb.longitude);
|
||||||
send(n2kMsg,msg.sourceId);
|
send(n2kMsg,msg.sourceId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,7 +112,7 @@ class SSISensor : public SensorTemplate<BUSTYPE,SensorBase::SPI>{
|
||||||
.flags = SPI_TRANS_USE_RXDATA,
|
.flags = SPI_TRANS_USE_RXDATA,
|
||||||
.cmd = 0,
|
.cmd = 0,
|
||||||
.addr = 0,
|
.addr = 0,
|
||||||
.length = bits+1,
|
.length = (size_t)bits+1,
|
||||||
.rxlength = 0};
|
.rxlength = 0};
|
||||||
esp_err_t ret = spi_device_queue_trans(device->device(), &ta, portMAX_DELAY);
|
esp_err_t ret = spi_device_queue_trans(device->device(), &ta, portMAX_DELAY);
|
||||||
if (ret != ESP_OK) return ret;
|
if (ret != ESP_OK) return ret;
|
||||||
|
|
|
@ -917,7 +917,7 @@ void setup() {
|
||||||
logger.flush();
|
logger.flush();
|
||||||
NMEA2000.SetMode(tNMEA2000::N2km_ListenAndNode, NodeAddress);
|
NMEA2000.SetMode(tNMEA2000::N2km_ListenAndNode, NodeAddress);
|
||||||
NMEA2000.SetForwardOwnMessages(false);
|
NMEA2000.SetForwardOwnMessages(false);
|
||||||
NMEA2000.SetHeartbeatInterval(NMEA2000_HEARTBEAT_INTERVAL);
|
NMEA2000.SetHeartbeatIntervalAndOffset(NMEA2000_HEARTBEAT_INTERVAL);
|
||||||
if (sendOutN2k){
|
if (sendOutN2k){
|
||||||
// Set the information for other bus devices, which messages we support
|
// Set the information for other bus devices, which messages we support
|
||||||
unsigned long *pgns=toN2KConverter->handledPgns();
|
unsigned long *pgns=toN2KConverter->handledPgns();
|
||||||
|
|
Loading…
Reference in New Issue