diff --git a/CHANGELOG.md b/CHANGELOG.md index 045a876d491e..3e09349d43e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ All notable changes to this project will be documented in this file. - Berry button to dynamically load GPIO Viewer with Berry backend (#20424) - Berry `debug_panel.tapp` to display real-time heap and wifi rssi - Berry `webserver.header` to read browser sent headers +- Berry provide lightweight options for `tasmota.wifi/eth/memory/rtc` ### Breaking Changed diff --git a/lib/libesp32/berry_mapping/src/be_mapping_utils.c b/lib/libesp32/berry_mapping/src/be_mapping_utils.c index 51f7388baf7c..18fad80af533 100644 --- a/lib/libesp32/berry_mapping/src/be_mapping_utils.c +++ b/lib/libesp32/berry_mapping/src/be_mapping_utils.c @@ -8,61 +8,104 @@ /* Insert an nil to a key */ void be_map_insert_nil(bvm *vm, const char *key) { - be_pushstring(vm, key); - be_pushnil(vm); - be_data_insert(vm, -3); - be_pop(vm, 2); + if (be_ismap(vm, -1)) { + be_pushstring(vm, key); + be_pushnil(vm); + be_data_insert(vm, -3); + be_pop(vm, 2); + } } /* Insert an int to a key */ +// On stack is either: +// Case 1; (-2) map instance, (-1) map +// Case 2; (-2) nil, (-1) string -> if key matches then update (-2) void be_map_insert_int(bvm *vm, const char *key, bint value) { - be_pushstring(vm, key); - be_pushint(vm, value); - be_data_insert(vm, -3); - be_pop(vm, 2); + if (be_ismap(vm, -1)) { + be_pushstring(vm, key); + be_pushint(vm, value); + be_data_insert(vm, -3); + be_pop(vm, 2); + } else if (be_isstring(vm, -1)) { + const char * needle = be_tostring(vm, -1); + if (strcmp(key, needle) == 0) { + be_pushint(vm, value); + be_moveto(vm, -1, -3); + be_pop(vm, 1); + } + } } /* Insert an bbool to a key */ void be_map_insert_bool(bvm *vm, const char *key, bbool value) { - be_pushstring(vm, key); - be_pushbool(vm, value); - be_data_insert(vm, -3); - be_pop(vm, 2); + if (be_ismap(vm, -1)) { + be_pushstring(vm, key); + be_pushbool(vm, value); + be_data_insert(vm, -3); + be_pop(vm, 2); + } else if (be_isstring(vm, -1)) { + const char * needle = be_tostring(vm, -1); + if (strcmp(key, needle) == 0) { + be_pushbool(vm, value); + be_moveto(vm, -1, -3); + be_pop(vm, 1); + } + } } /* Insert an real to a key */ /* if value == NAN, ignore */ void be_map_insert_real(bvm *vm, const char *key, breal value) { - if (!isnan(value)) { - be_pushstring(vm, key); - be_pushreal(vm, value); - be_data_insert(vm, -3); - be_pop(vm, 2); + if (be_ismap(vm, -1)) { + if (!isnan(value)) { + be_pushstring(vm, key); + be_pushreal(vm, value); + be_data_insert(vm, -3); + be_pop(vm, 2); + } + } else if (be_isstring(vm, -1)) { + const char * needle = be_tostring(vm, -1); + if (strcmp(key, needle) == 0) { + be_pushreal(vm, value); + be_moveto(vm, -1, -3); + be_pop(vm, 1); + } } } /* Insert an C string to a key */ void be_map_insert_str(bvm *vm, const char *key, const char *value) { - be_pushstring(vm, key); - be_pushstring(vm, value); - be_data_insert(vm, -3); - be_pop(vm, 2); + if (be_ismap(vm, -1)) { + be_pushstring(vm, key); + be_pushstring(vm, value); + be_data_insert(vm, -3); + be_pop(vm, 2); + } else if (be_isstring(vm, -1)) { + const char * needle = be_tostring(vm, -1); + if (strcmp(key, needle) == 0) { + be_pushstring(vm, value); + be_moveto(vm, -1, -3); + be_pop(vm, 1); + } + } } /* Insert list of bytes as individual integers to a key */ void be_map_insert_list_uint8(bvm *vm, const char *key, const uint8_t *value, size_t size) { - be_pushstring(vm, key); + if (be_ismap(vm, -1)) { + be_pushstring(vm, key); - be_newobject(vm, "list"); - for (uint32_t i=0; i < size; i++) { - be_pushint(vm, value[i]); - be_data_push(vm, -2); - be_pop(vm, 1); - } - be_pop(vm, 1); // now list is on top + be_newobject(vm, "list"); + for (uint32_t i=0; i < size; i++) { + be_pushint(vm, value[i]); + be_data_push(vm, -2); + be_pop(vm, 1); + } + be_pop(vm, 1); // now list is on top - be_data_insert(vm, -3); // insert into map, key/value - be_pop(vm, 2); // pop both key and value + be_data_insert(vm, -3); // insert into map, key/value + be_pop(vm, 2); // pop both key and value + } } /*********************************************************************************************\ diff --git a/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c b/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c index 5a6be028166f..528a3b8b880e 100644 --- a/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c @@ -111,14 +111,14 @@ class be_class_tasmota (scope: global, name: Tasmota) { get_option, func(l_getoption) millis, func(l_millis) time_reached, func(l_timereached) - rtc, func(l_rtc) + rtc, static_func(l_rtc) rtc_utc, func(l_rtc_utc) time_dump, func(l_time_dump) strftime, func(l_strftime) strptime, func(l_strptime) - memory, func(l_memory) - wifi, func(l_wifi) - eth, func(l_eth) + memory, static_func(l_memory) + wifi, static_func(l_wifi) + eth, static_func(l_eth) hostname, func(l_hostname) yield, func(l_yield) delay, func(l_delay) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino index c4df2e318b9b..f82bb0fb9007 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino @@ -171,16 +171,20 @@ extern "C" { int32_t l_rtc(struct bvm *vm); int32_t l_rtc(struct bvm *vm) { int32_t top = be_top(vm); // Get the number of arguments - if (top == 1) { // no argument (instance only) + if (top >= 1 && be_isstring(vm, 1)) { // argument is name + be_pushnil(vm); + be_pushvalue(vm, 1); + // (-2) nil, (-1) string -> if key matches then update (-2) + } else { be_newobject(vm, "map"); - be_map_insert_int(vm, "utc", Rtc.utc_time); - be_map_insert_int(vm, "local", Rtc.local_time); - be_map_insert_int(vm, "restart", Rtc.restart_time); - be_map_insert_int(vm, "timezone", Rtc.time_timezone); - be_pop(vm, 1); - be_return(vm); + // (-2) map instance, (-1) map } - be_raise(vm, kTypeError, nullptr); + be_map_insert_int(vm, "utc", Rtc.utc_time); + be_map_insert_int(vm, "local", Rtc.local_time); + be_map_insert_int(vm, "restart", Rtc.restart_time); + be_map_insert_int(vm, "timezone", Rtc.time_timezone); + be_pop(vm, 1); + be_return(vm); } // Berry: tasmota.rtc_utc() -> int @@ -196,28 +200,32 @@ extern "C" { int32_t l_memory(struct bvm *vm); int32_t l_memory(struct bvm *vm) { int32_t top = be_top(vm); // Get the number of arguments - if (top == 1) { // no argument (instance only) + if (top >= 1 && be_isstring(vm, 1)) { // argument is name + be_pushnil(vm); + be_pushvalue(vm, 1); + // (-2) nil, (-1) string -> if key matches then update (-2) + } else { be_newobject(vm, "map"); - be_map_insert_int(vm, "flash", ESP_getFlashChipMagicSize() / 1024); - be_map_insert_int(vm, "flash_real", ESP.getFlashChipSize() / 1024); - be_map_insert_int(vm, "program", ESP_getSketchSize() / 1024); - be_map_insert_int(vm, "program_free", ESP_getFreeSketchSpace() / 1024); - be_map_insert_int(vm, "heap_free", ESP_getFreeHeap() / 1024); - be_map_insert_int(vm, "frag", ESP_getHeapFragmentation()); - // give info about stack size - be_map_insert_int(vm, "stack_size", SET_ESP32_STACK_SIZE / 1024); - be_map_insert_real(vm, "stack_low", ((float)uxTaskGetStackHighWaterMark(nullptr)) / 1024); - if (UsePSRAM()) { - be_map_insert_int(vm, "psram", ESP.getPsramSize() / 1024); - be_map_insert_int(vm, "psram_free", ESP.getFreePsram() / 1024); - } - // IRAM information - int32_t iram_free = (int32_t)heap_caps_get_free_size(MALLOC_CAP_32BIT) - (int32_t)heap_caps_get_free_size(MALLOC_CAP_8BIT); - be_map_insert_int(vm, "iram_free", iram_free / 1024); - be_pop(vm, 1); - be_return(vm); + // (-2) map instance, (-1) map } - be_raise(vm, kTypeError, nullptr); + be_map_insert_int(vm, "flash", ESP_getFlashChipMagicSize() / 1024); + be_map_insert_int(vm, "flash_real", ESP.getFlashChipSize() / 1024); + be_map_insert_int(vm, "program", ESP_getSketchSize() / 1024); + be_map_insert_int(vm, "program_free", ESP_getFreeSketchSpace() / 1024); + be_map_insert_int(vm, "heap_free", ESP_getFreeHeap() / 1024); + be_map_insert_int(vm, "frag", ESP_getHeapFragmentation()); + // give info about stack size + be_map_insert_int(vm, "stack_size", SET_ESP32_STACK_SIZE / 1024); + be_map_insert_real(vm, "stack_low", ((float)uxTaskGetStackHighWaterMark(nullptr)) / 1024); + if (UsePSRAM()) { + be_map_insert_int(vm, "psram", ESP.getPsramSize() / 1024); + be_map_insert_int(vm, "psram_free", ESP.getFreePsram() / 1024); + } + // IRAM information + int32_t iram_free = (int32_t)heap_caps_get_free_size(MALLOC_CAP_32BIT) - (int32_t)heap_caps_get_free_size(MALLOC_CAP_8BIT); + be_map_insert_int(vm, "iram_free", iram_free / 1024); + be_pop(vm, 1); + be_return(vm); } // Berry: tasmota.wifi() -> map @@ -225,38 +233,42 @@ extern "C" { int32_t l_wifi(struct bvm *vm); int32_t l_wifi(struct bvm *vm) { int32_t top = be_top(vm); // Get the number of arguments - if (top == 1) { // no argument (instance only) + if (top >= 1 && be_isstring(vm, 1)) { // argument is name + be_pushnil(vm); + be_pushvalue(vm, 1); + // (-2) nil, (-1) string -> if key matches then update (-2) + } else { be_newobject(vm, "map"); - be_map_insert_str(vm, "mac", WiFi.macAddress().c_str()); - be_map_insert_bool(vm, "up", WifiHasIP()); - if (Settings->flag4.network_wifi) { - int32_t rssi = WiFi.RSSI(); - bool show_rssi = false; + // (-2) map instance, (-1) map + } + be_map_insert_str(vm, "mac", WiFi.macAddress().c_str()); + be_map_insert_bool(vm, "up", WifiHasIP()); + if (Settings->flag4.network_wifi) { + int32_t rssi = WiFi.RSSI(); + bool show_rssi = false; #ifdef USE_IPV6 - String ipv6_addr = WifiGetIPv6Str(); - if (ipv6_addr != "") { - be_map_insert_str(vm, "ip6", ipv6_addr.c_str()); - show_rssi = true; - } - ipv6_addr = WifiGetIPv6LinkLocalStr(); - if (ipv6_addr != "") { - be_map_insert_str(vm, "ip6local", ipv6_addr.c_str()); - show_rssi = true; - } + String ipv6_addr = WifiGetIPv6Str(); + if (ipv6_addr != "") { + be_map_insert_str(vm, "ip6", ipv6_addr.c_str()); + show_rssi = true; + } + ipv6_addr = WifiGetIPv6LinkLocalStr(); + if (ipv6_addr != "") { + be_map_insert_str(vm, "ip6local", ipv6_addr.c_str()); + show_rssi = true; + } #endif // USE_IPV6 - if (static_cast(WiFi.localIP()) != 0) { - be_map_insert_str(vm, "ip", IPAddress((uint32_t)WiFi.localIP()).toString().c_str()); // quick fix for IPAddress bug - show_rssi = true; - } - if (show_rssi) { - be_map_insert_int(vm, "rssi", rssi); - be_map_insert_int(vm, "quality", WifiGetRssiAsQuality(rssi)); - } + if (static_cast(WiFi.localIP()) != 0) { + be_map_insert_str(vm, "ip", IPAddress((uint32_t)WiFi.localIP()).toString().c_str()); // quick fix for IPAddress bug + show_rssi = true; + } + if (show_rssi) { + be_map_insert_int(vm, "rssi", rssi); + be_map_insert_int(vm, "quality", WifiGetRssiAsQuality(rssi)); } - be_pop(vm, 1); - be_return(vm); } - be_raise(vm, kTypeError, nullptr); + be_pop(vm, 1); + be_return(vm); } // Berry: tasmota.eth() -> map @@ -264,34 +276,38 @@ extern "C" { int32_t l_eth(struct bvm *vm); int32_t l_eth(struct bvm *vm) { int32_t top = be_top(vm); // Get the number of arguments - if (top == 1) { // no argument (instance only) + if (top >= 1 && be_isstring(vm, 1)) { // argument is name + be_pushnil(vm); + be_pushvalue(vm, 1); + // (-2) nil, (-1) string -> if key matches then update (-2) + } else { be_newobject(vm, "map"); + // (-2) map instance, (-1) map + } #ifdef USE_ETHERNET - be_map_insert_bool(vm, "up", EthernetHasIP()); - String eth_mac = EthernetMacAddress().c_str(); - if (eth_mac != "00:00:00:00:00:00") { - be_map_insert_str(vm, "mac", eth_mac.c_str()); - } - if (static_cast(EthernetLocalIP()) != 0) { - be_map_insert_str(vm, "ip", IPAddress((uint32_t)EthernetLocalIP()).toString().c_str()); // quick fix for IPAddress bug - } + be_map_insert_bool(vm, "up", EthernetHasIP()); + String eth_mac = EthernetMacAddress().c_str(); + if (eth_mac != "00:00:00:00:00:00") { + be_map_insert_str(vm, "mac", eth_mac.c_str()); + } + if (static_cast(EthernetLocalIP()) != 0) { + be_map_insert_str(vm, "ip", IPAddress((uint32_t)EthernetLocalIP()).toString().c_str()); // quick fix for IPAddress bug + } #ifdef USE_IPV6 - String ipv6_addr = EthernetGetIPv6Str(); - if (ipv6_addr != "") { - be_map_insert_str(vm, "ip6", ipv6_addr.c_str()); - } - ipv6_addr = EthernetGetIPv6LinkLocalStr(); - if (ipv6_addr != "") { - be_map_insert_str(vm, "ip6local", ipv6_addr.c_str()); - } + String ipv6_addr = EthernetGetIPv6Str(); + if (ipv6_addr != "") { + be_map_insert_str(vm, "ip6", ipv6_addr.c_str()); + } + ipv6_addr = EthernetGetIPv6LinkLocalStr(); + if (ipv6_addr != "") { + be_map_insert_str(vm, "ip6local", ipv6_addr.c_str()); + } #endif // USE_IPV6 #else // USE_ETHERNET - be_map_insert_bool(vm, "up", bfalse); + be_map_insert_bool(vm, "up", bfalse); #endif // USE_ETHERNET - be_pop(vm, 1); - be_return(vm); - } - be_raise(vm, kTypeError, nullptr); + be_pop(vm, 1); + be_return(vm); } // Berry: tasmota.hostname() -> string