diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1fe6389e4..846e61639 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 8054398d4..b5e7b1427 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 9876278f3..f0ab9d22c 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 37be387fe..1cbb6ffd4 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_3_berry_webserver.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webserver.ino
index f37be12b5..7df813e3f 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 c46606e47..f39a45271 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,8 +307,13 @@ 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;
+ berry.autoexec_done = false;
+ berry.repl_active = false;
+ berry.rules_busy = false;
+ berry.timeout = 0;
}
int32_t ret_code1, ret_code2;
@@ -367,6 +372,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
*
@@ -653,14 +669,16 @@ const char HTTP_BERRY_FORM_CMND[] PROGMEM =
"Check the documentation."
""
""
- // ""
- // "
"
"