diff --git a/lib/libesp32/Berry-0.1.10/src/port/be_port.cpp b/lib/libesp32/Berry-0.1.10/src/port/be_port.cpp index 003a1042ad42..cf67833c5bf2 100644 --- a/lib/libesp32/Berry-0.1.10/src/port/be_port.cpp +++ b/lib/libesp32/Berry-0.1.10/src/port/be_port.cpp @@ -64,15 +64,15 @@ BERRY_API void be_writebuffer(const char *buffer, size_t length) uint32_t idx = 0; while (idx < length) { int32_t cr_pos = -1; - // find next occurence of '\n' + // find next occurence of '\n' or '\r' for (uint32_t i = idx; i < length; i++) { - if (buffer[i] == '\n') { + if ((pgm_read_byte(&buffer[i]) == '\n') || (pgm_read_byte(&buffer[i]) == '\r')) { cr_pos = i; break; } } uint32_t chars_to_append = (cr_pos >= 0) ? cr_pos - idx : length - idx; // note cr_pos < length - snprintf(log_berry_buffer, sizeof(log_berry_buffer), "%s%.*s", log_berry_buffer, chars_to_append, buffer); // append at most `length` chars + snprintf(log_berry_buffer, sizeof(log_berry_buffer), "%s%.*s", log_berry_buffer, chars_to_append, &buffer[idx]); // append at most `length` chars if (cr_pos >= 0) { // flush berry_log(log_berry_buffer); diff --git a/tasmota/berry/tasmota.be b/tasmota/berry/tasmota.be index bff83c022e3a..8129b0a6ef63 100644 --- a/tasmota/berry/tasmota.be +++ b/tasmota/berry/tasmota.be @@ -1,8 +1,15 @@ import json import string tasmota = module("tasmota") def log(m) print(m) end +def save() end ####### +import string +import json +import gc +import tasmota +#// import alias +import tasmota as t def charsinstring(s,c) for i:0..size(s)-1 @@ -111,6 +118,15 @@ tasmota.delay = def(ms) end end +def load(f) + try + if f[0] != '/' f = '/' + f end + compile(f,'file')() + except .. as e + log(string.format("BRY: could not load file '%s' - %s",f,e)) + end +end + #- Test ################################################################# diff --git a/tasmota/xdrv_52_berry.ino b/tasmota/xdrv_52_berry.ino index b8f10eb25a4d..d6e4fa015d6d 100644 --- a/tasmota/xdrv_52_berry.ino +++ b/tasmota/xdrv_52_berry.ino @@ -184,6 +184,21 @@ extern "C" { optimistic_yield(10); be_return(vm); } + + // Berry: `save(file:string, f:closure) -> bool` + int32_t l_save(struct bvm *vm); + int32_t l_save(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top ==2 && be_isstring(vm, 1) && be_isclosure(vm, 2)) { // only 1 argument of type string accepted + const char *fname = be_tostring(vm, 1); + int32_t ret = be_savecode(vm, fname); + be_pushint(vm, ret); + be_return(vm); // Return + } + be_return_nil(vm); // Return nil when something goes wrong + } + + } // called as a replacement to Berry `print()` @@ -429,6 +444,31 @@ const char berry_prog[] PROGMEM = "end " "end " + // simple wrapper to load a file + // prefixes '/' if needed, and simpler to use than `compile()` + "def load(f) " + "try " + // check that the file ends with '.be' of '.bec' + "var fl = string.split(f,'.') " + "if (size(fl) <= 1 || (fl[-1] != 'be' && fl[-1] != 'bec')) " + "raise \"file extension is not '.be' or '.bec'\" " + "end " + "var native = f[size(f)-1] == 'c' " + // add prefix if needed + "if f[0] != '/' f = '/' + f end " + // load - works the same for .be and .bec + "var c = compile(f,'file') " + // save the compiled bytecode + "if !native " + "save(f+'c', c) " + "end " + // call the compiled code + "c() " + "except .. as e " + "log(string.format(\"BRY: could not load file '%s' - %s\",f,e)) " + "end " + "end " + // try to load "/autoexec.be" // "try compile('/autoexec.be','file')() except .. log('BRY: no /autoexec.bat file') end " @@ -455,6 +495,7 @@ void BrReset(void) { // Register functions be_regfunc(berry.vm, PSTR("log"), l_logInfo); + be_regfunc(berry.vm, PSTR("save"), l_save); AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry function registered, RAM consumed=%u (Heap=%u)"), heap_before - ESP.getFreeHeap(), ESP.getFreeHeap());