From 81f72553f3a2869b8cf9e00ec45bc243a09f6171 Mon Sep 17 00:00:00 2001
From: Stephan Hadinger
Date: Thu, 29 Jun 2023 22:17:17 +0200
Subject: [PATCH 1/2] Command ``BrRestart`` to restart the Berry VM
(experimental)
---
CHANGELOG.md | 1 +
lib/libesp32/berry_mapping/src/be_cb_module.c | 21 +++++++++++++++++++
lib/libesp32/berry_mapping/src/be_mapping.h | 2 ++
tasmota/include/i18n.h | 1 +
.../tasmota_xdrv_driver/xdrv_52_9_berry.ino | 16 ++++++++++++--
5 files changed, 39 insertions(+), 2 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1fe6389e4812..846e61639e07 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file.
- Command ``Delay -1`` to wait until next second (#18984)
- Matter add option to disable bridge mode (#18992)
- Support for SGP41 TVOC/NOx Sensor (#18880)
+- Command ``BrRestart`` to restart the Berry VM (experimental)
### Breaking Changed
- Berry `bool( [] )` and `bool( {} )` now evaluate as `false` (#18986)
diff --git a/lib/libesp32/berry_mapping/src/be_cb_module.c b/lib/libesp32/berry_mapping/src/be_cb_module.c
index 8054398d4956..b5e7b1427605 100644
--- a/lib/libesp32/berry_mapping/src/be_cb_module.c
+++ b/lib/libesp32/berry_mapping/src/be_cb_module.c
@@ -250,6 +250,7 @@ static int32_t call_berry_cb(int32_t num, int32_t v0, int32_t v1, int32_t v2, in
bvm * vm = be_cb_hooks[num].vm;
bvalue *f = &be_cb_hooks[num].f;
+ if (vm == NULL) { return 0; } // function is not alive anymore, don't crash
// push function (don't check type)
bvalue *top = be_incrtop(vm);
@@ -271,6 +272,26 @@ static int32_t call_berry_cb(int32_t num, int32_t v0, int32_t v1, int32_t v2, in
return ret;
}
+/*********************************************************************************************\
+ * `be_cb_deinit`:
+ * Clean any callback for this VM, they shouldn't call the registerd function anymore
+\*********************************************************************************************/
+void be_cb_deinit(bvm *vm) {
+ // remove all cb for this vm
+ for (int32_t slot = 0; slot < BE_MAX_CB; slot++) {
+ if (be_cb_hooks[slot].vm == vm) {
+ be_cb_hooks[slot].vm = NULL;
+ be_cb_hooks[slot].f.type == BE_NIL;
+ }
+ }
+ // remove the vm gen_cb for this vm
+ for (be_callback_handler_list_t **elt_ptr = &be_callback_handler_list_head; *elt_ptr != NULL; elt_ptr = &(*elt_ptr)->next) {
+ if (((*elt_ptr)->next != NULL) && ((*elt_ptr)->next->vm == vm)) {
+ (*elt_ptr)->next = (*elt_ptr)->next->next;
+ }
+ }
+}
+
/* @const_object_info_begin
module cb (scope: global) {
gen_cb, func(be_cb_gen_cb)
diff --git a/lib/libesp32/berry_mapping/src/be_mapping.h b/lib/libesp32/berry_mapping/src/be_mapping.h
index 9876278f391f..f0ab9d22c56b 100644
--- a/lib/libesp32/berry_mapping/src/be_mapping.h
+++ b/lib/libesp32/berry_mapping/src/be_mapping.h
@@ -109,6 +109,8 @@ extern int be_check_arg_type(bvm *vm, int arg_start, int argc, const char * arg_
extern int be_call_c_func(bvm *vm, const void * func, const char * return_type, const char * arg_type);
extern int be_call_ctype_func(bvm *vm, const void *definition); /* handler for Berry vm */
+extern void be_cb_deinit(bvm *vm); /* remove all callbacks from the VM (just before shutdown of VM) */
+
#ifdef __cplusplus
}
#endif
diff --git a/tasmota/include/i18n.h b/tasmota/include/i18n.h
index 37be387fe629..1cbb6ffd4384 100644
--- a/tasmota/include/i18n.h
+++ b/tasmota/include/i18n.h
@@ -764,6 +764,7 @@
// Commands xdrv_52_berry.ino - Berry scripting language
#define D_PRFX_BR "Br"
#define D_CMND_BR_RUN ""
+#define D_CMND_BR_RESTART "Restart"
#define D_BR_NOT_STARTED "Berry not started"
// Commands xdrv_60_shift595.ino - 74x595 family shift register driver
diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino
index c46606e47224..b8cf7113146d 100644
--- a/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino
+++ b/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino
@@ -37,11 +37,11 @@ extern "C" {
}
const char kBrCommands[] PROGMEM = D_PRFX_BR "|" // prefix
- D_CMND_BR_RUN
+ D_CMND_BR_RUN "|" D_CMND_BR_RESTART
;
void (* const BerryCommand[])(void) PROGMEM = {
- CmndBrRun,
+ CmndBrRun, CmndBrRestart
};
int32_t callBerryEventDispatcher(const char *type, const char *cmd, int32_t idx, const char *payload, uint32_t data_len = 0);
@@ -307,6 +307,7 @@ void BrShowState(void) {
void BerryInit(void) {
// clean previous VM if any
if (berry.vm != nullptr) {
+ be_cb_deinit(berry.vm); // deregister any C callback for this VM
be_vm_delete(berry.vm);
berry.vm = nullptr;
}
@@ -367,6 +368,17 @@ void BerryInit(void) {
}
}
+/*********************************************************************************************\
+ * BrRestart - restart a fresh new Berry vm, unloading everything from previous VM
+\*********************************************************************************************/
+void CmndBrRestart(void) {
+ if (berry.vm == nullptr) {
+ ResponseCmndChar_P("Berry VM not started");
+ }
+ BerryInit();
+ ResponseCmndChar_P("Berry VM restarted");
+}
+
/*********************************************************************************************\
* Execute a script in Flash file-system
*
From 4a46eb1dfe370bf153aef4043a7a1be027d4ca77 Mon Sep 17 00:00:00 2001
From: Stephan Hadinger
Date: Sun, 2 Jul 2023 21:43:34 +0200
Subject: [PATCH 2/2] Add web button for Berry Restart
---
.../xdrv_52_3_berry_webserver.ino | 1 -
.../tasmota_xdrv_driver/xdrv_52_9_berry.ino | 22 ++++++++++++++-----
2 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webserver.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webserver.ino
index f37be12b5603..7df813e3f247 100644
--- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webserver.ino
+++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webserver.ino
@@ -138,7 +138,6 @@ extern "C" {
const char * uri = be_tostring(vm, 1);
Webserver->sendHeader("Location", uri, true);
Webserver->send(302, "text/plain", "");
- // Webserver->sendHeader(F("Location"), String(F("http://")) + Webserver->client().localIP().toString(), true);
be_return_nil(vm);
}
be_raise(vm, kTypeError, nullptr);
diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino
index b8cf7113146d..f39a45271536 100644
--- a/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino
+++ b/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino
@@ -310,6 +310,10 @@ void BerryInit(void) {
be_cb_deinit(berry.vm); // deregister any C callback for this VM
be_vm_delete(berry.vm);
berry.vm = nullptr;
+ berry.autoexec_done = false;
+ berry.repl_active = false;
+ berry.rules_busy = false;
+ berry.timeout = 0;
}
int32_t ret_code1, ret_code2;
@@ -665,14 +669,16 @@ const char HTTP_BERRY_FORM_CMND[] PROGMEM =
"Check the documentation."
""
""
- // ""
- // "
"
"";
+ ""
+#ifdef USE_BERRY_DEBUG
+ "
"
+#endif // USE_BERRY_DEBUG
+ ;
const char HTTP_BTN_BERRY_CONSOLE[] PROGMEM =
"";
@@ -718,6 +724,12 @@ void HandleBerryConsole(void)
return;
}
+ if (Webserver->hasArg(F("rst"))) { // restart VM
+ BerryInit();
+ Webserver->sendHeader("Location", "/bc", true);
+ Webserver->send(302, "text/plain", "");
+ }
+
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP "Berry " D_CONSOLE));
WSContentStart_P(PSTR("Berry " D_CONSOLE));