HASPmota autostart when pages.jsonl exists (#23181)

This commit is contained in:
s-hadinger 2025-03-22 23:23:57 +01:00 committed by GitHub
parent caac9f1257
commit f331a64ac3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 1373 additions and 1329 deletions

View File

@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file.
- Matter prepare for ICD cluster (#23158)
- Berry `re.dump()` (#23162)
- Telnet server using command `Telnet <0|1|port>[,<IP filter>]`
- HASPmota autostart when `pages.jsonl` exists
### Breaking Changed
- Berry remove `Leds.create_matrix` from the standard library waiting for reimplementation (#23114)

View File

@ -2784,6 +2784,7 @@ end
# main class controller, meant to be a singleton and the only externally used class
class HASPmota
var started # (bool) is HASPmota already started?
var dark # (bool) use dark theme?
var hres, vres # (int) resolution
var scr # (lv_obj) default LVGL screen
@ -2865,6 +2866,8 @@ class HASPmota
# implicitly loads `pages.jsonl` from file-system // TODO allow to specicify file name
#====================================================================
def start(dark, templ_name)
if (self.started) return end
import path
if templ_name == nil templ_name = self.def_templ_name end
if !path.exists(templ_name)
@ -2896,6 +2899,7 @@ class HASPmota
self.lvh_pages = {}
# load from JSONL
self._load(templ_name)
self.started = true
end
#################################################################################

View File

@ -23,9 +23,11 @@
/*********************************************************************************************\
* Handlers for Berry calls and async
*
* This is called right after Berry is initialized
* and before the main loop is started.
\*********************************************************************************************/
const char berry_prog[] =
const char be_berry_init_code[] =
"import global "
#ifdef USE_BERRY_PYTHON_COMPAT
@ -97,6 +99,26 @@ const char berry_prog[] =
"import matter "
"global.matter_device = matter.Device() "
#endif
;
;
/*********************************************************************************************\
* This is called after `autoexec.be` is executed
\*********************************************************************************************/
const char be_post_autoxec_code[] =
"" // fallback to empty string
#if defined(USE_LVGL) && defined(USE_LVGL_HASPMOTA)
// HASPmota init
"do "
"import path "
"import display "
"if display.started() && path.exists('/pages.jsonl') "
"import haspmota "
"global.haspmota = haspmota " // make sure the global is also defined
"haspmota.start() "
"end "
"end "
#endif // USE_LVGL_HASPMOTA
;
#endif // USE_BERRY

View File

@ -176,6 +176,29 @@ int32_t callBerryEventDispatcher(const char *type, const char *cmd, int32_t idx,
return ret;
}
// execute an arbitrary string containing Berry code
int32_t callBerryString(bvm *vm, const char *code_source);
int32_t callBerryString(bvm *vm, const char *code_source) {
// do nothing if NULL or empty string
if (code_source == nullptr || code_source[0] == '\0') { return 0; }
int32_t ret_code;
ret_code = be_loadstring(vm, code_source);
if (ret_code == 0) {
ret_code = be_pcall(berry.vm, 0);
if (ret_code == 0) {
if (be_top(vm) > 1) {
be_error_pop_all(berry.vm); // clear Berry stack
} else {
be_pop(berry.vm, 1);
}
return 0; // no error
}
}
be_error_pop_all(vm); // clear Berry stack
return ret_code;
}
// simple wrapper to call `tasmota.<method_name>()`
static void callBerryTasmotaFunc(const char * method_name) {
bvm *vm = berry.vm;
@ -375,23 +398,9 @@ void BerryInit(void) {
// Set the GC threshold to 3584 bytes to avoid the first useless GC
berry.vm->gc.threshold = 3584;
ret_code1 = be_loadstring(berry.vm, berry_prog);
if (ret_code1 != 0) {
be_error_pop_all(berry.vm); // clear Berry stack
if (callBerryString(berry.vm, be_berry_init_code) != 0) {
break;
}
// AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry code loaded, RAM used=%u"), be_gc_memcount(berry.vm));
ret_code2 = be_pcall(berry.vm, 0);
if (ret_code2 != 0) {
be_error_pop_all(berry.vm); // clear Berry stack
break;
}
// AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry code ran, RAM used=%u"), be_gc_memcount(berry.vm));
if (be_top(berry.vm) > 1) {
be_error_pop_all(berry.vm); // clear Berry stack
} else {
be_pop(berry.vm, 1);
}
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_BERRY "Berry initialized, RAM used %u bytes"), callBerryGC());
berry_init_ok = true;
@ -402,7 +411,7 @@ void BerryInit(void) {
berry.leds_panel_loaded = !PinUsed(GPIO_WS2812);
#endif // USE_BERRY_LEDS_PANEL
// we generate a synthetic event `autoexec`
// we generate a synthetic event `preinit`
callBerryEventDispatcher(PSTR("preinit"), nullptr, 0, nullptr);
// Run pre-init
@ -913,6 +922,7 @@ bool Xdrv52(uint32_t function)
callBerryEventDispatcher(PSTR("autoexec"), nullptr, 0, nullptr);
BrLoad("autoexec.be"); // run autoexec.be at first tick, so we know all modules are initialized
callBerryString(berry.vm, be_post_autoxec_code);
berry.autoexec_done = true;
#ifdef USE_WEBSERVER