mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-25 11:46:31 +00:00
Merge branch 'arendst:development' into S3_Homekit
This commit is contained in:
commit
574be6b7f0
@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file.
|
|||||||
## [Unreleased] - Development
|
## [Unreleased] - Development
|
||||||
## [11.0.0.1]
|
## [11.0.0.1]
|
||||||
### Added
|
### Added
|
||||||
|
- Command ``SspmMap 0`` to reset Sonoff SPM default mapping
|
||||||
|
- Command ``TcpConnect <port><ip_address>`` to add client connection mode (#14874)
|
||||||
- ESP32 support for BLE Mi scale V1 (#13517)
|
- ESP32 support for BLE Mi scale V1 (#13517)
|
||||||
- ESP32 integrate Homekit in Bluetooth binary (#14818)
|
- ESP32 integrate Homekit in Bluetooth binary (#14818)
|
||||||
- ESP32 Berry always enable rules
|
- ESP32 Berry always enable rules
|
||||||
@ -21,6 +23,7 @@ All notable changes to this project will be documented in this file.
|
|||||||
- GPIO OptionE1 selection regression (#14821)
|
- GPIO OptionE1 selection regression (#14821)
|
||||||
- BL0939, BL0940 and BL0942 energy monitoring buffer miscompares resulting in wrong daily energy values regression from v9.5.0.8 (#14829)
|
- BL0939, BL0940 and BL0942 energy monitoring buffer miscompares resulting in wrong daily energy values regression from v9.5.0.8 (#14829)
|
||||||
- Orno WE517 power meter phase 2 current reactive (#14841)
|
- Orno WE517 power meter phase 2 current reactive (#14841)
|
||||||
|
- Wiegand 34-bit rfid reading and presentation (#14834)
|
||||||
|
|
||||||
## [Released]
|
## [Released]
|
||||||
|
|
||||||
|
@ -105,6 +105,8 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo
|
|||||||
|
|
||||||
## Changelog v11.0.0.1
|
## Changelog v11.0.0.1
|
||||||
### Added
|
### Added
|
||||||
|
- Command ``SspmMap 0`` to reset Sonoff SPM default mapping
|
||||||
|
- Command ``TcpConnect <port><ip_address>`` to add client connection mode [#14874](https://github.com/arendst/Tasmota/issues/14874)
|
||||||
- ESP32 Berry always enable rules
|
- ESP32 Berry always enable rules
|
||||||
- ESP32 Berry bootloop protection
|
- ESP32 Berry bootloop protection
|
||||||
- ESP32 support for BLE Mi scale V1 [#13517](https://github.com/arendst/Tasmota/issues/13517)
|
- ESP32 support for BLE Mi scale V1 [#13517](https://github.com/arendst/Tasmota/issues/13517)
|
||||||
@ -123,6 +125,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo
|
|||||||
- SSPM energy yesterday when zero
|
- SSPM energy yesterday when zero
|
||||||
- GPIO OptionE1 selection regression [#14821](https://github.com/arendst/Tasmota/issues/14821)
|
- GPIO OptionE1 selection regression [#14821](https://github.com/arendst/Tasmota/issues/14821)
|
||||||
- BL0939, BL0940 and BL0942 energy monitoring buffer miscompares resulting in wrong daily energy values regression from v9.5.0.8 [#14829](https://github.com/arendst/Tasmota/issues/14829)
|
- BL0939, BL0940 and BL0942 energy monitoring buffer miscompares resulting in wrong daily energy values regression from v9.5.0.8 [#14829](https://github.com/arendst/Tasmota/issues/14829)
|
||||||
|
- Wiegand 34-bit rfid reading and presentation [#14834](https://github.com/arendst/Tasmota/issues/14834)
|
||||||
- Orno WE517 power meter phase 2 current reactive [#14841](https://github.com/arendst/Tasmota/issues/14841)
|
- Orno WE517 power meter phase 2 current reactive [#14841](https://github.com/arendst/Tasmota/issues/14841)
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
@ -210,14 +210,14 @@ void directModeInput(IO_REG_TYPE pin)
|
|||||||
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux);
|
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux);
|
||||||
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown);
|
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown);
|
||||||
}
|
}
|
||||||
#elif ESP_IDF_VERSION_MAJOR > 3 // ESP32-S2 needs IDF 4.2 or later
|
//#elif ESP_IDF_VERSION_MAJOR > 3 // ESP32-S2 needs IDF 4.2 or later
|
||||||
int8_t rtc_io = esp32_gpioMux[pin].rtc;
|
// int8_t rtc_io = esp32_gpioMux[pin].rtc;
|
||||||
uint32_t rtc_reg = (rtc_io != -1)?rtc_io_desc[rtc_io].reg:0;
|
// uint32_t rtc_reg = (rtc_io != -1)?rtc_io_desc[rtc_io].reg:0;
|
||||||
if ( rtc_reg ) // RTC pins PULL settings
|
// if ( rtc_reg ) // RTC pins PULL settings
|
||||||
{
|
// {
|
||||||
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtc_io].mux);
|
// ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtc_io].mux);
|
||||||
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtc_io].pullup | rtc_io_desc[rtc_io].pulldown);
|
// ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtc_io].pullup | rtc_io_desc[rtc_io].pulldown);
|
||||||
}
|
// }
|
||||||
#endif
|
#endif
|
||||||
// Input
|
// Input
|
||||||
if ( pin < 32 )
|
if ( pin < 32 )
|
||||||
@ -225,13 +225,13 @@ void directModeInput(IO_REG_TYPE pin)
|
|||||||
else
|
else
|
||||||
GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32));
|
GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32));
|
||||||
|
|
||||||
uint32_t pinFunction((uint32_t)2 << FUN_DRV_S); // what are the drivers?
|
// uint32_t pinFunction((uint32_t)2 << FUN_DRV_S); // what are the drivers?
|
||||||
pinFunction |= FUN_IE; // input enable but required for output as well?
|
// pinFunction |= FUN_IE; // input enable but required for output as well?
|
||||||
pinFunction |= ((uint32_t)PIN_FUNC_GPIO << MCU_SEL_S);
|
// pinFunction |= ((uint32_t)PIN_FUNC_GPIO << MCU_SEL_S);
|
||||||
|
|
||||||
ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction;
|
// ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction;
|
||||||
|
|
||||||
GPIO.pin[pin].val = 0;
|
// GPIO.pin[pin].val = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -252,14 +252,14 @@ void directModeOutput(IO_REG_TYPE pin)
|
|||||||
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux);
|
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux);
|
||||||
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown);
|
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown);
|
||||||
}
|
}
|
||||||
#elif ESP_IDF_VERSION_MAJOR > 3 // ESP32-S2 needs IDF 4.2 or later
|
//#elif ESP_IDF_VERSION_MAJOR > 3 // ESP32-S2 needs IDF 4.2 or later
|
||||||
int8_t rtc_io = esp32_gpioMux[pin].rtc;
|
// int8_t rtc_io = esp32_gpioMux[pin].rtc;
|
||||||
uint32_t rtc_reg = (rtc_io != -1)?rtc_io_desc[rtc_io].reg:0;
|
// uint32_t rtc_reg = (rtc_io != -1)?rtc_io_desc[rtc_io].reg:0;
|
||||||
if ( rtc_reg ) // RTC pins PULL settings
|
// if ( rtc_reg ) // RTC pins PULL settings
|
||||||
{
|
// {
|
||||||
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtc_io].mux);
|
// ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtc_io].mux);
|
||||||
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtc_io].pullup | rtc_io_desc[rtc_io].pulldown);
|
// ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[rtc_io].pullup | rtc_io_desc[rtc_io].pulldown);
|
||||||
}
|
// }
|
||||||
#endif
|
#endif
|
||||||
// Output
|
// Output
|
||||||
if ( pin < 32 )
|
if ( pin < 32 )
|
||||||
@ -267,13 +267,13 @@ void directModeOutput(IO_REG_TYPE pin)
|
|||||||
else // already validated to pins <= 33
|
else // already validated to pins <= 33
|
||||||
GPIO.enable1_w1ts.val = ((uint32_t)1 << (pin - 32));
|
GPIO.enable1_w1ts.val = ((uint32_t)1 << (pin - 32));
|
||||||
|
|
||||||
uint32_t pinFunction((uint32_t)2 << FUN_DRV_S); // what are the drivers?
|
// uint32_t pinFunction((uint32_t)2 << FUN_DRV_S); // what are the drivers?
|
||||||
pinFunction |= FUN_IE; // input enable but required for output as well?
|
// pinFunction |= FUN_IE; // input enable but required for output as well?
|
||||||
pinFunction |= ((uint32_t)PIN_FUNC_GPIO << MCU_SEL_S);
|
// pinFunction |= ((uint32_t)PIN_FUNC_GPIO << MCU_SEL_S);
|
||||||
|
|
||||||
ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction;
|
// ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction;
|
||||||
|
|
||||||
GPIO.pin[pin].val = 0;
|
// GPIO.pin[pin].val = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ be_extern_native_module(cb);
|
|||||||
/* Tasmota specific */
|
/* Tasmota specific */
|
||||||
be_extern_native_module(python_compat);
|
be_extern_native_module(python_compat);
|
||||||
be_extern_native_module(re);
|
be_extern_native_module(re);
|
||||||
|
be_extern_native_module(mqtt);
|
||||||
be_extern_native_module(persist);
|
be_extern_native_module(persist);
|
||||||
be_extern_native_module(autoconf);
|
be_extern_native_module(autoconf);
|
||||||
be_extern_native_module(tapp);
|
be_extern_native_module(tapp);
|
||||||
@ -108,6 +109,7 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = {
|
|||||||
&be_native_module(python_compat),
|
&be_native_module(python_compat),
|
||||||
&be_native_module(re),
|
&be_native_module(re),
|
||||||
&be_native_module(path),
|
&be_native_module(path),
|
||||||
|
&be_native_module(mqtt),
|
||||||
&be_native_module(persist),
|
&be_native_module(persist),
|
||||||
#ifdef USE_AUTOCONF
|
#ifdef USE_AUTOCONF
|
||||||
&be_native_module(autoconf),
|
&be_native_module(autoconf),
|
||||||
@ -157,7 +159,7 @@ extern void be_load_wirelib(bvm *vm);
|
|||||||
extern void be_load_onewirelib(bvm *vm);
|
extern void be_load_onewirelib(bvm *vm);
|
||||||
extern void be_load_serial_lib(bvm *vm);
|
extern void be_load_serial_lib(bvm *vm);
|
||||||
extern void be_load_Driver_class(bvm *vm);
|
extern void be_load_Driver_class(bvm *vm);
|
||||||
extern void be_load_Timer_class(bvm *vm);
|
extern void be_load_Trigger_class(bvm *vm);
|
||||||
extern void be_load_I2C_Driver_class(bvm *vm);
|
extern void be_load_I2C_Driver_class(bvm *vm);
|
||||||
extern void be_load_AXP192_class(bvm *vm);
|
extern void be_load_AXP192_class(bvm *vm);
|
||||||
extern void be_load_md5_lib(bvm *vm);
|
extern void be_load_md5_lib(bvm *vm);
|
||||||
@ -198,7 +200,7 @@ BERRY_API void be_load_custom_libs(bvm *vm)
|
|||||||
#if !BE_USE_PRECOMPILED_OBJECT
|
#if !BE_USE_PRECOMPILED_OBJECT
|
||||||
/* be_load_xxxlib(vm); */
|
/* be_load_xxxlib(vm); */
|
||||||
#endif
|
#endif
|
||||||
be_load_Timer_class(vm);
|
be_load_Trigger_class(vm);
|
||||||
be_load_tasmota_ntvlib(vm);
|
be_load_tasmota_ntvlib(vm);
|
||||||
be_load_tasmota_log_reader_class(vm);
|
be_load_tasmota_log_reader_class(vm);
|
||||||
be_load_Driver_class(vm);
|
be_load_Driver_class(vm);
|
||||||
|
@ -175,6 +175,14 @@
|
|||||||
**/
|
**/
|
||||||
#define BE_USE_DEBUG_GC 0
|
#define BE_USE_DEBUG_GC 0
|
||||||
|
|
||||||
|
/* Macro: BE_USE_MEM_ALIGNED
|
||||||
|
* Some embedded processors have special memory areas
|
||||||
|
* with read/write constraints of being aligned to 32 bits boundaries.
|
||||||
|
* This options tries to move such memory areas to this region.
|
||||||
|
* Default: 0
|
||||||
|
**/
|
||||||
|
#define BE_USE_MEM_ALIGNED 1
|
||||||
|
|
||||||
/* Macro: BE_USE_XXX_MODULE
|
/* Macro: BE_USE_XXX_MODULE
|
||||||
* These macros control whether the related module is compiled.
|
* These macros control whether the related module is compiled.
|
||||||
* When they are true, they will enable related modules. At this
|
* When they are true, they will enable related modules. At this
|
||||||
@ -215,8 +223,6 @@ extern "C" {
|
|||||||
extern void berry_free(void *ptr);
|
extern void berry_free(void *ptr);
|
||||||
extern void *berry_realloc(void *ptr, size_t size);
|
extern void *berry_realloc(void *ptr, size_t size);
|
||||||
extern void *berry_malloc32(size_t size);
|
extern void *berry_malloc32(size_t size);
|
||||||
extern void berry_free32(void *ptr);
|
|
||||||
extern void *berry_realloc32(void *ptr, size_t size);
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -100,7 +100,7 @@ extern const bcstring be_const_str_STATE_DEFAULT;
|
|||||||
extern const bcstring be_const_str_TAP_X3A_X20Loaded_X20Tasmota_X20App_X20_X27_X25s_X27;
|
extern const bcstring be_const_str_TAP_X3A_X20Loaded_X20Tasmota_X20App_X20_X27_X25s_X27;
|
||||||
extern const bcstring be_const_str_Tasmota;
|
extern const bcstring be_const_str_Tasmota;
|
||||||
extern const bcstring be_const_str_Tele;
|
extern const bcstring be_const_str_Tele;
|
||||||
extern const bcstring be_const_str_Timer;
|
extern const bcstring be_const_str_Trigger;
|
||||||
extern const bcstring be_const_str_True;
|
extern const bcstring be_const_str_True;
|
||||||
extern const bcstring be_const_str_Unknown;
|
extern const bcstring be_const_str_Unknown;
|
||||||
extern const bcstring be_const_str_Unknown_X20command;
|
extern const bcstring be_const_str_Unknown_X20command;
|
||||||
@ -526,6 +526,7 @@ extern const bcstring be_const_str_length_X20in_X20bits_X20must_X20be_X20between
|
|||||||
extern const bcstring be_const_str_light;
|
extern const bcstring be_const_str_light;
|
||||||
extern const bcstring be_const_str_light_X20must_X20be_X20of_X20class_X20_X27light_state_X27;
|
extern const bcstring be_const_str_light_X20must_X20be_X20of_X20class_X20_X27light_state_X27;
|
||||||
extern const bcstring be_const_str_light_state;
|
extern const bcstring be_const_str_light_state;
|
||||||
|
extern const bcstring be_const_str_light_to_id;
|
||||||
extern const bcstring be_const_str_lights;
|
extern const bcstring be_const_str_lights;
|
||||||
extern const bcstring be_const_str_line_dsc;
|
extern const bcstring be_const_str_line_dsc;
|
||||||
extern const bcstring be_const_str_list;
|
extern const bcstring be_const_str_list;
|
||||||
@ -759,6 +760,7 @@ extern const bcstring be_const_str_strftime;
|
|||||||
extern const bcstring be_const_str_string;
|
extern const bcstring be_const_str_string;
|
||||||
extern const bcstring be_const_str_strip;
|
extern const bcstring be_const_str_strip;
|
||||||
extern const bcstring be_const_str_strptime;
|
extern const bcstring be_const_str_strptime;
|
||||||
|
extern const bcstring be_const_str_subscribe;
|
||||||
extern const bcstring be_const_str_success;
|
extern const bcstring be_const_str_success;
|
||||||
extern const bcstring be_const_str_super;
|
extern const bcstring be_const_str_super;
|
||||||
extern const bcstring be_const_str_sys;
|
extern const bcstring be_const_str_sys;
|
||||||
@ -788,6 +790,7 @@ extern const bcstring be_const_str_touch_update;
|
|||||||
extern const bcstring be_const_str_toupper;
|
extern const bcstring be_const_str_toupper;
|
||||||
extern const bcstring be_const_str_tr;
|
extern const bcstring be_const_str_tr;
|
||||||
extern const bcstring be_const_str_traceback;
|
extern const bcstring be_const_str_traceback;
|
||||||
|
extern const bcstring be_const_str_trig;
|
||||||
extern const bcstring be_const_str_true;
|
extern const bcstring be_const_str_true;
|
||||||
extern const bcstring be_const_str_try;
|
extern const bcstring be_const_str_try;
|
||||||
extern const bcstring be_const_str_try_rule;
|
extern const bcstring be_const_str_try_rule;
|
||||||
@ -795,6 +798,7 @@ extern const bcstring be_const_str_type;
|
|||||||
extern const bcstring be_const_str_type_error;
|
extern const bcstring be_const_str_type_error;
|
||||||
extern const bcstring be_const_str_udp;
|
extern const bcstring be_const_str_udp;
|
||||||
extern const bcstring be_const_str_unknown_X20instruction;
|
extern const bcstring be_const_str_unknown_X20instruction;
|
||||||
|
extern const bcstring be_const_str_unsubscribe;
|
||||||
extern const bcstring be_const_str_update;
|
extern const bcstring be_const_str_update;
|
||||||
extern const bcstring be_const_str_upper;
|
extern const bcstring be_const_str_upper;
|
||||||
extern const bcstring be_const_str_url_encode;
|
extern const bcstring be_const_str_url_encode;
|
||||||
|
File diff suppressed because it is too large
Load Diff
19
lib/libesp32/berry/generate/be_fixed_mqtt.h
Normal file
19
lib/libesp32/berry/generate/be_fixed_mqtt.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#include "be_constobj.h"
|
||||||
|
|
||||||
|
static be_define_const_map_slots(m_libmqtt_map) {
|
||||||
|
{ be_const_key(unsubscribe, -1), be_const_ctype_func(be_mqtt_unsubscribe) },
|
||||||
|
{ be_const_key(subscribe, -1), be_const_ctype_func(be_mqtt_subscribe) },
|
||||||
|
{ be_const_key(publish, 1), be_const_func(be_mqtt_publish) },
|
||||||
|
};
|
||||||
|
|
||||||
|
static be_define_const_map(
|
||||||
|
m_libmqtt_map,
|
||||||
|
3
|
||||||
|
);
|
||||||
|
|
||||||
|
static be_define_const_module(
|
||||||
|
m_libmqtt,
|
||||||
|
"mqtt"
|
||||||
|
);
|
||||||
|
|
||||||
|
BE_EXPORT_VARIABLE be_define_const_native_module(mqtt);
|
@ -40,6 +40,7 @@ void be_gc_init(bvm *vm)
|
|||||||
{
|
{
|
||||||
vm->gc.usage = sizeof(bvm);
|
vm->gc.usage = sizeof(bvm);
|
||||||
be_gc_setsteprate(vm, 200);
|
be_gc_setsteprate(vm, 200);
|
||||||
|
be_gc_init_memory_pools(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void be_gc_deleteall(bvm *vm)
|
void be_gc_deleteall(bvm *vm)
|
||||||
@ -543,6 +544,8 @@ void be_gc_collect(bvm *vm)
|
|||||||
return; /* the GC cannot run for some reason */
|
return; /* the GC cannot run for some reason */
|
||||||
}
|
}
|
||||||
#if BE_USE_PERF_COUNTERS
|
#if BE_USE_PERF_COUNTERS
|
||||||
|
size_t slors_used_before_gc, slots_allocated_before_gc;
|
||||||
|
be_gc_memory_pools_info(vm, &slors_used_before_gc, &slots_allocated_before_gc);
|
||||||
vm->counter_gc_kept = 0;
|
vm->counter_gc_kept = 0;
|
||||||
vm->counter_gc_freed = 0;
|
vm->counter_gc_freed = 0;
|
||||||
#endif
|
#endif
|
||||||
@ -563,8 +566,13 @@ void be_gc_collect(bvm *vm)
|
|||||||
reset_fixedlist(vm);
|
reset_fixedlist(vm);
|
||||||
/* step 5: calculate the next GC threshold */
|
/* step 5: calculate the next GC threshold */
|
||||||
vm->gc.threshold = next_threshold(vm->gc);
|
vm->gc.threshold = next_threshold(vm->gc);
|
||||||
|
be_gc_memory_pools(vm); /* free unsued memory pools */
|
||||||
#if BE_USE_PERF_COUNTERS
|
#if BE_USE_PERF_COUNTERS
|
||||||
if (vm->obshook != NULL) (*vm->obshook)(vm, BE_OBS_GC_END, vm->gc.usage, vm->counter_gc_kept, vm->counter_gc_freed);
|
size_t slors_used_after_gc, slots_allocated_after_gc;
|
||||||
|
be_gc_memory_pools_info(vm, &slors_used_after_gc, &slots_allocated_after_gc);
|
||||||
|
if (vm->obshook != NULL) (*vm->obshook)(vm, BE_OBS_GC_END, vm->gc.usage, vm->counter_gc_kept, vm->counter_gc_freed,
|
||||||
|
slors_used_before_gc, slots_allocated_before_gc,
|
||||||
|
slors_used_after_gc, slots_allocated_after_gc);
|
||||||
#else
|
#else
|
||||||
if (vm->obshook != NULL) (*vm->obshook)(vm, BE_OBS_GC_END, vm->gc.usage);
|
if (vm->obshook != NULL) (*vm->obshook)(vm, BE_OBS_GC_END, vm->gc.usage);
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,6 +26,12 @@
|
|||||||
#define realloc BE_EXPLICIT_REALLOC
|
#define realloc BE_EXPLICIT_REALLOC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void* malloc_from_pool(bvm *vm, size_t size);
|
||||||
|
static void free_from_pool(bvm *vm, void* ptr, size_t old_size);
|
||||||
|
|
||||||
|
#define POOL16_SIZE 16
|
||||||
|
#define POOL32_SIZE 32
|
||||||
|
|
||||||
BERRY_API void* be_os_malloc(size_t size)
|
BERRY_API void* be_os_malloc(size_t size)
|
||||||
{
|
{
|
||||||
return malloc(size);
|
return malloc(size);
|
||||||
@ -41,39 +47,310 @@ BERRY_API void* be_os_realloc(void *ptr, size_t size)
|
|||||||
return realloc(ptr, size);
|
return realloc(ptr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* _realloc(void *ptr, size_t old_size, size_t new_size)
|
|
||||||
{
|
|
||||||
if (old_size == new_size) { /* the block unchanged */
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
if (ptr && new_size) { /* realloc block */
|
|
||||||
return realloc(ptr, new_size);
|
|
||||||
}
|
|
||||||
if (new_size) { /* alloc a new block */
|
|
||||||
be_assert(ptr == NULL && old_size == 0);
|
|
||||||
return malloc(new_size);
|
|
||||||
}
|
|
||||||
be_assert(new_size == 0);
|
|
||||||
|
|
||||||
#if BE_USE_DEBUG_GC
|
|
||||||
memset(ptr, 0xFF, old_size); /* fill the structure with invalid pointers */
|
|
||||||
#endif
|
|
||||||
free(ptr);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
BERRY_API void* be_realloc(bvm *vm, void *ptr, size_t old_size, size_t new_size)
|
BERRY_API void* be_realloc(bvm *vm, void *ptr, size_t old_size, size_t new_size)
|
||||||
{
|
{
|
||||||
void *block = _realloc(ptr, old_size, new_size);
|
void *block = NULL;
|
||||||
if (!block && new_size) { /* allocation failure */
|
// serial_debug("be_realloc ptr=%p old_size=%i new_size=%i\n", ptr, old_size, new_size);
|
||||||
|
|
||||||
|
bbool gc_occured = bfalse; /* if allocation failed, retry after forced GC */
|
||||||
|
if (old_size == new_size) { /* the block unchanged, this also captures creation of a zero byte object */
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
/* from now on, block == NULL means allocation failure */
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
/* Case 1: new allocation */
|
||||||
|
if (!ptr || (old_size == 0)) {
|
||||||
|
block = malloc_from_pool(vm, new_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Case 2: deallocate */
|
||||||
|
else if (new_size == 0) {
|
||||||
|
#if BE_USE_DEBUG_GC
|
||||||
|
memset(ptr, 0xFF, old_size); /* fill the structure with invalid pointers */
|
||||||
|
#endif
|
||||||
|
free_from_pool(vm, ptr, old_size);
|
||||||
|
break; /* early exit */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Case 3: reallocate with a different size */
|
||||||
|
else if (new_size && old_size) { // TODO we already know they are not null TODO
|
||||||
|
if (new_size <= POOL32_SIZE || old_size <=POOL32_SIZE) {
|
||||||
|
/* complex case with different pools */
|
||||||
|
if (new_size <= POOL16_SIZE && old_size <= POOL16_SIZE) {
|
||||||
|
// no change of slot
|
||||||
|
block = ptr;
|
||||||
|
break;
|
||||||
|
} else if (new_size > POOL16_SIZE && old_size > POOL16_SIZE && new_size <= POOL32_SIZE && old_size <= POOL32_SIZE) {
|
||||||
|
// no change of slot
|
||||||
|
block = ptr;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
/* one of the buffer is out of pool, the other not */
|
||||||
|
block = malloc_from_pool(vm, new_size);
|
||||||
|
if (block) {
|
||||||
|
/* copy memory */
|
||||||
|
size_t min_size = old_size < new_size ? old_size : new_size;
|
||||||
|
memmove(block, ptr, min_size);
|
||||||
|
// serial_debug("memmove from %p to %p size=%i\n", ptr, block, min_size);
|
||||||
|
free_from_pool(vm, ptr, old_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
block = realloc(ptr, new_size);
|
||||||
|
// serial_debug("realloc from %p to %p size=%i", ptr, block, new_size);
|
||||||
|
}
|
||||||
|
} /* end of reallocation */
|
||||||
|
|
||||||
|
/* exit allocator, do we need to GC ? */
|
||||||
|
if (block) { break; } /* all good */
|
||||||
|
if (gc_occured) { /* already tried gc, can't do much anymore */
|
||||||
|
be_throw(vm, BE_MALLOC_FAIL); /* lack of heap space */
|
||||||
|
}
|
||||||
|
// serial_debug("be_realloc force_gc\n");
|
||||||
|
/* force GC now */
|
||||||
vm->gc.status |= GC_ALLOC;
|
vm->gc.status |= GC_ALLOC;
|
||||||
be_gc_collect(vm); /* try to allocate again after GC */
|
be_gc_collect(vm); /* try to allocate again after GC */
|
||||||
vm->gc.status &= ~GC_ALLOC;
|
vm->gc.status &= ~GC_ALLOC;
|
||||||
block = _realloc(ptr, old_size, new_size);
|
gc_occured = btrue; /* don't try again GC */
|
||||||
if (!block) { /* lack of heap space */
|
|
||||||
be_throw(vm, BE_MALLOC_FAIL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
vm->gc.usage = vm->gc.usage + new_size - old_size; /* update allocated count */
|
vm->gc.usage = vm->gc.usage + new_size - old_size; /* update allocated count */
|
||||||
|
|
||||||
|
// serial_debug("be_realloc ret=%p\n", block);
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BERRY_API void* be_move_to_aligned(bvm *vm, void *ptr, size_t size) {
|
||||||
|
#if BE_USE_MEM_ALIGNED
|
||||||
|
if (size <= POOL32_SIZE) {
|
||||||
|
return ptr; /* if in memory pool, don't move it so be_free() will continue to work */
|
||||||
|
}
|
||||||
|
void* iram = berry_malloc32(size);
|
||||||
|
if (iram) {
|
||||||
|
memcpy(iram, ptr, size); /* new_size is always smaller than initial mem zone */
|
||||||
|
free(ptr); // TODO gc size is now wrong
|
||||||
|
return iram;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Special allocator for structures under 32 bytes */
|
||||||
|
typedef uint8_t mem16[16]; /* memory line of 16 bytes */
|
||||||
|
typedef uint8_t mem32[32]; /* memory line of 32 bytes */
|
||||||
|
#define POOL16_SLOTS 31
|
||||||
|
#define POOL16_BITMAP_FULL ((1UL<<POOL16_SLOTS)-1) /* 31 bits set to 1 - 0x7FFFFFFF */
|
||||||
|
#define POOL32_SLOTS 15
|
||||||
|
#define POOL32_BITMAP_FULL ((1UL<<POOL32_SLOTS)-1) /* 15 bits set to 1 - 0x7FFF*/
|
||||||
|
|
||||||
|
typedef struct gc16_t {
|
||||||
|
uint32_t bitmap; /* bitmap or allocated lines, 0 is free */
|
||||||
|
struct gc16_t* next;
|
||||||
|
mem16 lines[POOL16_SLOTS];
|
||||||
|
} gc16_t;
|
||||||
|
|
||||||
|
typedef struct gc32_t {
|
||||||
|
uint32_t bitmap; /* bitmap or allocated lines, 0 is free */
|
||||||
|
struct gc32_t* next;
|
||||||
|
mem32 lines[POOL32_SLOTS];
|
||||||
|
} gc32_t;
|
||||||
|
|
||||||
|
static void* malloc_from_pool(bvm *vm, size_t size) {
|
||||||
|
if (size == 0) return NULL;
|
||||||
|
if (size <= POOL16_SIZE) {
|
||||||
|
/* allocate in pool 16 */
|
||||||
|
gc16_t* pool16 = vm->gc.pool16;
|
||||||
|
while (pool16) {
|
||||||
|
/* look for an empty slot */
|
||||||
|
if (pool16->bitmap != 0x0000) {
|
||||||
|
/* there is a free slot */
|
||||||
|
#ifdef __GNUC__
|
||||||
|
int bit = __builtin_ffs(pool16->bitmap) - 1;
|
||||||
|
#else
|
||||||
|
int bit = ffs(pool16->bitmap) - 1;
|
||||||
|
#endif
|
||||||
|
if (bit >= 0) {
|
||||||
|
/* we found a free slot */
|
||||||
|
// bitClear(pool16->bitmap, bit);
|
||||||
|
pool16->bitmap &= ~(1UL << bit);
|
||||||
|
// serial_debug("malloc_from_pool found slot in pool %p, bit %i, ptr=%p\n", pool16, bit, &pool16->lines[bit]);
|
||||||
|
return &pool16->lines[bit];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pool16 = pool16->next;
|
||||||
|
}
|
||||||
|
/* no slot available, we allocate a new pool */
|
||||||
|
pool16 = (gc16_t*) malloc(sizeof(gc16_t));
|
||||||
|
if (!pool16) { return NULL; } /* out of memory */
|
||||||
|
pool16->next = vm->gc.pool16;
|
||||||
|
pool16->bitmap = POOL16_BITMAP_FULL - 1; /* allocate first line */
|
||||||
|
vm->gc.pool16 = pool16; /* insert at head of linked list */
|
||||||
|
// serial_debug("malloc_from_pool allocated new pool %p, size=%i p=%p\n", pool16, sizeof(gc16_t), &pool16->lines[0]);
|
||||||
|
return &pool16->lines[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size <= POOL32_SIZE) {
|
||||||
|
/* allocate in pool 32 */
|
||||||
|
gc32_t* pool32 = vm->gc.pool32;
|
||||||
|
while (pool32) {
|
||||||
|
/* look for an empty slot */
|
||||||
|
if (pool32->bitmap != 0x0000) {
|
||||||
|
/* there is a free slot */
|
||||||
|
#ifdef __GNUC__
|
||||||
|
int bit = __builtin_ffs(pool32->bitmap) - 1;
|
||||||
|
#else
|
||||||
|
int bit = ffs(pool32->bitmap) - 1;
|
||||||
|
#endif
|
||||||
|
if (bit >= 0) {
|
||||||
|
/* we found a free slot */
|
||||||
|
// bitClear(pool32->bitmap, bit);
|
||||||
|
pool32->bitmap &= ~(1UL << bit);
|
||||||
|
// serial_debug("malloc_from_pool found slot in pool %p, bit %i, ptr=%p\n", pool32, bit, &pool32->lines[bit]);
|
||||||
|
return &pool32->lines[bit];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pool32 = pool32->next;
|
||||||
|
}
|
||||||
|
/* no slot available, we allocate a new pool */
|
||||||
|
pool32 = (gc32_t*) malloc(sizeof(gc32_t));
|
||||||
|
if (!pool32) { return NULL; } /* out of memory */
|
||||||
|
pool32->next = vm->gc.pool32;
|
||||||
|
pool32->bitmap = POOL32_BITMAP_FULL - 1; /* allocate first line */
|
||||||
|
vm->gc.pool32 = pool32; /* insert at head of linked list */
|
||||||
|
// serial_debug("malloc_from_pool allocated new pool %p, size=%i p=%p\n", pool32, sizeof(gc32_t), &pool32->lines[0]);
|
||||||
|
return &pool32->lines[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return malloc(size); /* default to system malloc */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free_from_pool(bvm *vm, void* ptr, size_t old_size) {
|
||||||
|
if (old_size <= POOL16_SIZE) {
|
||||||
|
gc16_t* pool16 = vm->gc.pool16;
|
||||||
|
while (pool16) {
|
||||||
|
int32_t offset = (uint8_t*)ptr - (uint8_t*) &pool16->lines[0];
|
||||||
|
// serial_debug("free_from_pool ptr=%p pool=%p offset=%i\n", ptr,pool16, offset);
|
||||||
|
if ((offset >= 0) && (offset < POOL16_SLOTS*16) && ((offset & 0x0F) == 0)) {
|
||||||
|
int bit = offset >> 4;
|
||||||
|
// serial_debug("free_from_pool ptr=%p fond pool=%p bit=%i\n", ptr, pool16, bit);
|
||||||
|
// bitSet(pool16->bitmap, bit);
|
||||||
|
pool16->bitmap |= 1UL << bit;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pool16 = pool16->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (old_size <= POOL32_SIZE) {
|
||||||
|
gc32_t* pool32 = vm->gc.pool32;
|
||||||
|
while (pool32) {
|
||||||
|
int32_t offset = (uint8_t*)ptr - (uint8_t*) &pool32->lines[0];
|
||||||
|
// serial_debug("free_from_pool pool=%p offset=%i\n", pool32, offset);
|
||||||
|
if ((offset >= 0) && (offset < POOL16_SLOTS*16) && ((offset & 0x1F) == 0)) {
|
||||||
|
int bit = offset >> 5;
|
||||||
|
// serial_debug("free_from_pool ptr=%p fond pool=%p bit=%i\n", ptr, pool32, bit);
|
||||||
|
// bitSet(pool32->bitmap, bit);
|
||||||
|
pool32->bitmap |= 1UL << bit;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pool32 = pool32->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// serial_debug("free_from_pool free=%p\n", ptr);
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BERRY_API void be_gc_memory_pools(bvm *vm) {
|
||||||
|
gc16_t** prev16 = &vm->gc.pool16;
|
||||||
|
gc16_t* pool16 = vm->gc.pool16;
|
||||||
|
while (pool16) {
|
||||||
|
if (pool16->bitmap == POOL16_BITMAP_FULL) {
|
||||||
|
/* pool is empty, we can free it */
|
||||||
|
*prev16 = pool16->next;
|
||||||
|
gc16_t* pool_to_freed = pool16;
|
||||||
|
pool16 = pool16->next; /* move to next */
|
||||||
|
free(pool_to_freed);
|
||||||
|
} else {
|
||||||
|
prev16 = &pool16->next;
|
||||||
|
pool16 = pool16->next; /* move to next */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gc32_t** prev32 = &vm->gc.pool32;
|
||||||
|
gc32_t* pool32 = vm->gc.pool32;
|
||||||
|
while (pool32) {
|
||||||
|
if (pool32->bitmap == POOL32_BITMAP_FULL) {
|
||||||
|
/* pool is empty, we can free it */
|
||||||
|
*prev32 = pool32->next;
|
||||||
|
gc32_t* pool_to_freed = pool32;
|
||||||
|
pool32 = pool32->next; /* move to next */
|
||||||
|
free(pool_to_freed);
|
||||||
|
} else {
|
||||||
|
prev32 = &pool32->next;
|
||||||
|
pool32 = pool32->next; /* move to next */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BERRY_API void be_gc_init_memory_pools(bvm *vm) {
|
||||||
|
vm->gc.pool16 = NULL;
|
||||||
|
vm->gc.pool32 = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
BERRY_API void be_gc_free_memory_pools(bvm *vm) {
|
||||||
|
gc16_t* pool16 = vm->gc.pool16;
|
||||||
|
while (pool16) {
|
||||||
|
gc16_t* pool_to_freed = pool16;
|
||||||
|
pool16 = pool16->next;
|
||||||
|
be_os_free(pool_to_freed);
|
||||||
|
pool16 = pool16->next;
|
||||||
|
}
|
||||||
|
vm->gc.pool16 = NULL;
|
||||||
|
|
||||||
|
gc32_t* pool32 = vm->gc.pool32;
|
||||||
|
while (pool32) {
|
||||||
|
gc32_t* pool_to_freed = pool32;
|
||||||
|
pool32 = pool32->next;
|
||||||
|
be_os_free(pool_to_freed);
|
||||||
|
pool32 = pool32->next;
|
||||||
|
}
|
||||||
|
vm->gc.pool32 = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* https://github.com/hcs0/Hackers-Delight/blob/master/pop.c.txt - count number of 1-bits */
|
||||||
|
static int pop0(uint32_t n) {
|
||||||
|
n = (n & 0x55555555u) + ((n >> 1) & 0x55555555u);
|
||||||
|
n = (n & 0x33333333u) + ((n >> 2) & 0x33333333u);
|
||||||
|
n = (n & 0x0f0f0f0fu) + ((n >> 4) & 0x0f0f0f0fu);
|
||||||
|
n = (n & 0x00ff00ffu) + ((n >> 8) & 0x00ff00ffu);
|
||||||
|
n = (n & 0x0000ffffu) + ((n >>16) & 0x0000ffffu);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define count_bits_1(v) __builtin_popcount(v)
|
||||||
|
#else
|
||||||
|
#define count_bits_1(v) pop0(v)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
BERRY_API void be_gc_memory_pools_info(bvm *vm, size_t* slots_used, size_t* slots_allocated) {
|
||||||
|
size_t used = 0;
|
||||||
|
size_t allocated = 0;
|
||||||
|
|
||||||
|
gc16_t* pool16 = vm->gc.pool16;
|
||||||
|
while (pool16) {
|
||||||
|
allocated += POOL16_SLOTS;
|
||||||
|
used += POOL16_SLOTS - count_bits_1(pool16->bitmap);
|
||||||
|
pool16 = pool16->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
gc32_t* pool32 = vm->gc.pool32;
|
||||||
|
while (pool32) {
|
||||||
|
allocated += POOL32_SLOTS;
|
||||||
|
used += POOL32_SLOTS - count_bits_1(pool32->bitmap);
|
||||||
|
pool32 = pool32->next;
|
||||||
|
}
|
||||||
|
if (slots_used) { *slots_used = used; }
|
||||||
|
if (slots_allocated) { *slots_allocated = allocated; }
|
||||||
|
}
|
@ -21,6 +21,14 @@ BERRY_API void* be_os_malloc(size_t size);
|
|||||||
BERRY_API void be_os_free(void *ptr);
|
BERRY_API void be_os_free(void *ptr);
|
||||||
BERRY_API void* be_os_realloc(void *ptr, size_t size);
|
BERRY_API void* be_os_realloc(void *ptr, size_t size);
|
||||||
BERRY_API void* be_realloc(bvm *vm, void *ptr, size_t old_size, size_t new_size);
|
BERRY_API void* be_realloc(bvm *vm, void *ptr, size_t old_size, size_t new_size);
|
||||||
|
BERRY_API void be_gc_memory_pools(bvm *vm);
|
||||||
|
BERRY_API void be_gc_free_memory_pools(bvm *vm);
|
||||||
|
BERRY_API void be_gc_init_memory_pools(bvm *vm);
|
||||||
|
BERRY_API void be_gc_memory_pools_info(bvm *vm, size_t* slots_used, size_t* slots_allocated);
|
||||||
|
|
||||||
|
/* The following moves a portion of memory to constraint regions with 32-bits read/write acess */
|
||||||
|
/* Effective only if `BE_USE_MEM_ALIGNED` is set to `1`*/
|
||||||
|
BERRY_API void* be_move_to_aligned(bvm *vm, void *ptr, size_t size);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -312,16 +312,23 @@ static void end_func(bparser *parser)
|
|||||||
be_code_ret(finfo, NULL); /* append a return to last code */
|
be_code_ret(finfo, NULL); /* append a return to last code */
|
||||||
end_block(parser); /* close block */
|
end_block(parser); /* close block */
|
||||||
setupvals(finfo); /* close upvals */
|
setupvals(finfo); /* close upvals */
|
||||||
proto->code = be_vector_release_32(vm, &finfo->code); /* compact all vectors and return NULL if empty */
|
proto->code = be_vector_release(vm, &finfo->code); /* compact all vectors and return NULL if empty */
|
||||||
proto->codesize = finfo->pc;
|
proto->codesize = finfo->pc;
|
||||||
proto->ktab = be_vector_release_32(vm, &finfo->kvec);
|
proto->ktab = be_vector_release(vm, &finfo->kvec);
|
||||||
proto->nconst = be_vector_count(&finfo->kvec);
|
proto->nconst = be_vector_count(&finfo->kvec);
|
||||||
proto->ptab = be_vector_release(vm, &finfo->pvec);
|
proto->ptab = be_vector_release(vm, &finfo->pvec);
|
||||||
proto->nproto = be_vector_count(&finfo->pvec);
|
proto->nproto = be_vector_count(&finfo->pvec);
|
||||||
|
#if BE_USE_MEM_ALIGNED
|
||||||
|
proto->code = be_move_to_aligned(vm, proto->code, proto->codesize * sizeof(binstruction)); /* move `code` to 4-bytes aligned memory region */
|
||||||
|
proto->ktab = be_move_to_aligned(vm, proto->ktab, proto->nconst * sizeof(bvalue)); /* move `ktab` to 4-bytes aligned memory region */
|
||||||
|
#endif /* BE_USE_MEM_ALIGNED */
|
||||||
#if BE_DEBUG_RUNTIME_INFO
|
#if BE_DEBUG_RUNTIME_INFO
|
||||||
proto->lineinfo = be_vector_release_32(vm, &finfo->linevec);
|
proto->lineinfo = be_vector_release(vm, &finfo->linevec); /* move `lineinfo` to 4-bytes aligned memory region */
|
||||||
proto->nlineinfo = be_vector_count(&finfo->linevec);
|
proto->nlineinfo = be_vector_count(&finfo->linevec);
|
||||||
#endif
|
#if BE_USE_MEM_ALIGNED
|
||||||
|
proto->lineinfo = be_move_to_aligned(vm, proto->lineinfo, proto->nlineinfo * sizeof(blineinfo));
|
||||||
|
#endif /* BE_USE_MEM_ALIGNED */
|
||||||
|
#endif /* BE_DEBUG_RUNTIME_INFO */
|
||||||
#if BE_DEBUG_VAR_INFO
|
#if BE_DEBUG_VAR_INFO
|
||||||
proto->varinfo = be_vector_release(vm, &finfo->varvec);
|
proto->varinfo = be_vector_release(vm, &finfo->varvec);
|
||||||
proto->nvarinfo = be_vector_count(&finfo->varvec);
|
proto->nvarinfo = be_vector_count(&finfo->varvec);
|
||||||
|
@ -114,32 +114,6 @@ void* be_vector_release(bvm *vm, bvector *vector)
|
|||||||
return vector->data;
|
return vector->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free not used */
|
|
||||||
void* be_vector_release_32(bvm *vm, bvector *vector)
|
|
||||||
{
|
|
||||||
size_t size = vector->size;
|
|
||||||
int count = be_vector_count(vector);
|
|
||||||
if (count == 0) {
|
|
||||||
be_free(vm, vector->data, vector->capacity * size);
|
|
||||||
vector->capacity = 0;
|
|
||||||
vector->data = NULL;
|
|
||||||
vector->end = NULL;
|
|
||||||
} else if (count < vector->capacity) {
|
|
||||||
vector->data = be_realloc(vm,
|
|
||||||
vector->data, vector->capacity * size, count * size); // TODO - can we skip that step?
|
|
||||||
void* iram = berry_malloc32(count * size);
|
|
||||||
if (iram) {
|
|
||||||
memcpy(iram, vector->data, count * size);
|
|
||||||
free(vector->data);
|
|
||||||
vector->data = iram;
|
|
||||||
}
|
|
||||||
// vm->gc.usage = vm->gc.usage + count * size - vector->capacity * size; /* update allocated count */
|
|
||||||
vector->end = (char*)vector->data + ((size_t)count - 1) * size;
|
|
||||||
vector->capacity = count;
|
|
||||||
}
|
|
||||||
return vector->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* use binary search to find the vector capacity between 0-1024 */
|
/* use binary search to find the vector capacity between 0-1024 */
|
||||||
static int binary_search(int value)
|
static int binary_search(int value)
|
||||||
{
|
{
|
||||||
|
@ -491,6 +491,7 @@ BERRY_API void be_vm_delete(bvm *vm)
|
|||||||
be_stack_delete(vm, &vm->tracestack);
|
be_stack_delete(vm, &vm->tracestack);
|
||||||
be_free(vm, vm->stack, (vm->stacktop - vm->stack) * sizeof(bvalue));
|
be_free(vm, vm->stack, (vm->stacktop - vm->stack) * sizeof(bvalue));
|
||||||
be_globalvar_deinit(vm);
|
be_globalvar_deinit(vm);
|
||||||
|
be_gc_free_memory_pools(vm);
|
||||||
#if BE_USE_DEBUG_HOOK
|
#if BE_USE_DEBUG_HOOK
|
||||||
/* free native hook */
|
/* free native hook */
|
||||||
if (var_istype(&vm->hook, BE_COMPTR))
|
if (var_istype(&vm->hook, BE_COMPTR))
|
||||||
@ -904,7 +905,11 @@ newframe: /* a new call frame */
|
|||||||
if (var_isinstance(a) && var_isstr(b)) {
|
if (var_isinstance(a) && var_isstr(b)) {
|
||||||
binstance *obj = var_toobj(a);
|
binstance *obj = var_toobj(a);
|
||||||
bstring *attr = var_tostr(b);
|
bstring *attr = var_tostr(b);
|
||||||
if (!be_instance_setmember(vm, obj, attr, c)) {
|
bvalue result = *c;
|
||||||
|
if (var_isfunction(&result)) {
|
||||||
|
var_markstatic(&result);
|
||||||
|
}
|
||||||
|
if (!be_instance_setmember(vm, obj, attr, &result)) {
|
||||||
reg = vm->reg;
|
reg = vm->reg;
|
||||||
vm_error(vm, "attribute_error",
|
vm_error(vm, "attribute_error",
|
||||||
"class '%s' cannot assign to attribute '%s'",
|
"class '%s' cannot assign to attribute '%s'",
|
||||||
|
@ -46,10 +46,14 @@ typedef struct {
|
|||||||
int status;
|
int status;
|
||||||
} bcallframe;
|
} bcallframe;
|
||||||
|
|
||||||
|
struct gc16_t; /* memory pool for 0-16 bytes or less objects */
|
||||||
|
struct gc32_t; /* memory pool for 17-32 bytes */
|
||||||
struct bgc {
|
struct bgc {
|
||||||
bgcobject *list; /* the GC-object list */
|
bgcobject *list; /* the GC-object list */
|
||||||
bgcobject *gray; /* the gray object list */
|
bgcobject *gray; /* the gray object list */
|
||||||
bgcobject *fixed; /* the fixed objecct list */
|
bgcobject *fixed; /* the fixed objecct list */
|
||||||
|
struct gc16_t* pool16;
|
||||||
|
struct gc32_t* pool32;
|
||||||
size_t usage; /* the count of bytes currently allocated */
|
size_t usage; /* the count of bytes currently allocated */
|
||||||
size_t threshold; /* he threshold of allocation for the next GC */
|
size_t threshold; /* he threshold of allocation for the next GC */
|
||||||
bbyte steprate; /* the rate of increase in the distribution between two GCs (percentage) */
|
bbyte steprate; /* the rate of increase in the distribution between two GCs (percentage) */
|
||||||
@ -80,7 +84,6 @@ struct bupval {
|
|||||||
} u;
|
} u;
|
||||||
int refcnt;
|
int refcnt;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bvm {
|
struct bvm {
|
||||||
bglobaldesc gbldesc; /* global description */
|
bglobaldesc gbldesc; /* global description */
|
||||||
bvalue *stack; /* stack space */
|
bvalue *stack; /* stack space */
|
||||||
|
@ -6,6 +6,363 @@
|
|||||||
|
|
||||||
#if defined(USE_EMULATION) && defined(USE_EMULATION_HUE)
|
#if defined(USE_EMULATION) && defined(USE_EMULATION_HUE)
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
** Solidified function: full_status
|
||||||
|
********************************************************************/
|
||||||
|
be_local_closure(hue_bridge_monad_full_status, /* name */
|
||||||
|
be_nested_proto(
|
||||||
|
11, /* nstack */
|
||||||
|
2, /* argc */
|
||||||
|
2, /* varg */
|
||||||
|
0, /* has upvals */
|
||||||
|
NULL, /* no upvals */
|
||||||
|
0, /* has sup protos */
|
||||||
|
NULL, /* no sub protos */
|
||||||
|
1, /* has constants */
|
||||||
|
( &(const bvalue[ 8]) { /* constants */
|
||||||
|
/* K0 */ be_nested_str(hue_ntv),
|
||||||
|
/* K1 */ be_nested_str(lights),
|
||||||
|
/* K2 */ be_nested_str(contains),
|
||||||
|
/* K3 */ be_nested_str(full_state),
|
||||||
|
/* K4 */ be_nested_str(light),
|
||||||
|
/* K5 */ be_nested_str(name),
|
||||||
|
/* K6 */ be_nested_str(model),
|
||||||
|
/* K7 */ be_nested_str(manuf),
|
||||||
|
}),
|
||||||
|
&be_const_str_full_status,
|
||||||
|
&be_const_str_solidified,
|
||||||
|
( &(const binstruction[17]) { /* code */
|
||||||
|
0xA40A0000, // 0000 IMPORT R2 K0
|
||||||
|
0x880C0101, // 0001 GETMBR R3 R0 K1
|
||||||
|
0x8C0C0702, // 0002 GETMET R3 R3 K2
|
||||||
|
0x5C140200, // 0003 MOVE R5 R1
|
||||||
|
0x7C0C0400, // 0004 CALL R3 2
|
||||||
|
0x780E0009, // 0005 JMPF R3 #0010
|
||||||
|
0x880C0101, // 0006 GETMBR R3 R0 K1
|
||||||
|
0x940C0601, // 0007 GETIDX R3 R3 R1
|
||||||
|
0x8C100503, // 0008 GETMET R4 R2 K3
|
||||||
|
0x5C180200, // 0009 MOVE R6 R1
|
||||||
|
0x941C0704, // 000A GETIDX R7 R3 K4
|
||||||
|
0x94200705, // 000B GETIDX R8 R3 K5
|
||||||
|
0x94240706, // 000C GETIDX R9 R3 K6
|
||||||
|
0x94280707, // 000D GETIDX R10 R3 K7
|
||||||
|
0x7C100C00, // 000E CALL R4 6
|
||||||
|
0x80040800, // 000F RET 1 R4
|
||||||
|
0x80000000, // 0010 RET 0
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
/*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
** Solidified function: hue_status
|
||||||
|
********************************************************************/
|
||||||
|
be_local_closure(hue_bridge_monad_hue_status, /* name */
|
||||||
|
be_nested_proto(
|
||||||
|
6, /* nstack */
|
||||||
|
2, /* argc */
|
||||||
|
2, /* varg */
|
||||||
|
0, /* has upvals */
|
||||||
|
NULL, /* no upvals */
|
||||||
|
0, /* has sup protos */
|
||||||
|
NULL, /* no sub protos */
|
||||||
|
1, /* has constants */
|
||||||
|
( &(const bvalue[ 5]) { /* constants */
|
||||||
|
/* K0 */ be_nested_str(hue_ntv),
|
||||||
|
/* K1 */ be_nested_str(lights),
|
||||||
|
/* K2 */ be_nested_str(contains),
|
||||||
|
/* K3 */ be_nested_str(light_state),
|
||||||
|
/* K4 */ be_nested_str(light),
|
||||||
|
}),
|
||||||
|
&be_const_str_hue_status,
|
||||||
|
&be_const_str_solidified,
|
||||||
|
( &(const binstruction[13]) { /* code */
|
||||||
|
0xA40A0000, // 0000 IMPORT R2 K0
|
||||||
|
0x880C0101, // 0001 GETMBR R3 R0 K1
|
||||||
|
0x8C0C0702, // 0002 GETMET R3 R3 K2
|
||||||
|
0x5C140200, // 0003 MOVE R5 R1
|
||||||
|
0x7C0C0400, // 0004 CALL R3 2
|
||||||
|
0x780E0005, // 0005 JMPF R3 #000C
|
||||||
|
0x8C0C0503, // 0006 GETMET R3 R2 K3
|
||||||
|
0x88140101, // 0007 GETMBR R5 R0 K1
|
||||||
|
0x94140A01, // 0008 GETIDX R5 R5 R1
|
||||||
|
0x94140B04, // 0009 GETIDX R5 R5 K4
|
||||||
|
0x7C0C0400, // 000A CALL R3 2
|
||||||
|
0x80040600, // 000B RET 1 R3
|
||||||
|
0x80000000, // 000C RET 0
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
/*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
** Solidified function: add_light
|
||||||
|
********************************************************************/
|
||||||
|
be_local_closure(hue_bridge_monad_add_light, /* name */
|
||||||
|
be_nested_proto(
|
||||||
|
10, /* nstack */
|
||||||
|
6, /* argc */
|
||||||
|
2, /* varg */
|
||||||
|
0, /* has upvals */
|
||||||
|
NULL, /* no upvals */
|
||||||
|
0, /* has sup protos */
|
||||||
|
NULL, /* no sub protos */
|
||||||
|
1, /* has constants */
|
||||||
|
( &(const bvalue[14]) { /* constants */
|
||||||
|
/* K0 */ be_nested_str(int),
|
||||||
|
/* K1 */ be_nested_str(value_error),
|
||||||
|
/* K2 */ be_nested_str(id_X20must_X20be_X20of_X20type_X20_X27int_X27),
|
||||||
|
/* K3 */ be_nested_str(light_state),
|
||||||
|
/* K4 */ be_nested_str(light_X20must_X20be_X20of_X20class_X20_X27light_state_X27),
|
||||||
|
/* K5 */ be_const_int(0),
|
||||||
|
/* K6 */ be_nested_str(missing_X20name),
|
||||||
|
/* K7 */ be_nested_str(Unknown),
|
||||||
|
/* K8 */ be_nested_str(Tasmota),
|
||||||
|
/* K9 */ be_nested_str(lights),
|
||||||
|
/* K10 */ be_nested_str(light),
|
||||||
|
/* K11 */ be_nested_str(name),
|
||||||
|
/* K12 */ be_nested_str(model),
|
||||||
|
/* K13 */ be_nested_str(manuf),
|
||||||
|
}),
|
||||||
|
&be_const_str_add_light,
|
||||||
|
&be_const_str_solidified,
|
||||||
|
( &(const binstruction[43]) { /* code */
|
||||||
|
0x60180004, // 0000 GETGBL R6 G4
|
||||||
|
0x5C1C0200, // 0001 MOVE R7 R1
|
||||||
|
0x7C180200, // 0002 CALL R6 1
|
||||||
|
0x20180D00, // 0003 NE R6 R6 K0
|
||||||
|
0x781A0000, // 0004 JMPF R6 #0006
|
||||||
|
0xB0060302, // 0005 RAISE 1 K1 K2
|
||||||
|
0x6018000F, // 0006 GETGBL R6 G15
|
||||||
|
0x5C1C0400, // 0007 MOVE R7 R2
|
||||||
|
0xB8220600, // 0008 GETNGBL R8 K3
|
||||||
|
0x7C180400, // 0009 CALL R6 2
|
||||||
|
0x741A0000, // 000A JMPT R6 #000C
|
||||||
|
0xB0060304, // 000B RAISE 1 K1 K4
|
||||||
|
0x60180008, // 000C GETGBL R6 G8
|
||||||
|
0x5C1C0600, // 000D MOVE R7 R3
|
||||||
|
0x7C180200, // 000E CALL R6 1
|
||||||
|
0x5C0C0C00, // 000F MOVE R3 R6
|
||||||
|
0x6018000C, // 0010 GETGBL R6 G12
|
||||||
|
0x5C1C0600, // 0011 MOVE R7 R3
|
||||||
|
0x7C180200, // 0012 CALL R6 1
|
||||||
|
0x1C180D05, // 0013 EQ R6 R6 K5
|
||||||
|
0x781A0000, // 0014 JMPF R6 #0016
|
||||||
|
0xB0060306, // 0015 RAISE 1 K1 K6
|
||||||
|
0x5C180800, // 0016 MOVE R6 R4
|
||||||
|
0x741A0000, // 0017 JMPT R6 #0019
|
||||||
|
0x58100007, // 0018 LDCONST R4 K7
|
||||||
|
0x5C180A00, // 0019 MOVE R6 R5
|
||||||
|
0x741A0000, // 001A JMPT R6 #001C
|
||||||
|
0x58140008, // 001B LDCONST R5 K8
|
||||||
|
0x88180109, // 001C GETMBR R6 R0 K9
|
||||||
|
0x601C0013, // 001D GETGBL R7 G19
|
||||||
|
0x7C1C0000, // 001E CALL R7 0
|
||||||
|
0x981E1402, // 001F SETIDX R7 K10 R2
|
||||||
|
0x981E1603, // 0020 SETIDX R7 K11 R3
|
||||||
|
0x60200008, // 0021 GETGBL R8 G8
|
||||||
|
0x5C240800, // 0022 MOVE R9 R4
|
||||||
|
0x7C200200, // 0023 CALL R8 1
|
||||||
|
0x981E1808, // 0024 SETIDX R7 K12 R8
|
||||||
|
0x60200008, // 0025 GETGBL R8 G8
|
||||||
|
0x5C240A00, // 0026 MOVE R9 R5
|
||||||
|
0x7C200200, // 0027 CALL R8 1
|
||||||
|
0x981E1A08, // 0028 SETIDX R7 K13 R8
|
||||||
|
0x98180207, // 0029 SETIDX R6 R1 R7
|
||||||
|
0x80000000, // 002A RET 0
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
/*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
** Solidified function: remove_light
|
||||||
|
********************************************************************/
|
||||||
|
be_local_closure(hue_bridge_monad_remove_light, /* name */
|
||||||
|
be_nested_proto(
|
||||||
|
5, /* nstack */
|
||||||
|
2, /* argc */
|
||||||
|
2, /* varg */
|
||||||
|
0, /* has upvals */
|
||||||
|
NULL, /* no upvals */
|
||||||
|
0, /* has sup protos */
|
||||||
|
NULL, /* no sub protos */
|
||||||
|
1, /* has constants */
|
||||||
|
( &(const bvalue[ 2]) { /* constants */
|
||||||
|
/* K0 */ be_nested_str(lights),
|
||||||
|
/* K1 */ be_nested_str(remove),
|
||||||
|
}),
|
||||||
|
&be_const_str_remove_light,
|
||||||
|
&be_const_str_solidified,
|
||||||
|
( &(const binstruction[ 5]) { /* code */
|
||||||
|
0x88080100, // 0000 GETMBR R2 R0 K0
|
||||||
|
0x8C080501, // 0001 GETMET R2 R2 K1
|
||||||
|
0x5C100200, // 0002 MOVE R4 R1
|
||||||
|
0x7C080400, // 0003 CALL R2 2
|
||||||
|
0x80000000, // 0004 RET 0
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
/*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
** Solidified function: init
|
||||||
|
********************************************************************/
|
||||||
|
be_local_closure(hue_bridge_monad_init, /* name */
|
||||||
|
be_nested_proto(
|
||||||
|
2, /* nstack */
|
||||||
|
1, /* argc */
|
||||||
|
2, /* varg */
|
||||||
|
0, /* has upvals */
|
||||||
|
NULL, /* no upvals */
|
||||||
|
0, /* has sup protos */
|
||||||
|
NULL, /* no sub protos */
|
||||||
|
1, /* has constants */
|
||||||
|
( &(const bvalue[ 1]) { /* constants */
|
||||||
|
/* K0 */ be_nested_str(lights),
|
||||||
|
}),
|
||||||
|
&be_const_str_init,
|
||||||
|
&be_const_str_solidified,
|
||||||
|
( &(const binstruction[ 4]) { /* code */
|
||||||
|
0x60040013, // 0000 GETGBL R1 G19
|
||||||
|
0x7C040000, // 0001 CALL R1 0
|
||||||
|
0x90020001, // 0002 SETMBR R0 K0 R1
|
||||||
|
0x80000000, // 0003 RET 0
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
/*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
** Solidified function: discover
|
||||||
|
********************************************************************/
|
||||||
|
be_local_closure(hue_bridge_monad_discover, /* name */
|
||||||
|
be_nested_proto(
|
||||||
|
11, /* nstack */
|
||||||
|
1, /* argc */
|
||||||
|
2, /* varg */
|
||||||
|
0, /* has upvals */
|
||||||
|
NULL, /* no upvals */
|
||||||
|
0, /* has sup protos */
|
||||||
|
NULL, /* no sub protos */
|
||||||
|
1, /* has constants */
|
||||||
|
( &(const bvalue[13]) { /* constants */
|
||||||
|
/* K0 */ be_nested_str(hue_ntv),
|
||||||
|
/* K1 */ be_nested_str(json),
|
||||||
|
/* K2 */ be_nested_str(string),
|
||||||
|
/* K3 */ be_nested_str(lights),
|
||||||
|
/* K4 */ be_nested_str(keys),
|
||||||
|
/* K5 */ be_nested_str(full_status),
|
||||||
|
/* K6 */ be_nested_str(_X22),
|
||||||
|
/* K7 */ be_nested_str(_X22_X3A),
|
||||||
|
/* K8 */ be_nested_str(push),
|
||||||
|
/* K9 */ be_nested_str(stop_iteration),
|
||||||
|
/* K10 */ be_const_int(0),
|
||||||
|
/* K11 */ be_nested_str(concat),
|
||||||
|
/* K12 */ be_nested_str(_X2C),
|
||||||
|
}),
|
||||||
|
&be_const_str_discover,
|
||||||
|
&be_const_str_solidified,
|
||||||
|
( &(const binstruction[40]) { /* code */
|
||||||
|
0xA4060000, // 0000 IMPORT R1 K0
|
||||||
|
0xA40A0200, // 0001 IMPORT R2 K1
|
||||||
|
0xA40E0400, // 0002 IMPORT R3 K2
|
||||||
|
0x60100012, // 0003 GETGBL R4 G18
|
||||||
|
0x7C100000, // 0004 CALL R4 0
|
||||||
|
0x60140010, // 0005 GETGBL R5 G16
|
||||||
|
0x88180103, // 0006 GETMBR R6 R0 K3
|
||||||
|
0x8C180D04, // 0007 GETMET R6 R6 K4
|
||||||
|
0x7C180200, // 0008 CALL R6 1
|
||||||
|
0x7C140200, // 0009 CALL R5 1
|
||||||
|
0xA802000F, // 000A EXBLK 0 #001B
|
||||||
|
0x5C180A00, // 000B MOVE R6 R5
|
||||||
|
0x7C180000, // 000C CALL R6 0
|
||||||
|
0x8C1C0105, // 000D GETMET R7 R0 K5
|
||||||
|
0x5C240C00, // 000E MOVE R9 R6
|
||||||
|
0x7C1C0400, // 000F CALL R7 2
|
||||||
|
0x781E0008, // 0010 JMPF R7 #001A
|
||||||
|
0x60200008, // 0011 GETGBL R8 G8
|
||||||
|
0x5C240C00, // 0012 MOVE R9 R6
|
||||||
|
0x7C200200, // 0013 CALL R8 1
|
||||||
|
0x00220C08, // 0014 ADD R8 K6 R8
|
||||||
|
0x00201107, // 0015 ADD R8 R8 K7
|
||||||
|
0x001C1007, // 0016 ADD R7 R8 R7
|
||||||
|
0x8C200908, // 0017 GETMET R8 R4 K8
|
||||||
|
0x5C280E00, // 0018 MOVE R10 R7
|
||||||
|
0x7C200400, // 0019 CALL R8 2
|
||||||
|
0x7001FFEF, // 001A JMP #000B
|
||||||
|
0x58140009, // 001B LDCONST R5 K9
|
||||||
|
0xAC140200, // 001C CATCH R5 1 0
|
||||||
|
0xB0080000, // 001D RAISE 2 R0 R0
|
||||||
|
0x6014000C, // 001E GETGBL R5 G12
|
||||||
|
0x5C180800, // 001F MOVE R6 R4
|
||||||
|
0x7C140200, // 0020 CALL R5 1
|
||||||
|
0x24140B0A, // 0021 GT R5 R5 K10
|
||||||
|
0x78160003, // 0022 JMPF R5 #0027
|
||||||
|
0x8C14090B, // 0023 GETMET R5 R4 K11
|
||||||
|
0x581C000C, // 0024 LDCONST R7 K12
|
||||||
|
0x7C140400, // 0025 CALL R5 2
|
||||||
|
0x80040A00, // 0026 RET 1 R5
|
||||||
|
0x80000000, // 0027 RET 0
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
/*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
** Solidified function: light_to_id
|
||||||
|
********************************************************************/
|
||||||
|
be_local_closure(hue_bridge_monad_light_to_id, /* name */
|
||||||
|
be_nested_proto(
|
||||||
|
5, /* nstack */
|
||||||
|
2, /* argc */
|
||||||
|
2, /* varg */
|
||||||
|
0, /* has upvals */
|
||||||
|
NULL, /* no upvals */
|
||||||
|
0, /* has sup protos */
|
||||||
|
NULL, /* no sub protos */
|
||||||
|
1, /* has constants */
|
||||||
|
( &(const bvalue[ 4]) { /* constants */
|
||||||
|
/* K0 */ be_nested_str(lights),
|
||||||
|
/* K1 */ be_nested_str(keys),
|
||||||
|
/* K2 */ be_nested_str(light),
|
||||||
|
/* K3 */ be_nested_str(stop_iteration),
|
||||||
|
}),
|
||||||
|
&be_const_str_light_to_id,
|
||||||
|
&be_const_str_solidified,
|
||||||
|
( &(const binstruction[20]) { /* code */
|
||||||
|
0x60080010, // 0000 GETGBL R2 G16
|
||||||
|
0x880C0100, // 0001 GETMBR R3 R0 K0
|
||||||
|
0x8C0C0701, // 0002 GETMET R3 R3 K1
|
||||||
|
0x7C0C0200, // 0003 CALL R3 1
|
||||||
|
0x7C080200, // 0004 CALL R2 1
|
||||||
|
0xA8020009, // 0005 EXBLK 0 #0010
|
||||||
|
0x5C0C0400, // 0006 MOVE R3 R2
|
||||||
|
0x7C0C0000, // 0007 CALL R3 0
|
||||||
|
0x88100100, // 0008 GETMBR R4 R0 K0
|
||||||
|
0x94100803, // 0009 GETIDX R4 R4 R3
|
||||||
|
0x94100902, // 000A GETIDX R4 R4 K2
|
||||||
|
0x1C100204, // 000B EQ R4 R1 R4
|
||||||
|
0x78120001, // 000C JMPF R4 #000F
|
||||||
|
0xA8040001, // 000D EXBLK 1 1
|
||||||
|
0x80040600, // 000E RET 1 R3
|
||||||
|
0x7001FFF5, // 000F JMP #0006
|
||||||
|
0x58080003, // 0010 LDCONST R2 K3
|
||||||
|
0xAC080200, // 0011 CATCH R2 1 0
|
||||||
|
0xB0080000, // 0012 RAISE 2 R0 R0
|
||||||
|
0x80000000, // 0013 RET 0
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
/*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
** Solidified function: cmd
|
** Solidified function: cmd
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
@ -228,37 +585,6 @@ be_local_closure(hue_bridge_monad_cmd, /* name */
|
|||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
** Solidified function: remove_light
|
|
||||||
********************************************************************/
|
|
||||||
be_local_closure(hue_bridge_monad_remove_light, /* name */
|
|
||||||
be_nested_proto(
|
|
||||||
5, /* nstack */
|
|
||||||
2, /* argc */
|
|
||||||
2, /* varg */
|
|
||||||
0, /* has upvals */
|
|
||||||
NULL, /* no upvals */
|
|
||||||
0, /* has sup protos */
|
|
||||||
NULL, /* no sub protos */
|
|
||||||
1, /* has constants */
|
|
||||||
( &(const bvalue[ 2]) { /* constants */
|
|
||||||
/* K0 */ be_nested_str(lights),
|
|
||||||
/* K1 */ be_nested_str(remove),
|
|
||||||
}),
|
|
||||||
&be_const_str_remove_light,
|
|
||||||
&be_const_str_solidified,
|
|
||||||
( &(const binstruction[ 5]) { /* code */
|
|
||||||
0x88080100, // 0000 GETMBR R2 R0 K0
|
|
||||||
0x8C080501, // 0001 GETMET R2 R2 K1
|
|
||||||
0x5C100200, // 0002 MOVE R4 R1
|
|
||||||
0x7C080400, // 0003 CALL R2 2
|
|
||||||
0x80000000, // 0004 RET 0
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
||||||
/*******************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
** Solidified function: groups
|
** Solidified function: groups
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
@ -322,301 +648,24 @@ be_local_closure(hue_bridge_monad_groups, /* name */
|
|||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
** Solidified function: hue_status
|
|
||||||
********************************************************************/
|
|
||||||
be_local_closure(hue_bridge_monad_hue_status, /* name */
|
|
||||||
be_nested_proto(
|
|
||||||
6, /* nstack */
|
|
||||||
2, /* argc */
|
|
||||||
2, /* varg */
|
|
||||||
0, /* has upvals */
|
|
||||||
NULL, /* no upvals */
|
|
||||||
0, /* has sup protos */
|
|
||||||
NULL, /* no sub protos */
|
|
||||||
1, /* has constants */
|
|
||||||
( &(const bvalue[ 5]) { /* constants */
|
|
||||||
/* K0 */ be_nested_str(hue_ntv),
|
|
||||||
/* K1 */ be_nested_str(lights),
|
|
||||||
/* K2 */ be_nested_str(contains),
|
|
||||||
/* K3 */ be_nested_str(light_state),
|
|
||||||
/* K4 */ be_nested_str(light),
|
|
||||||
}),
|
|
||||||
&be_const_str_hue_status,
|
|
||||||
&be_const_str_solidified,
|
|
||||||
( &(const binstruction[13]) { /* code */
|
|
||||||
0xA40A0000, // 0000 IMPORT R2 K0
|
|
||||||
0x880C0101, // 0001 GETMBR R3 R0 K1
|
|
||||||
0x8C0C0702, // 0002 GETMET R3 R3 K2
|
|
||||||
0x5C140200, // 0003 MOVE R5 R1
|
|
||||||
0x7C0C0400, // 0004 CALL R3 2
|
|
||||||
0x780E0005, // 0005 JMPF R3 #000C
|
|
||||||
0x8C0C0503, // 0006 GETMET R3 R2 K3
|
|
||||||
0x88140101, // 0007 GETMBR R5 R0 K1
|
|
||||||
0x94140A01, // 0008 GETIDX R5 R5 R1
|
|
||||||
0x94140B04, // 0009 GETIDX R5 R5 K4
|
|
||||||
0x7C0C0400, // 000A CALL R3 2
|
|
||||||
0x80040600, // 000B RET 1 R3
|
|
||||||
0x80000000, // 000C RET 0
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
||||||
/*******************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
** Solidified function: add_light
|
|
||||||
********************************************************************/
|
|
||||||
be_local_closure(hue_bridge_monad_add_light, /* name */
|
|
||||||
be_nested_proto(
|
|
||||||
10, /* nstack */
|
|
||||||
6, /* argc */
|
|
||||||
2, /* varg */
|
|
||||||
0, /* has upvals */
|
|
||||||
NULL, /* no upvals */
|
|
||||||
0, /* has sup protos */
|
|
||||||
NULL, /* no sub protos */
|
|
||||||
1, /* has constants */
|
|
||||||
( &(const bvalue[14]) { /* constants */
|
|
||||||
/* K0 */ be_nested_str(int),
|
|
||||||
/* K1 */ be_nested_str(value_error),
|
|
||||||
/* K2 */ be_nested_str(id_X20must_X20be_X20of_X20type_X20_X27int_X27),
|
|
||||||
/* K3 */ be_nested_str(light_state),
|
|
||||||
/* K4 */ be_nested_str(light_X20must_X20be_X20of_X20class_X20_X27light_state_X27),
|
|
||||||
/* K5 */ be_const_int(0),
|
|
||||||
/* K6 */ be_nested_str(missing_X20name),
|
|
||||||
/* K7 */ be_nested_str(Unknown),
|
|
||||||
/* K8 */ be_nested_str(Tasmota),
|
|
||||||
/* K9 */ be_nested_str(lights),
|
|
||||||
/* K10 */ be_nested_str(light),
|
|
||||||
/* K11 */ be_nested_str(name),
|
|
||||||
/* K12 */ be_nested_str(model),
|
|
||||||
/* K13 */ be_nested_str(manuf),
|
|
||||||
}),
|
|
||||||
&be_const_str_add_light,
|
|
||||||
&be_const_str_solidified,
|
|
||||||
( &(const binstruction[43]) { /* code */
|
|
||||||
0x60180004, // 0000 GETGBL R6 G4
|
|
||||||
0x5C1C0200, // 0001 MOVE R7 R1
|
|
||||||
0x7C180200, // 0002 CALL R6 1
|
|
||||||
0x20180D00, // 0003 NE R6 R6 K0
|
|
||||||
0x781A0000, // 0004 JMPF R6 #0006
|
|
||||||
0xB0060302, // 0005 RAISE 1 K1 K2
|
|
||||||
0x6018000F, // 0006 GETGBL R6 G15
|
|
||||||
0x5C1C0400, // 0007 MOVE R7 R2
|
|
||||||
0xB8220600, // 0008 GETNGBL R8 K3
|
|
||||||
0x7C180400, // 0009 CALL R6 2
|
|
||||||
0x741A0000, // 000A JMPT R6 #000C
|
|
||||||
0xB0060304, // 000B RAISE 1 K1 K4
|
|
||||||
0x60180008, // 000C GETGBL R6 G8
|
|
||||||
0x5C1C0600, // 000D MOVE R7 R3
|
|
||||||
0x7C180200, // 000E CALL R6 1
|
|
||||||
0x5C0C0C00, // 000F MOVE R3 R6
|
|
||||||
0x6018000C, // 0010 GETGBL R6 G12
|
|
||||||
0x5C1C0600, // 0011 MOVE R7 R3
|
|
||||||
0x7C180200, // 0012 CALL R6 1
|
|
||||||
0x1C180D05, // 0013 EQ R6 R6 K5
|
|
||||||
0x781A0000, // 0014 JMPF R6 #0016
|
|
||||||
0xB0060306, // 0015 RAISE 1 K1 K6
|
|
||||||
0x5C180800, // 0016 MOVE R6 R4
|
|
||||||
0x741A0000, // 0017 JMPT R6 #0019
|
|
||||||
0x58100007, // 0018 LDCONST R4 K7
|
|
||||||
0x5C180A00, // 0019 MOVE R6 R5
|
|
||||||
0x741A0000, // 001A JMPT R6 #001C
|
|
||||||
0x58140008, // 001B LDCONST R5 K8
|
|
||||||
0x88180109, // 001C GETMBR R6 R0 K9
|
|
||||||
0x601C0013, // 001D GETGBL R7 G19
|
|
||||||
0x7C1C0000, // 001E CALL R7 0
|
|
||||||
0x981E1402, // 001F SETIDX R7 K10 R2
|
|
||||||
0x981E1603, // 0020 SETIDX R7 K11 R3
|
|
||||||
0x60200008, // 0021 GETGBL R8 G8
|
|
||||||
0x5C240800, // 0022 MOVE R9 R4
|
|
||||||
0x7C200200, // 0023 CALL R8 1
|
|
||||||
0x981E1808, // 0024 SETIDX R7 K12 R8
|
|
||||||
0x60200008, // 0025 GETGBL R8 G8
|
|
||||||
0x5C240A00, // 0026 MOVE R9 R5
|
|
||||||
0x7C200200, // 0027 CALL R8 1
|
|
||||||
0x981E1A08, // 0028 SETIDX R7 K13 R8
|
|
||||||
0x98180207, // 0029 SETIDX R6 R1 R7
|
|
||||||
0x80000000, // 002A RET 0
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
||||||
/*******************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
** Solidified function: init
|
|
||||||
********************************************************************/
|
|
||||||
be_local_closure(hue_bridge_monad_init, /* name */
|
|
||||||
be_nested_proto(
|
|
||||||
2, /* nstack */
|
|
||||||
1, /* argc */
|
|
||||||
2, /* varg */
|
|
||||||
0, /* has upvals */
|
|
||||||
NULL, /* no upvals */
|
|
||||||
0, /* has sup protos */
|
|
||||||
NULL, /* no sub protos */
|
|
||||||
1, /* has constants */
|
|
||||||
( &(const bvalue[ 1]) { /* constants */
|
|
||||||
/* K0 */ be_nested_str(lights),
|
|
||||||
}),
|
|
||||||
&be_const_str_init,
|
|
||||||
&be_const_str_solidified,
|
|
||||||
( &(const binstruction[ 4]) { /* code */
|
|
||||||
0x60040013, // 0000 GETGBL R1 G19
|
|
||||||
0x7C040000, // 0001 CALL R1 0
|
|
||||||
0x90020001, // 0002 SETMBR R0 K0 R1
|
|
||||||
0x80000000, // 0003 RET 0
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
||||||
/*******************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
** Solidified function: discover
|
|
||||||
********************************************************************/
|
|
||||||
be_local_closure(hue_bridge_monad_discover, /* name */
|
|
||||||
be_nested_proto(
|
|
||||||
11, /* nstack */
|
|
||||||
1, /* argc */
|
|
||||||
2, /* varg */
|
|
||||||
0, /* has upvals */
|
|
||||||
NULL, /* no upvals */
|
|
||||||
0, /* has sup protos */
|
|
||||||
NULL, /* no sub protos */
|
|
||||||
1, /* has constants */
|
|
||||||
( &(const bvalue[13]) { /* constants */
|
|
||||||
/* K0 */ be_nested_str(hue_ntv),
|
|
||||||
/* K1 */ be_nested_str(json),
|
|
||||||
/* K2 */ be_nested_str(string),
|
|
||||||
/* K3 */ be_nested_str(lights),
|
|
||||||
/* K4 */ be_nested_str(keys),
|
|
||||||
/* K5 */ be_nested_str(full_status),
|
|
||||||
/* K6 */ be_nested_str(_X22),
|
|
||||||
/* K7 */ be_nested_str(_X22_X3A),
|
|
||||||
/* K8 */ be_nested_str(push),
|
|
||||||
/* K9 */ be_nested_str(stop_iteration),
|
|
||||||
/* K10 */ be_const_int(0),
|
|
||||||
/* K11 */ be_nested_str(concat),
|
|
||||||
/* K12 */ be_nested_str(_X2C),
|
|
||||||
}),
|
|
||||||
&be_const_str_discover,
|
|
||||||
&be_const_str_solidified,
|
|
||||||
( &(const binstruction[40]) { /* code */
|
|
||||||
0xA4060000, // 0000 IMPORT R1 K0
|
|
||||||
0xA40A0200, // 0001 IMPORT R2 K1
|
|
||||||
0xA40E0400, // 0002 IMPORT R3 K2
|
|
||||||
0x60100012, // 0003 GETGBL R4 G18
|
|
||||||
0x7C100000, // 0004 CALL R4 0
|
|
||||||
0x60140010, // 0005 GETGBL R5 G16
|
|
||||||
0x88180103, // 0006 GETMBR R6 R0 K3
|
|
||||||
0x8C180D04, // 0007 GETMET R6 R6 K4
|
|
||||||
0x7C180200, // 0008 CALL R6 1
|
|
||||||
0x7C140200, // 0009 CALL R5 1
|
|
||||||
0xA802000F, // 000A EXBLK 0 #001B
|
|
||||||
0x5C180A00, // 000B MOVE R6 R5
|
|
||||||
0x7C180000, // 000C CALL R6 0
|
|
||||||
0x8C1C0105, // 000D GETMET R7 R0 K5
|
|
||||||
0x5C240C00, // 000E MOVE R9 R6
|
|
||||||
0x7C1C0400, // 000F CALL R7 2
|
|
||||||
0x781E0008, // 0010 JMPF R7 #001A
|
|
||||||
0x60200008, // 0011 GETGBL R8 G8
|
|
||||||
0x5C240C00, // 0012 MOVE R9 R6
|
|
||||||
0x7C200200, // 0013 CALL R8 1
|
|
||||||
0x00220C08, // 0014 ADD R8 K6 R8
|
|
||||||
0x00201107, // 0015 ADD R8 R8 K7
|
|
||||||
0x001C1007, // 0016 ADD R7 R8 R7
|
|
||||||
0x8C200908, // 0017 GETMET R8 R4 K8
|
|
||||||
0x5C280E00, // 0018 MOVE R10 R7
|
|
||||||
0x7C200400, // 0019 CALL R8 2
|
|
||||||
0x7001FFEF, // 001A JMP #000B
|
|
||||||
0x58140009, // 001B LDCONST R5 K9
|
|
||||||
0xAC140200, // 001C CATCH R5 1 0
|
|
||||||
0xB0080000, // 001D RAISE 2 R0 R0
|
|
||||||
0x6014000C, // 001E GETGBL R5 G12
|
|
||||||
0x5C180800, // 001F MOVE R6 R4
|
|
||||||
0x7C140200, // 0020 CALL R5 1
|
|
||||||
0x24140B0A, // 0021 GT R5 R5 K10
|
|
||||||
0x78160003, // 0022 JMPF R5 #0027
|
|
||||||
0x8C14090B, // 0023 GETMET R5 R4 K11
|
|
||||||
0x581C000C, // 0024 LDCONST R7 K12
|
|
||||||
0x7C140400, // 0025 CALL R5 2
|
|
||||||
0x80040A00, // 0026 RET 1 R5
|
|
||||||
0x80000000, // 0027 RET 0
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
||||||
/*******************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
** Solidified function: full_status
|
|
||||||
********************************************************************/
|
|
||||||
be_local_closure(hue_bridge_monad_full_status, /* name */
|
|
||||||
be_nested_proto(
|
|
||||||
11, /* nstack */
|
|
||||||
2, /* argc */
|
|
||||||
2, /* varg */
|
|
||||||
0, /* has upvals */
|
|
||||||
NULL, /* no upvals */
|
|
||||||
0, /* has sup protos */
|
|
||||||
NULL, /* no sub protos */
|
|
||||||
1, /* has constants */
|
|
||||||
( &(const bvalue[ 8]) { /* constants */
|
|
||||||
/* K0 */ be_nested_str(hue_ntv),
|
|
||||||
/* K1 */ be_nested_str(lights),
|
|
||||||
/* K2 */ be_nested_str(contains),
|
|
||||||
/* K3 */ be_nested_str(full_state),
|
|
||||||
/* K4 */ be_nested_str(light),
|
|
||||||
/* K5 */ be_nested_str(name),
|
|
||||||
/* K6 */ be_nested_str(model),
|
|
||||||
/* K7 */ be_nested_str(manuf),
|
|
||||||
}),
|
|
||||||
&be_const_str_full_status,
|
|
||||||
&be_const_str_solidified,
|
|
||||||
( &(const binstruction[17]) { /* code */
|
|
||||||
0xA40A0000, // 0000 IMPORT R2 K0
|
|
||||||
0x880C0101, // 0001 GETMBR R3 R0 K1
|
|
||||||
0x8C0C0702, // 0002 GETMET R3 R3 K2
|
|
||||||
0x5C140200, // 0003 MOVE R5 R1
|
|
||||||
0x7C0C0400, // 0004 CALL R3 2
|
|
||||||
0x780E0009, // 0005 JMPF R3 #0010
|
|
||||||
0x880C0101, // 0006 GETMBR R3 R0 K1
|
|
||||||
0x940C0601, // 0007 GETIDX R3 R3 R1
|
|
||||||
0x8C100503, // 0008 GETMET R4 R2 K3
|
|
||||||
0x5C180200, // 0009 MOVE R6 R1
|
|
||||||
0x941C0704, // 000A GETIDX R7 R3 K4
|
|
||||||
0x94200705, // 000B GETIDX R8 R3 K5
|
|
||||||
0x94240706, // 000C GETIDX R9 R3 K6
|
|
||||||
0x94280707, // 000D GETIDX R10 R3 K7
|
|
||||||
0x7C100C00, // 000E CALL R4 6
|
|
||||||
0x80040800, // 000F RET 1 R4
|
|
||||||
0x80000000, // 0010 RET 0
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
||||||
/*******************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
** Solidified class: hue_bridge_monad
|
** Solidified class: hue_bridge_monad
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
be_local_class(hue_bridge_monad,
|
be_local_class(hue_bridge_monad,
|
||||||
1,
|
1,
|
||||||
NULL,
|
NULL,
|
||||||
be_nested_map(9,
|
be_nested_map(10,
|
||||||
( (struct bmapnode*) &(const bmapnode[]) {
|
( (struct bmapnode*) &(const bmapnode[]) {
|
||||||
{ be_const_key(lights, 1), be_const_var(0) },
|
{ be_const_key(lights, -1), be_const_var(0) },
|
||||||
{ be_const_key(groups, -1), be_const_closure(hue_bridge_monad_groups_closure) },
|
{ be_const_key(groups, 6), be_const_closure(hue_bridge_monad_groups_closure) },
|
||||||
{ be_const_key(remove_light, 3), be_const_closure(hue_bridge_monad_remove_light_closure) },
|
|
||||||
{ be_const_key(discover, -1), be_const_closure(hue_bridge_monad_discover_closure) },
|
|
||||||
{ be_const_key(hue_status, -1), be_const_closure(hue_bridge_monad_hue_status_closure) },
|
{ be_const_key(hue_status, -1), be_const_closure(hue_bridge_monad_hue_status_closure) },
|
||||||
{ be_const_key(add_light, -1), be_const_closure(hue_bridge_monad_add_light_closure) },
|
{ be_const_key(add_light, -1), be_const_closure(hue_bridge_monad_add_light_closure) },
|
||||||
{ be_const_key(cmd, 7), be_const_closure(hue_bridge_monad_cmd_closure) },
|
{ be_const_key(remove_light, 8), be_const_closure(hue_bridge_monad_remove_light_closure) },
|
||||||
{ be_const_key(init, -1), be_const_closure(hue_bridge_monad_init_closure) },
|
{ be_const_key(init, -1), be_const_closure(hue_bridge_monad_init_closure) },
|
||||||
{ be_const_key(full_status, -1), be_const_closure(hue_bridge_monad_full_status_closure) },
|
{ be_const_key(cmd, -1), be_const_closure(hue_bridge_monad_cmd_closure) },
|
||||||
|
{ be_const_key(light_to_id, -1), be_const_closure(hue_bridge_monad_light_to_id_closure) },
|
||||||
|
{ be_const_key(discover, -1), be_const_closure(hue_bridge_monad_discover_closure) },
|
||||||
|
{ be_const_key(full_status, 1), be_const_closure(hue_bridge_monad_full_status_closure) },
|
||||||
})),
|
})),
|
||||||
be_str_literal("hue_bridge_monad")
|
be_str_literal("hue_bridge_monad")
|
||||||
);
|
);
|
||||||
|
21
lib/libesp32/berry_tasmota/src/be_mqtt_lib.cpp
Normal file
21
lib/libesp32/berry_tasmota/src/be_mqtt_lib.cpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/********************************************************************
|
||||||
|
* Berry module `mqtt`
|
||||||
|
*
|
||||||
|
*******************************************************************/
|
||||||
|
|
||||||
|
#include "be_constobj.h"
|
||||||
|
#include "be_mapping.h"
|
||||||
|
|
||||||
|
extern int be_mqtt_publish(bvm *vm);
|
||||||
|
|
||||||
|
extern void be_mqtt_subscribe(const char* topic); BE_FUNC_CTYPE_DECLARE(be_mqtt_subscribe, "", "s")
|
||||||
|
extern void be_mqtt_unsubscribe(const char* topic); BE_FUNC_CTYPE_DECLARE(be_mqtt_unsubscribe, "", "s")
|
||||||
|
|
||||||
|
/* @const_object_info_begin
|
||||||
|
module mqtt (scope: global) {
|
||||||
|
publish, func(be_mqtt_publish)
|
||||||
|
subscribe, ctype_func(be_mqtt_subscribe)
|
||||||
|
unsubscribe, ctype_func(be_mqtt_unsubscribe)
|
||||||
|
}
|
||||||
|
@const_object_info_end */
|
||||||
|
#include "be_fixed_mqtt.h"
|
@ -487,8 +487,8 @@ be_local_closure(Tasmota_exec_tele, /* name */
|
|||||||
/* K6 */ be_nested_str(Tele),
|
/* K6 */ be_nested_str(Tele),
|
||||||
/* K7 */ be_const_int(0),
|
/* K7 */ be_const_int(0),
|
||||||
/* K8 */ be_nested_str(try_rule),
|
/* K8 */ be_nested_str(try_rule),
|
||||||
/* K9 */ be_nested_str(k),
|
/* K9 */ be_nested_str(trig),
|
||||||
/* K10 */ be_nested_str(v),
|
/* K10 */ be_nested_str(f),
|
||||||
/* K11 */ be_const_int(1),
|
/* K11 */ be_const_int(1),
|
||||||
}),
|
}),
|
||||||
&be_const_str_exec_tele,
|
&be_const_str_exec_tele,
|
||||||
@ -559,7 +559,7 @@ be_local_closure(Tasmota_run_deferred, /* name */
|
|||||||
/* K1 */ be_const_int(0),
|
/* K1 */ be_const_int(0),
|
||||||
/* K2 */ be_nested_str(size),
|
/* K2 */ be_nested_str(size),
|
||||||
/* K3 */ be_nested_str(time_reached),
|
/* K3 */ be_nested_str(time_reached),
|
||||||
/* K4 */ be_nested_str(due),
|
/* K4 */ be_nested_str(trig),
|
||||||
/* K5 */ be_nested_str(f),
|
/* K5 */ be_nested_str(f),
|
||||||
/* K6 */ be_nested_str(remove),
|
/* K6 */ be_nested_str(remove),
|
||||||
/* K7 */ be_const_int(1),
|
/* K7 */ be_const_int(1),
|
||||||
@ -1123,45 +1123,51 @@ be_local_closure(Tasmota_time_str, /* name */
|
|||||||
********************************************************************/
|
********************************************************************/
|
||||||
be_local_closure(Tasmota_remove_rule, /* name */
|
be_local_closure(Tasmota_remove_rule, /* name */
|
||||||
be_nested_proto(
|
be_nested_proto(
|
||||||
6, /* nstack */
|
7, /* nstack */
|
||||||
2, /* argc */
|
3, /* argc */
|
||||||
2, /* varg */
|
2, /* varg */
|
||||||
0, /* has upvals */
|
0, /* has upvals */
|
||||||
NULL, /* no upvals */
|
NULL, /* no upvals */
|
||||||
0, /* has sup protos */
|
0, /* has sup protos */
|
||||||
NULL, /* no sub protos */
|
NULL, /* no sub protos */
|
||||||
1, /* has constants */
|
1, /* has constants */
|
||||||
( &(const bvalue[ 5]) { /* constants */
|
( &(const bvalue[ 6]) { /* constants */
|
||||||
/* K0 */ be_nested_str(_rules),
|
/* K0 */ be_nested_str(_rules),
|
||||||
/* K1 */ be_const_int(0),
|
/* K1 */ be_const_int(0),
|
||||||
/* K2 */ be_nested_str(k),
|
/* K2 */ be_nested_str(trig),
|
||||||
/* K3 */ be_nested_str(remove),
|
/* K3 */ be_nested_str(id),
|
||||||
/* K4 */ be_const_int(1),
|
/* K4 */ be_nested_str(remove),
|
||||||
|
/* K5 */ be_const_int(1),
|
||||||
}),
|
}),
|
||||||
&be_const_str_remove_rule,
|
&be_const_str_remove_rule,
|
||||||
&be_const_str_solidified,
|
&be_const_str_solidified,
|
||||||
( &(const binstruction[21]) { /* code */
|
( &(const binstruction[26]) { /* code */
|
||||||
0x88080100, // 0000 GETMBR R2 R0 K0
|
0x880C0100, // 0000 GETMBR R3 R0 K0
|
||||||
0x780A0011, // 0001 JMPF R2 #0014
|
0x780E0016, // 0001 JMPF R3 #0019
|
||||||
0x58080001, // 0002 LDCONST R2 K1
|
0x580C0001, // 0002 LDCONST R3 K1
|
||||||
0x600C000C, // 0003 GETGBL R3 G12
|
0x6010000C, // 0003 GETGBL R4 G12
|
||||||
0x88100100, // 0004 GETMBR R4 R0 K0
|
0x88140100, // 0004 GETMBR R5 R0 K0
|
||||||
0x7C0C0200, // 0005 CALL R3 1
|
0x7C100200, // 0005 CALL R4 1
|
||||||
0x140C0403, // 0006 LT R3 R2 R3
|
0x14100604, // 0006 LT R4 R3 R4
|
||||||
0x780E000B, // 0007 JMPF R3 #0014
|
0x78120010, // 0007 JMPF R4 #0019
|
||||||
0x880C0100, // 0008 GETMBR R3 R0 K0
|
0x88100100, // 0008 GETMBR R4 R0 K0
|
||||||
0x940C0602, // 0009 GETIDX R3 R3 R2
|
0x94100803, // 0009 GETIDX R4 R4 R3
|
||||||
0x880C0702, // 000A GETMBR R3 R3 K2
|
0x88100902, // 000A GETMBR R4 R4 K2
|
||||||
0x1C0C0601, // 000B EQ R3 R3 R1
|
0x1C100801, // 000B EQ R4 R4 R1
|
||||||
0x780E0004, // 000C JMPF R3 #0012
|
0x78120009, // 000C JMPF R4 #0017
|
||||||
0x880C0100, // 000D GETMBR R3 R0 K0
|
0x88100100, // 000D GETMBR R4 R0 K0
|
||||||
0x8C0C0703, // 000E GETMET R3 R3 K3
|
0x94100803, // 000E GETIDX R4 R4 R3
|
||||||
0x5C140400, // 000F MOVE R5 R2
|
0x88100903, // 000F GETMBR R4 R4 K3
|
||||||
0x7C0C0400, // 0010 CALL R3 2
|
0x1C100802, // 0010 EQ R4 R4 R2
|
||||||
0x70020000, // 0011 JMP #0013
|
0x78120004, // 0011 JMPF R4 #0017
|
||||||
0x00080504, // 0012 ADD R2 R2 K4
|
0x88100100, // 0012 GETMBR R4 R0 K0
|
||||||
0x7001FFEE, // 0013 JMP #0003
|
0x8C100904, // 0013 GETMET R4 R4 K4
|
||||||
0x80000000, // 0014 RET 0
|
0x5C180600, // 0014 MOVE R6 R3
|
||||||
|
0x7C100400, // 0015 CALL R4 2
|
||||||
|
0x70020000, // 0016 JMP #0018
|
||||||
|
0x000C0705, // 0017 ADD R3 R3 K5
|
||||||
|
0x7001FFE9, // 0018 JMP #0003
|
||||||
|
0x80000000, // 0019 RET 0
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -1550,8 +1556,8 @@ be_local_closure(Tasmota_add_cmd, /* name */
|
|||||||
********************************************************************/
|
********************************************************************/
|
||||||
be_local_closure(Tasmota_add_rule, /* name */
|
be_local_closure(Tasmota_add_rule, /* name */
|
||||||
be_nested_proto(
|
be_nested_proto(
|
||||||
9, /* nstack */
|
10, /* nstack */
|
||||||
3, /* argc */
|
4, /* argc */
|
||||||
2, /* varg */
|
2, /* varg */
|
||||||
0, /* has upvals */
|
0, /* has upvals */
|
||||||
NULL, /* no upvals */
|
NULL, /* no upvals */
|
||||||
@ -1563,36 +1569,37 @@ be_local_closure(Tasmota_add_rule, /* name */
|
|||||||
/* K1 */ be_nested_str(_rules),
|
/* K1 */ be_nested_str(_rules),
|
||||||
/* K2 */ be_nested_str(function),
|
/* K2 */ be_nested_str(function),
|
||||||
/* K3 */ be_nested_str(push),
|
/* K3 */ be_nested_str(push),
|
||||||
/* K4 */ be_nested_str(kv),
|
/* K4 */ be_nested_str(Trigger),
|
||||||
/* K5 */ be_nested_str(value_error),
|
/* K5 */ be_nested_str(value_error),
|
||||||
/* K6 */ be_nested_str(the_X20second_X20argument_X20is_X20not_X20a_X20function),
|
/* K6 */ be_nested_str(the_X20second_X20argument_X20is_X20not_X20a_X20function),
|
||||||
}),
|
}),
|
||||||
&be_const_str_add_rule,
|
&be_const_str_add_rule,
|
||||||
&be_const_str_solidified,
|
&be_const_str_solidified,
|
||||||
( &(const binstruction[23]) { /* code */
|
( &(const binstruction[24]) { /* code */
|
||||||
0x8C0C0100, // 0000 GETMET R3 R0 K0
|
0x8C100100, // 0000 GETMET R4 R0 K0
|
||||||
0x5C140400, // 0001 MOVE R5 R2
|
0x5C180400, // 0001 MOVE R6 R2
|
||||||
0x7C0C0400, // 0002 CALL R3 2
|
0x7C100400, // 0002 CALL R4 2
|
||||||
0x880C0101, // 0003 GETMBR R3 R0 K1
|
0x88100101, // 0003 GETMBR R4 R0 K1
|
||||||
0x740E0002, // 0004 JMPT R3 #0008
|
0x74120002, // 0004 JMPT R4 #0008
|
||||||
0x600C0012, // 0005 GETGBL R3 G18
|
0x60100012, // 0005 GETGBL R4 G18
|
||||||
0x7C0C0000, // 0006 CALL R3 0
|
0x7C100000, // 0006 CALL R4 0
|
||||||
0x90020203, // 0007 SETMBR R0 K1 R3
|
0x90020204, // 0007 SETMBR R0 K1 R4
|
||||||
0x600C0004, // 0008 GETGBL R3 G4
|
0x60100004, // 0008 GETGBL R4 G4
|
||||||
0x5C100400, // 0009 MOVE R4 R2
|
0x5C140400, // 0009 MOVE R5 R2
|
||||||
0x7C0C0200, // 000A CALL R3 1
|
0x7C100200, // 000A CALL R4 1
|
||||||
0x1C0C0702, // 000B EQ R3 R3 K2
|
0x1C100902, // 000B EQ R4 R4 K2
|
||||||
0x780E0007, // 000C JMPF R3 #0015
|
0x78120008, // 000C JMPF R4 #0016
|
||||||
0x880C0101, // 000D GETMBR R3 R0 K1
|
0x88100101, // 000D GETMBR R4 R0 K1
|
||||||
0x8C0C0703, // 000E GETMET R3 R3 K3
|
0x8C100903, // 000E GETMET R4 R4 K3
|
||||||
0x8C140104, // 000F GETMET R5 R0 K4
|
0xB81A0800, // 000F GETNGBL R6 K4
|
||||||
0x5C1C0200, // 0010 MOVE R7 R1
|
0x5C1C0200, // 0010 MOVE R7 R1
|
||||||
0x5C200400, // 0011 MOVE R8 R2
|
0x5C200400, // 0011 MOVE R8 R2
|
||||||
0x7C140600, // 0012 CALL R5 3
|
0x5C240600, // 0012 MOVE R9 R3
|
||||||
0x7C0C0400, // 0013 CALL R3 2
|
0x7C180600, // 0013 CALL R6 3
|
||||||
0x70020000, // 0014 JMP #0016
|
0x7C100400, // 0014 CALL R4 2
|
||||||
0xB0060B06, // 0015 RAISE 1 K5 K6
|
0x70020000, // 0015 JMP #0017
|
||||||
0x80000000, // 0016 RET 0
|
0xB0060B06, // 0016 RAISE 1 K5 K6
|
||||||
|
0x80000000, // 0017 RET 0
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -1622,8 +1629,8 @@ be_local_closure(Tasmota_exec_rules, /* name */
|
|||||||
/* K6 */ be_const_int(3),
|
/* K6 */ be_const_int(3),
|
||||||
/* K7 */ be_const_int(0),
|
/* K7 */ be_const_int(0),
|
||||||
/* K8 */ be_nested_str(try_rule),
|
/* K8 */ be_nested_str(try_rule),
|
||||||
/* K9 */ be_nested_str(k),
|
/* K9 */ be_nested_str(trig),
|
||||||
/* K10 */ be_nested_str(v),
|
/* K10 */ be_nested_str(f),
|
||||||
/* K11 */ be_const_int(1),
|
/* K11 */ be_const_int(1),
|
||||||
}),
|
}),
|
||||||
&be_const_str_exec_rules,
|
&be_const_str_exec_rules,
|
||||||
@ -1907,7 +1914,7 @@ be_local_closure(Tasmota_set_timer, /* name */
|
|||||||
/* K0 */ be_nested_str(check_not_method),
|
/* K0 */ be_nested_str(check_not_method),
|
||||||
/* K1 */ be_nested_str(_timers),
|
/* K1 */ be_nested_str(_timers),
|
||||||
/* K2 */ be_nested_str(push),
|
/* K2 */ be_nested_str(push),
|
||||||
/* K3 */ be_nested_str(Timer),
|
/* K3 */ be_nested_str(Trigger),
|
||||||
/* K4 */ be_nested_str(millis),
|
/* K4 */ be_nested_str(millis),
|
||||||
}),
|
}),
|
||||||
&be_const_str_set_timer,
|
&be_const_str_set_timer,
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
/********************************************************************
|
/********************************************************************
|
||||||
* Tasmota lib
|
* Tasmota lib
|
||||||
*
|
*
|
||||||
* class Timer
|
* class Trigger
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
#include "be_constobj.h"
|
#include "be_constobj.h"
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
** Solidified function: tostring
|
** Solidified function: tostring
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
be_local_closure(Timer_tostring, /* name */
|
be_local_closure(Trigger_tostring, /* name */
|
||||||
be_nested_proto(
|
be_nested_proto(
|
||||||
10, /* nstack */
|
10, /* nstack */
|
||||||
1, /* argc */
|
1, /* argc */
|
||||||
0, /* varg */
|
2, /* varg */
|
||||||
0, /* has upvals */
|
0, /* has upvals */
|
||||||
NULL, /* no upvals */
|
NULL, /* no upvals */
|
||||||
0, /* has sup protos */
|
0, /* has sup protos */
|
||||||
@ -22,7 +22,7 @@ be_local_closure(Timer_tostring, /* name */
|
|||||||
/* K0 */ be_nested_str(string),
|
/* K0 */ be_nested_str(string),
|
||||||
/* K1 */ be_nested_str(format),
|
/* K1 */ be_nested_str(format),
|
||||||
/* K2 */ be_nested_str(_X3Cinstance_X3A_X20_X25s_X28_X25s_X2C_X20_X25s_X2C_X20_X25s_X29),
|
/* K2 */ be_nested_str(_X3Cinstance_X3A_X20_X25s_X28_X25s_X2C_X20_X25s_X2C_X20_X25s_X29),
|
||||||
/* K3 */ be_nested_str(due),
|
/* K3 */ be_nested_str(trig),
|
||||||
/* K4 */ be_nested_str(f),
|
/* K4 */ be_nested_str(f),
|
||||||
/* K5 */ be_nested_str(id),
|
/* K5 */ be_nested_str(id),
|
||||||
}),
|
}),
|
||||||
@ -57,18 +57,18 @@ be_local_closure(Timer_tostring, /* name */
|
|||||||
/********************************************************************
|
/********************************************************************
|
||||||
** Solidified function: init
|
** Solidified function: init
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
be_local_closure(Timer_init, /* name */
|
be_local_closure(Trigger_init, /* name */
|
||||||
be_nested_proto(
|
be_nested_proto(
|
||||||
4, /* nstack */
|
4, /* nstack */
|
||||||
4, /* argc */
|
4, /* argc */
|
||||||
0, /* varg */
|
2, /* varg */
|
||||||
0, /* has upvals */
|
0, /* has upvals */
|
||||||
NULL, /* no upvals */
|
NULL, /* no upvals */
|
||||||
0, /* has sup protos */
|
0, /* has sup protos */
|
||||||
NULL, /* no sub protos */
|
NULL, /* no sub protos */
|
||||||
1, /* has constants */
|
1, /* has constants */
|
||||||
( &(const bvalue[ 3]) { /* constants */
|
( &(const bvalue[ 3]) { /* constants */
|
||||||
/* K0 */ be_nested_str(due),
|
/* K0 */ be_nested_str(trig),
|
||||||
/* K1 */ be_nested_str(f),
|
/* K1 */ be_nested_str(f),
|
||||||
/* K2 */ be_nested_str(id),
|
/* K2 */ be_nested_str(id),
|
||||||
}),
|
}),
|
||||||
@ -86,25 +86,25 @@ be_local_closure(Timer_init, /* name */
|
|||||||
|
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
** Solidified class: Timer
|
** Solidified class: Trigger
|
||||||
********************************************************************/
|
********************************************************************/
|
||||||
be_local_class(Timer,
|
be_local_class(Trigger,
|
||||||
3,
|
3,
|
||||||
NULL,
|
NULL,
|
||||||
be_nested_map(5,
|
be_nested_map(5,
|
||||||
( (struct bmapnode*) &(const bmapnode[]) {
|
( (struct bmapnode*) &(const bmapnode[]) {
|
||||||
{ be_const_key(tostring, 4), be_const_closure(Timer_tostring_closure) },
|
{ be_const_key(tostring, 3), be_const_closure(Trigger_tostring_closure) },
|
||||||
{ be_const_key(id, 2), be_const_var(2) },
|
{ be_const_key(id, 2), be_const_var(2) },
|
||||||
{ be_const_key(f, -1), be_const_var(1) },
|
{ be_const_key(f, -1), be_const_var(1) },
|
||||||
{ be_const_key(due, -1), be_const_var(0) },
|
{ be_const_key(init, -1), be_const_closure(Trigger_init_closure) },
|
||||||
{ be_const_key(init, -1), be_const_closure(Timer_init_closure) },
|
{ be_const_key(trig, -1), be_const_var(0) },
|
||||||
})),
|
})),
|
||||||
be_str_literal("Timer")
|
be_str_literal("Trigger")
|
||||||
);
|
);
|
||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
|
|
||||||
void be_load_Timer_class(bvm *vm) {
|
void be_load_Trigger_class(bvm *vm) {
|
||||||
be_pushntvclass(vm, &be_class_Timer);
|
be_pushntvclass(vm, &be_class_Trigger);
|
||||||
be_setglobal(vm, "Timer");
|
be_setglobal(vm, "Trigger");
|
||||||
be_pop(vm, 1);
|
be_pop(vm, 1);
|
||||||
}
|
}
|
@ -1,17 +1,17 @@
|
|||||||
#- Native code used for testing and code solidification -#
|
#- Native code used for testing and code solidification -#
|
||||||
#- Do not use it -#
|
#- Do not use it -#
|
||||||
|
|
||||||
class Timer
|
class Trigger
|
||||||
var due, f, id
|
var trig, f, id
|
||||||
def init(due, f, id)
|
def init(trig, f, id)
|
||||||
self.due = due
|
self.trig = trig
|
||||||
self.f = f
|
self.f = f
|
||||||
self.id = id
|
self.id = id
|
||||||
end
|
end
|
||||||
def tostring()
|
def tostring()
|
||||||
import string
|
import string
|
||||||
return string.format("<instance: %s(%s, %s, %s)", str(classof(self)),
|
return string.format("<instance: %s(%s, %s, %s)", str(classof(self)),
|
||||||
str(self.due), str(self.f), str(self.id))
|
str(self.trig), str(self.f), str(self.id))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -58,20 +58,6 @@ class Tasmota
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# create a specific sub-class for rules: pattern(string) -> closure
|
|
||||||
# Classs KV has two members k and v
|
|
||||||
def kv(k, v)
|
|
||||||
class KV
|
|
||||||
var k, v
|
|
||||||
def init(k,v)
|
|
||||||
self.k = k
|
|
||||||
self.v = v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return KV(k, v)
|
|
||||||
end
|
|
||||||
|
|
||||||
# add `chars_in_string(s:string,c:string) -> int``
|
# add `chars_in_string(s:string,c:string) -> int``
|
||||||
# looks for any char in c, and return the position of the first char
|
# looks for any char in c, and return the position of the first char
|
||||||
# or -1 if not found
|
# or -1 if not found
|
||||||
@ -130,23 +116,23 @@ class Tasmota
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Rules
|
# Rules
|
||||||
def add_rule(pat,f)
|
def add_rule(pat, f, id)
|
||||||
self.check_not_method(f)
|
self.check_not_method(f)
|
||||||
if !self._rules
|
if !self._rules
|
||||||
self._rules=[]
|
self._rules=[]
|
||||||
end
|
end
|
||||||
if type(f) == 'function'
|
if type(f) == 'function'
|
||||||
self._rules.push(self.kv(pat, f))
|
self._rules.push(Trigger(pat, f, id))
|
||||||
else
|
else
|
||||||
raise 'value_error', 'the second argument is not a function'
|
raise 'value_error', 'the second argument is not a function'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def remove_rule(pat)
|
def remove_rule(pat, id)
|
||||||
if self._rules
|
if self._rules
|
||||||
var i = 0
|
var i = 0
|
||||||
while i < size(self._rules)
|
while i < size(self._rules)
|
||||||
if self._rules[i].k == pat
|
if self._rules[i].trig == pat && self._rules[i].id == id
|
||||||
self._rules.remove(i) #- don't increment i since we removed the object -#
|
self._rules.remove(i) #- don't increment i since we removed the object -#
|
||||||
else
|
else
|
||||||
i += 1
|
i += 1
|
||||||
@ -214,8 +200,8 @@ class Tasmota
|
|||||||
if self._rules
|
if self._rules
|
||||||
var i = 0
|
var i = 0
|
||||||
while i < size(self._rules)
|
while i < size(self._rules)
|
||||||
var kv = self._rules[i]
|
var tr = self._rules[i]
|
||||||
ret = self.try_rule(ev,kv.k,kv.v) || ret #- call should be first to avoid evaluation shortcut if ret is already true -#
|
ret = self.try_rule(ev,tr.trig,tr.f) || ret #- call should be first to avoid evaluation shortcut if ret is already true -#
|
||||||
i += 1
|
i += 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -239,8 +225,8 @@ class Tasmota
|
|||||||
|
|
||||||
var i = 0
|
var i = 0
|
||||||
while i < size(self._rules)
|
while i < size(self._rules)
|
||||||
var kv = self._rules[i]
|
var tr = self._rules[i]
|
||||||
ret = self.try_rule(ev,kv.k,kv.v) || ret #- call should be first to avoid evaluation shortcut -#
|
ret = self.try_rule(ev,tr.trig,tr.f) || ret #- call should be first to avoid evaluation shortcut -#
|
||||||
i += 1
|
i += 1
|
||||||
end
|
end
|
||||||
return ret
|
return ret
|
||||||
@ -251,7 +237,7 @@ class Tasmota
|
|||||||
def set_timer(delay,f,id)
|
def set_timer(delay,f,id)
|
||||||
self.check_not_method(f)
|
self.check_not_method(f)
|
||||||
if !self._timers self._timers=[] end
|
if !self._timers self._timers=[] end
|
||||||
self._timers.push(Timer(self.millis(delay),f,id))
|
self._timers.push(Trigger(self.millis(delay),f,id))
|
||||||
end
|
end
|
||||||
|
|
||||||
# run every 50ms tick
|
# run every 50ms tick
|
||||||
@ -259,7 +245,7 @@ class Tasmota
|
|||||||
if self._timers
|
if self._timers
|
||||||
var i=0
|
var i=0
|
||||||
while i<self._timers.size()
|
while i<self._timers.size()
|
||||||
if self.time_reached(self._timers[i].due)
|
if self.time_reached(self._timers[i].trig)
|
||||||
var f=self._timers[i].f
|
var f=self._timers[i].f
|
||||||
self._timers.remove(i)
|
self._timers.remove(i)
|
||||||
f()
|
f()
|
||||||
|
@ -28,6 +28,15 @@ hue_bridge.init = def (m)
|
|||||||
self.lights.remove(id)
|
self.lights.remove(id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# get id from light object
|
||||||
|
def light_to_id(l)
|
||||||
|
for id: self.lights.keys()
|
||||||
|
if l == self.lights[id]['light']
|
||||||
|
return id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# return the status of a single light by id
|
# return the status of a single light by id
|
||||||
def hue_status(id)
|
def hue_status(id)
|
||||||
import hue_ntv
|
import hue_ntv
|
||||||
|
@ -89,8 +89,9 @@ lib_extra_dirs = ${library.lib_extra_dirs}
|
|||||||
|
|
||||||
|
|
||||||
[env:tasmota32_base]
|
[env:tasmota32_base]
|
||||||
; *** Uncomment next line ";" to enable development Tasmota Arduino version ESP32
|
; *** Uncomment next lines ";" to enable development Tasmota Arduino version ESP32
|
||||||
;platform = https://github.com/Jason2866/platform-espressif32/releases/download/v2.0.2.1/platform-espressif32-2.0.2.1.zip
|
;platform = https://github.com/Jason2866/platform-espressif32.git#IDF44/ESP32-S3
|
||||||
|
;platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/664/framework-arduinoespressif32-v4.4_dev-73c0f44528.tar.gz
|
||||||
build_unflags = ${esp32_defaults.build_unflags}
|
build_unflags = ${esp32_defaults.build_unflags}
|
||||||
build_flags = ${esp32_defaults.build_flags}
|
build_flags = ${esp32_defaults.build_flags}
|
||||||
|
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Herzschlag"
|
#define D_SENSOR_HEARTBEAT "Herzschlag"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 - RX"
|
#define D_SENSOR_HRG15_RX "HRG15 - RX"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 - TX"
|
#define D_SENSOR_HRG15_TX "HRG15 - TX"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Battito cardiaco"
|
#define D_SENSOR_HEARTBEAT "Battito cardiaco"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 - SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 - SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 - RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 - RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "Kierunek wiatru"
|
#define D_SENSOR_VINDRIKTNING_RX "Kierunek wiatru"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -847,6 +847,8 @@
|
|||||||
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
#define D_SENSOR_HRG15_RX "HRG15 Rx"
|
||||||
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
#define D_SENSOR_HRG15_TX "HRG15 Tx"
|
||||||
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
#define D_SENSOR_VINDRIKTNING_RX "VINDRIKTNING"
|
||||||
|
#define D_SENSOR_BL6523_TX "BL6523 Tx"
|
||||||
|
#define D_SENSOR_BL6523_RX "BL6523 Rx"
|
||||||
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
#define D_SENSOR_HEARTBEAT "Heartbeat"
|
||||||
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
#define D_GPIO_SHIFT595_SRCLK "74x595 SRCLK"
|
||||||
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
#define D_GPIO_SHIFT595_RCLK "74x595 RCLK"
|
||||||
|
@ -1097,7 +1097,7 @@ void CmndSetoptionBase(bool indexed) {
|
|||||||
SettingsSave(2);
|
SettingsSave(2);
|
||||||
}
|
}
|
||||||
#ifdef USE_HOME_ASSISTANT
|
#ifdef USE_HOME_ASSISTANT
|
||||||
if ((19 == pindex) || (30 == pindex)) {
|
if ((19 == pindex) || (30 == pindex) || (114 == pindex)) {
|
||||||
HAssDiscover(); // Delayed execution to provide enough resources during hass_discovery or hass_light
|
HAssDiscover(); // Delayed execution to provide enough resources during hass_discovery or hass_light
|
||||||
}
|
}
|
||||||
#endif // USE_HOME_ASSISTANT
|
#endif // USE_HOME_ASSISTANT
|
||||||
|
@ -509,13 +509,7 @@ void *special_calloc(size_t num, size_t size) {
|
|||||||
|
|
||||||
// Variants for IRAM heap, which need all accesses to be 32 bits aligned
|
// Variants for IRAM heap, which need all accesses to be 32 bits aligned
|
||||||
void *special_malloc32(uint32_t size) {
|
void *special_malloc32(uint32_t size) {
|
||||||
return heap_caps_malloc(size, UsePSRAM() ? MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT : MALLOC_CAP_32BIT);
|
return heap_caps_malloc(size, MALLOC_CAP_32BIT);
|
||||||
}
|
|
||||||
void *special_realloc32(void *ptr, size_t size) {
|
|
||||||
return heap_caps_realloc(ptr, size, UsePSRAM() ? MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT : MALLOC_CAP_32BIT);
|
|
||||||
}
|
|
||||||
void *special_calloc32(size_t num, size_t size) {
|
|
||||||
return heap_caps_calloc(num, size, UsePSRAM() ? MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT : MALLOC_CAP_32BIT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float CpuTemperature(void) {
|
float CpuTemperature(void) {
|
||||||
|
@ -789,9 +789,11 @@ void ResponseAppendFeatures(void)
|
|||||||
feature8 |= 0x00100000; // xnrg_21_sdm230.ino
|
feature8 |= 0x00100000; // xnrg_21_sdm230.ino
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_CM110x
|
#ifdef USE_CM110x
|
||||||
feature8 |= 0x00200000; // xsns_95_cm110x.ino
|
feature8 |= 0x00200000; // xsns_95_cm110x.ino
|
||||||
|
#endif
|
||||||
|
#if defined(USE_ENERGY_SENSOR) && defined(USE_BL6523)
|
||||||
|
feature8 |= 0x00400000; // xnrg_22_bl6523.ino
|
||||||
#endif
|
#endif
|
||||||
// feature8 |= 0x00400000;
|
|
||||||
// feature8 |= 0x00800000;
|
// feature8 |= 0x00800000;
|
||||||
|
|
||||||
// feature8 |= 0x01000000;
|
// feature8 |= 0x01000000;
|
||||||
|
@ -182,6 +182,7 @@ enum UserSelectablePins {
|
|||||||
GPIO_SDM230_TX, GPIO_SDM230_RX, // SDM230 Serial interface
|
GPIO_SDM230_TX, GPIO_SDM230_RX, // SDM230 Serial interface
|
||||||
GPIO_ADC_MQ, // Analog MQ Sensor
|
GPIO_ADC_MQ, // Analog MQ Sensor
|
||||||
GPIO_CM11_TXD, GPIO_CM11_RXD, // CM11 Serial interface
|
GPIO_CM11_TXD, GPIO_CM11_RXD, // CM11 Serial interface
|
||||||
|
GPIO_BL6523_TX, GPIO_BL6523_RX, // BL6523 based Watt meter Serial interface
|
||||||
GPIO_SENSOR_END };
|
GPIO_SENSOR_END };
|
||||||
|
|
||||||
enum ProgramSelectablePins {
|
enum ProgramSelectablePins {
|
||||||
@ -403,6 +404,7 @@ const char kSensorNames[] PROGMEM =
|
|||||||
D_SENSOR_SDM230_TX "|" D_SENSOR_SDM230_RX "|"
|
D_SENSOR_SDM230_TX "|" D_SENSOR_SDM230_RX "|"
|
||||||
D_SENSOR_ADC_MQ "|"
|
D_SENSOR_ADC_MQ "|"
|
||||||
D_SENSOR_CM11_TX "|" D_SENSOR_CM11_RX "|"
|
D_SENSOR_CM11_TX "|" D_SENSOR_CM11_RX "|"
|
||||||
|
D_SENSOR_BL6523_TX "|" D_SENSOR_BL6523_RX "|"
|
||||||
;
|
;
|
||||||
|
|
||||||
const char kSensorNamesFixed[] PROGMEM =
|
const char kSensorNamesFixed[] PROGMEM =
|
||||||
@ -770,6 +772,10 @@ const uint16_t kGpioNiceList[] PROGMEM = {
|
|||||||
AGPIO(GPIO_SDM230_TX), // SDM230 Serial interface
|
AGPIO(GPIO_SDM230_TX), // SDM230 Serial interface
|
||||||
AGPIO(GPIO_SDM230_RX), // SDM230 Serial interface
|
AGPIO(GPIO_SDM230_RX), // SDM230 Serial interface
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef USE_BL6523
|
||||||
|
AGPIO(GPIO_BL6523_TX), // BL6523 based Watt meter Serial interface
|
||||||
|
AGPIO(GPIO_BL6523_RX), // BL6523 based Watt meter Serial interface
|
||||||
|
#endif
|
||||||
#endif // USE_ENERGY_SENSOR
|
#endif // USE_ENERGY_SENSOR
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------------------*\
|
/*-------------------------------------------------------------------------------------------*\
|
||||||
|
@ -373,6 +373,17 @@ struct GVARS {
|
|||||||
int16_t strind;
|
int16_t strind;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef USE_SCRIPT_SPI
|
||||||
|
struct SCRIPT_SPI {
|
||||||
|
int8_t sclk;
|
||||||
|
int8_t mosi;
|
||||||
|
int8_t miso;
|
||||||
|
int8_t cs[4];
|
||||||
|
SPIClass *spip;
|
||||||
|
SPISettings settings;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define NUM_RES 0xfe
|
#define NUM_RES 0xfe
|
||||||
#define STR_RES 0xfd
|
#define STR_RES 0xfd
|
||||||
@ -454,6 +465,10 @@ struct SCRIPT_MEM {
|
|||||||
#endif
|
#endif
|
||||||
float retval;
|
float retval;
|
||||||
char *retstr;
|
char *retstr;
|
||||||
|
#ifdef USE_SCRIPT_SPI
|
||||||
|
struct SCRIPT_SPI spi;
|
||||||
|
#endif
|
||||||
|
|
||||||
} glob_script_mem;
|
} glob_script_mem;
|
||||||
|
|
||||||
|
|
||||||
@ -4005,6 +4020,96 @@ extern char *SML_GetSVal(uint32_t index);
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
#endif //USE_SCRIPT_SERIAL
|
#endif //USE_SCRIPT_SERIAL
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_SCRIPT_SPI
|
||||||
|
if (!strncmp(lp, "spi(", 4)) {
|
||||||
|
lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0);
|
||||||
|
uint8_t sel = fvar;
|
||||||
|
uint8_t index;
|
||||||
|
switch (sel) {
|
||||||
|
case 0:
|
||||||
|
// set bus pins
|
||||||
|
lp = GetNumericArgument(lp , OPER_EQU, &fvar, 0);
|
||||||
|
glob_script_mem.spi.sclk = fvar;
|
||||||
|
|
||||||
|
if (glob_script_mem.spi.sclk < 0) {
|
||||||
|
// attach to existing Tasmota SPI
|
||||||
|
lp = GetNumericArgument(lp , OPER_EQU, &fvar, 0);
|
||||||
|
fvar *= 1000000;
|
||||||
|
glob_script_mem.spi.settings = SPISettings(fvar, MSBFIRST, SPI_MODE0);
|
||||||
|
|
||||||
|
if (TasmotaGlobal.spi_enabled) {
|
||||||
|
#ifdef EPS8266
|
||||||
|
SPI.begin();
|
||||||
|
glob_script_mem.spi.spip = &SPI;
|
||||||
|
#endif // EPS8266
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
if (glob_script_mem.spi.sclk == -1) {
|
||||||
|
SPI.begin(Pin(GPIO_SPI_CLK), Pin(GPIO_SPI_MISO), Pin(GPIO_SPI_MOSI), -1);
|
||||||
|
glob_script_mem.spi.spip = &SPI;
|
||||||
|
} else {
|
||||||
|
glob_script_mem.spi.spip = new SPIClass(HSPI);
|
||||||
|
glob_script_mem.spi.spip->begin(Pin(GPIO_SPI_CLK, 1), Pin(GPIO_SPI_MISO, 1), Pin(GPIO_SPI_MOSI, 1), -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ESP32
|
||||||
|
} else {
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR("error: spi pins not defined"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pinMode(glob_script_mem.spi.sclk , OUTPUT);
|
||||||
|
digitalWrite(glob_script_mem.spi.sclk , 0);
|
||||||
|
|
||||||
|
lp = GetNumericArgument(lp , OPER_EQU, &fvar, 0);
|
||||||
|
glob_script_mem.spi.mosi = fvar;
|
||||||
|
if (glob_script_mem.spi.mosi >= 0) {
|
||||||
|
pinMode(glob_script_mem.spi.mosi , OUTPUT);
|
||||||
|
digitalWrite(glob_script_mem.spi.mosi , 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
lp = GetNumericArgument(lp , OPER_EQU, &fvar, 0);
|
||||||
|
glob_script_mem.spi.miso = fvar;
|
||||||
|
if (glob_script_mem.spi.miso >= 0) {
|
||||||
|
pinMode(glob_script_mem.spi.miso , INPUT_PULLUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Is_gpio_used(glob_script_mem.spi.mosi) || Is_gpio_used(glob_script_mem.spi.miso)
|
||||||
|
|| Is_gpio_used(glob_script_mem.spi.sclk) ) {
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR("warning: pins already used"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
// set cs
|
||||||
|
lp = GetNumericArgument(lp , OPER_EQU, &fvar, 0);
|
||||||
|
index = fvar;
|
||||||
|
index &= 3;
|
||||||
|
lp = GetNumericArgument(lp , OPER_EQU, &fvar, 0);
|
||||||
|
glob_script_mem.spi.cs[index] = fvar;
|
||||||
|
pinMode(glob_script_mem.spi.cs[index] , OUTPUT);
|
||||||
|
digitalWrite(glob_script_mem.spi.cs[index] , 1);
|
||||||
|
if (Is_gpio_used(glob_script_mem.spi.cs[index])) {
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR("warning: pins already used"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
// transfer bytes
|
||||||
|
lp = GetNumericArgument(lp , OPER_EQU, &fvar, 0);
|
||||||
|
uint8_t index = fvar;
|
||||||
|
lp = GetNumericArgument(lp , OPER_EQU, &fvar, 0);
|
||||||
|
uint32_t val = fvar;
|
||||||
|
lp = GetNumericArgument(lp , OPER_EQU, &fvar, 0);
|
||||||
|
script_sspi_trans(index & 3, val, fvar);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
len = 0;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
#endif // USE_SCRIPT_SPI
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
@ -5402,7 +5507,7 @@ int16_t Run_script_sub(const char *type, int8_t tlen, struct GVARS *gv) {
|
|||||||
} else {
|
} else {
|
||||||
glob_script_mem.retstr = 0;
|
glob_script_mem.retstr = 0;
|
||||||
}
|
}
|
||||||
section = 0;
|
section = 99;
|
||||||
goto next_line;
|
goto next_line;
|
||||||
} else if (!strncmp(lp, "break", 5)) {
|
} else if (!strncmp(lp, "break", 5)) {
|
||||||
lp += 5;
|
lp += 5;
|
||||||
@ -5413,7 +5518,8 @@ int16_t Run_script_sub(const char *type, int8_t tlen, struct GVARS *gv) {
|
|||||||
}
|
}
|
||||||
floop = 0;
|
floop = 0;
|
||||||
} else {
|
} else {
|
||||||
section = 0;
|
section = 99;
|
||||||
|
// leave immediately
|
||||||
}
|
}
|
||||||
goto next_line;
|
goto next_line;
|
||||||
} else if (!strncmp(lp, "dp", 2) && isdigit(*(lp + 2))) {
|
} else if (!strncmp(lp, "dp", 2) && isdigit(*(lp + 2))) {
|
||||||
@ -5973,6 +6079,7 @@ int16_t Run_script_sub(const char *type, int8_t tlen, struct GVARS *gv) {
|
|||||||
}
|
}
|
||||||
// next line
|
// next line
|
||||||
next_line:
|
next_line:
|
||||||
|
if (section == 99) return 0;
|
||||||
if (*lp==SCRIPT_EOL) {
|
if (*lp==SCRIPT_EOL) {
|
||||||
lp++;
|
lp++;
|
||||||
} else {
|
} else {
|
||||||
@ -5990,6 +6097,55 @@ int16_t Run_script_sub(const char *type, int8_t tlen, struct GVARS *gv) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_SCRIPT_SPI
|
||||||
|
// transfer 1-3 bytes
|
||||||
|
uint32_t script_sspi_trans(uint32_t cs_index, uint32_t val, uint32_t size) {
|
||||||
|
uint32_t out = 0;
|
||||||
|
|
||||||
|
digitalWrite(glob_script_mem.spi.cs[cs_index], 0);
|
||||||
|
|
||||||
|
if (glob_script_mem.spi.sclk < 0) {
|
||||||
|
// use existing hardware spi
|
||||||
|
glob_script_mem.spi.spip->beginTransaction(glob_script_mem.spi.settings);
|
||||||
|
if (size == 1) {
|
||||||
|
out = glob_script_mem.spi.spip->transfer(val);
|
||||||
|
}
|
||||||
|
if (size == 2) {
|
||||||
|
out = glob_script_mem.spi.spip->transfer16(val);
|
||||||
|
}
|
||||||
|
if (size == 3) {
|
||||||
|
out = glob_script_mem.spi.spip->transfer(val >> 16);
|
||||||
|
out <<= 16;
|
||||||
|
out |= glob_script_mem.spi.spip->transfer16(val);
|
||||||
|
}
|
||||||
|
//SPI.transferBytes();
|
||||||
|
glob_script_mem.spi.spip->endTransaction();
|
||||||
|
digitalWrite(glob_script_mem.spi.cs[cs_index], 1);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size < 1 || size > 3) size = 1;
|
||||||
|
uint32_t bit = 1 << ((size * 8) - 1);
|
||||||
|
while (bit) {
|
||||||
|
digitalWrite(glob_script_mem.spi.sclk, 0);
|
||||||
|
if (glob_script_mem.spi.mosi >= 0) {
|
||||||
|
if (val & bit) digitalWrite(glob_script_mem.spi.mosi, 1);
|
||||||
|
else digitalWrite(glob_script_mem.spi.mosi, 0);
|
||||||
|
}
|
||||||
|
digitalWrite(glob_script_mem.spi.sclk, 1);
|
||||||
|
if (glob_script_mem.spi.miso >= 0) {
|
||||||
|
if (digitalRead(glob_script_mem.spi.miso)) {
|
||||||
|
out |= bit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bit >>= 1;
|
||||||
|
}
|
||||||
|
digitalWrite(glob_script_mem.spi.cs[cs_index], 1);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
#endif // USE_SCRIPT_SPI
|
||||||
|
|
||||||
#ifdef USE_SCRIPT_SERIAL
|
#ifdef USE_SCRIPT_SERIAL
|
||||||
bool Script_Close_Serial() {
|
bool Script_Close_Serial() {
|
||||||
if (glob_script_mem.sp) {
|
if (glob_script_mem.sp) {
|
||||||
@ -6004,7 +6160,7 @@ bool Script_Close_Serial() {
|
|||||||
#endif //USE_SCRIPT_SERIAL
|
#endif //USE_SCRIPT_SERIAL
|
||||||
|
|
||||||
bool Is_gpio_used(uint8_t gpiopin) {
|
bool Is_gpio_used(uint8_t gpiopin) {
|
||||||
if ((gpiopin < nitems(TasmotaGlobal.gpio_pin)) && (TasmotaGlobal.gpio_pin[gpiopin] > 0)) {
|
if (gpiopin >= 0 && (gpiopin < nitems(TasmotaGlobal.gpio_pin)) && (TasmotaGlobal.gpio_pin[gpiopin] > 0)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -52,7 +52,8 @@ enum ZnpSubsystem {
|
|||||||
Z_SAPI = 0x06,
|
Z_SAPI = 0x06,
|
||||||
Z_UTIL = 0x07,
|
Z_UTIL = 0x07,
|
||||||
Z_DEBUG = 0x08,
|
Z_DEBUG = 0x08,
|
||||||
Z_APP = 0x09
|
Z_APP = 0x09,
|
||||||
|
Z_APP_CNF = 0x0F, // new in ZStacK 3
|
||||||
};
|
};
|
||||||
#endif // USE_ZIGBEE_ZNP
|
#endif // USE_ZIGBEE_ZNP
|
||||||
|
|
||||||
@ -1103,6 +1104,14 @@ enum Z_Util {
|
|||||||
Z_UTIL_ZCL_KEY_ESTABLISH_IND = 0xE1
|
Z_UTIL_ZCL_KEY_ESTABLISH_IND = 0xE1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum Z_App_Cnf {
|
||||||
|
Z_APP_CNF_BDB_START_COMMISSIONING = 0x05,
|
||||||
|
Z_APP_CNF_BDB_SET_CHANNEL = 0x08,
|
||||||
|
Z_APP_CNF_BDB_SET_TC_REQUIRE_KEY_EXCHANGE = 0x09,
|
||||||
|
Z_APP_CNF_BDB_COMMISSIONING_NOTIFICATION = 0x80,
|
||||||
|
Z_APP_CNF_BDB_SET_NWK_FRAME_COUNTER = 0xFF,
|
||||||
|
};
|
||||||
|
|
||||||
enum ZCL_Global_Commands {
|
enum ZCL_Global_Commands {
|
||||||
ZCL_READ_ATTRIBUTES = 0x00,
|
ZCL_READ_ATTRIBUTES = 0x00,
|
||||||
ZCL_READ_ATTRIBUTES_RESPONSE = 0x01,
|
ZCL_READ_ATTRIBUTES_RESPONSE = 0x01,
|
||||||
|
@ -80,6 +80,7 @@ const uint8_t ZIGBEE_LABEL_INIT_DEVICE = 14; // Init ZNP as end-device
|
|||||||
const uint8_t ZIGBEE_LABEL_START_DEVICE = 15; // Start ZNP as end-device
|
const uint8_t ZIGBEE_LABEL_START_DEVICE = 15; // Start ZNP as end-device
|
||||||
const uint8_t ZIGBEE_LABEL_START_ROUTER_DEVICE = 16; // Start common to router and device
|
const uint8_t ZIGBEE_LABEL_START_ROUTER_DEVICE = 16; // Start common to router and device
|
||||||
const uint8_t ZIGBEE_LABEL_ZB3_INIT = 17; // check parameters for ZB3
|
const uint8_t ZIGBEE_LABEL_ZB3_INIT = 17; // check parameters for ZB3
|
||||||
|
const uint8_t ZIGBEE_LABEL_COORD_STARTED = 18; // Coordinator has started
|
||||||
const uint8_t ZIGBEE_LABEL_FACT_RESET_ROUTER_DEVICE_POST = 19; // common post configuration for router and device
|
const uint8_t ZIGBEE_LABEL_FACT_RESET_ROUTER_DEVICE_POST = 19; // common post configuration for router and device
|
||||||
const uint8_t ZIGBEE_LABEL_READY = 20; // goto label 20 for main loop
|
const uint8_t ZIGBEE_LABEL_READY = 20; // goto label 20 for main loop
|
||||||
const uint8_t ZIGBEE_LABEL_MAIN_LOOP = 21; // main loop
|
const uint8_t ZIGBEE_LABEL_MAIN_LOOP = 21; // main loop
|
||||||
|
@ -223,6 +223,16 @@ const uint32_t ZB_ALL_CHANNELS = 0x07FFF800;
|
|||||||
ZBR(ZBS_W_ALL_CHANN, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, CONF_CHANLIST,0x00, 0x00, 0x04 /* len */,
|
ZBR(ZBS_W_ALL_CHANN, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, CONF_CHANLIST,0x00, 0x00, 0x04 /* len */,
|
||||||
Z_B0(ZB_ALL_CHANNELS), Z_B1(ZB_ALL_CHANNELS), Z_B2(ZB_ALL_CHANNELS), Z_B3(ZB_ALL_CHANNELS),
|
Z_B0(ZB_ALL_CHANNELS), Z_B1(ZB_ALL_CHANNELS), Z_B2(ZB_ALL_CHANNELS), Z_B3(ZB_ALL_CHANNELS),
|
||||||
/*0x00, 0x08, 0x00, 0x00*/ ) // 21098400000400F8FF7F
|
/*0x00, 0x08, 0x00, 0x00*/ ) // 21098400000400F8FF7F
|
||||||
|
|
||||||
|
// Configure BDB Channels
|
||||||
|
ZBR(ZBS_W_BDB_CHANN, Z_SREQ | Z_APP_CNF, Z_APP_CNF_BDB_SET_CHANNEL, 0x01 /*primary*/,
|
||||||
|
Z_B0(USE_ZIGBEE_CHANNEL_MASK), Z_B1(USE_ZIGBEE_CHANNEL_MASK), Z_B2(USE_ZIGBEE_CHANNEL_MASK), Z_B3(USE_ZIGBEE_CHANNEL_MASK),
|
||||||
|
/*0x00, 0x08, 0x00, 0x00*/ ) // 2F0801xxxxxxxx
|
||||||
|
// Configure BDB Channels secondary channel to zeroes
|
||||||
|
ZBM(ZBS_W_BDB_CHANN2, Z_SREQ | Z_APP_CNF, Z_APP_CNF_BDB_SET_CHANNEL, 0x00 /*secondary*/,
|
||||||
|
0x00, 0x08, 0x00, 0x00 ) // 2F080000000000
|
||||||
|
ZBM(ZBR_W_BDB_CHANN_OK, Z_SRSP | Z_APP_CNF, Z_APP_CNF_BDB_SET_CHANNEL, Z_SUCCESS ) // 6F0800
|
||||||
|
|
||||||
// Write Logical Type = 00 = coordinator
|
// Write Logical Type = 00 = coordinator
|
||||||
ZBM(ZBS_W_LOGTYP_COORD, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, CONF_LOGICAL_TYPE,0x00, 0x00, 0x01 /* len */, 0x00 ) // 21098700000100
|
ZBM(ZBS_W_LOGTYP_COORD, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, CONF_LOGICAL_TYPE,0x00, 0x00, 0x01 /* len */, 0x00 ) // 21098700000100
|
||||||
// Write Logical Type = 01 = router
|
// Write Logical Type = 01 = router
|
||||||
@ -263,6 +273,10 @@ ZBM(AREQ_STARTUPFROMAPP, Z_AREQ | Z_ZDO, ZDO_STATE_CHANGE_IND ) // 45C00xx -
|
|||||||
ZBM(AREQ_STARTUPFROMAPP_COORD, Z_AREQ | Z_ZDO, ZDO_STATE_CHANGE_IND, ZDO_DEV_ZB_COORD ) // 45C009 + 08 = starting, 09 = started
|
ZBM(AREQ_STARTUPFROMAPP_COORD, Z_AREQ | Z_ZDO, ZDO_STATE_CHANGE_IND, ZDO_DEV_ZB_COORD ) // 45C009 + 08 = starting, 09 = started
|
||||||
ZBM(AREQ_STARTUPFROMAPP_ROUTER, Z_AREQ | Z_ZDO, ZDO_STATE_CHANGE_IND, ZDO_DEV_ROUTER ) // 45C009 + 02 = looking PanID, 07 = started
|
ZBM(AREQ_STARTUPFROMAPP_ROUTER, Z_AREQ | Z_ZDO, ZDO_STATE_CHANGE_IND, ZDO_DEV_ROUTER ) // 45C009 + 02 = looking PanID, 07 = started
|
||||||
ZBM(AREQ_STARTUPFROMAPP_DEVICE, Z_AREQ | Z_ZDO, ZDO_STATE_CHANGE_IND, ZDO_DEV_END_DEVICE ) // 45C009 + 02 = looking PanID, 06 = started
|
ZBM(AREQ_STARTUPFROMAPP_DEVICE, Z_AREQ | Z_ZDO, ZDO_STATE_CHANGE_IND, ZDO_DEV_END_DEVICE ) // 45C009 + 02 = looking PanID, 06 = started
|
||||||
|
// BDB START Commissioning
|
||||||
|
ZBM(ZBS_BDB_START_COMMIS, Z_SREQ | Z_APP_CNF, Z_APP_CNF_BDB_START_COMMISSIONING, 0x04 /*mode*/) // 2F0504
|
||||||
|
ZBM(ZBR_BDB_START_COMMIS, Z_SRSP | Z_APP_CNF, Z_APP_CNF_BDB_START_COMMISSIONING, Z_SUCCESS) // 6F0500
|
||||||
|
|
||||||
// GetDeviceInfo
|
// GetDeviceInfo
|
||||||
ZBM(ZBS_GETDEVICEINFO, Z_SREQ | Z_UTIL, Z_UTIL_GET_DEVICE_INFO ) // 2700
|
ZBM(ZBS_GETDEVICEINFO, Z_SREQ | Z_UTIL, Z_UTIL_GET_DEVICE_INFO ) // 2700
|
||||||
ZBM(ZBR_GETDEVICEINFO, Z_SRSP | Z_UTIL, Z_UTIL_GET_DEVICE_INFO, Z_SUCCESS ) // Ex= 6700.00.6263151D004B1200.0000.07.09.00
|
ZBM(ZBR_GETDEVICEINFO, Z_SRSP | Z_UTIL, Z_UTIL_GET_DEVICE_INFO, Z_SUCCESS ) // Ex= 6700.00.6263151D004B1200.0000.07.09.00
|
||||||
@ -296,8 +310,10 @@ ZBM(AREQ_ZDO_NODEDESCRSP, Z_AREQ | Z_ZDO, ZDO_NODE_DESC_RSP) // 4582
|
|||||||
// Z_ZDO:activeEpReq
|
// Z_ZDO:activeEpReq
|
||||||
ZBM(ZBS_ZDO_ACTIVEEPREQ, Z_SREQ | Z_ZDO, ZDO_ACTIVE_EP_REQ, 0x00, 0x00, 0x00, 0x00) // 250500000000
|
ZBM(ZBS_ZDO_ACTIVEEPREQ, Z_SREQ | Z_ZDO, ZDO_ACTIVE_EP_REQ, 0x00, 0x00, 0x00, 0x00) // 250500000000
|
||||||
ZBM(ZBR_ZDO_ACTIVEEPREQ, Z_SRSP | Z_ZDO, ZDO_ACTIVE_EP_REQ, Z_SUCCESS) // 65050000
|
ZBM(ZBR_ZDO_ACTIVEEPREQ, Z_SRSP | Z_ZDO, ZDO_ACTIVE_EP_REQ, Z_SUCCESS) // 65050000
|
||||||
ZBM(ZBR_ZDO_ACTIVEEPRSP_NONE, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP, 0x00, 0x00 /* srcAddr */, Z_SUCCESS,
|
// ZBM(ZBR_ZDO_ACTIVEEPRSP_NONE, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP, 0x00, 0x00 /* srcAddr */, Z_SUCCESS,
|
||||||
0x00, 0x00 /* nwkaddr */, 0x00 /* activeepcount */) // 45050000 - no Ep running
|
// 0x00, 0x00 /* nwkaddr */, 0x00 /* activeepcount */) // 45050000 - no Ep running
|
||||||
|
// Change #14819 - we now allow some EP to be alreaady declared
|
||||||
|
ZBM(ZBR_ZDO_ACTIVEEPRSP_SUCESS, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP, 0x00, 0x00 /* srcAddr */, Z_SUCCESS) // 45050000xxxx - no Ep running
|
||||||
ZBM(ZBR_ZDO_ACTIVEEPRSP_OK, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP, 0x00, 0x00 /* srcAddr */, Z_SUCCESS,
|
ZBM(ZBR_ZDO_ACTIVEEPRSP_OK, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP, 0x00, 0x00 /* srcAddr */, Z_SUCCESS,
|
||||||
0x00, 0x00 /* nwkaddr */, 0x02 /* activeepcount */, 0x0B, 0x01 /* the actual endpoints */) // 25050000 - no Ep running
|
0x00, 0x00 /* nwkaddr */, 0x02 /* activeepcount */, 0x0B, 0x01 /* the actual endpoints */) // 25050000 - no Ep running
|
||||||
|
|
||||||
@ -371,6 +387,10 @@ void ZNP_UpdateConfig(uint8_t zb_channel, uint16_t zb_pan_id, uint64_t zb_ext_pa
|
|||||||
ZBW(ZBS_W_CHANN, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, CONF_CHANLIST,0x00, 0x00, 0x04 /* len */,
|
ZBW(ZBS_W_CHANN, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, CONF_CHANLIST,0x00, 0x00, 0x04 /* len */,
|
||||||
Z_B0(zb_channel_mask), Z_B1(zb_channel_mask), Z_B2(zb_channel_mask), Z_B3(zb_channel_mask),
|
Z_B0(zb_channel_mask), Z_B1(zb_channel_mask), Z_B2(zb_channel_mask), Z_B3(zb_channel_mask),
|
||||||
/*0x00, 0x08, 0x00, 0x00*/ ) // 210984000004xxxxxxxx
|
/*0x00, 0x08, 0x00, 0x00*/ ) // 210984000004xxxxxxxx
|
||||||
|
// Write BDB Channel ID - ZStack3 specific
|
||||||
|
ZBW(ZBS_W_BDB_CHANN, Z_SREQ | Z_APP_CNF, Z_APP_CNF_BDB_SET_CHANNEL, 0x01 /*primary*/,
|
||||||
|
Z_B0(zb_channel_mask), Z_B1(zb_channel_mask), Z_B2(zb_channel_mask), Z_B3(zb_channel_mask),
|
||||||
|
/*0x00, 0x08, 0x00, 0x00*/ ) // 2F0801xxxxxxxx
|
||||||
// Write precfgkey
|
// Write precfgkey
|
||||||
ZBW(ZBS_W_PFGK, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, CONF_PRECFGKEY,0x00, 0x00,
|
ZBW(ZBS_W_PFGK, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, CONF_PRECFGKEY,0x00, 0x00,
|
||||||
0x10 /* len */,
|
0x10 /* len */,
|
||||||
@ -401,7 +421,7 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
|
|||||||
ZI_WAIT(15500) // wait for 15 seconds for Tasmota to stabilize
|
ZI_WAIT(15500) // wait for 15 seconds for Tasmota to stabilize
|
||||||
|
|
||||||
//ZI_MQTT_STATE(ZIGBEE_STATUS_BOOT, "Booting")
|
//ZI_MQTT_STATE(ZIGBEE_STATUS_BOOT, "Booting")
|
||||||
ZI_LOG(LOG_LEVEL_INFO, D_LOG_ZIGBEE "rebooting CC2530 device")
|
ZI_LOG(LOG_LEVEL_INFO, D_LOG_ZIGBEE "rebooting ZNP device")
|
||||||
|
|
||||||
ZI_CALL(&ZNP_Reset_Device, 0) // LOW = reset
|
ZI_CALL(&ZNP_Reset_Device, 0) // LOW = reset
|
||||||
ZI_WAIT(100) // wait for .1 second
|
ZI_WAIT(100) // wait for .1 second
|
||||||
@ -434,34 +454,54 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
|
|||||||
ZI_SEND(ZBS_PFGKEN) // check PFGKEN
|
ZI_SEND(ZBS_PFGKEN) // check PFGKEN
|
||||||
ZI_WAIT_RECV(1000, ZBR_PFGKEN)
|
ZI_WAIT_RECV(1000, ZBR_PFGKEN)
|
||||||
|
|
||||||
|
ZI_LABEL(ZIGBEE_LABEL_START_COORD)
|
||||||
|
// Check if the MCU is running ZStack3, it so goto ZIGBEE_LABEL_ZB3_INIT, or continue
|
||||||
ZI_CALL(&Z_GotoZB3, ZIGBEE_LABEL_ZB3_INIT)
|
ZI_CALL(&Z_GotoZB3, ZIGBEE_LABEL_ZB3_INIT)
|
||||||
|
// ======================================================================
|
||||||
|
// Start procedure for ZStack 1.2
|
||||||
|
// ======================================================================
|
||||||
ZI_SEND(ZBS_PFGK) // check PFGK on ZB1.2
|
ZI_SEND(ZBS_PFGK) // check PFGK on ZB1.2
|
||||||
ZI_WAIT_RECV(1000, ZBR_PFGK)
|
ZI_WAIT_RECV(1000, ZBR_PFGK)
|
||||||
ZI_GOTO(ZIGBEE_LABEL_START_COORD)
|
|
||||||
|
|
||||||
ZI_LABEL(ZIGBEE_LABEL_ZB3_INIT)
|
|
||||||
ZI_SEND(ZBS_PFGK3) // check PFGK on ZB3
|
|
||||||
ZI_WAIT_RECV(1000, ZBR_PFGK3)
|
|
||||||
//ZI_LOG(LOG_LEVEL_INFO, D_LOG_ZIGBEE "zigbee configuration ok")
|
|
||||||
// all is good, we can start
|
// all is good, we can start
|
||||||
|
|
||||||
ZI_LABEL(ZIGBEE_LABEL_START_COORD) // START ZNP App
|
|
||||||
ZI_MQTT_STATE(ZIGBEE_STATUS_STARTING, kConfiguredCoord)
|
ZI_MQTT_STATE(ZIGBEE_STATUS_STARTING, kConfiguredCoord)
|
||||||
ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT)
|
ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) // set any failure to ABORT
|
||||||
// Z_ZDO:startupFromApp
|
ZI_SEND(ZBS_STARTUPFROMAPP) // start coordinator
|
||||||
//ZI_LOG(LOG_LEVEL_INFO, D_LOG_ZIGBEE "starting zigbee coordinator")
|
|
||||||
ZI_SEND(ZBS_STARTUPFROMAPP) // start coordinator
|
|
||||||
ZI_WAIT_RECV(5000, ZBR_STARTUPFROMAPP) // wait for sync ack of command
|
ZI_WAIT_RECV(5000, ZBR_STARTUPFROMAPP) // wait for sync ack of command
|
||||||
ZI_WAIT_UNTIL_FUNC(20000, AREQ_STARTUPFROMAPP, &ZNP_ReceiveStateChange) // wait for async message that coordinator started, max 20s
|
ZI_WAIT_UNTIL_FUNC(20000, AREQ_STARTUPFROMAPP, &ZNP_ReceiveStateChange) // wait for async message that coordinator started, max 20s
|
||||||
|
ZI_GOTO(ZIGBEE_LABEL_COORD_STARTED)
|
||||||
|
|
||||||
|
// ======================================================================
|
||||||
|
// Start procedure for ZStack 3
|
||||||
|
// ======================================================================
|
||||||
|
ZI_LABEL(ZIGBEE_LABEL_ZB3_INIT)
|
||||||
|
ZI_SEND(ZBS_PFGK3) // check PFGK on ZB3
|
||||||
|
ZI_WAIT_RECV(1000, ZBR_PFGK3)
|
||||||
|
|
||||||
|
ZI_MQTT_STATE(ZIGBEE_STATUS_STARTING, kConfiguredCoord)
|
||||||
|
ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) // set any failure to ABORT
|
||||||
|
// Set channel mask for primary and secondary, using BDB_SET_CHANNEL
|
||||||
|
ZI_SEND(ZBS_W_BDB_CHANN) // set channel for primary network
|
||||||
|
ZI_WAIT_RECV(2000, ZBR_W_BDB_CHANN_OK)
|
||||||
|
ZI_SEND(ZBS_W_BDB_CHANN2) // no channel for secondary network
|
||||||
|
ZI_WAIT_RECV(2000, ZBR_W_BDB_CHANN_OK)
|
||||||
|
// all is good, we can start
|
||||||
|
ZI_SEND(ZBS_BDB_START_COMMIS) // start coordinator
|
||||||
|
ZI_WAIT_RECV(5000, ZBR_BDB_START_COMMIS) // wait for sync ack of command
|
||||||
|
ZI_WAIT_UNTIL_FUNC(20000, AREQ_STARTUPFROMAPP, &ZNP_ReceiveStateChange) // wait for async message that coordinator started, max 20s
|
||||||
|
|
||||||
|
// ======================================================================
|
||||||
|
// Coordinator has started, to post-configuration
|
||||||
|
// ======================================================================
|
||||||
|
ZI_LABEL(ZIGBEE_LABEL_COORD_STARTED) // Coordinator has started
|
||||||
ZI_SEND(ZBS_GETDEVICEINFO) // GetDeviceInfo
|
ZI_SEND(ZBS_GETDEVICEINFO) // GetDeviceInfo
|
||||||
ZI_WAIT_RECV_FUNC(2000, ZBR_GETDEVICEINFO, &ZNP_ReceiveDeviceInfo)
|
ZI_WAIT_RECV_FUNC(2000, ZBR_GETDEVICEINFO, &ZNP_ReceiveDeviceInfo)
|
||||||
//ZI_WAIT_RECV(2000, ZBR_GETDEVICEINFO) // memorize info
|
|
||||||
ZI_SEND(ZBS_ZDO_NODEDESCREQ) // Z_ZDO:nodeDescReq
|
ZI_SEND(ZBS_ZDO_NODEDESCREQ) // Z_ZDO:nodeDescReq
|
||||||
ZI_WAIT_RECV(1000, ZBR_ZDO_NODEDESCREQ)
|
ZI_WAIT_RECV(1000, ZBR_ZDO_NODEDESCREQ)
|
||||||
ZI_WAIT_UNTIL(5000, AREQ_ZDO_NODEDESCRSP)
|
ZI_WAIT_UNTIL(5000, AREQ_ZDO_NODEDESCRSP)
|
||||||
ZI_SEND(ZBS_ZDO_ACTIVEEPREQ) // Z_ZDO:activeEpReq
|
ZI_SEND(ZBS_ZDO_ACTIVEEPREQ) // Z_ZDO:activeEpReq
|
||||||
ZI_WAIT_RECV(1000, ZBR_ZDO_ACTIVEEPREQ)
|
ZI_WAIT_RECV(1000, ZBR_ZDO_ACTIVEEPREQ)
|
||||||
ZI_WAIT_UNTIL(1000, ZBR_ZDO_ACTIVEEPRSP_NONE)
|
ZI_WAIT_UNTIL(1000, ZBR_ZDO_ACTIVEEPRSP_SUCESS)
|
||||||
ZI_SEND(ZBS_AF_REGISTER01) // Z_AF register for endpoint 01, profile 0x0104 Home Automation
|
ZI_SEND(ZBS_AF_REGISTER01) // Z_AF register for endpoint 01, profile 0x0104 Home Automation
|
||||||
ZI_WAIT_RECV(1000, ZBR_AF_REGISTER)
|
ZI_WAIT_RECV(1000, ZBR_AF_REGISTER)
|
||||||
ZI_SEND(ZBS_AF_REGISTER0B) // Z_AF register for endpoint 0B, profile 0x0104 Home Automation
|
ZI_SEND(ZBS_AF_REGISTER0B) // Z_AF register for endpoint 0B, profile 0x0104 Home Automation
|
||||||
@ -495,6 +535,9 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
|
|||||||
ZI_WAIT_FOREVER()
|
ZI_WAIT_FOREVER()
|
||||||
ZI_GOTO(ZIGBEE_LABEL_READY)
|
ZI_GOTO(ZIGBEE_LABEL_READY)
|
||||||
|
|
||||||
|
// ======================================================================
|
||||||
|
// Wrong configuration, do a factory reset and push configuration
|
||||||
|
// ======================================================================
|
||||||
ZI_LABEL(ZIGBEE_LABEL_FACT_RESET_COORD) // reformat device
|
ZI_LABEL(ZIGBEE_LABEL_FACT_RESET_COORD) // reformat device
|
||||||
ZI_MQTT_STATE(ZIGBEE_STATUS_RESET_CONF, kResetting)
|
ZI_MQTT_STATE(ZIGBEE_STATUS_RESET_CONF, kResetting)
|
||||||
//ZI_LOG(LOG_LEVEL_INFO, D_LOG_ZIGBEE "zigbee bad configuration of device, doing a factory reset")
|
//ZI_LOG(LOG_LEVEL_INFO, D_LOG_ZIGBEE "zigbee bad configuration of device, doing a factory reset")
|
||||||
|
@ -51,7 +51,7 @@ void EZ_RSTACK(uint8_t reset_code) {
|
|||||||
default: reason_str = PSTR("Unknown"); break;
|
default: reason_str = PSTR("Unknown"); break;
|
||||||
}
|
}
|
||||||
Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{"
|
Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{"
|
||||||
"\"Status\":%d,\"Message\":\"EFR32 booted\",\"RestartReason\":\"%s\""
|
"\"Status\":%d,\"Message\":\"EFR32 EZSP booted\",\"RestartReason\":\"%s\""
|
||||||
",\"Code\":%d}}"),
|
",\"Code\":%d}}"),
|
||||||
ZIGBEE_STATUS_BOOT, reason_str, reset_code);
|
ZIGBEE_STATUS_BOOT, reason_str, reset_code);
|
||||||
|
|
||||||
@ -418,7 +418,7 @@ int32_t ZNP_Reboot(int32_t res, SBuffer &buf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{"
|
Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{"
|
||||||
"\"Status\":%d,\"Message\":\"CCxxxx booted\",\"RestartReason\":\"%s\""
|
"\"Status\":%d,\"Message\":\"CCxxxx ZNP booted\",\"RestartReason\":\"%s\""
|
||||||
",\"MajorRel\":%d,\"MinorRel\":%d}}"),
|
",\"MajorRel\":%d,\"MinorRel\":%d}}"),
|
||||||
ZIGBEE_STATUS_BOOT, reason_str,
|
ZIGBEE_STATUS_BOOT, reason_str,
|
||||||
major_rel, minor_rel);
|
major_rel, minor_rel);
|
||||||
|
@ -178,7 +178,7 @@ bool Xdrv29(uint8_t function)
|
|||||||
DeepSleepEverySecond();
|
DeepSleepEverySecond();
|
||||||
break;
|
break;
|
||||||
case FUNC_AFTER_TELEPERIOD:
|
case FUNC_AFTER_TELEPERIOD:
|
||||||
if (DeepSleepEnabled() && !deepsleep_flag) {
|
if (DeepSleepEnabled() && !deepsleep_flag && (Settings->tele_period == 10 || Settings->tele_period == 300 || millis() > 20000 )) {
|
||||||
deepsleep_flag = DEEPSLEEP_START_COUNTDOWN; // Start deepsleep in 4 seconds
|
deepsleep_flag = DEEPSLEEP_START_COUNTDOWN; // Start deepsleep in 4 seconds
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -41,11 +41,11 @@ IPAddress ip_filter;
|
|||||||
TasmotaSerial *TCPSerial = nullptr;
|
TasmotaSerial *TCPSerial = nullptr;
|
||||||
|
|
||||||
const char kTCPCommands[] PROGMEM = "TCP" "|" // prefix
|
const char kTCPCommands[] PROGMEM = "TCP" "|" // prefix
|
||||||
"Start" "|" "Baudrate" "|" "Config"
|
"Start" "|" "Baudrate" "|" "Config" "|" "Connect"
|
||||||
;
|
;
|
||||||
|
|
||||||
void (* const TCPCommand[])(void) PROGMEM = {
|
void (* const TCPCommand[])(void) PROGMEM = {
|
||||||
&CmndTCPStart, &CmndTCPBaudrate, &CmndTCPConfig
|
&CmndTCPStart, &CmndTCPBaudrate, &CmndTCPConfig, &CmndTCPConnect
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -216,6 +216,45 @@ void CmndTCPConfig(void) {
|
|||||||
ResponseCmndChar_P(GetSerialConfig(0x7F & Settings->tcp_config).c_str());
|
ResponseCmndChar_P(GetSerialConfig(0x7F & Settings->tcp_config).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Command `Connect`
|
||||||
|
// Params: port,<IPv4>
|
||||||
|
//
|
||||||
|
void CmndTCPConnect(void) {
|
||||||
|
int32_t tcp_port = XdrvMailbox.payload;
|
||||||
|
|
||||||
|
if (ArgC() == 2) {
|
||||||
|
char sub_string[XdrvMailbox.data_len];
|
||||||
|
WiFiClient new_client;
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_TCP "Connecting to %s on port %d"), ArgV(sub_string, 2),tcp_port);
|
||||||
|
if (new_client.connect(ArgV(sub_string, 2),tcp_port)) {
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_TCP "connected!"));
|
||||||
|
} else {
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_TCP "error connecting!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// find an empty slot
|
||||||
|
uint32_t i;
|
||||||
|
for (i=0; i<nitems(client_tcp); i++) {
|
||||||
|
WiFiClient &client = client_tcp[i];
|
||||||
|
if (!client) {
|
||||||
|
client = new_client;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i >= nitems(client_tcp)) {
|
||||||
|
i = client_next++ % nitems(client_tcp);
|
||||||
|
WiFiClient &client = client_tcp[i];
|
||||||
|
client.stop();
|
||||||
|
client = new_client;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_TCP "Usage: port,ip_address"));
|
||||||
|
}
|
||||||
|
|
||||||
|
ResponseCmndDone();
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Interface
|
* Interface
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
89
tasmota/xdrv_52_3_berry_mqtt.ino
Normal file
89
tasmota/xdrv_52_3_berry_mqtt.ino
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
xdrv_52_3_berry_mqtt.ino - Berry scripting language, native fucnctions
|
||||||
|
|
||||||
|
Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Mappgin from internal light and a generic `light_state` Berry class
|
||||||
|
|
||||||
|
#ifdef USE_BERRY
|
||||||
|
|
||||||
|
#include "berry.h"
|
||||||
|
|
||||||
|
// Berry: `tasmota.publish(topic, payload [, retain:bool, start:int, len:int]) -> nil``
|
||||||
|
// is_method is true if called from Tasmota class, false if called from mqtt module
|
||||||
|
int32_t be_mqtt_publish(struct bvm *vm, bool is_method) {
|
||||||
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
if (top >= 2+is_method && be_isstring(vm, 1+is_method) && (be_isstring(vm, 2+is_method) || be_isbytes(vm, 2+is_method))) { // 2 mandatory string arguments
|
||||||
|
bool retain = false;
|
||||||
|
int32_t payload_start = 0;
|
||||||
|
int32_t len = -1; // send all of it
|
||||||
|
if (top >= 3+is_method) { retain = be_tobool(vm, 3+is_method); }
|
||||||
|
if (top >= 4+is_method) {
|
||||||
|
payload_start = be_toint(vm, 4+is_method);
|
||||||
|
if (payload_start < 0) payload_start = 0;
|
||||||
|
}
|
||||||
|
if (top >= 5+is_method) { len = be_toint(vm, 5+is_method); }
|
||||||
|
const char * topic = be_tostring(vm, 1+is_method);
|
||||||
|
const char * payload = nullptr;
|
||||||
|
size_t payload_len = 0;
|
||||||
|
|
||||||
|
if (be_isstring(vm, 2+is_method)) {
|
||||||
|
payload = be_tostring(vm, 2+is_method);
|
||||||
|
payload_len = strlen(payload);
|
||||||
|
} else {
|
||||||
|
payload = (const char *) be_tobytes(vm, 2+is_method, &payload_len);
|
||||||
|
}
|
||||||
|
if (!payload) { be_raise(vm, "value_error", "Empty payload"); }
|
||||||
|
|
||||||
|
// adjust start and len
|
||||||
|
if (payload_start >= payload_len) { len = 0; } // send empty packet
|
||||||
|
else if (len < 0) { len = payload_len - payload_start; } // send all packet, adjust len
|
||||||
|
else if (payload_start + len > payload_len) { len = payload_len - payload_start; } // len is too long, adjust
|
||||||
|
// adjust start
|
||||||
|
payload = payload + payload_start;
|
||||||
|
|
||||||
|
be_pop(vm, be_top(vm)); // clear stack to avoid any indirect warning message in subsequent calls to Berry
|
||||||
|
|
||||||
|
MqttPublishPayload(topic, payload, len, retain);
|
||||||
|
|
||||||
|
be_return_nil(vm); // Return
|
||||||
|
}
|
||||||
|
be_raise(vm, kTypeError, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
int32_t l_publish(struct bvm *vm);
|
||||||
|
int32_t l_publish(struct bvm *vm) {
|
||||||
|
return be_mqtt_publish(vm, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t be_mqtt_publish(struct bvm *vm) {
|
||||||
|
return be_mqtt_publish(vm, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void be_mqtt_subscribe(const char* topic) {
|
||||||
|
if (!topic) { return; }
|
||||||
|
MqttSubscribe(topic);
|
||||||
|
}
|
||||||
|
|
||||||
|
void be_mqtt_unsubscribe(const char* topic) {
|
||||||
|
if (!topic) { return; }
|
||||||
|
MqttUnsubscribe(topic);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_BERRY
|
@ -68,49 +68,6 @@ const uint32_t BERRY_MAX_REPL_LOGS = 1024; // max number of print output recor
|
|||||||
*
|
*
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
extern "C" {
|
extern "C" {
|
||||||
// Berry: `tasmota.publish(topic, payload [, retain:bool, start:int, len:int]) -> nil``
|
|
||||||
//
|
|
||||||
int32_t l_publish(struct bvm *vm);
|
|
||||||
int32_t l_publish(struct bvm *vm) {
|
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
|
||||||
if (top >= 3 && be_isstring(vm, 2) && (be_isstring(vm, 3) || be_isbytes(vm, 3))) { // 2 mandatory string arguments
|
|
||||||
bool retain = false;
|
|
||||||
int32_t payload_start = 0;
|
|
||||||
int32_t len = -1; // send all of it
|
|
||||||
if (top >= 4) { retain = be_tobool(vm, 4); }
|
|
||||||
if (top >= 5) {
|
|
||||||
payload_start = be_toint(vm, 5);
|
|
||||||
if (payload_start < 0) payload_start = 0;
|
|
||||||
}
|
|
||||||
if (top >= 6) { len = be_toint(vm, 6); }
|
|
||||||
const char * topic = be_tostring(vm, 2);
|
|
||||||
const char * payload = nullptr;
|
|
||||||
size_t payload_len = 0;
|
|
||||||
|
|
||||||
if (be_isstring(vm, 3)) {
|
|
||||||
payload = be_tostring(vm, 3);
|
|
||||||
payload_len = strlen(payload);
|
|
||||||
} else {
|
|
||||||
payload = (const char *) be_tobytes(vm, 3, &payload_len);
|
|
||||||
}
|
|
||||||
if (!payload) { be_raise(vm, "value_error", "Empty payload"); }
|
|
||||||
|
|
||||||
// adjust start and len
|
|
||||||
if (payload_start >= payload_len) { len = 0; } // send empty packet
|
|
||||||
else if (len < 0) { len = payload_len - payload_start; } // send all packet, adjust len
|
|
||||||
else if (payload_start + len > payload_len) { len = payload_len - payload_start; } // len is too long, adjust
|
|
||||||
// adjust start
|
|
||||||
payload = payload + payload_start;
|
|
||||||
|
|
||||||
be_pop(vm, be_top(vm)); // clear stack to avoid any indirect warning message in subsequent calls to Berry
|
|
||||||
|
|
||||||
MqttPublishPayload(topic, payload, len, retain);
|
|
||||||
|
|
||||||
be_return_nil(vm); // Return
|
|
||||||
}
|
|
||||||
be_raise(vm, kTypeError, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Berry: `tasmota.publish_result(payload:string, subtopic:string) -> nil``
|
// Berry: `tasmota.publish_result(payload:string, subtopic:string) -> nil``
|
||||||
//
|
//
|
||||||
int32_t l_publish_result(struct bvm *vm);
|
int32_t l_publish_result(struct bvm *vm);
|
||||||
@ -220,11 +177,10 @@ extern "C" {
|
|||||||
if (UsePSRAM()) {
|
if (UsePSRAM()) {
|
||||||
be_map_insert_int(vm, "psram", ESP.getPsramSize() / 1024);
|
be_map_insert_int(vm, "psram", ESP.getPsramSize() / 1024);
|
||||||
be_map_insert_int(vm, "psram_free", ESP.getFreePsram() / 1024);
|
be_map_insert_int(vm, "psram_free", ESP.getFreePsram() / 1024);
|
||||||
} else {
|
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
// 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_pop(vm, 1);
|
||||||
be_return(vm);
|
be_return(vm);
|
||||||
}
|
}
|
||||||
|
@ -89,21 +89,7 @@ extern "C" {
|
|||||||
#ifdef USE_BERRY_IRAM
|
#ifdef USE_BERRY_IRAM
|
||||||
return special_malloc32(size);
|
return special_malloc32(size);
|
||||||
#else
|
#else
|
||||||
return special_malloc(size);
|
return NULL; /* return NULL to indicate that IRAM is not enabled */
|
||||||
#endif
|
|
||||||
}
|
|
||||||
void *berry_realloc32(void *ptr, size_t size) {
|
|
||||||
#ifdef USE_BERRY_IRAM
|
|
||||||
return special_realloc32(ptr, size);
|
|
||||||
#else
|
|
||||||
return special_realloc(ptr, size);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
void *berry_calloc32(size_t num, size_t size) {
|
|
||||||
#ifdef USE_BERRY_IRAM
|
|
||||||
return special_calloc32(num, size);
|
|
||||||
#else
|
|
||||||
return special_calloc(num, size);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,8 +220,14 @@ void BerryObservability(bvm *vm, int event...) {
|
|||||||
uint32_t gc_elapsed = millis() - gc_time;
|
uint32_t gc_elapsed = millis() - gc_time;
|
||||||
uint32_t vm_scanned = va_arg(param, uint32_t);
|
uint32_t vm_scanned = va_arg(param, uint32_t);
|
||||||
uint32_t vm_freed = va_arg(param, uint32_t);
|
uint32_t vm_freed = va_arg(param, uint32_t);
|
||||||
AddLog(LOG_LEVEL_DEBUG_MORE, D_LOG_BERRY "GC from %i to %i bytes, objects freed %i/%i (in %d ms)",
|
size_t slots_used_before_gc = va_arg(param, size_t);
|
||||||
vm_usage, vm_usage2, vm_freed, vm_scanned, gc_elapsed);
|
size_t slots_allocated_before_gc = va_arg(param, size_t);
|
||||||
|
size_t slots_used_after_gc = va_arg(param, size_t);
|
||||||
|
size_t slots_allocated_after_gc = va_arg(param, size_t);
|
||||||
|
AddLog(LOG_LEVEL_DEBUG_MORE, D_LOG_BERRY "GC from %i to %i bytes, objects freed %i/%i (in %d ms) - slots from %i/%i to %i/%i",
|
||||||
|
vm_usage, vm_usage2, vm_freed, vm_scanned, gc_elapsed,
|
||||||
|
slots_used_before_gc, slots_allocated_before_gc,
|
||||||
|
slots_used_after_gc, slots_allocated_after_gc);
|
||||||
// make new threshold tighter when we reach high memory usage
|
// make new threshold tighter when we reach high memory usage
|
||||||
if (!UsePSRAM() && vm->gc.threshold > 20*1024) {
|
if (!UsePSRAM() && vm->gc.threshold > 20*1024) {
|
||||||
vm->gc.threshold = vm->gc.usage + 10*1024; // increase by only 10 KB
|
vm->gc.threshold = vm->gc.usage + 10*1024; // increase by only 10 KB
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
* Green led is controlled by ARM processor indicating SD-Card access.
|
* Green led is controlled by ARM processor indicating SD-Card access.
|
||||||
* ESP32 is used as interface between eWelink and ARM processor in SPM-Main unit communicating over proprietary serial protocol.
|
* ESP32 is used as interface between eWelink and ARM processor in SPM-Main unit communicating over proprietary serial protocol.
|
||||||
* Power on sequence for two SPM-4Relay modules is 00-00-15-10-(0F)-(13)-(13)-(19)-0C-09-04-09-04-0B-0B
|
* Power on sequence for two SPM-4Relay modules is 00-00-15-10-(0F)-(13)-(13)-(19)-0C-09-04-09-04-0B-0B
|
||||||
* Up to six months of daily energy are stored onthe SD-Card. Previous data is lost.
|
* Up to 180 days of daily energy are stored on the SD-Card. Previous data is lost.
|
||||||
* Tasmota support is based on Sonoff SPM v1.0.0 ARM firmware.
|
* Tasmota support is based on Sonoff SPM v1.0.0 ARM firmware.
|
||||||
* Energy history cannot be guaranteed using either SD-Card or internal flash. As a solution Tasmota stores the total energy and yesterday energy just after midnight.
|
* Energy history cannot be guaranteed using either SD-Card or internal flash. As a solution Tasmota stores the total energy and yesterday energy just after midnight.
|
||||||
*
|
*
|
||||||
@ -55,6 +55,7 @@
|
|||||||
* SspmHistory<relay> - Retrieve daily energy of last six month (as defined by ARM firmware)
|
* SspmHistory<relay> - Retrieve daily energy of last six month (as defined by ARM firmware)
|
||||||
* SspmIAmHere<relay> - Blink ERROR in SPM-4Relay where relay resides
|
* SspmIAmHere<relay> - Blink ERROR in SPM-4Relay where relay resides
|
||||||
* SspmLog<relay> [x] - Retrieve relay power state change and cause logging
|
* SspmLog<relay> [x] - Retrieve relay power state change and cause logging
|
||||||
|
* SspmMap 0 - Start a scan to fill default mapping
|
||||||
* SspmMap 2,3,1,.. - Map scanned module number to physical module number using positional numbering
|
* SspmMap 2,3,1,.. - Map scanned module number to physical module number using positional numbering
|
||||||
* SspmOverload<relay> 0 - Set default overload detection parameters as read from module during initial scan
|
* SspmOverload<relay> 0 - Set default overload detection parameters as read from module during initial scan
|
||||||
* SspmOverload<relay> <delay>,<min_power>,<max_power>,<min_voltage>,<max_voltage,<max_current>
|
* SspmOverload<relay> <delay>,<min_power>,<max_power>,<min_voltage>,<max_voltage,<max_current>
|
||||||
@ -1409,11 +1410,21 @@ void SSPMHandleReceivedData(void) {
|
|||||||
Sspm->min_voltage = SSPMGetValue(&SspmBuffer[46]); // x.xxV
|
Sspm->min_voltage = SSPMGetValue(&SspmBuffer[46]); // x.xxV
|
||||||
}
|
}
|
||||||
uint32_t module_id = SspmBuffer[19] << 8 | SspmBuffer[20];
|
uint32_t module_id = SspmBuffer[19] << 8 | SspmBuffer[20];
|
||||||
if (0 == Sspm->Settings.module_map[Sspm->module_max]) {
|
// if (0 == Sspm->Settings.module_map[Sspm->module_max]) {
|
||||||
Sspm->Settings.module_map[Sspm->module_max] = module_id;
|
// Sspm->Settings.module_map[Sspm->module_max] = module_id;
|
||||||
}
|
// }
|
||||||
int mapped = SSPMGetModuleNumberFromMapIfFound(module_id);
|
int mapped = SSPMGetModuleNumberFromMapIfFound(module_id);
|
||||||
if (-1 == mapped) { Sspm->map_change = true; }
|
if (-1 == mapped) {
|
||||||
|
// Scanned module not in mapped list. Append if possible
|
||||||
|
for (uint32_t module = Sspm->module_max; module < SSPM_MAX_MODULES; module++) {
|
||||||
|
if (0 == Sspm->Settings.module_map[module]) {
|
||||||
|
Sspm->Settings.module_map[module] = module_id;
|
||||||
|
mapped = module;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Sspm->map_change = true;
|
||||||
|
}
|
||||||
mapped++;
|
mapped++;
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("SPM: 4Relay %d (mapped to %d) type %d version %d.%d.%d found with id %12_H"),
|
AddLog(LOG_LEVEL_INFO, PSTR("SPM: 4Relay %d (mapped to %d) type %d version %d.%d.%d found with id %12_H"),
|
||||||
Sspm->module_max +1, mapped, SspmBuffer[35], SspmBuffer[36], SspmBuffer[37], SspmBuffer[38], Sspm->module[Sspm->module_max]);
|
Sspm->module_max +1, mapped, SspmBuffer[35], SspmBuffer[36], SspmBuffer[37], SspmBuffer[38], Sspm->module[Sspm->module_max]);
|
||||||
@ -2212,9 +2223,16 @@ void CmndSSPMReset(void) {
|
|||||||
|
|
||||||
void CmndSSPMMap(void) {
|
void CmndSSPMMap(void) {
|
||||||
// Map scanned module number to physical module number using positional numbering
|
// Map scanned module number to physical module number using positional numbering
|
||||||
// SspmMap 1,3,4,2
|
// SspmMap 0 - start a scan to fill default mapping
|
||||||
|
// SspmMap 1,3,4,2 - map modules
|
||||||
// TODO: Might need input checks on count and valid different numbers
|
// TODO: Might need input checks on count and valid different numbers
|
||||||
if (Sspm->module_max) { // Valid after initial scan
|
if (0 == XdrvMailbox.payload) {
|
||||||
|
for (uint32_t module = 0; module < SSPM_MAX_MODULES; module++) {
|
||||||
|
Sspm->Settings.module_map[module] = 0; // Clear mapping slots
|
||||||
|
}
|
||||||
|
CmndSSPMScan(); // Start scan to fill default mapping
|
||||||
|
}
|
||||||
|
else if (Sspm->module_max) { // Valid after initial scan
|
||||||
char *p;
|
char *p;
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
for (char* str = strtok_r(XdrvMailbox.data, ",", &p); str && i < Sspm->module_max; str = strtok_r(nullptr, ",", &p)) {
|
for (char* str = strtok_r(XdrvMailbox.data, ",", &p); str && i < Sspm->module_max; str = strtok_r(nullptr, ",", &p)) {
|
||||||
|
357
tasmota/xnrg_22_bl6523.ino
Normal file
357
tasmota/xnrg_22_bl6523.ino
Normal file
@ -0,0 +1,357 @@
|
|||||||
|
/*
|
||||||
|
xnrg_22_bl6523.ino - BL6523 based Watt hour meter support for Tasmota
|
||||||
|
|
||||||
|
Copyright (C) 2022 Jeevas Vasudevan
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef USE_ENERGY_SENSOR
|
||||||
|
#ifdef USE_BL6523
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Chinese BL6523 based Watt hour meter
|
||||||
|
*
|
||||||
|
* This meter provides accurate Voltage, Frequency, Ampere, Wattage, Power Factor, KWh
|
||||||
|
* To use Tasmota the user needs to add an ESP8266 or ESP32
|
||||||
|
* Three lines need to be connected via 1KOhh resistors to ESP from the main board(RX,TX GND)
|
||||||
|
*
|
||||||
|
* Connection Eg (ESP8266) - Non - Isolated:
|
||||||
|
* BL6523 RX ->1KOhm-> ESP IO4(D2) (Should be Input Capable)
|
||||||
|
* BL6523 TX ->1KOhm-> ESP IO5(D1) (Should be Input Capable)
|
||||||
|
* BL6523 GND -> ESP GND
|
||||||
|
*
|
||||||
|
* Connection Eg (ESP32) - Non - Isolated:
|
||||||
|
* BL6523 RX ->1KOhm-> ESP IO4 (Should be Input Capable)
|
||||||
|
* BL6523 TX ->1KOhm-> ESP IO5 (Should be Input Capable)
|
||||||
|
* BL6523 GND -> ESP GND
|
||||||
|
*
|
||||||
|
* To build add the below to user_config_override.h
|
||||||
|
* #define USE_ENERGY_SENSOR // Enable Energy sensor framework
|
||||||
|
* #define USE_BL6523 // Add support for Chinese BL6523 based Watt hour meter (+1k code)¸
|
||||||
|
*
|
||||||
|
* After Installation use the below template sample:
|
||||||
|
* {"NAME":"BL6523 Smart Meter","GPIO":[0,0,0,0,7488,7520,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":18}
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
#define XNRG_22 22
|
||||||
|
|
||||||
|
#include <TasmotaSerial.h>
|
||||||
|
|
||||||
|
#define BL6523_RX_DATASET_SIZE 2
|
||||||
|
#define BL6523_TX_DATASET_SIZE 4
|
||||||
|
|
||||||
|
#define BL6523_BAUD 4800
|
||||||
|
#define BL6523_REG_AMPS 0x05
|
||||||
|
#define BL6523_REG_VOLTS 0x07
|
||||||
|
#define BL6523_REG_FREQ 0x09
|
||||||
|
#define BL6523_REG_WATTS 0x0A
|
||||||
|
#define BL6523_REG_POWF 0x08
|
||||||
|
#define BL6523_REG_WATTHR 0x0C
|
||||||
|
|
||||||
|
#define SINGLE_PHASE 0
|
||||||
|
#define RX_WAIT 100
|
||||||
|
|
||||||
|
#define BL6523_IREF 297899
|
||||||
|
#define BL6523_UREF 13304
|
||||||
|
#define BL6523_FREF 3907
|
||||||
|
#define BL6523_PREF 707
|
||||||
|
#define BL6523_PWHRREF_D 33 // Substract this from BL6523_PREF to get WattHr Div.
|
||||||
|
|
||||||
|
TasmotaSerial *Bl6523RxSerial;
|
||||||
|
TasmotaSerial *Bl6523TxSerial;
|
||||||
|
|
||||||
|
struct BL6523
|
||||||
|
{
|
||||||
|
uint8_t type = 1;
|
||||||
|
uint8_t valid = 0;
|
||||||
|
uint8_t got_data_stone = 0;
|
||||||
|
bool discovery_triggered = false;
|
||||||
|
} Bl6523;
|
||||||
|
|
||||||
|
bool Bl6523ReadData(void)
|
||||||
|
{
|
||||||
|
uint32_t powf_word = 0, powf_buf = 0, i = 0;
|
||||||
|
float powf = 0.0f;
|
||||||
|
|
||||||
|
if (!Bl6523RxSerial->available())
|
||||||
|
{
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, PSTR("BL6:No Rx Data available" ));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((Bl6523RxSerial->peek() != 0x35) && Bl6523RxSerial->available())
|
||||||
|
{
|
||||||
|
Bl6523RxSerial->read();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Bl6523RxSerial->available() < BL6523_RX_DATASET_SIZE)
|
||||||
|
{
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, PSTR("BL6:Rx less than expected" ));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t rx_buffer[BL6523_RX_DATASET_SIZE];
|
||||||
|
Bl6523RxSerial->readBytes(rx_buffer, BL6523_RX_DATASET_SIZE);
|
||||||
|
Bl6523RxSerial->flush(); // Make room for another burst
|
||||||
|
|
||||||
|
AddLogBuffer(LOG_LEVEL_DEBUG_MORE, rx_buffer, BL6523_RX_DATASET_SIZE);
|
||||||
|
|
||||||
|
i=0;
|
||||||
|
while (Bl6523TxSerial->available() < BL6523_TX_DATASET_SIZE)
|
||||||
|
{
|
||||||
|
// sleep till TX buffer is full
|
||||||
|
delay(10);
|
||||||
|
if ( i++ > RX_WAIT ){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t tx_buffer[BL6523_TX_DATASET_SIZE];
|
||||||
|
Bl6523TxSerial->readBytes(tx_buffer, BL6523_TX_DATASET_SIZE);
|
||||||
|
Bl6523TxSerial->flush(); // Make room for another burst
|
||||||
|
|
||||||
|
|
||||||
|
AddLogBuffer(LOG_LEVEL_DEBUG_MORE, tx_buffer, BL6523_TX_DATASET_SIZE);
|
||||||
|
|
||||||
|
/* Checksum: (Addr+Data_L+Data_M+Data_H) & 0xFF, then byte invert */
|
||||||
|
uint8_t crc = rx_buffer[1]; //Addr
|
||||||
|
for (uint32_t i = 0; i < (BL6523_TX_DATASET_SIZE - 1); i++)
|
||||||
|
{
|
||||||
|
crc += tx_buffer[i]; //Add Data_L,Data_M and Data_H to Addr
|
||||||
|
}
|
||||||
|
crc &= 0xff; // Bitwise AND 0xFF
|
||||||
|
crc = ~crc; // Invert the byte
|
||||||
|
if (crc != tx_buffer[BL6523_TX_DATASET_SIZE - 1])
|
||||||
|
{
|
||||||
|
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("BL6:" D_CHECKSUM_FAILURE));
|
||||||
|
Bl6523TxSerial->flush();
|
||||||
|
Bl6523RxSerial->flush();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* WRITE DATA (format: command(write->0xCA) address data_low data_mid data_high checksum )
|
||||||
|
WRITE Sample(RX):
|
||||||
|
RX: CA 3E 55 00 00 6C (WRPROT - allow)
|
||||||
|
RX: CA 14 00 00 10 DB (MODE)
|
||||||
|
RX: CA 15 04 00 00 E6 (GAIN - IB 16x gain )
|
||||||
|
RX: CA 19 08 00 00 DE (WA_CFDIV )
|
||||||
|
RX: CA 3E AA 00 00 17 (WRPROT - disable)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* READ DATA (format: command(read->0x35) address data_low data_mid data_high checksum )
|
||||||
|
READ Sample(RX-TX) Data:
|
||||||
|
RX: 35 05 TX: E4 00 00 16 (IA rms )
|
||||||
|
RX: 35 07 TX: D5 A3 2E 52 (V rms )
|
||||||
|
RX: 35 09 TX: F0 FB 02 09 (FREQ)
|
||||||
|
RX: 35 0A TX: 00 00 00 F5 (WATT)
|
||||||
|
RX: 35 08 TX: 00 00 00 F7 (PF)
|
||||||
|
RX: 35 0C TX: 00 00 00 F3 (WATT_HR)
|
||||||
|
*/
|
||||||
|
|
||||||
|
switch(rx_buffer[1]) {
|
||||||
|
case BL6523_REG_AMPS :
|
||||||
|
Energy.current[SINGLE_PHASE] = (float)((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]) / Settings->energy_current_calibration; // 1.260 A
|
||||||
|
break;
|
||||||
|
case BL6523_REG_VOLTS :
|
||||||
|
Energy.voltage[SINGLE_PHASE] = (float)((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]) / Settings->energy_voltage_calibration; // 230.2 V
|
||||||
|
break;
|
||||||
|
case BL6523_REG_FREQ :
|
||||||
|
Energy.frequency[SINGLE_PHASE] = (float)((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]) / Settings->energy_frequency_calibration; // 50.0 Hz
|
||||||
|
break;
|
||||||
|
case BL6523_REG_WATTS :
|
||||||
|
Energy.active_power[SINGLE_PHASE] = (float)((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]) / Settings->energy_power_calibration; // -196.3 W
|
||||||
|
break;
|
||||||
|
case BL6523_REG_POWF :
|
||||||
|
/* Power factor =(sign bit)*((PF[22]×2^-1)+(PF[21]×2^-2)+。。。)
|
||||||
|
Eg., reg value 0x7FFFFF(HEX) -> PF 1, 0x800000(HEX) -> -1, 0x400000(HEX) -> 0.5
|
||||||
|
*/
|
||||||
|
powf = 0.0f;
|
||||||
|
powf_buf = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]);
|
||||||
|
powf_word = (powf_buf >> 23) ? ~(powf_buf & 0x7fffff) : powf_buf & 0x7fffff; //Extract the 23 bits and invert if sign bit(24) is set
|
||||||
|
for (int i = 0; i < 23; i++){ // Accumulate powf from 23 bits
|
||||||
|
powf += ((powf_word >> (22-i)) * pow(2,(0-(i+1))));
|
||||||
|
powf_word = powf_word & (0x7fffff >> (1+i));
|
||||||
|
}
|
||||||
|
powf = (powf_buf >> 23) ? (0.0f - (powf)) : powf; // Negate if sign bit(24) is set
|
||||||
|
Energy.power_factor[SINGLE_PHASE] = powf;
|
||||||
|
break;
|
||||||
|
case BL6523_REG_WATTHR :
|
||||||
|
Energy.import_active[SINGLE_PHASE] = (float)((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]) / ( Settings->energy_power_calibration - BL6523_PWHRREF_D ); // 6.216 kWh => used in EnergyUpdateTotal()
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Energy.data_valid[SINGLE_PHASE] = 0;
|
||||||
|
EnergyUpdateTotal();
|
||||||
|
if (!Bl6523.discovery_triggered)
|
||||||
|
{
|
||||||
|
TasmotaGlobal.discovery_counter = 1; // force TasDiscovery()
|
||||||
|
Bl6523.discovery_triggered = true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
|
|
||||||
|
void Bl6523Update(void)
|
||||||
|
{ // Every 250 millisecond
|
||||||
|
if (Bl6523ReadData())
|
||||||
|
{
|
||||||
|
Bl6523.valid = 60;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Bl6523.valid) {
|
||||||
|
Bl6523.valid--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************/
|
||||||
|
|
||||||
|
void Bl6523Init(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
Bl6523.type = 0;
|
||||||
|
Bl6523RxSerial = new TasmotaSerial(Pin(GPIO_BL6523_RX), -1, 1);
|
||||||
|
Bl6523TxSerial = new TasmotaSerial(Pin(GPIO_BL6523_TX), -1, 1);
|
||||||
|
if ((Bl6523RxSerial->begin(BL6523_BAUD)) && (Bl6523TxSerial->begin(BL6523_BAUD)))
|
||||||
|
{
|
||||||
|
if (Bl6523RxSerial->hardwareSerial())
|
||||||
|
{
|
||||||
|
ClaimSerial();
|
||||||
|
}
|
||||||
|
if (Bl6523TxSerial->hardwareSerial())
|
||||||
|
{
|
||||||
|
ClaimSerial();
|
||||||
|
}
|
||||||
|
Bl6523.type = 1;
|
||||||
|
Energy.phase_count = 1;
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, PSTR("BL6:Init Success" ));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, PSTR("BL6:Init Failure!" ));
|
||||||
|
TasmotaGlobal.energy_driver = ENERGY_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bl6523Command(void) {
|
||||||
|
bool serviced = true;
|
||||||
|
|
||||||
|
int32_t value = (int32_t)(CharToFloat(XdrvMailbox.data) * 1000); // 1.234 = 1234, -1.234 = -1234
|
||||||
|
uint32_t abs_value = abs(value) / 10; // 1.23 = 123, -1.23 = 123
|
||||||
|
|
||||||
|
if ((CMND_POWERCAL == Energy.command_code) || (CMND_VOLTAGECAL == Energy.command_code) || (CMND_CURRENTCAL == Energy.command_code)) {
|
||||||
|
// Service in xdrv_03_energy.ino
|
||||||
|
}
|
||||||
|
else if (CMND_POWERSET == Energy.command_code) {
|
||||||
|
if (XdrvMailbox.data_len) {
|
||||||
|
if ((abs_value > 100) && (abs_value < 200000)) { // Between 1.00 and 2000.00 W
|
||||||
|
Settings->energy_power_calibration = abs_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (CMND_VOLTAGESET == Energy.command_code) {
|
||||||
|
if (XdrvMailbox.data_len) {
|
||||||
|
if ((abs_value > 10000) && (abs_value < 26000)) { // Between 100.00 and 260.00 V
|
||||||
|
Settings->energy_voltage_calibration = abs_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (CMND_CURRENTSET == Energy.command_code) {
|
||||||
|
if (XdrvMailbox.data_len) {
|
||||||
|
if ((abs_value > 1000) && (abs_value < 1000000)) { // Between 10.00 mA and 10.00000 A
|
||||||
|
Settings->energy_current_calibration = abs_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (CMND_FREQUENCYSET == Energy.command_code) {
|
||||||
|
if (XdrvMailbox.data_len) {
|
||||||
|
if ((abs_value > 4500) && (abs_value < 6500)) { // Between 45.00 and 65.00 Hz
|
||||||
|
Settings->energy_frequency_calibration = abs_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (CMND_ENERGYCONFIG == Energy.command_code) {
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, PSTR("NRG: Config index %d, payload %d, value %d, data '%s'"),
|
||||||
|
XdrvMailbox.index, XdrvMailbox.payload, value, XdrvMailbox.data ? XdrvMailbox.data : "null" );
|
||||||
|
|
||||||
|
// EnergyConfig1 to 3 = Set Energy.current[channel] in A like 0.417 for 417mA
|
||||||
|
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index < 4)) {
|
||||||
|
//Bl6523.current[XdrvMailbox.index -1] = value;
|
||||||
|
}
|
||||||
|
// EnergyConfig4 to 6 = Set Energy.active_power[channel] in W like 100 for 100W
|
||||||
|
if ((XdrvMailbox.index > 3) && (XdrvMailbox.index < 7)) {
|
||||||
|
//Bl6523.power[XdrvMailbox.index -4] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else serviced = false; // Unknown command
|
||||||
|
|
||||||
|
return serviced;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bl6523DrvInit(void)
|
||||||
|
{
|
||||||
|
if (PinUsed(GPIO_BL6523_RX) && PinUsed(GPIO_BL6523_TX)) {
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, PSTR("BL6:PreInit Success" ));
|
||||||
|
TasmotaGlobal.energy_driver = XNRG_22;
|
||||||
|
if (HLW_PREF_PULSE == Settings->energy_power_calibration) {
|
||||||
|
Settings->energy_frequency_calibration = BL6523_FREF;
|
||||||
|
Settings->energy_voltage_calibration = BL6523_UREF;
|
||||||
|
Settings->energy_current_calibration = BL6523_IREF;
|
||||||
|
Settings->energy_power_calibration = BL6523_PREF;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, PSTR("BL6:PreInit Failure!" ));
|
||||||
|
TasmotaGlobal.energy_driver = ENERGY_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Interface
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
bool Xnrg22(uint8_t function)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
switch (function)
|
||||||
|
{
|
||||||
|
case FUNC_EVERY_250_MSECOND:
|
||||||
|
Bl6523Update();
|
||||||
|
break;
|
||||||
|
case FUNC_COMMAND:
|
||||||
|
result = Bl6523Command();
|
||||||
|
break;
|
||||||
|
case FUNC_INIT:
|
||||||
|
Bl6523Init();
|
||||||
|
break;
|
||||||
|
case FUNC_PRE_INIT:
|
||||||
|
Bl6523DrvInit();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_BL6523
|
||||||
|
#endif // USE_ENERGY_SENSOR
|
@ -37,7 +37,13 @@
|
|||||||
* Rule:
|
* Rule:
|
||||||
* on wiegand#uid=4302741608 do publish cmnd/ailight/power 2 endon
|
* on wiegand#uid=4302741608 do publish cmnd/ailight/power 2 endon
|
||||||
*
|
*
|
||||||
* contains:
|
* 20220215
|
||||||
|
* - fix 34-bit size parity chk
|
||||||
|
* - fix 64-bit representation after removal of %llu support (Tasmota does not support 64-bit decimal output specifier (%llu) saving 60k code)
|
||||||
|
* - change internal rfid size from uint64_t to uint32_t
|
||||||
|
* - limited max amount of kaypad presses to a 32-bit number (at least 999999999)
|
||||||
|
* ---
|
||||||
|
* 20201101
|
||||||
* - fix for #11047 Wiegand 26/34 missed some key press if they are press at normal speed
|
* - fix for #11047 Wiegand 26/34 missed some key press if they are press at normal speed
|
||||||
* - removed testing code for tests without attached hardware
|
* - removed testing code for tests without attached hardware
|
||||||
* - added SetOption123 0-Wiegand UID decimal (default) 1-Wiegand UID hexadecimal
|
* - added SetOption123 0-Wiegand UID decimal (default) 1-Wiegand UID hexadecimal
|
||||||
@ -102,23 +108,21 @@ class Wiegand {
|
|||||||
#if (DEV_WIEGAND_TEST_MODE!=1)
|
#if (DEV_WIEGAND_TEST_MODE!=1)
|
||||||
private:
|
private:
|
||||||
#endif //(DEV_WIEGAND_TEST_MODE==1)
|
#endif //(DEV_WIEGAND_TEST_MODE==1)
|
||||||
uint64_t CheckAndConvertRfid(uint64_t,uint16_t);
|
uint32_t CheckAndConvertRfid(uint64_t,uint16_t);
|
||||||
uint8_t CalculateParities(uint64_t, int);
|
uint8_t CalculateParities(uint64_t, int);
|
||||||
bool WiegandConversion (uint64_t , uint16_t );
|
bool WiegandConversion (uint64_t , uint16_t );
|
||||||
void setOutputFormat(void); // fix output HEX format
|
|
||||||
void HandleKeyPad(void); //handle one tag for multi key strokes
|
void HandleKeyPad(void); //handle one tag for multi key strokes
|
||||||
|
|
||||||
|
|
||||||
static void handleD0Interrupt(void);
|
static void handleD0Interrupt(void);
|
||||||
static void handleD1Interrupt(void);
|
static void handleD1Interrupt(void);
|
||||||
static void handleDxInterrupt(int in); // fix #11047
|
static void handleDxInterrupt(int in); // fix #11047
|
||||||
static void ClearRFIDBuffer(int);
|
static void ClearRFIDBuffer(int);
|
||||||
|
|
||||||
uint64_t rfid;
|
uint32_t rfid;
|
||||||
uint32_t tagSize;
|
uint32_t tagSize;
|
||||||
const char* outFormat;
|
const char* outFormat;
|
||||||
uint64_t mqttRFIDKeypadBuffer;
|
uint32_t mqttRFIDKeypadBuffer;
|
||||||
uint64_t webRFIDKeypadBuffer;
|
uint32_t webRFIDKeypadBuffer;
|
||||||
|
|
||||||
static volatile uint64_t rfidBuffer;
|
static volatile uint64_t rfidBuffer;
|
||||||
static volatile uint16_t bitCount;
|
static volatile uint16_t bitCount;
|
||||||
@ -145,15 +149,14 @@ volatile bool Wiegand::CodeComplete;
|
|||||||
volatile RFID_store Wiegand::rfid_found[WIEGAND_RFID_ARRAY_SIZE];
|
volatile RFID_store Wiegand::rfid_found[WIEGAND_RFID_ARRAY_SIZE];
|
||||||
volatile int Wiegand::currentFoundRFIDcount;
|
volatile int Wiegand::currentFoundRFIDcount;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void IRAM_ATTR Wiegand::ClearRFIDBuffer(int endIndex = WIEGAND_RFID_ARRAY_SIZE) {
|
void IRAM_ATTR Wiegand::ClearRFIDBuffer(int endIndex = WIEGAND_RFID_ARRAY_SIZE) {
|
||||||
currentFoundRFIDcount=WIEGAND_RFID_ARRAY_SIZE-endIndex; // clear all buffers
|
currentFoundRFIDcount = WIEGAND_RFID_ARRAY_SIZE - endIndex; // clear all buffers
|
||||||
for (int i= 0; i < endIndex; i++) {
|
for (uint32_t i = 0; i < endIndex; i++) {
|
||||||
rfid_found[i].RFID=0;
|
rfid_found[i].RFID=0;
|
||||||
rfid_found[i].bitCount=0;
|
rfid_found[i].bitCount=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR Wiegand::handleD1Interrupt() { // Receive a 1 bit. (D0=high & D1=low)
|
void IRAM_ATTR Wiegand::handleD1Interrupt() { // Receive a 1 bit. (D0=high & D1=low)
|
||||||
handleDxInterrupt(1);
|
handleDxInterrupt(1);
|
||||||
}
|
}
|
||||||
@ -163,9 +166,9 @@ void IRAM_ATTR Wiegand::handleD0Interrupt() { // Receive a 0 bit. (D0=low & D1=
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR Wiegand::handleDxInterrupt(int in) {
|
void IRAM_ATTR Wiegand::handleDxInterrupt(int in) {
|
||||||
unsigned long curTime = micros(); // to be sure I will use micros() instead of millis() overflow is handle by using the minus operator to compare
|
uint32_t curTime = micros(); // to be sure I will use micros() instead of millis() overflow is handle by using the minus operator to compare
|
||||||
unsigned long diffTime= curTime - lastFoundTime;
|
uint32_t diffTime = curTime - lastFoundTime;
|
||||||
if ( (diffTime > CodeGapTime) && (bitCount > 0)) {
|
if ((diffTime > CodeGapTime) && (bitCount > 0)) {
|
||||||
// previous RFID tag (key pad numer)is complete. Will be detected by the code ending gap
|
// previous RFID tag (key pad numer)is complete. Will be detected by the code ending gap
|
||||||
// one bit will take the time of impulse_time + impulse_gap_time. it (bitTime) will be recalculated each time an impulse is detected
|
// one bit will take the time of impulse_time + impulse_gap_time. it (bitTime) will be recalculated each time an impulse is detected
|
||||||
// the devices will add some inter_code_gap_time to separate codes this will be much longer than the bit_time. (WIEGAND_CODE_GAP_FACTOR)
|
// the devices will add some inter_code_gap_time to separate codes this will be much longer than the bit_time. (WIEGAND_CODE_GAP_FACTOR)
|
||||||
@ -188,7 +191,7 @@ void IRAM_ATTR Wiegand::handleDxInterrupt(int in) {
|
|||||||
FirstBitTimeStamp = (curTime != 0) ? curTime : 1; // accept 1µs differenct to avoid a miss the first timestamp if curTime is 0.
|
FirstBitTimeStamp = (curTime != 0) ? curTime : 1; // accept 1µs differenct to avoid a miss the first timestamp if curTime is 0.
|
||||||
}
|
}
|
||||||
else if (bitCount == 2) { // only calculate once per RFID tag, but restrict to values, which are in within a plausible range
|
else if (bitCount == 2) { // only calculate once per RFID tag, but restrict to values, which are in within a plausible range
|
||||||
bitTime = ((diffTime > (WIEGAND_BIT_TIME_DEFAULT/4)) && (diffTime < (4*WIEGAND_BIT_TIME_DEFAULT))) ? diffTime : WIEGAND_BIT_TIME_DEFAULT;
|
bitTime = ((diffTime > (WIEGAND_BIT_TIME_DEFAULT / 4)) && (diffTime < (4 * WIEGAND_BIT_TIME_DEFAULT))) ? diffTime : WIEGAND_BIT_TIME_DEFAULT;
|
||||||
CodeGapTime = WIEGAND_CODE_GAP_FACTOR * bitTime;
|
CodeGapTime = WIEGAND_CODE_GAP_FACTOR * bitTime;
|
||||||
}
|
}
|
||||||
//save current rfid in array otherwise we will never see the last found tag
|
//save current rfid in array otherwise we will never see the last found tag
|
||||||
@ -243,7 +246,7 @@ void Wiegand::Init() {
|
|||||||
#endif // DEV_WIEGAND_TEST_MODE>0
|
#endif // DEV_WIEGAND_TEST_MODE>0
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t Wiegand::CheckAndConvertRfid(uint64_t rfidIn, uint16_t bitCount) {
|
uint32_t Wiegand::CheckAndConvertRfid(uint64_t rfidIn, uint16_t bitCount) {
|
||||||
uint8_t evenParityBit = 0;
|
uint8_t evenParityBit = 0;
|
||||||
uint8_t oddParityBit = (uint8_t) (rfidIn & 0x1); // Last bit = odd parity
|
uint8_t oddParityBit = (uint8_t) (rfidIn & 0x1); // Last bit = odd parity
|
||||||
uint8_t calcParity = 0;
|
uint8_t calcParity = 0;
|
||||||
@ -264,8 +267,8 @@ uint64_t Wiegand::CheckAndConvertRfid(uint64_t rfidIn, uint16_t bitCount) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 34:
|
case 34:
|
||||||
evenParityBit = (rfidIn & 0x400000000) ? 0x80 : 0;
|
evenParityBit = (rfidIn & 0x200000000) ? 0x80 : 0;
|
||||||
rfidIn = (rfidIn & 0x3FFFFFFFE) >>1;
|
rfidIn = (rfidIn & 0x1FFFFFFFE) >>1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -273,8 +276,8 @@ uint64_t Wiegand::CheckAndConvertRfid(uint64_t rfidIn, uint16_t bitCount) {
|
|||||||
}
|
}
|
||||||
calcParity = CalculateParities(rfidIn, bitCount); // Check result on http://www.ccdesignworks.com/wiegand_calc.htm with raw tag as input
|
calcParity = CalculateParities(rfidIn, bitCount); // Check result on http://www.ccdesignworks.com/wiegand_calc.htm with raw tag as input
|
||||||
if (calcParity != (evenParityBit | oddParityBit)) { // Parity bit is wrong
|
if (calcParity != (evenParityBit | oddParityBit)) { // Parity bit is wrong
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, PSTR("WIE: %_X parity error"), &rfidIn); // Print up to uint64_t
|
||||||
rfidIn=0;
|
rfidIn=0;
|
||||||
AddLog(LOG_LEVEL_DEBUG, PSTR("WIE: %llu parity error"), rfidIn);
|
|
||||||
}
|
}
|
||||||
#if (DEV_WIEGAND_TEST_MODE)>0
|
#if (DEV_WIEGAND_TEST_MODE)>0
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("WIE: even (left) parity: %u "), (evenParityBit>>7));
|
AddLog(LOG_LEVEL_INFO, PSTR("WIE: even (left) parity: %u "), (evenParityBit>>7));
|
||||||
@ -282,10 +285,10 @@ uint64_t Wiegand::CheckAndConvertRfid(uint64_t rfidIn, uint16_t bitCount) {
|
|||||||
AddLog(LOG_LEVEL_INFO, PSTR("WIE: odd (right) parity: %u "), oddParityBit);
|
AddLog(LOG_LEVEL_INFO, PSTR("WIE: odd (right) parity: %u "), oddParityBit);
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("WIE: odd (calc) parity: %u "), (calcParity & 0x01));
|
AddLog(LOG_LEVEL_INFO, PSTR("WIE: odd (calc) parity: %u "), (calcParity & 0x01));
|
||||||
#endif // DEV_WIEGAND_TEST_MODE>0
|
#endif // DEV_WIEGAND_TEST_MODE>0
|
||||||
return rfidIn;
|
return (uint32_t)rfidIn;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t Wiegand::CalculateParities(uint64_t tagWithoutParities, int tag_size=26) {
|
uint8_t Wiegand::CalculateParities(uint64_t tagWithoutParities, int tag_size = 26) {
|
||||||
// tag_size is the size of the final tag including the 2 parity bits
|
// tag_size is the size of the final tag including the 2 parity bits
|
||||||
// So length if the tagWithoutParities should be (tag_size-2) !! That will be not profed and
|
// So length if the tagWithoutParities should be (tag_size-2) !! That will be not profed and
|
||||||
// lead to wrong results if the input value is larger!
|
// lead to wrong results if the input value is larger!
|
||||||
@ -295,7 +298,7 @@ uint8_t Wiegand::CalculateParities(uint64_t tagWithoutParities, int tag_size=26)
|
|||||||
tag_size -= 2;
|
tag_size -= 2;
|
||||||
if (tag_size <= 0) { return retValue; } // Prohibit div zero exception and other wrong inputs
|
if (tag_size <= 0) { return retValue; } // Prohibit div zero exception and other wrong inputs
|
||||||
uint8_t parity = 1; // Check for odd parity on LSB
|
uint8_t parity = 1; // Check for odd parity on LSB
|
||||||
for (uint8_t i = 0; i < (tag_size / 2); i++) {
|
for (uint32_t i = 0; i < (tag_size / 2); i++) {
|
||||||
parity ^= (tagWithoutParities & 1);
|
parity ^= (tagWithoutParities & 1);
|
||||||
tagWithoutParities >>= 1;
|
tagWithoutParities >>= 1;
|
||||||
}
|
}
|
||||||
@ -314,53 +317,47 @@ uint8_t Wiegand::CalculateParities(uint64_t tagWithoutParities, int tag_size=26)
|
|||||||
bool Wiegand::WiegandConversion (uint64_t rfidBuffer, uint16_t bitCount) {
|
bool Wiegand::WiegandConversion (uint64_t rfidBuffer, uint16_t bitCount) {
|
||||||
bool bRet = false;
|
bool bRet = false;
|
||||||
#if (DEV_WIEGAND_TEST_MODE)>0
|
#if (DEV_WIEGAND_TEST_MODE)>0
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("WIE: Raw tag %llu, Bit count %u"), rfidBuffer, bitCount);
|
AddLog(LOG_LEVEL_INFO, PSTR("WIE: Raw tag %_X, Bit count %u"), &rfidBuffer, bitCount); // Print up to uint64_t
|
||||||
#endif // DEV_WIEGAND_TEST_MODE>0
|
#endif // DEV_WIEGAND_TEST_MODE>0
|
||||||
if ((24 == bitCount) || (26 == bitCount) || (32 == bitCount) || (34 == bitCount)) {
|
if ((24 == bitCount) || (26 == bitCount) || (32 == bitCount) || (34 == bitCount)) {
|
||||||
// 24, 26, 32, 34-bit Wiegand codes
|
// 24, 26, 32, 34-bit Wiegand codes
|
||||||
rfid = CheckAndConvertRfid(rfidBuffer, bitCount);
|
rfid = CheckAndConvertRfid(rfidBuffer, bitCount);
|
||||||
tagSize = bitCount;
|
tagSize = bitCount;
|
||||||
|
bRet = true;
|
||||||
|
}
|
||||||
|
else if (4 == bitCount) {
|
||||||
|
// 4-bit Wiegand codes for keypads
|
||||||
|
rfid = (uint32_t)(rfidBuffer & 0x0000000F);
|
||||||
|
tagSize = bitCount;
|
||||||
|
bRet = true;
|
||||||
|
}
|
||||||
|
else if (8 == bitCount) {
|
||||||
|
// 8-bit Wiegand codes for keypads with integrity
|
||||||
|
// 8-bit Wiegand keyboard data, high nibble is the "NOT" of low nibble
|
||||||
|
// eg if key 1 pressed, data=E1 in binary 11100001 , high nibble=1110 , low nibble = 0001
|
||||||
|
char highNibble = (rfidBuffer & 0xf0) >>4;
|
||||||
|
char lowNibble = (rfidBuffer & 0x0f);
|
||||||
|
if (lowNibble == (~highNibble & 0x0f)) { // Check if low nibble matches the "NOT" of high nibble.
|
||||||
|
rfid = (uint32_t)(lowNibble);
|
||||||
bRet = true;
|
bRet = true;
|
||||||
}
|
|
||||||
else if (4 == bitCount) {
|
|
||||||
// 4-bit Wiegand codes for keypads
|
|
||||||
rfid = (int)(rfidBuffer & 0x0000000F);
|
|
||||||
tagSize = bitCount;
|
|
||||||
bRet = true;
|
|
||||||
}
|
|
||||||
else if (8 == bitCount) {
|
|
||||||
// 8-bit Wiegand codes for keypads with integrity
|
|
||||||
// 8-bit Wiegand keyboard data, high nibble is the "NOT" of low nibble
|
|
||||||
// eg if key 1 pressed, data=E1 in binary 11100001 , high nibble=1110 , low nibble = 0001
|
|
||||||
char highNibble = (rfidBuffer & 0xf0) >>4;
|
|
||||||
char lowNibble = (rfidBuffer & 0x0f);
|
|
||||||
if (lowNibble == (~highNibble & 0x0f)) { // Check if low nibble matches the "NOT" of high nibble.
|
|
||||||
rfid = (int)(lowNibble);
|
|
||||||
bRet = true;
|
|
||||||
} else {
|
|
||||||
bRet = false;
|
|
||||||
}
|
|
||||||
tagSize = bitCount;
|
|
||||||
} else {
|
} else {
|
||||||
// Time reached but unknown bitCount, clear and start again
|
|
||||||
tagSize = 0;
|
|
||||||
bRet = false;
|
bRet = false;
|
||||||
}
|
}
|
||||||
|
tagSize = bitCount;
|
||||||
|
} else {
|
||||||
|
// Time reached but unknown bitCount, clear and start again
|
||||||
|
tagSize = 0;
|
||||||
|
bRet = false;
|
||||||
|
}
|
||||||
#if (DEV_WIEGAND_TEST_MODE)>0
|
#if (DEV_WIEGAND_TEST_MODE)>0
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("WIE: Tag out %llu, tag size %u "), rfid, tagSize);
|
AddLog(LOG_LEVEL_INFO, PSTR("WIE: Tag out %u, tag size %u "), rfid, tagSize);
|
||||||
#endif // DEV_WIEGAND_TEST_MODE>0
|
#endif // DEV_WIEGAND_TEST_MODE>0
|
||||||
return bRet;
|
return bRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiegand::setOutputFormat(void)
|
|
||||||
{
|
|
||||||
if (GetOption(WIEGAND_OPTION_HEX) == 0) { outFormat = "u"; }
|
|
||||||
else { outFormat = "X" WIEGAND_OPTION_HEX_POSTFIX ; }
|
|
||||||
}
|
|
||||||
|
|
||||||
void Wiegand::HandleKeyPad(void) { // will be called if a valid key pad input was recognized
|
void Wiegand::HandleKeyPad(void) { // will be called if a valid key pad input was recognized
|
||||||
if (GetOption(WIEGAND_OPTION_KEYPAD_TO_TAG) == 0) { // handle all key pad inputs as ONE Tag until # is recognized
|
if (GetOption(WIEGAND_OPTION_KEYPAD_TO_TAG) == 0) { // handle all key pad inputs as ONE Tag until # is recognized
|
||||||
if ( (tagSize == 4) || (tagSize == 8) ) {
|
if ((tagSize == 4) || (tagSize == 8)) {
|
||||||
//only handle Keypad strokes if it is requested
|
//only handle Keypad strokes if it is requested
|
||||||
if (rfid >= 0x0a) { // # * as end of input detected -> all key values which are larger than 9
|
if (rfid >= 0x0a) { // # * as end of input detected -> all key values which are larger than 9
|
||||||
rfid = mqttRFIDKeypadBuffer; // original tagsize of 4 or 8 will be kept.
|
rfid = mqttRFIDKeypadBuffer; // original tagsize of 4 or 8 will be kept.
|
||||||
@ -368,7 +365,7 @@ void Wiegand::HandleKeyPad(void) { // will be called if a valid key pad input wa
|
|||||||
mqttRFIDKeypadBuffer = 0;
|
mqttRFIDKeypadBuffer = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mqttRFIDKeypadBuffer = (mqttRFIDKeypadBuffer*10)+rfid; //left shift + new key
|
mqttRFIDKeypadBuffer = (mqttRFIDKeypadBuffer * 10) + rfid; //left shift + new key
|
||||||
webRFIDKeypadBuffer = mqttRFIDKeypadBuffer; // visualising the current typed keys
|
webRFIDKeypadBuffer = mqttRFIDKeypadBuffer; // visualising the current typed keys
|
||||||
rfid = 0;
|
rfid = 0;
|
||||||
tagSize = 0;
|
tagSize = 0;
|
||||||
@ -382,38 +379,33 @@ void Wiegand::HandleKeyPad(void) { // will be called if a valid key pad input wa
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Wiegand::ScanForTag() {
|
void Wiegand::ScanForTag() {
|
||||||
unsigned long startTime = micros();
|
uint32_t startTime = micros();
|
||||||
handleDxInterrupt(3);
|
handleDxInterrupt(3);
|
||||||
if (currentFoundRFIDcount > 0) {
|
if (currentFoundRFIDcount > 0) {
|
||||||
unsigned int lastFoundRFIDcount = currentFoundRFIDcount;
|
uint32_t lastFoundRFIDcount = currentFoundRFIDcount;
|
||||||
#if (DEV_WIEGAND_TEST_MODE)>0
|
#if (DEV_WIEGAND_TEST_MODE)>0
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("WIE: ScanForTag(). bitTime: %0lu lastFoundTime: %0lu RFIDS in buffer: %lu"), bitTime, lastFoundTime, currentFoundRFIDcount);
|
AddLog(LOG_LEVEL_INFO, PSTR("WIE: ScanForTag(). bitTime: %u lastFoundTime: %u RFIDS in buffer: %u"), bitTime, lastFoundTime, currentFoundRFIDcount);
|
||||||
#endif
|
#endif
|
||||||
// format MQTT output
|
for (uint32_t i = 0; i < WIEGAND_RFID_ARRAY_SIZE; i++) {
|
||||||
// setOutputFormat();
|
if (rfid_found[i].RFID != 0 || (rfid_found[i].RFID == 0 && i == 0)) {
|
||||||
// char sFormat[50];
|
uint32_t oldTag = rfid;
|
||||||
// snprintf( sFormat, 50, PSTR(",\"Wiegand\":{\"UID\":%%0ll%s,\"" D_JSON_SIZE "\":%%%s}}"), outFormat, outFormat);
|
|
||||||
for (int i= 0; i < WIEGAND_RFID_ARRAY_SIZE; i++)
|
|
||||||
{
|
|
||||||
if (rfid_found[i].RFID != 0 || (rfid_found[i].RFID == 0 && i == 0)) {
|
|
||||||
uint64_t oldTag = rfid;
|
|
||||||
bool validKey = WiegandConversion(rfid_found[i].RFID, rfid_found[i].bitCount);
|
bool validKey = WiegandConversion(rfid_found[i].RFID, rfid_found[i].bitCount);
|
||||||
#if (DEV_WIEGAND_TEST_MODE)>0
|
#if (DEV_WIEGAND_TEST_MODE)>0
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("WIE: ValidKey: %d Previous tag %llu"), validKey, oldTag);
|
AddLog(LOG_LEVEL_INFO, PSTR("WIE: ValidKey %d, Previous tag %u"), validKey, oldTag);
|
||||||
#endif // DEV_WIEGAND_TEST_MODE>0
|
#endif // DEV_WIEGAND_TEST_MODE>0
|
||||||
if (validKey) { // Only in case of valid key do action. Issue#10585
|
if (validKey) { // Only in case of valid key do action. Issue#10585
|
||||||
HandleKeyPad(); //support one tag for multi key input
|
HandleKeyPad(); //support one tag for multi key input
|
||||||
if (tagSize>0) { //do output only for rfids which are complete
|
if (tagSize > 0) { //do output only for rfids which are complete
|
||||||
if (oldTag == rfid) {
|
if (oldTag == rfid) {
|
||||||
AddLog(LOG_LEVEL_DEBUG, PSTR("WIE: Old tag"));
|
AddLog(LOG_LEVEL_DEBUG, PSTR("WIE: Old tag"));
|
||||||
}
|
}
|
||||||
// ResponseTime_P(sFormat, rfid, tagSize);
|
ResponseTime_P(PSTR(",\"Wiegand\":{\"UID\":"));
|
||||||
// Tasmota does not support 64-bit decimal output specifier (%llu) saving 60k code
|
|
||||||
if (GetOption(WIEGAND_OPTION_HEX) == 0) {
|
if (GetOption(WIEGAND_OPTION_HEX) == 0) {
|
||||||
ResponseTime_P(PSTR(",\"Wiegand\":{\"UID\":%lu,\"" D_JSON_SIZE "\":%d}}"), (uint32_t)rfid, tagSize);
|
ResponseAppend_P(PSTR("%u"), rfid);
|
||||||
} else {
|
} else {
|
||||||
ResponseTime_P(PSTR(",\"Wiegand\":{\"UID\":\"%2_X" WIEGAND_OPTION_HEX_POSTFIX "\",\"" D_JSON_SIZE "\":\"%X" WIEGAND_OPTION_HEX_POSTFIX "\"}}"), &rfid, tagSize);
|
ResponseAppend_P(PSTR("\"%X" WIEGAND_OPTION_HEX_POSTFIX "\""), rfid);
|
||||||
}
|
}
|
||||||
|
ResponseAppend_P(PSTR(",\"" D_JSON_SIZE "\":%d}}"), tagSize);
|
||||||
MqttPublishTeleSensor();
|
MqttPublishTeleSensor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -422,33 +414,29 @@ void Wiegand::ScanForTag() {
|
|||||||
if (currentFoundRFIDcount > lastFoundRFIDcount) {
|
if (currentFoundRFIDcount > lastFoundRFIDcount) {
|
||||||
// if that happens: we need to move the id found during the loop to top of the array
|
// if that happens: we need to move the id found during the loop to top of the array
|
||||||
// and correct the currentFoundRFIDcount
|
// and correct the currentFoundRFIDcount
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("WIE: ScanForTag() %lu tags added while working on buffer"), (currentFoundRFIDcount-lastFoundRFIDcount));
|
AddLog(LOG_LEVEL_INFO, PSTR("WIE: ScanForTag() %u tags added while working on buffer"), (currentFoundRFIDcount - lastFoundRFIDcount));
|
||||||
}
|
}
|
||||||
ClearRFIDBuffer(); //reset array
|
ClearRFIDBuffer(); //reset array
|
||||||
#if (DEV_WIEGAND_TEST_MODE)>0
|
#if (DEV_WIEGAND_TEST_MODE)>0
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("WIE: ScanForTag() time elapsed %lu"), (micros() - startTime));
|
AddLog(LOG_LEVEL_INFO, PSTR("WIE: ScanForTag() time elapsed %u"), (micros() - startTime));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_WEBSERVER
|
#ifdef USE_WEBSERVER
|
||||||
void Wiegand::Show(void) {
|
void Wiegand::Show(void) {
|
||||||
// setOutputFormat();
|
WSContentSend_P(PSTR("{s}Wiegand UID{m}"));
|
||||||
// char sFormat [30];
|
if (GetOption(WIEGAND_OPTION_HEX) == 0) {
|
||||||
// snprintf( sFormat, 30,PSTR("{s}Wiegand UID{m}%%ll%s {e}"), outFormat);
|
WSContentSend_P(PSTR("%u"), (tagSize > 0) ? rfid : webRFIDKeypadBuffer);
|
||||||
// if (tagSize>0) { WSContentSend_PD(sFormat, rfid); }
|
} else {
|
||||||
// else { WSContentSend_PD(sFormat, webRFIDKeypadBuffer); }
|
WSContentSend_P(PSTR("%X" WIEGAND_OPTION_HEX_POSTFIX), (tagSize > 0) ? rfid : webRFIDKeypadBuffer);
|
||||||
// Tasmota does not support 64-bit decimal output specifier (%llu) saving 60k code
|
}
|
||||||
if (GetOption(WIEGAND_OPTION_HEX) == 0) {
|
WSContentSend_P(PSTR("{e}"));
|
||||||
WSContentSend_P(PSTR("{s}Wiegand UID{m}%lu{e}"), (tagSize>0) ? (uint32_t)rfid : (uint32_t)webRFIDKeypadBuffer);
|
|
||||||
} else {
|
|
||||||
WSContentSend_P(PSTR("{s}Wiegand UID{m}%2_X" WIEGAND_OPTION_HEX_POSTFIX "{e}"), (tagSize>0) ? &rfid : &webRFIDKeypadBuffer);
|
|
||||||
}
|
|
||||||
#if (DEV_WIEGAND_TEST_MODE)>0
|
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("WIE: Tag %llu, Bits %u"), rfid, bitCount);
|
|
||||||
#endif // DEV_WIEGAND_TEST_MODE>0
|
|
||||||
|
|
||||||
|
|
||||||
|
#if (DEV_WIEGAND_TEST_MODE)>0
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR("WIE: Tag %u, Bits %u"), rfid, bitCount);
|
||||||
|
#endif // DEV_WIEGAND_TEST_MODE>0
|
||||||
}
|
}
|
||||||
#endif // USE_WEBSERVER
|
#endif // USE_WEBSERVER
|
||||||
|
|
||||||
|
@ -262,7 +262,7 @@ a_features = [[
|
|||||||
"USE_MCP2515","USE_TASMESH","USE_WIFI_RANGE_EXTENDER","USE_INFLUXDB",
|
"USE_MCP2515","USE_TASMESH","USE_WIFI_RANGE_EXTENDER","USE_INFLUXDB",
|
||||||
"USE_HRG15","USE_VINDRIKTNING","USE_SCD40","USE_HM330X",
|
"USE_HRG15","USE_VINDRIKTNING","USE_SCD40","USE_HM330X",
|
||||||
"USE_HDC2010","USE_LSC_MCSL","USE_SONOFF_SPM","USE_SHIFT595",
|
"USE_HDC2010","USE_LSC_MCSL","USE_SONOFF_SPM","USE_SHIFT595",
|
||||||
"USE_SDM230","USE_CM110x","","",
|
"USE_SDM230","USE_CM110x","USE_BL6523","",
|
||||||
"","","","",
|
"","","","",
|
||||||
"","","",""
|
"","","",""
|
||||||
]]
|
]]
|
||||||
@ -292,7 +292,7 @@ else:
|
|||||||
obj = json.load(fp)
|
obj = json.load(fp)
|
||||||
|
|
||||||
def StartDecode():
|
def StartDecode():
|
||||||
print ("\n*** decode-status.py v20220115 by Theo Arends and Jacek Ziolkowski ***")
|
print ("\n*** decode-status.py v11.0.0.1 by Theo Arends and Jacek Ziolkowski ***")
|
||||||
|
|
||||||
# print("Decoding\n{}".format(obj))
|
# print("Decoding\n{}".format(obj))
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user