Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Command BrRestart to restart the Berry VM (experimental) #19003

Merged
merged 2 commits into from
Jul 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
21 changes: 21 additions & 0 deletions lib/libesp32/berry_mapping/src/be_cb_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions lib/libesp32/berry_mapping/src/be_mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions tasmota/include/i18n.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webserver.ino
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
38 changes: 31 additions & 7 deletions tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
*
Expand Down Expand Up @@ -653,14 +669,16 @@ const char HTTP_BERRY_FORM_CMND[] PROGMEM =
"Check the <a href='https://tasmota.github.io/docs/Berry/' target='_blank'>documentation</a>."
"</div>"
"</div>"
// "<textarea readonly id='t1' cols='340' wrap='off'></textarea>"
// "<br><br>"
"<form method='get' id='fo' onsubmit='return l(1);'>"
"<textarea id='c1' class='br0 bri' rows='4' cols='340' wrap='soft' autofocus required></textarea>"
// "<input id='c1' class='bri' type='text' rows='5' placeholder='" D_ENTER_COMMAND "' autofocus><br>"
// "<input type='submit' value=\"Run code (or press 'Enter' twice)\">"
"<button type='submit'>Run code (or press 'Enter' twice)</button>"
"</form>";
"</form>"
#ifdef USE_BERRY_DEBUG
"<p><form method='post' >"
"<button type='submit' name='rst' class='bred' onclick=\"if(confirm('Confirm removing endpoint')){clearTimeout(lt);return true;}else{return false;}\">Restart Berry VM (for devs only)</button>"
"</form></p>"
#endif // USE_BERRY_DEBUG
;

const char HTTP_BTN_BERRY_CONSOLE[] PROGMEM =
"<p><form action='bc' method='get'><button>Berry Scripting console</button></form></p>";
Expand Down Expand Up @@ -706,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));
Expand Down