From a0ed3838408cd2a62889d478d2885b666f244359 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 27 Nov 2022 18:08:53 +0100 Subject: [PATCH 1/2] Berry add module `mdns` --- CHANGELOG.md | 1 + lib/libesp32/berry/default/be_modtab.c | 4 + lib/libesp32/berry/src/be_api.c | 25 ++++ lib/libesp32/berry/src/berry.h | 2 + .../berry_tasmota/src/be_mdns_module.cpp | 122 ++++++++++++++++++ .../berry_tasmota/src/be_tasmota_lib.c | 2 + .../xdrv_52_3_berry_tasmota.ino | 8 ++ 7 files changed, 164 insertions(+) create mode 100644 lib/libesp32/berry_tasmota/src/be_mdns_module.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 3928ddfb3..4dad9ab1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file. - Command ``SetOption35 0..255`` to skip number of received messages in Serial Bridge (default 0) (#17140) - Teleinfo TEMPO (BBR) contract (#17160) - Support for HLK-LD2410 24GHz smart wave motion sensor +- Berry add module ``mdns`` ### Breaking Changed diff --git a/lib/libesp32/berry/default/be_modtab.c b/lib/libesp32/berry/default/be_modtab.c index 5b018304e..62c38ab0c 100644 --- a/lib/libesp32/berry/default/be_modtab.c +++ b/lib/libesp32/berry/default/be_modtab.c @@ -50,6 +50,7 @@ be_extern_native_module(partition_core); be_extern_native_module(crc); be_extern_native_module(crypto); be_extern_native_module(ULP); +be_extern_native_module(mdns); #ifdef USE_ZIGBEE be_extern_native_module(zigbee); #endif // USE_ZIGBEE @@ -173,6 +174,9 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = { &be_native_module(MI32), &be_native_module(BLE), #endif //USE_MI_ESP32 +#ifdef USE_DISCOVERY + &be_native_module(mdns), +#endif // USE_DISCOVERY #endif // TASMOTA /* user-defined modules register end */ NULL /* do not remove */ diff --git a/lib/libesp32/berry/src/be_api.c b/lib/libesp32/berry/src/be_api.c index 763187430..fb2b8e017 100644 --- a/lib/libesp32/berry/src/be_api.c +++ b/lib/libesp32/berry/src/be_api.c @@ -208,6 +208,31 @@ BERRY_API bbool be_isinstance(bvm *vm, int index) return var_isinstance(v); } +static bbool be_isinstanceofbuiltin(bvm *vm, int rel_index, const char *classname) +{ + bbool ret = bfalse; + int index = be_absindex(vm, rel_index); + if (be_isinstance(vm, index)) { + be_getbuiltin(vm, classname); + if (be_isderived(vm, index)) { + ret = btrue; + } + be_pop(vm, 1); + } + return ret; +} + +BERRY_API bbool be_ismapinstance(bvm *vm, int index) +{ + return be_isinstanceofbuiltin(vm, index, "map"); +} + +BERRY_API bbool be_islistinstance(bvm *vm, int index) +{ + return be_isinstanceofbuiltin(vm, index, "list"); +} + + BERRY_API bbool be_ismodule(bvm *vm, int index) { bvalue *v = be_indexof(vm, index); diff --git a/lib/libesp32/berry/src/berry.h b/lib/libesp32/berry/src/berry.h index 6d48e87f2..70ab0f87c 100644 --- a/lib/libesp32/berry/src/berry.h +++ b/lib/libesp32/berry/src/berry.h @@ -464,6 +464,8 @@ BERRY_API bbool be_isfunction(bvm *vm, int index); BERRY_API bbool be_isproto(bvm *vm, int index); BERRY_API bbool be_isclass(bvm *vm, int index); BERRY_API bbool be_isinstance(bvm *vm, int index); +BERRY_API bbool be_ismapinstance(bvm *vm, int index); +BERRY_API bbool be_islistinstance(bvm *vm, int index); BERRY_API bbool be_ismodule(bvm *vm, int index); BERRY_API bbool be_islist(bvm *vm, int index); BERRY_API bbool be_ismap(bvm *vm, int index); diff --git a/lib/libesp32/berry_tasmota/src/be_mdns_module.cpp b/lib/libesp32/berry_tasmota/src/be_mdns_module.cpp new file mode 100644 index 000000000..d0c534d2b --- /dev/null +++ b/lib/libesp32/berry_tasmota/src/be_mdns_module.cpp @@ -0,0 +1,122 @@ +/******************************************************************** + * Berry module `mdns` + * + * To use: `import mdns` + * + * MDNS support + *******************************************************************/ +#include "be_constobj.h" +#include "be_mapping.h" +#include "be_mem.h" + +#ifdef USE_DISCOVERY +#include "mdns.h" +#include + +// +// `mdsn.start([hostname:string]) -> nil` +extern char* NetworkHostname(void); +static void m_mdns_start(struct bvm *vm, const char* hostname) { + esp_err_t err = mdns_init(); + if (err != ESP_OK) { + be_raisef(vm, "internal_error", "could not initialize mdns err=%i", err); + } + if (hostname == NULL) { + hostname = NetworkHostname(); // revert to default hostname if none is specified + } + err = mdns_hostname_set(hostname); + if (err != ESP_OK) { + be_raisef(vm, "internal_error", "could not set hostname err=%i", err); + } +} +BE_FUNC_CTYPE_DECLARE(m_mdns_start, "", "@[s]") + +// +// `msdn.stop() -> nil`` +static void m_mdns_stop(void) { + mdns_free(); +} +BE_FUNC_CTYPE_DECLARE(m_mdns_stop, "", "") + + +static void m_mdns_set_hostname(struct bvm *vm, const char * hostname) { + esp_err_t err = mdns_hostname_set(hostname); + if (err != ESP_OK) { + be_raisef(vm, "internal_error", "mdns set_hostname err=%i", err); + } +} +BE_FUNC_CTYPE_DECLARE(m_mdns_set_hostname, "", "@s") + +// +// `mdns.add_service(service:string, proto:string, port:int, txt:map) -> nil` +// +// Test: +// import mdns mdns.add_service("_arduino","_tcp",1111, {"board":"tasmota", "tcp_check":"no", "ssh_upload":"no", "auth_upload":"no"}) +// +// import mdns mdns.add_service("_matterc","_udp", 5540, {"VP":"65521+32768", "SII":5000, "SAI":300, "T":1, "D":3840, "CM":1, "PH":33, "PI":""}) +static int32_t m_mdns_add_service(struct bvm *vm) { + int32_t top = be_top(vm); + if (top >= 3 && be_isstring(vm, 1) && be_isstring(vm, 2) && be_isint(vm, 3)) { + const char* service_type = be_tostring(vm, 1); + const char* proto = be_tostring(vm, 2); + uint16_t port = be_toint(vm, 3); + + mdns_txt_item_t * txt_items = NULL; + int32_t txt_num = 0; + if (top >= 4 && be_ismapinstance(vm, 4)) { + // parse txt map + be_getmember(vm, 4, ".p"); + int32_t map_len = be_data_size(vm, -1); + if (map_len > 0) { + uint32_t i= 0; + txt_items = (mdns_txt_item_t*) be_os_malloc(sizeof(mdns_txt_item_t) * map_len); + if (txt_items != NULL) { + be_pushiter(vm, -1); /* map iterator use 1 register */ + while (be_iter_hasnext(vm, -2) && i < map_len) { + be_iter_next(vm, -2); + const char* key = be_tostring(vm, -2); + const char* val = be_tostring(vm, -1); + size_t key_len = strlen(key)+1; + txt_items[i].key = (const char*)be_os_malloc(key_len); + if (txt_items[i].key) { strcpy((char*)txt_items[i].key, key); } + size_t val_len = strlen(val)+1; + txt_items[i].value = (const char*)be_os_malloc(val_len); + if (txt_items[i].value) { strcpy((char*)txt_items[i].value, val); } + be_pop(vm, 2); + i++; + } + txt_num = i; + } else { + txt_num = 0; // failed to allocate, pretend it's empty + } + be_pop(vm, 1); /* pop iterator */ + } + } + esp_err_t err = mdns_service_add(NULL, service_type, proto, port, txt_items, txt_num); + // free all allocated memory + if (txt_items != NULL) { + for (uint32_t i = 0; i < txt_num; i++) { + if (txt_items[i].key != NULL) { be_os_free((void*)txt_items[i].key); } + if (txt_items[i].value != NULL) { be_os_free((void*)txt_items[i].value); } + } + be_os_free(txt_items); + } + if (err != ESP_OK) { + be_raisef(vm, "internal_error", "mdns service_add err=%i", err); + } + be_return_nil(vm); + } + be_raise(vm, "value_error", "wrong or missing arguments"); +} + +/* @const_object_info_begin +module mdns (scope: global) { + start, ctype_func(m_mdns_start) + stop, ctype_func(m_mdns_stop) + set_hostname, ctype_func(m_mdns_set_hostname) + add_service, func(m_mdns_add_service) +} +@const_object_info_end */ +#include "be_fixed_mdns.h" + +#endif // USE_DISCOVERY \ No newline at end of file diff --git a/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c b/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c index dcef3a479..b3d7c540d 100644 --- a/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c @@ -27,6 +27,7 @@ extern int l_strptime(bvm *vm); extern int l_memory(bvm *vm); extern int l_wifi(bvm *vm); extern int l_eth(bvm *vm); +extern int l_hostname(bvm *vm); extern int l_yield(bvm *vm); extern int l_delay(bvm *vm); extern int l_delay_microseconds(bvm *vm); @@ -101,6 +102,7 @@ class be_class_tasmota (scope: global, name: Tasmota) { memory, func(l_memory) wifi, func(l_wifi) eth, func(l_eth) + hostname, func(l_hostname) yield, func(l_yield) delay, func(l_delay) delay_microseconds, func(l_delay_microseconds) 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 4406c6fca..624bbc5d9 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino @@ -256,6 +256,14 @@ extern "C" { be_raise(vm, kTypeError, nullptr); } + // Berry: tasmota.hostname() -> string + // + int32_t l_hostname(struct bvm *vm); + int32_t l_hostname(struct bvm *vm) { + be_pushstring(vm, NetworkHostname()); + be_return(vm); + } + static void l_push_time(bvm *vm, struct tm *t, const char *unparsed) { be_newobject(vm, "map"); be_map_insert_int(vm, "year", t->tm_year + 1900); From b1eac8eb0587db49ff267d325af8c1b4a5793784 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 27 Nov 2022 18:17:41 +0100 Subject: [PATCH 2/2] Fix Berry mdns comments --- lib/libesp32/berry_tasmota/src/be_mdns_module.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/libesp32/berry_tasmota/src/be_mdns_module.cpp b/lib/libesp32/berry_tasmota/src/be_mdns_module.cpp index d0c534d2b..843090650 100644 --- a/lib/libesp32/berry_tasmota/src/be_mdns_module.cpp +++ b/lib/libesp32/berry_tasmota/src/be_mdns_module.cpp @@ -15,6 +15,7 @@ // // `mdsn.start([hostname:string]) -> nil` +// start or restart mdns, specify hostname or use tasmota.hostname() if none provided (default) extern char* NetworkHostname(void); static void m_mdns_start(struct bvm *vm, const char* hostname) { esp_err_t err = mdns_init(); @@ -32,13 +33,16 @@ static void m_mdns_start(struct bvm *vm, const char* hostname) { BE_FUNC_CTYPE_DECLARE(m_mdns_start, "", "@[s]") // -// `msdn.stop() -> nil`` +// `msdn.stop() -> nil` +// free all mdns resources static void m_mdns_stop(void) { mdns_free(); } BE_FUNC_CTYPE_DECLARE(m_mdns_stop, "", "") - +// +// `mdns.set_hostname(hostname:string) -> nil` +// change the hostname static void m_mdns_set_hostname(struct bvm *vm, const char * hostname) { esp_err_t err = mdns_hostname_set(hostname); if (err != ESP_OK) { @@ -50,6 +54,8 @@ BE_FUNC_CTYPE_DECLARE(m_mdns_set_hostname, "", "@s") // // `mdns.add_service(service:string, proto:string, port:int, txt:map) -> nil` // +// add a service declaration using the current hostname as instance name, and specify TXT fields as a `map` +// // Test: // import mdns mdns.add_service("_arduino","_tcp",1111, {"board":"tasmota", "tcp_check":"no", "ssh_upload":"no", "auth_upload":"no"}) //