From c8b8fe2da4f9347cd8190b4965ddfe2d7e83091f Mon Sep 17 00:00:00 2001 From: jeevasdev Date: Tue, 15 Feb 2022 13:51:43 +1100 Subject: [PATCH 01/25] Added support for BL6523 chipset based Energy Monitors --- tasmota/language/af_AF.h | 2 + tasmota/language/bg_BG.h | 2 + tasmota/language/cs_CZ.h | 2 + tasmota/language/de_DE.h | 2 + tasmota/language/el_GR.h | 2 + tasmota/language/en_GB.h | 2 + tasmota/language/es_ES.h | 2 + tasmota/language/fr_FR.h | 2 + tasmota/language/fy_NL.h | 2 + tasmota/language/he_HE.h | 2 + tasmota/language/hu_HU.h | 2 + tasmota/language/it_IT.h | 2 + tasmota/language/ko_KO.h | 2 + tasmota/language/nl_NL.h | 2 + tasmota/language/pl_PL.h | 2 + tasmota/language/pt_BR.h | 2 + tasmota/language/pt_PT.h | 2 + tasmota/language/ro_RO.h | 2 + tasmota/language/ru_RU.h | 2 + tasmota/language/sk_SK.h | 2 + tasmota/language/sv_SE.h | 2 + tasmota/language/tr_TR.h | 2 + tasmota/language/uk_UA.h | 2 + tasmota/language/vi_VN.h | 2 + tasmota/language/zh_CN.h | 2 + tasmota/language/zh_TW.h | 2 + tasmota/tasmota_template.h | 6 + tasmota/xsns_96_bl6523.ino | 353 +++++++++++++++++++++++++++++++++++++ 28 files changed, 411 insertions(+) create mode 100644 tasmota/xsns_96_bl6523.ino diff --git a/tasmota/language/af_AF.h b/tasmota/language/af_AF.h index 60460a97a..8a2c5e5f0 100644 --- a/tasmota/language/af_AF.h +++ b/tasmota/language/af_AF.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/language/bg_BG.h b/tasmota/language/bg_BG.h index 602091030..41485e29a 100644 --- a/tasmota/language/bg_BG.h +++ b/tasmota/language/bg_BG.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/language/cs_CZ.h b/tasmota/language/cs_CZ.h index 1a731d7fa..2a6f91636 100644 --- a/tasmota/language/cs_CZ.h +++ b/tasmota/language/cs_CZ.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/language/de_DE.h b/tasmota/language/de_DE.h index bd4306de9..2c020ad3e 100644 --- a/tasmota/language/de_DE.h +++ b/tasmota/language/de_DE.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/language/el_GR.h b/tasmota/language/el_GR.h index df9fd6fff..98b58c971 100644 --- a/tasmota/language/el_GR.h +++ b/tasmota/language/el_GR.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/language/en_GB.h b/tasmota/language/en_GB.h index 71bd64bac..8de4e9743 100644 --- a/tasmota/language/en_GB.h +++ b/tasmota/language/en_GB.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/language/es_ES.h b/tasmota/language/es_ES.h index a317601ad..0831d4c8b 100644 --- a/tasmota/language/es_ES.h +++ b/tasmota/language/es_ES.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/language/fr_FR.h b/tasmota/language/fr_FR.h index 8a28c747d..5671da05d 100644 --- a/tasmota/language/fr_FR.h +++ b/tasmota/language/fr_FR.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/language/fy_NL.h b/tasmota/language/fy_NL.h index 7addac432..8305f8aac 100644 --- a/tasmota/language/fy_NL.h +++ b/tasmota/language/fy_NL.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/language/he_HE.h b/tasmota/language/he_HE.h index 9c0941429..e72ff9d8e 100644 --- a/tasmota/language/he_HE.h +++ b/tasmota/language/he_HE.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/language/hu_HU.h b/tasmota/language/hu_HU.h index 6fad9fbb5..702a476e4 100644 --- a/tasmota/language/hu_HU.h +++ b/tasmota/language/hu_HU.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/language/it_IT.h b/tasmota/language/it_IT.h index 9a5c7a78c..6a8ad1b93 100644 --- a/tasmota/language/it_IT.h +++ b/tasmota/language/it_IT.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 - RX" #define D_SENSOR_HRG15_TX "HRG15 - TX" #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_GPIO_SHIFT595_SRCLK "74x595 - SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 - RCLK" diff --git a/tasmota/language/ko_KO.h b/tasmota/language/ko_KO.h index 85306451c..713e3be14 100644 --- a/tasmota/language/ko_KO.h +++ b/tasmota/language/ko_KO.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/language/nl_NL.h b/tasmota/language/nl_NL.h index 17803a9b0..e4d5e8916 100644 --- a/tasmota/language/nl_NL.h +++ b/tasmota/language/nl_NL.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/language/pl_PL.h b/tasmota/language/pl_PL.h index 1b83b5639..64b3347d6 100644 --- a/tasmota/language/pl_PL.h +++ b/tasmota/language/pl_PL.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/language/pt_BR.h b/tasmota/language/pt_BR.h index b3314554e..038d8354d 100644 --- a/tasmota/language/pt_BR.h +++ b/tasmota/language/pt_BR.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/language/pt_PT.h b/tasmota/language/pt_PT.h index 357aec476..932a10650 100644 --- a/tasmota/language/pt_PT.h +++ b/tasmota/language/pt_PT.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/language/ro_RO.h b/tasmota/language/ro_RO.h index ab325f19a..6c5433891 100644 --- a/tasmota/language/ro_RO.h +++ b/tasmota/language/ro_RO.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/language/ru_RU.h b/tasmota/language/ru_RU.h index 927a5e38d..845bc6f30 100644 --- a/tasmota/language/ru_RU.h +++ b/tasmota/language/ru_RU.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/language/sk_SK.h b/tasmota/language/sk_SK.h index 322b412cb..3b2883bf2 100644 --- a/tasmota/language/sk_SK.h +++ b/tasmota/language/sk_SK.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/language/sv_SE.h b/tasmota/language/sv_SE.h index ed1298eb2..38697b695 100644 --- a/tasmota/language/sv_SE.h +++ b/tasmota/language/sv_SE.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/language/tr_TR.h b/tasmota/language/tr_TR.h index b238b88b9..e76e8076d 100644 --- a/tasmota/language/tr_TR.h +++ b/tasmota/language/tr_TR.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/language/uk_UA.h b/tasmota/language/uk_UA.h index b75e1f04a..5e4a99e10 100644 --- a/tasmota/language/uk_UA.h +++ b/tasmota/language/uk_UA.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/language/vi_VN.h b/tasmota/language/vi_VN.h index 13242d134..f52e6599a 100644 --- a/tasmota/language/vi_VN.h +++ b/tasmota/language/vi_VN.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/language/zh_CN.h b/tasmota/language/zh_CN.h index bd9b96293..882d9756e 100644 --- a/tasmota/language/zh_CN.h +++ b/tasmota/language/zh_CN.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/language/zh_TW.h b/tasmota/language/zh_TW.h index 8689fcddd..b7eb80a67 100644 --- a/tasmota/language/zh_TW.h +++ b/tasmota/language/zh_TW.h @@ -847,6 +847,8 @@ #define D_SENSOR_HRG15_RX "HRG15 Rx" #define D_SENSOR_HRG15_TX "HRG15 Tx" #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_GPIO_SHIFT595_SRCLK "74x595 SRCLK" #define D_GPIO_SHIFT595_RCLK "74x595 RCLK" diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index 615c48630..7af28acd4 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -172,6 +172,7 @@ enum UserSelectablePins { GPIO_MCP2515_CS, // MCP2515 Chip Select GPIO_HRG15_TX, GPIO_HRG15_RX, // Hydreon RG-15 rain sensor serial interface GPIO_VINDRIKTNING_RX, // IKEA VINDRIKTNING Serial interface + GPIO_BL6523_TX, GPIO_BL6523_RX, // BL6523 based Watt meter Serial interface GPIO_BL0939_RX, // BL0939 Serial interface (Dual R3 v2) GPIO_BL0942_RX, // BL0942 Serial interface GPIO_HM330X_SET, // HM330X SET pin (sleep when low) @@ -393,6 +394,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_MCP2515_CS "|" D_SENSOR_HRG15_TX "|" D_SENSOR_HRG15_RX "|" D_SENSOR_VINDRIKTNING_RX "|" + D_SENSOR_BL6523_TX "|" D_SENSOR_BL6523_RX "|" D_SENSOR_BL0939_RX "|" D_SENSOR_BL0942_RX "|" D_SENSOR_HM330X_SET "|" @@ -812,6 +814,10 @@ const uint16_t kGpioNiceList[] PROGMEM = { #ifdef USE_VINDRIKTNING AGPIO(GPIO_VINDRIKTNING_RX), #endif +#ifdef USE_BL6523 + AGPIO(GPIO_BL6523_TX), + AGPIO(GPIO_BL6523_RX), +#endif #ifdef USE_HM330X AGPIO(GPIO_HM330X_SET), // HM330X Sleep pin (active low) #endif diff --git a/tasmota/xsns_96_bl6523.ino b/tasmota/xsns_96_bl6523.ino new file mode 100644 index 000000000..7587a897f --- /dev/null +++ b/tasmota/xsns_96_bl6523.ino @@ -0,0 +1,353 @@ +/* + xsns_96_bl6523.ino - Chinese bl6523 based Watt hour meter support for Tasmota + + Copyright (C) 2022 Jeevas Vasudevan and the Internet + + 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 . +*/ + +#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_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 XSNS_96 96 + +#include + +#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 + +/* No idea how to derive human readable units from the byte stream. +For now dividing the 24-bit values with below constants seems to yield something sane +that matches whatever displayed in the screen of my 240v model. Probably it would be possible +to extract these values from the write register commands (0xCA).*/ +#define BL6523_DIV_AMPS 297899.4f +#define BL6523_DIV_VOLTS 13304.0f +#define BL6523_DIV_FREQ 3907.0f +#define BL6523_DIV_WATTS 707.0f +#define BL6523_DIV_WATTHR 674.0f + +TasmotaSerial *Bl6523RxSerial; +TasmotaSerial *Bl6523TxSerial; + +struct BL6523 +{ + uint32_t amps = 0; + uint32_t volts = 0; + uint32_t freq = 0; + uint32_t watts = 0; + uint32_t powf = 0; + uint32_t watthr = 0; + + uint8_t type = 1; + uint8_t valid = 0; + uint8_t got_data_stone = 0; + bool discovery_triggered = false; +} Bl6523; + +bool Bl6523ReadData(void) +{ + + if (!Bl6523RxSerial->available()) + { + AddLog(LOG_LEVEL_DEBUG, PSTR("BL6523 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("BL6523 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); + + while (Bl6523TxSerial->available() < BL6523_TX_DATASET_SIZE) + { + // sleep till TX buffer is full + unsigned long timeout = millis() + 10; + while (millis() < timeout) {} + } + + + 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("BL6523 : " 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 : + Bl6523.amps = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]); + Bl6523.got_data_stone |= 1<<0; + break; + case BL6523_REG_VOLTS : + Bl6523.volts = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]); + Bl6523.got_data_stone |= 1<<1; + break; + case BL6523_REG_FREQ : + Bl6523.freq = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]); + Bl6523.got_data_stone |= 1<<2; + break; + case BL6523_REG_WATTS : + Bl6523.watts = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]); + Bl6523.got_data_stone |= 1<<3; + break; + case BL6523_REG_POWF : + Bl6523.powf = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]); + Bl6523.got_data_stone |= 1<<4; + break; + case BL6523_REG_WATTHR : + Bl6523.watthr = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]); + Bl6523.got_data_stone |= 1<<5; + break; + default : + break; +} + +AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("Amps: %d Volts: %d Freq: %d Watts: %d PowF: %d WattHr: %d"), Bl6523.amps, Bl6523.volts, Bl6523.freq, Bl6523.watts, Bl6523.powf, Bl6523.watthr); + + 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; + if ((PinUsed(GPIO_BL6523_RX)) && (PinUsed(GPIO_BL6523_TX))) + { + 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; + AddLog(LOG_LEVEL_DEBUG, PSTR("BL6523 Init Success " )); + } + } +} + +#ifdef USE_WEBSERVER +const char HTTP_BL6523_SNM[] PROGMEM = "{s}BL6523 Smart Energy Monitor{m}{e}"; // {s} = , {m} = , {e} = +const char HTTP_BL6523_SNS[] PROGMEM = "{s} %s {m}%s {e}"; // {s} = , {m} = , {e} = +#endif // USE_WEBSERVER + +void Bl6523Show(bool json) +{ + uint32_t powf_word = 0; + float amps = 0.0f, volts = 0.0f, freq = 0.0f, watts = 0.0f, powf = 0.0f, watthr = 0 .0f; + char amps_str[12], volts_str[12], freq_str[12]; + char watts_str[12], powf_str[12], watthr_str[12]; + + if (Bl6523.valid) + { + + amps = (float)Bl6523.amps / BL6523_DIV_AMPS; + volts = (float)Bl6523.volts / BL6523_DIV_VOLTS; + freq = (float)Bl6523.freq / BL6523_DIV_FREQ; + watts = (float)Bl6523.watts / BL6523_DIV_WATTS; + + /* 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_word = Bl6523.powf & 0x7fffff; //Extract the 23 bits + 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 = (Bl6523.powf >> 23) ? (0.0f - (~powf)) : powf; // Negate if sign bit(24) is set + + watthr = (float)Bl6523.watthr / BL6523_DIV_WATTHR; + + ext_snprintf_P(amps_str, sizeof(amps_str), PSTR("%3_f"), &s); + ext_snprintf_P(volts_str, sizeof(volts_str), PSTR("%2_f"), &volts); + ext_snprintf_P(freq_str, sizeof(freq_str), PSTR("%2_f"), &freq); + ext_snprintf_P(watts_str, sizeof(watts_str), PSTR("%3_f"), &watts); + ext_snprintf_P(powf_str, sizeof(powf_str), PSTR("%2_f"), &powf); + ext_snprintf_P(watthr_str, sizeof(watthr_str), PSTR("%3_f"), &watthr); + + if (json) + { + ResponseAppend_P(PSTR(",\"BL6523\":{")); + ResponseAppend_P(PSTR("\"Amps\":%s,"), amps_str); + ResponseAppend_P(PSTR("\"Volts\":%s,"), volts_str); + ResponseAppend_P(PSTR("\"Freq\":%s,"), freq_str); + ResponseAppend_P(PSTR("\"Watts\":%s,"), watts_str); + ResponseAppend_P(PSTR("\"Powf\":%s,"), powf_str); + ResponseAppend_P(PSTR("\"WattHr\":%s"), watthr_str); + ResponseJsonEnd(); +#ifdef USE_DOMOTICZ + if (0 == TasmotaGlobal.tele_period) + { + DomoticzSensor(DZ_CURRENT, amps_str); // Amps + DomoticzSensor(DZ_VOLTAGE, volts_str); // Voltage + DomoticzSensor(DZ_COUNT, freq_str); // Frequency + DomoticzSensor(DZ_ILLUMINANCE, watts_str); // Watts + DomoticzSensor(DZ_P1_SMART_METER, powf_str); // Power Factor + DomoticzSensor(DZ_POWER_ENERGY, watthr_str); // WattHour + } +#endif // USE_DOMOTICZ +#ifdef USE_WEBSERVER + } + else + { + WSContentSend_PD(HTTP_BL6523_SNM); + WSContentSend_PD(HTTP_BL6523_SNS, PSTR("Amps:"), amps_str); + WSContentSend_PD(HTTP_BL6523_SNS, PSTR("Volts:"), volts_str); + WSContentSend_PD(HTTP_BL6523_SNS, PSTR("Freq:"), freq_str); + WSContentSend_PD(HTTP_BL6523_SNS, PSTR("Watts:"), watts_str); + WSContentSend_PD(HTTP_BL6523_SNS, PSTR("PowF:"), powf_str); + WSContentSend_PD(HTTP_BL6523_SNS, PSTR("WattHr:"), watthr_str); +#endif // USE_WEBSERVER + } + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xsns96(uint8_t function) +{ + bool result = false; + + if (Bl6523.type) + { + switch (function) + { + case FUNC_EVERY_250_MSECOND: + Bl6523Update(); + break; + case FUNC_JSON_APPEND: + Bl6523Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Bl6523Show(0); + break; +#endif // USE_WEBSERVER + case FUNC_INIT: + Bl6523Init(); + break; + } + } + return result; +} + +#endif // USE_BL6523 \ No newline at end of file From 73e3b4447758065b6cef47a194d0966aae57ed4c Mon Sep 17 00:00:00 2001 From: jeevasdev Date: Tue, 15 Feb 2022 20:41:25 +1100 Subject: [PATCH 02/25] Converted BL6523 to nrg driver --- tasmota/tasmota_template.h | 6 + tasmota/xnrg_22_bl6523.ino | 355 +++++++++++++++++++++++++++++++++++++ 2 files changed, 361 insertions(+) create mode 100644 tasmota/xnrg_22_bl6523.ino diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index 7af28acd4..fc57e9825 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -183,6 +183,7 @@ enum UserSelectablePins { GPIO_SDM230_TX, GPIO_SDM230_RX, // SDM230 Serial interface GPIO_ADC_MQ, // Analog MQ Sensor GPIO_CM11_TXD, GPIO_CM11_RXD, // CM11 Serial interface + GPIO_BL6523_TX, GPIO_BL6523_RX, // BL6523 based Watt meter Serial interface GPIO_SENSOR_END }; enum ProgramSelectablePins { @@ -405,6 +406,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_SDM230_TX "|" D_SENSOR_SDM230_RX "|" D_SENSOR_ADC_MQ "|" D_SENSOR_CM11_TX "|" D_SENSOR_CM11_RX "|" + D_SENSOR_BL6523_TX "|" D_SENSOR_BL6523_RX "|" ; const char kSensorNamesFixed[] PROGMEM = @@ -772,6 +774,10 @@ const uint16_t kGpioNiceList[] PROGMEM = { AGPIO(GPIO_SDM230_TX), // SDM230 Serial interface AGPIO(GPIO_SDM230_RX), // SDM230 Serial interface #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 /*-------------------------------------------------------------------------------------------*\ diff --git a/tasmota/xnrg_22_bl6523.ino b/tasmota/xnrg_22_bl6523.ino new file mode 100644 index 000000000..98b39780f --- /dev/null +++ b/tasmota/xnrg_22_bl6523.ino @@ -0,0 +1,355 @@ +/* + xsns_96_bl6523.ino - Chinese bl6523 based Watt hour meter support for Tasmota + + Copyright (C) 2022 Jeevas Vasudevan and the Internet + + 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 . +*/ +#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_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 + +#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 + +/* No idea how to derive human readable units from the byte stream. +For now dividing the 24-bit values with below constants seems to yield something sane +that matches whatever displayed in the screen of my 240v model. Probably it would be possible +to extract these values from the write register commands (0xCA).*/ +#define BL6523_DIV_AMPS 297899.4f +#define BL6523_DIV_VOLTS 13304.0f +#define BL6523_DIV_FREQ 3907.0f +#define BL6523_DIV_WATTS 707.0f +#define BL6523_DIV_WATTHR 674.0f + +TasmotaSerial *Bl6523RxSerial; +TasmotaSerial *Bl6523TxSerial; + +struct BL6523 +{ + uint32_t amps = 0; + uint32_t volts = 0; + uint32_t freq = 0; + uint32_t watts = 0; + uint32_t powf = 0; + uint32_t watthr = 0; + + uint8_t type = 1; + uint8_t valid = 0; + uint8_t got_data_stone = 0; + bool discovery_triggered = false; +} Bl6523; + +bool Bl6523ReadData(void) +{ + + if (!Bl6523RxSerial->available()) + { + AddLog(LOG_LEVEL_DEBUG, PSTR("BL6523 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("BL6523 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); + + while (Bl6523TxSerial->available() < BL6523_TX_DATASET_SIZE) + { + // sleep till TX buffer is full + unsigned long timeout = millis() + 10; + while (millis() < timeout) {} + } + + + 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("BL6523 : " 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 : + Bl6523.amps = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]); + Bl6523.got_data_stone |= 1<<0; + break; + case BL6523_REG_VOLTS : + Bl6523.volts = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]); + Bl6523.got_data_stone |= 1<<1; + break; + case BL6523_REG_FREQ : + Bl6523.freq = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]); + Bl6523.got_data_stone |= 1<<2; + break; + case BL6523_REG_WATTS : + Bl6523.watts = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]); + Bl6523.got_data_stone |= 1<<3; + break; + case BL6523_REG_POWF : + Bl6523.powf = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]); + Bl6523.got_data_stone |= 1<<4; + break; + case BL6523_REG_WATTHR : + Bl6523.watthr = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]); + Bl6523.got_data_stone |= 1<<5; + break; + default : + break; +} + +AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("Amps: %d Volts: %d Freq: %d Watts: %d PowF: %d WattHr: %d"), Bl6523.amps, Bl6523.volts, Bl6523.freq, Bl6523.watts, Bl6523.powf, Bl6523.watthr); + + 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; + if ((PinUsed(GPIO_BL6523_RX)) && (PinUsed(GPIO_BL6523_TX))) + { + 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; + AddLog(LOG_LEVEL_DEBUG, PSTR("BL6523 Init Success " )); + } + } +} + +#ifdef USE_WEBSERVER +const char HTTP_BL6523_SNM[] PROGMEM = "{s}BL6523 Smart Energy Monitor{m}{e}"; // {s} = , {m} = , {e} = +const char HTTP_BL6523_SNS[] PROGMEM = "{s} %s {m}%s {e}"; // {s} = , {m} = , {e} = +#endif // USE_WEBSERVER + +void Bl6523Show(bool json) +{ + uint32_t powf_word = 0; + float amps = 0.0f, volts = 0.0f, freq = 0.0f, watts = 0.0f, powf = 0.0f, watthr = 0.0f; + char amps_str[12], volts_str[12], freq_str[12]; + char watts_str[12], powf_str[12], watthr_str[12]; + + if (Bl6523.valid) + { + + amps = (float)Bl6523.amps / BL6523_DIV_AMPS; + volts = (float)Bl6523.volts / BL6523_DIV_VOLTS; + freq = (float)Bl6523.freq / BL6523_DIV_FREQ; + watts = (float)Bl6523.watts / BL6523_DIV_WATTS; + + /* 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_word = (Bl6523.powf >> 23) ? ~(Bl6523.powf & 0x7fffff) : Bl6523.powf & 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 = (Bl6523.powf >> 23) ? (0.0f - (powf)) : powf; // Negate if sign bit(24) is set + + watthr = (float)Bl6523.watthr / BL6523_DIV_WATTHR; + + ext_snprintf_P(amps_str, sizeof(amps_str), PSTR("%3_f"), &s); + ext_snprintf_P(volts_str, sizeof(volts_str), PSTR("%2_f"), &volts); + ext_snprintf_P(freq_str, sizeof(freq_str), PSTR("%2_f"), &freq); + ext_snprintf_P(watts_str, sizeof(watts_str), PSTR("%3_f"), &watts); + ext_snprintf_P(powf_str, sizeof(powf_str), PSTR("%2_f"), &powf); + ext_snprintf_P(watthr_str, sizeof(watthr_str), PSTR("%3_f"), &watthr); + + if (json) + { + ResponseAppend_P(PSTR(",\"BL6523\":{")); + ResponseAppend_P(PSTR("\"Amps\":%s,"), amps_str); + ResponseAppend_P(PSTR("\"Volts\":%s,"), volts_str); + ResponseAppend_P(PSTR("\"Freq\":%s,"), freq_str); + ResponseAppend_P(PSTR("\"Watts\":%s,"), watts_str); + ResponseAppend_P(PSTR("\"Powf\":%s,"), powf_str); + ResponseAppend_P(PSTR("\"WattHr\":%s"), watthr_str); + ResponseJsonEnd(); +#ifdef USE_DOMOTICZ + if (0 == TasmotaGlobal.tele_period) + { + DomoticzSensor(DZ_CURRENT, amps_str); // Amps + DomoticzSensor(DZ_VOLTAGE, volts_str); // Voltage + DomoticzSensor(DZ_COUNT, freq_str); // Frequency + DomoticzSensor(DZ_ILLUMINANCE, watts_str); // Watts + DomoticzSensor(DZ_P1_SMART_METER, powf_str); // Power Factor + DomoticzSensor(DZ_POWER_ENERGY, watthr_str); // WattHour + } +#endif // USE_DOMOTICZ +#ifdef USE_WEBSERVER + } + else + { + WSContentSend_PD(HTTP_BL6523_SNM); + WSContentSend_PD(HTTP_BL6523_SNS, PSTR("Amps:"), amps_str); + WSContentSend_PD(HTTP_BL6523_SNS, PSTR("Volts:"), volts_str); + WSContentSend_PD(HTTP_BL6523_SNS, PSTR("Freq:"), freq_str); + WSContentSend_PD(HTTP_BL6523_SNS, PSTR("Watts:"), watts_str); + WSContentSend_PD(HTTP_BL6523_SNS, PSTR("PowF:"), powf_str); + WSContentSend_PD(HTTP_BL6523_SNS, PSTR("WattHr:"), watthr_str); +#endif // USE_WEBSERVER + } + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xnrg22(uint8_t function) +{ + bool result = false; + +if ( FUNC_INIT == function ) +{ + Bl6523Init(); +} +else if ( Bl6523.type ) + { + switch (function) + { + case FUNC_EVERY_250_MSECOND: + Bl6523Update(); + break; + case FUNC_JSON_APPEND: + Bl6523Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Bl6523Show(0); + break; +#endif // USE_WEBSERVER + } + } + return result; +} + +#endif // USE_BL6523 +#endif // USE_ENERGY_SENSOR \ No newline at end of file From 6a7cb4f95e79869827f15a0b5102810145c5a558 Mon Sep 17 00:00:00 2001 From: jeevasdev Date: Tue, 15 Feb 2022 21:03:30 +1100 Subject: [PATCH 03/25] Squashed commit of the following: commit 1dc0638bbe4901efbe2c0bacefbcc32dac08e8ea Author: jeevasdev Date: Tue Feb 15 20:37:14 2022 +1100 Converted to xnrg as per review comment. commit fa5570b0980e4bff1773a72eb417d8853f5c9e8e Author: jeevasdev Date: Tue Feb 15 13:46:50 2022 +1100 Added helper message to main comment. commit bf7864fb56885161a19855a2ae92fe8a9348a8be Author: jeevasdev Date: Tue Feb 15 13:43:45 2022 +1100 Added BL6523 language files. commit 0920d5c530b8253c12e436437b2954913ef1126d Author: jeevasdev Date: Tue Feb 15 13:34:34 2022 +1100 Added BL6523 to tasmota_template. commit e119fc8a044e47179169b0caa7f1e31d099b4932 Author: jeevasdev Date: Tue Feb 15 13:28:38 2022 +1100 Add BL6523 based smartmeter support main ino. --- tasmota/xsns_96_bl6523.ino | 353 ------------------------------------- 1 file changed, 353 deletions(-) delete mode 100644 tasmota/xsns_96_bl6523.ino diff --git a/tasmota/xsns_96_bl6523.ino b/tasmota/xsns_96_bl6523.ino deleted file mode 100644 index 7587a897f..000000000 --- a/tasmota/xsns_96_bl6523.ino +++ /dev/null @@ -1,353 +0,0 @@ -/* - xsns_96_bl6523.ino - Chinese bl6523 based Watt hour meter support for Tasmota - - Copyright (C) 2022 Jeevas Vasudevan and the Internet - - 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 . -*/ - -#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_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 XSNS_96 96 - -#include - -#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 - -/* No idea how to derive human readable units from the byte stream. -For now dividing the 24-bit values with below constants seems to yield something sane -that matches whatever displayed in the screen of my 240v model. Probably it would be possible -to extract these values from the write register commands (0xCA).*/ -#define BL6523_DIV_AMPS 297899.4f -#define BL6523_DIV_VOLTS 13304.0f -#define BL6523_DIV_FREQ 3907.0f -#define BL6523_DIV_WATTS 707.0f -#define BL6523_DIV_WATTHR 674.0f - -TasmotaSerial *Bl6523RxSerial; -TasmotaSerial *Bl6523TxSerial; - -struct BL6523 -{ - uint32_t amps = 0; - uint32_t volts = 0; - uint32_t freq = 0; - uint32_t watts = 0; - uint32_t powf = 0; - uint32_t watthr = 0; - - uint8_t type = 1; - uint8_t valid = 0; - uint8_t got_data_stone = 0; - bool discovery_triggered = false; -} Bl6523; - -bool Bl6523ReadData(void) -{ - - if (!Bl6523RxSerial->available()) - { - AddLog(LOG_LEVEL_DEBUG, PSTR("BL6523 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("BL6523 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); - - while (Bl6523TxSerial->available() < BL6523_TX_DATASET_SIZE) - { - // sleep till TX buffer is full - unsigned long timeout = millis() + 10; - while (millis() < timeout) {} - } - - - 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("BL6523 : " 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 : - Bl6523.amps = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]); - Bl6523.got_data_stone |= 1<<0; - break; - case BL6523_REG_VOLTS : - Bl6523.volts = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]); - Bl6523.got_data_stone |= 1<<1; - break; - case BL6523_REG_FREQ : - Bl6523.freq = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]); - Bl6523.got_data_stone |= 1<<2; - break; - case BL6523_REG_WATTS : - Bl6523.watts = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]); - Bl6523.got_data_stone |= 1<<3; - break; - case BL6523_REG_POWF : - Bl6523.powf = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]); - Bl6523.got_data_stone |= 1<<4; - break; - case BL6523_REG_WATTHR : - Bl6523.watthr = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]); - Bl6523.got_data_stone |= 1<<5; - break; - default : - break; -} - -AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("Amps: %d Volts: %d Freq: %d Watts: %d PowF: %d WattHr: %d"), Bl6523.amps, Bl6523.volts, Bl6523.freq, Bl6523.watts, Bl6523.powf, Bl6523.watthr); - - 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; - if ((PinUsed(GPIO_BL6523_RX)) && (PinUsed(GPIO_BL6523_TX))) - { - 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; - AddLog(LOG_LEVEL_DEBUG, PSTR("BL6523 Init Success " )); - } - } -} - -#ifdef USE_WEBSERVER -const char HTTP_BL6523_SNM[] PROGMEM = "{s}BL6523 Smart Energy Monitor{m}{e}"; // {s} = , {m} = , {e} = -const char HTTP_BL6523_SNS[] PROGMEM = "{s} %s {m}%s {e}"; // {s} = , {m} = , {e} = -#endif // USE_WEBSERVER - -void Bl6523Show(bool json) -{ - uint32_t powf_word = 0; - float amps = 0.0f, volts = 0.0f, freq = 0.0f, watts = 0.0f, powf = 0.0f, watthr = 0 .0f; - char amps_str[12], volts_str[12], freq_str[12]; - char watts_str[12], powf_str[12], watthr_str[12]; - - if (Bl6523.valid) - { - - amps = (float)Bl6523.amps / BL6523_DIV_AMPS; - volts = (float)Bl6523.volts / BL6523_DIV_VOLTS; - freq = (float)Bl6523.freq / BL6523_DIV_FREQ; - watts = (float)Bl6523.watts / BL6523_DIV_WATTS; - - /* 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_word = Bl6523.powf & 0x7fffff; //Extract the 23 bits - 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 = (Bl6523.powf >> 23) ? (0.0f - (~powf)) : powf; // Negate if sign bit(24) is set - - watthr = (float)Bl6523.watthr / BL6523_DIV_WATTHR; - - ext_snprintf_P(amps_str, sizeof(amps_str), PSTR("%3_f"), &s); - ext_snprintf_P(volts_str, sizeof(volts_str), PSTR("%2_f"), &volts); - ext_snprintf_P(freq_str, sizeof(freq_str), PSTR("%2_f"), &freq); - ext_snprintf_P(watts_str, sizeof(watts_str), PSTR("%3_f"), &watts); - ext_snprintf_P(powf_str, sizeof(powf_str), PSTR("%2_f"), &powf); - ext_snprintf_P(watthr_str, sizeof(watthr_str), PSTR("%3_f"), &watthr); - - if (json) - { - ResponseAppend_P(PSTR(",\"BL6523\":{")); - ResponseAppend_P(PSTR("\"Amps\":%s,"), amps_str); - ResponseAppend_P(PSTR("\"Volts\":%s,"), volts_str); - ResponseAppend_P(PSTR("\"Freq\":%s,"), freq_str); - ResponseAppend_P(PSTR("\"Watts\":%s,"), watts_str); - ResponseAppend_P(PSTR("\"Powf\":%s,"), powf_str); - ResponseAppend_P(PSTR("\"WattHr\":%s"), watthr_str); - ResponseJsonEnd(); -#ifdef USE_DOMOTICZ - if (0 == TasmotaGlobal.tele_period) - { - DomoticzSensor(DZ_CURRENT, amps_str); // Amps - DomoticzSensor(DZ_VOLTAGE, volts_str); // Voltage - DomoticzSensor(DZ_COUNT, freq_str); // Frequency - DomoticzSensor(DZ_ILLUMINANCE, watts_str); // Watts - DomoticzSensor(DZ_P1_SMART_METER, powf_str); // Power Factor - DomoticzSensor(DZ_POWER_ENERGY, watthr_str); // WattHour - } -#endif // USE_DOMOTICZ -#ifdef USE_WEBSERVER - } - else - { - WSContentSend_PD(HTTP_BL6523_SNM); - WSContentSend_PD(HTTP_BL6523_SNS, PSTR("Amps:"), amps_str); - WSContentSend_PD(HTTP_BL6523_SNS, PSTR("Volts:"), volts_str); - WSContentSend_PD(HTTP_BL6523_SNS, PSTR("Freq:"), freq_str); - WSContentSend_PD(HTTP_BL6523_SNS, PSTR("Watts:"), watts_str); - WSContentSend_PD(HTTP_BL6523_SNS, PSTR("PowF:"), powf_str); - WSContentSend_PD(HTTP_BL6523_SNS, PSTR("WattHr:"), watthr_str); -#endif // USE_WEBSERVER - } - } -} - -/*********************************************************************************************\ - * Interface -\*********************************************************************************************/ - -bool Xsns96(uint8_t function) -{ - bool result = false; - - if (Bl6523.type) - { - switch (function) - { - case FUNC_EVERY_250_MSECOND: - Bl6523Update(); - break; - case FUNC_JSON_APPEND: - Bl6523Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Bl6523Show(0); - break; -#endif // USE_WEBSERVER - case FUNC_INIT: - Bl6523Init(); - break; - } - } - return result; -} - -#endif // USE_BL6523 \ No newline at end of file From cf09c5246ed343c61ed0104f895682d6582a03ca Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Tue, 15 Feb 2022 12:11:45 +0100 Subject: [PATCH 04/25] Zigbee ZStack3 fix to changing channel --- tasmota/xdrv_23_zigbee_0_constants.ino | 11 ++- tasmota/xdrv_23_zigbee_1_headers.ino | 1 + tasmota/xdrv_23_zigbee_7_0_statemachine.ino | 75 ++++++++++++++++----- tasmota/xdrv_23_zigbee_8_parsers.ino | 4 +- 4 files changed, 72 insertions(+), 19 deletions(-) diff --git a/tasmota/xdrv_23_zigbee_0_constants.ino b/tasmota/xdrv_23_zigbee_0_constants.ino index d7a5a7aad..ac2aae6ed 100644 --- a/tasmota/xdrv_23_zigbee_0_constants.ino +++ b/tasmota/xdrv_23_zigbee_0_constants.ino @@ -52,7 +52,8 @@ enum ZnpSubsystem { Z_SAPI = 0x06, Z_UTIL = 0x07, Z_DEBUG = 0x08, - Z_APP = 0x09 + Z_APP = 0x09, + Z_APP_CNF = 0x0F, // new in ZStacK 3 }; #endif // USE_ZIGBEE_ZNP @@ -1103,6 +1104,14 @@ enum Z_Util { 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 { ZCL_READ_ATTRIBUTES = 0x00, ZCL_READ_ATTRIBUTES_RESPONSE = 0x01, diff --git a/tasmota/xdrv_23_zigbee_1_headers.ino b/tasmota/xdrv_23_zigbee_1_headers.ino index 3e541aa7d..063c6ddc6 100644 --- a/tasmota/xdrv_23_zigbee_1_headers.ino +++ b/tasmota/xdrv_23_zigbee_1_headers.ino @@ -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_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_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_READY = 20; // goto label 20 for main loop const uint8_t ZIGBEE_LABEL_MAIN_LOOP = 21; // main loop diff --git a/tasmota/xdrv_23_zigbee_7_0_statemachine.ino b/tasmota/xdrv_23_zigbee_7_0_statemachine.ino index 3fd21ad51..13f301b29 100644 --- a/tasmota/xdrv_23_zigbee_7_0_statemachine.ino +++ b/tasmota/xdrv_23_zigbee_7_0_statemachine.ino @@ -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 */, 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 + +// 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 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 @@ -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_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 +// 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 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 @@ -296,8 +310,10 @@ ZBM(AREQ_ZDO_NODEDESCRSP, Z_AREQ | Z_ZDO, ZDO_NODE_DESC_RSP) // 4582 // Z_ZDO:activeEpReq 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_ACTIVEEPRSP_NONE, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP, 0x00, 0x00 /* srcAddr */, Z_SUCCESS, - 0x00, 0x00 /* nwkaddr */, 0x00 /* activeepcount */) // 45050000 - no Ep running +// 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 +// 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, 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 */, 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 + // 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 ZBW(ZBS_W_PFGK, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, CONF_PRECFGKEY,0x00, 0x00, 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_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_WAIT(100) // wait for .1 second @@ -434,34 +454,54 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = { ZI_SEND(ZBS_PFGKEN) // check 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) + // ====================================================================== + // Start procedure for ZStack 1.2 + // ====================================================================== ZI_SEND(ZBS_PFGK) // check PFGK on ZB1.2 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 - - ZI_LABEL(ZIGBEE_LABEL_START_COORD) // START ZNP App ZI_MQTT_STATE(ZIGBEE_STATUS_STARTING, kConfiguredCoord) - ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) - // Z_ZDO:startupFromApp - //ZI_LOG(LOG_LEVEL_INFO, D_LOG_ZIGBEE "starting zigbee coordinator") - ZI_SEND(ZBS_STARTUPFROMAPP) // start coordinator + ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) // set any failure to ABORT + ZI_SEND(ZBS_STARTUPFROMAPP) // start coordinator 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_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_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_WAIT_RECV(1000, ZBR_ZDO_NODEDESCREQ) ZI_WAIT_UNTIL(5000, AREQ_ZDO_NODEDESCRSP) ZI_SEND(ZBS_ZDO_ACTIVEEPREQ) // Z_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_WAIT_RECV(1000, ZBR_AF_REGISTER) 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_GOTO(ZIGBEE_LABEL_READY) + // ====================================================================== + // Wrong configuration, do a factory reset and push configuration + // ====================================================================== ZI_LABEL(ZIGBEE_LABEL_FACT_RESET_COORD) // reformat device 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") diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index 2f3b9688f..0e1abe0a4 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -51,7 +51,7 @@ void EZ_RSTACK(uint8_t reset_code) { default: reason_str = PSTR("Unknown"); break; } Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"Message\":\"EFR32 booted\",\"RestartReason\":\"%s\"" + "\"Status\":%d,\"Message\":\"EFR32 EZSP booted\",\"RestartReason\":\"%s\"" ",\"Code\":%d}}"), 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 "\":{" - "\"Status\":%d,\"Message\":\"CCxxxx booted\",\"RestartReason\":\"%s\"" + "\"Status\":%d,\"Message\":\"CCxxxx ZNP booted\",\"RestartReason\":\"%s\"" ",\"MajorRel\":%d,\"MinorRel\":%d}}"), ZIGBEE_STATUS_BOOT, reason_str, major_rel, minor_rel); From c074573f099ffba8ab8090801d4b20bbfae3b229 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 15 Feb 2022 14:32:42 +0100 Subject: [PATCH 05/25] Fix wiegand 34-bit rfid reading and presentation Fix wiegand 34-bit rfid reading and presentation (#14834) --- CHANGELOG.md | 1 + RELEASENOTES.md | 1 + tasmota/xsns_82_wiegand.ino | 16 ++++++++++------ 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3d974890..f5c2badd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ All notable changes to this project will be documented in this file. - 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) - Orno WE517 power meter phase 2 current reactive (#14841) +- Wiegand 34-bit rfid reading and presentation (#14834) ## [Released] diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 45636d317..a4187f10d 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -123,6 +123,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo - SSPM energy yesterday when zero - 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) +- 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) ### Removed diff --git a/tasmota/xsns_82_wiegand.ino b/tasmota/xsns_82_wiegand.ino index beaf49153..5aaa22d4f 100644 --- a/tasmota/xsns_82_wiegand.ino +++ b/tasmota/xsns_82_wiegand.ino @@ -37,7 +37,11 @@ * Rule: * 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) + * --- + * 20201101 * - 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 * - added SetOption123 0-Wiegand UID decimal (default) 1-Wiegand UID hexadecimal @@ -264,8 +268,8 @@ uint64_t Wiegand::CheckAndConvertRfid(uint64_t rfidIn, uint16_t bitCount) { break; case 34: - evenParityBit = (rfidIn & 0x400000000) ? 0x80 : 0; - rfidIn = (rfidIn & 0x3FFFFFFFE) >>1; + evenParityBit = (rfidIn & 0x200000000) ? 0x80 : 0; + rfidIn = (rfidIn & 0x1FFFFFFFE) >>1; break; default: @@ -274,7 +278,7 @@ 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 if (calcParity != (evenParityBit | oddParityBit)) { // Parity bit is wrong rfidIn=0; - AddLog(LOG_LEVEL_DEBUG, PSTR("WIE: %llu parity error"), rfidIn); + AddLog(LOG_LEVEL_DEBUG, PSTR("WIE: %_X parity error"), &rfidIn); } #if (DEV_WIEGAND_TEST_MODE)>0 AddLog(LOG_LEVEL_INFO, PSTR("WIE: even (left) parity: %u "), (evenParityBit>>7)); @@ -412,7 +416,7 @@ void Wiegand::ScanForTag() { if (GetOption(WIEGAND_OPTION_HEX) == 0) { ResponseTime_P(PSTR(",\"Wiegand\":{\"UID\":%lu,\"" D_JSON_SIZE "\":%d}}"), (uint32_t)rfid, tagSize); } else { - ResponseTime_P(PSTR(",\"Wiegand\":{\"UID\":\"%2_X" WIEGAND_OPTION_HEX_POSTFIX "\",\"" D_JSON_SIZE "\":\"%X" WIEGAND_OPTION_HEX_POSTFIX "\"}}"), &rfid, tagSize); + ResponseTime_P(PSTR(",\"Wiegand\":{\"UID\":\"%1_X" WIEGAND_OPTION_HEX_POSTFIX "\",\"" D_JSON_SIZE "\":%d}}"), &rfid, tagSize); } MqttPublishTeleSensor(); } @@ -443,7 +447,7 @@ void Wiegand::Show(void) { if (GetOption(WIEGAND_OPTION_HEX) == 0) { 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); + WSContentSend_P(PSTR("{s}Wiegand UID{m}%1_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); From f2bd57c5e6915a7f63f495aed0fb8641b64b32ba Mon Sep 17 00:00:00 2001 From: jeevasdev Date: Wed, 16 Feb 2022 02:32:29 +1100 Subject: [PATCH 06/25] NRG sensor rewrite. --- tasmota/tasmota_template.h | 6 -- tasmota/xnrg_22_bl6523.ino | 162 +++++++++++-------------------------- 2 files changed, 49 insertions(+), 119 deletions(-) diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index fc57e9825..3c2ab3902 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -172,7 +172,6 @@ enum UserSelectablePins { GPIO_MCP2515_CS, // MCP2515 Chip Select GPIO_HRG15_TX, GPIO_HRG15_RX, // Hydreon RG-15 rain sensor serial interface GPIO_VINDRIKTNING_RX, // IKEA VINDRIKTNING Serial interface - GPIO_BL6523_TX, GPIO_BL6523_RX, // BL6523 based Watt meter Serial interface GPIO_BL0939_RX, // BL0939 Serial interface (Dual R3 v2) GPIO_BL0942_RX, // BL0942 Serial interface GPIO_HM330X_SET, // HM330X SET pin (sleep when low) @@ -395,7 +394,6 @@ const char kSensorNames[] PROGMEM = D_SENSOR_MCP2515_CS "|" D_SENSOR_HRG15_TX "|" D_SENSOR_HRG15_RX "|" D_SENSOR_VINDRIKTNING_RX "|" - D_SENSOR_BL6523_TX "|" D_SENSOR_BL6523_RX "|" D_SENSOR_BL0939_RX "|" D_SENSOR_BL0942_RX "|" D_SENSOR_HM330X_SET "|" @@ -820,10 +818,6 @@ const uint16_t kGpioNiceList[] PROGMEM = { #ifdef USE_VINDRIKTNING AGPIO(GPIO_VINDRIKTNING_RX), #endif -#ifdef USE_BL6523 - AGPIO(GPIO_BL6523_TX), - AGPIO(GPIO_BL6523_RX), -#endif #ifdef USE_HM330X AGPIO(GPIO_HM330X_SET), // HM330X Sleep pin (active low) #endif diff --git a/tasmota/xnrg_22_bl6523.ino b/tasmota/xnrg_22_bl6523.ino index 98b39780f..28d7e2f0c 100644 --- a/tasmota/xnrg_22_bl6523.ino +++ b/tasmota/xnrg_22_bl6523.ino @@ -36,7 +36,8 @@ * BL6523 GND -> ESP GND * * To build add the below to user_config_override.h - * #define USE_BL6523 // Add support for Chinese BL6523 based Watt hour meter (+1k code)¸ + * #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} @@ -57,6 +58,8 @@ #define BL6523_REG_POWF 0x08 #define BL6523_REG_WATTHR 0x0C +#define SINGLE_PHASE 0 + /* No idea how to derive human readable units from the byte stream. For now dividing the 24-bit values with below constants seems to yield something sane that matches whatever displayed in the screen of my 240v model. Probably it would be possible @@ -72,13 +75,6 @@ TasmotaSerial *Bl6523TxSerial; struct BL6523 { - uint32_t amps = 0; - uint32_t volts = 0; - uint32_t freq = 0; - uint32_t watts = 0; - uint32_t powf = 0; - uint32_t watthr = 0; - uint8_t type = 1; uint8_t valid = 0; uint8_t got_data_stone = 0; @@ -87,6 +83,8 @@ struct BL6523 bool Bl6523ReadData(void) { + uint32_t powf_word = 0, powf_buf = 0; + float powf = 0.0f; if (!Bl6523RxSerial->available()) { @@ -163,35 +161,39 @@ RX: 35 0C TX: 00 00 00 F3 (WATT_HR) switch(rx_buffer[1]) { case BL6523_REG_AMPS : - Bl6523.amps = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]); - Bl6523.got_data_stone |= 1<<0; + Energy.current[SINGLE_PHASE] = (float)((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]) / BL6523_DIV_AMPS; // 1.260 A break; case BL6523_REG_VOLTS : - Bl6523.volts = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]); - Bl6523.got_data_stone |= 1<<1; + Energy.voltage[SINGLE_PHASE] = (float)((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]) / BL6523_DIV_VOLTS; // 230.2 V break; case BL6523_REG_FREQ : - Bl6523.freq = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]); - Bl6523.got_data_stone |= 1<<2; + Energy.frequency[SINGLE_PHASE] = (float)((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]) / BL6523_DIV_FREQ; // 50.0 Hz break; case BL6523_REG_WATTS : - Bl6523.watts = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]); - Bl6523.got_data_stone |= 1<<3; + Energy.active_power[SINGLE_PHASE] = (float)((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]) / BL6523_DIV_WATTS; // -196.3 W break; case BL6523_REG_POWF : - Bl6523.powf = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]); - Bl6523.got_data_stone |= 1<<4; + /* 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 : - Bl6523.watthr = ((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]); - Bl6523.got_data_stone |= 1<<5; + Energy.import_active[SINGLE_PHASE] = (float)((tx_buffer[2] << 16) | (tx_buffer[1] << 8) | tx_buffer[0]) / BL6523_DIV_WATTHR; // 6.216 kWh => used in EnergyUpdateTotal() break; default : break; } - -AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("Amps: %d Volts: %d Freq: %d Watts: %d PowF: %d WattHr: %d"), Bl6523.amps, Bl6523.volts, Bl6523.freq, Bl6523.watts, Bl6523.powf, Bl6523.watthr); - + Energy.data_valid[SINGLE_PHASE] = 0; + EnergyUpdateTotal(); if (!Bl6523.discovery_triggered) { TasmotaGlobal.discovery_counter = 1; // force TasDiscovery() @@ -221,9 +223,8 @@ void Bl6523Update(void) void Bl6523Init(void) { - Bl6523.type = 0; - if ((PinUsed(GPIO_BL6523_RX)) && (PinUsed(GPIO_BL6523_TX))) - { + + 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))) @@ -237,86 +238,29 @@ void Bl6523Init(void) ClaimSerial(); } Bl6523.type = 1; + Energy.phase_count = 1; AddLog(LOG_LEVEL_DEBUG, PSTR("BL6523 Init Success " )); } - } + else + { + AddLog(LOG_LEVEL_DEBUG, PSTR("BL6523 Init Failure! " )); + TasmotaGlobal.energy_driver = ENERGY_NONE; + } + } -#ifdef USE_WEBSERVER -const char HTTP_BL6523_SNM[] PROGMEM = "{s}BL6523 Smart Energy Monitor{m}{e}"; // {s} = , {m} = , {e} = -const char HTTP_BL6523_SNS[] PROGMEM = "{s} %s {m}%s {e}"; // {s} = , {m} = , {e} = -#endif // USE_WEBSERVER - -void Bl6523Show(bool json) +void Bl6523DrvInit(void) { - uint32_t powf_word = 0; - float amps = 0.0f, volts = 0.0f, freq = 0.0f, watts = 0.0f, powf = 0.0f, watthr = 0.0f; - char amps_str[12], volts_str[12], freq_str[12]; - char watts_str[12], powf_str[12], watthr_str[12]; - - if (Bl6523.valid) - { - - amps = (float)Bl6523.amps / BL6523_DIV_AMPS; - volts = (float)Bl6523.volts / BL6523_DIV_VOLTS; - freq = (float)Bl6523.freq / BL6523_DIV_FREQ; - watts = (float)Bl6523.watts / BL6523_DIV_WATTS; - - /* 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_word = (Bl6523.powf >> 23) ? ~(Bl6523.powf & 0x7fffff) : Bl6523.powf & 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 = (Bl6523.powf >> 23) ? (0.0f - (powf)) : powf; // Negate if sign bit(24) is set - - watthr = (float)Bl6523.watthr / BL6523_DIV_WATTHR; - - ext_snprintf_P(amps_str, sizeof(amps_str), PSTR("%3_f"), &s); - ext_snprintf_P(volts_str, sizeof(volts_str), PSTR("%2_f"), &volts); - ext_snprintf_P(freq_str, sizeof(freq_str), PSTR("%2_f"), &freq); - ext_snprintf_P(watts_str, sizeof(watts_str), PSTR("%3_f"), &watts); - ext_snprintf_P(powf_str, sizeof(powf_str), PSTR("%2_f"), &powf); - ext_snprintf_P(watthr_str, sizeof(watthr_str), PSTR("%3_f"), &watthr); - - if (json) - { - ResponseAppend_P(PSTR(",\"BL6523\":{")); - ResponseAppend_P(PSTR("\"Amps\":%s,"), amps_str); - ResponseAppend_P(PSTR("\"Volts\":%s,"), volts_str); - ResponseAppend_P(PSTR("\"Freq\":%s,"), freq_str); - ResponseAppend_P(PSTR("\"Watts\":%s,"), watts_str); - ResponseAppend_P(PSTR("\"Powf\":%s,"), powf_str); - ResponseAppend_P(PSTR("\"WattHr\":%s"), watthr_str); - ResponseJsonEnd(); -#ifdef USE_DOMOTICZ - if (0 == TasmotaGlobal.tele_period) - { - DomoticzSensor(DZ_CURRENT, amps_str); // Amps - DomoticzSensor(DZ_VOLTAGE, volts_str); // Voltage - DomoticzSensor(DZ_COUNT, freq_str); // Frequency - DomoticzSensor(DZ_ILLUMINANCE, watts_str); // Watts - DomoticzSensor(DZ_P1_SMART_METER, powf_str); // Power Factor - DomoticzSensor(DZ_POWER_ENERGY, watthr_str); // WattHour - } -#endif // USE_DOMOTICZ -#ifdef USE_WEBSERVER - } - else - { - WSContentSend_PD(HTTP_BL6523_SNM); - WSContentSend_PD(HTTP_BL6523_SNS, PSTR("Amps:"), amps_str); - WSContentSend_PD(HTTP_BL6523_SNS, PSTR("Volts:"), volts_str); - WSContentSend_PD(HTTP_BL6523_SNS, PSTR("Freq:"), freq_str); - WSContentSend_PD(HTTP_BL6523_SNS, PSTR("Watts:"), watts_str); - WSContentSend_PD(HTTP_BL6523_SNS, PSTR("PowF:"), powf_str); - WSContentSend_PD(HTTP_BL6523_SNS, PSTR("WattHr:"), watthr_str); -#endif // USE_WEBSERVER - } + if (PinUsed(GPIO_BL6523_RX) && PinUsed(GPIO_BL6523_TX)) { + AddLog(LOG_LEVEL_DEBUG, PSTR("BL6523 PreInit Success " )); + TasmotaGlobal.energy_driver = XNRG_22; } + else + { + AddLog(LOG_LEVEL_DEBUG, PSTR("BL6523 PreInit Failure! " )); + TasmotaGlobal.energy_driver = ENERGY_NONE; + } + } /*********************************************************************************************\ @@ -327,27 +271,19 @@ bool Xnrg22(uint8_t function) { bool result = false; -if ( FUNC_INIT == function ) -{ - Bl6523Init(); -} -else if ( Bl6523.type ) - { switch (function) { case FUNC_EVERY_250_MSECOND: Bl6523Update(); break; - case FUNC_JSON_APPEND: - Bl6523Show(1); + case FUNC_INIT: + Bl6523Init(); break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Bl6523Show(0); + case FUNC_PRE_INIT: + Bl6523DrvInit(); break; -#endif // USE_WEBSERVER } - } + return result; } From a5e840ff5e36bb3200906edccb2470c284f16bb5 Mon Sep 17 00:00:00 2001 From: jeevasdev Date: Wed, 16 Feb 2022 03:04:28 +1100 Subject: [PATCH 07/25] Trim Log messages. --- tasmota/xnrg_22_bl6523.ino | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tasmota/xnrg_22_bl6523.ino b/tasmota/xnrg_22_bl6523.ino index 28d7e2f0c..a2d09d0bb 100644 --- a/tasmota/xnrg_22_bl6523.ino +++ b/tasmota/xnrg_22_bl6523.ino @@ -88,7 +88,7 @@ bool Bl6523ReadData(void) if (!Bl6523RxSerial->available()) { - AddLog(LOG_LEVEL_DEBUG, PSTR("BL6523 No Rx Data available " )); + AddLog(LOG_LEVEL_DEBUG, PSTR("BL6:No Rx Data available" )); return false; } @@ -99,7 +99,7 @@ bool Bl6523ReadData(void) if (Bl6523RxSerial->available() < BL6523_RX_DATASET_SIZE) { - AddLog(LOG_LEVEL_DEBUG, PSTR("BL6523 Rx less than expected " )); + AddLog(LOG_LEVEL_DEBUG, PSTR("BL6:Rx less than expected" )); return false; } @@ -134,7 +134,7 @@ bool Bl6523ReadData(void) crc = ~crc; // Invert the byte if (crc != tx_buffer[BL6523_TX_DATASET_SIZE - 1]) { - AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("BL6523 : " D_CHECKSUM_FAILURE)); + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("BL6:" D_CHECKSUM_FAILURE)); Bl6523TxSerial->flush(); Bl6523RxSerial->flush(); return false; @@ -239,11 +239,11 @@ void Bl6523Init(void) } Bl6523.type = 1; Energy.phase_count = 1; - AddLog(LOG_LEVEL_DEBUG, PSTR("BL6523 Init Success " )); + AddLog(LOG_LEVEL_DEBUG, PSTR("BL6:Init Success" )); } else { - AddLog(LOG_LEVEL_DEBUG, PSTR("BL6523 Init Failure! " )); + AddLog(LOG_LEVEL_DEBUG, PSTR("BL6:Init Failure!" )); TasmotaGlobal.energy_driver = ENERGY_NONE; } @@ -252,12 +252,12 @@ void Bl6523Init(void) void Bl6523DrvInit(void) { if (PinUsed(GPIO_BL6523_RX) && PinUsed(GPIO_BL6523_TX)) { - AddLog(LOG_LEVEL_DEBUG, PSTR("BL6523 PreInit Success " )); + AddLog(LOG_LEVEL_DEBUG, PSTR("BL6:PreInit Success" )); TasmotaGlobal.energy_driver = XNRG_22; } else { - AddLog(LOG_LEVEL_DEBUG, PSTR("BL6523 PreInit Failure! " )); + AddLog(LOG_LEVEL_DEBUG, PSTR("BL6:PreInit Failure!" )); TasmotaGlobal.energy_driver = ENERGY_NONE; } From 5f64dc38e094dee09533463c305e28756162acbf Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Tue, 15 Feb 2022 17:35:09 +0100 Subject: [PATCH 08/25] Berry instance variables are never methods --- lib/libesp32/berry/src/be_vm.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/libesp32/berry/src/be_vm.c b/lib/libesp32/berry/src/be_vm.c index 622930526..66bec1f31 100644 --- a/lib/libesp32/berry/src/be_vm.c +++ b/lib/libesp32/berry/src/be_vm.c @@ -904,7 +904,11 @@ newframe: /* a new call frame */ if (var_isinstance(a) && var_isstr(b)) { binstance *obj = var_toobj(a); 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; vm_error(vm, "attribute_error", "class '%s' cannot assign to attribute '%s'", From 4566aaee05b1750e47601dd457fd777f90b306f5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 15 Feb 2022 17:52:45 +0100 Subject: [PATCH 09/25] Refactor wiegand to 32-bit Refactor wiegand from 64-bit to 32-bit while keeping full 34-bit support --- tasmota/xsns_82_wiegand.ino | 184 ++++++++++++++++-------------------- 1 file changed, 84 insertions(+), 100 deletions(-) diff --git a/tasmota/xsns_82_wiegand.ino b/tasmota/xsns_82_wiegand.ino index 5aaa22d4f..9908e7a55 100644 --- a/tasmota/xsns_82_wiegand.ino +++ b/tasmota/xsns_82_wiegand.ino @@ -40,6 +40,8 @@ * 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 @@ -106,23 +108,21 @@ class Wiegand { #if (DEV_WIEGAND_TEST_MODE!=1) private: #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); bool WiegandConversion (uint64_t , uint16_t ); - void setOutputFormat(void); // fix output HEX format void HandleKeyPad(void); //handle one tag for multi key strokes - static void handleD0Interrupt(void); static void handleD1Interrupt(void); static void handleDxInterrupt(int in); // fix #11047 static void ClearRFIDBuffer(int); - uint64_t rfid; + uint32_t rfid; uint32_t tagSize; const char* outFormat; - uint64_t mqttRFIDKeypadBuffer; - uint64_t webRFIDKeypadBuffer; + uint32_t mqttRFIDKeypadBuffer; + uint32_t webRFIDKeypadBuffer; static volatile uint64_t rfidBuffer; static volatile uint16_t bitCount; @@ -149,15 +149,14 @@ volatile bool Wiegand::CodeComplete; volatile RFID_store Wiegand::rfid_found[WIEGAND_RFID_ARRAY_SIZE]; volatile int Wiegand::currentFoundRFIDcount; - - void IRAM_ATTR Wiegand::ClearRFIDBuffer(int endIndex = WIEGAND_RFID_ARRAY_SIZE) { - currentFoundRFIDcount=WIEGAND_RFID_ARRAY_SIZE-endIndex; // clear all buffers - for (int i= 0; i < endIndex; i++) { - rfid_found[i].RFID=0; - rfid_found[i].bitCount=0; - } + currentFoundRFIDcount = WIEGAND_RFID_ARRAY_SIZE - endIndex; // clear all buffers + for (uint32_t i = 0; i < endIndex; i++) { + rfid_found[i].RFID=0; + rfid_found[i].bitCount=0; + } } + void IRAM_ATTR Wiegand::handleD1Interrupt() { // Receive a 1 bit. (D0=high & D1=low) handleDxInterrupt(1); } @@ -167,9 +166,9 @@ void IRAM_ATTR Wiegand::handleD0Interrupt() { // Receive a 0 bit. (D0=low & D1= } 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 - unsigned long diffTime= curTime - lastFoundTime; - if ( (diffTime > CodeGapTime) && (bitCount > 0)) { + uint32_t curTime = micros(); // to be sure I will use micros() instead of millis() overflow is handle by using the minus operator to compare + uint32_t diffTime = curTime - lastFoundTime; + if ((diffTime > CodeGapTime) && (bitCount > 0)) { // 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 // 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) @@ -192,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. } 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; } //save current rfid in array otherwise we will never see the last found tag @@ -247,7 +246,7 @@ void Wiegand::Init() { #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 oddParityBit = (uint8_t) (rfidIn & 0x1); // Last bit = odd parity uint8_t calcParity = 0; @@ -277,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 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; - AddLog(LOG_LEVEL_DEBUG, PSTR("WIE: %_X parity error"), &rfidIn); } #if (DEV_WIEGAND_TEST_MODE)>0 AddLog(LOG_LEVEL_INFO, PSTR("WIE: even (left) parity: %u "), (evenParityBit>>7)); @@ -286,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 (calc) parity: %u "), (calcParity & 0x01)); #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 // 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! @@ -299,7 +298,7 @@ uint8_t Wiegand::CalculateParities(uint64_t tagWithoutParities, int tag_size=26) tag_size -= 2; if (tag_size <= 0) { return retValue; } // Prohibit div zero exception and other wrong inputs 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); tagWithoutParities >>= 1; } @@ -318,53 +317,47 @@ uint8_t Wiegand::CalculateParities(uint64_t tagWithoutParities, int tag_size=26) bool Wiegand::WiegandConversion (uint64_t rfidBuffer, uint16_t bitCount) { bool bRet = false; #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 - if ((24 == bitCount) || (26 == bitCount) || (32 == bitCount) || (34 == bitCount)) { - // 24, 26, 32, 34-bit Wiegand codes - rfid = CheckAndConvertRfid(rfidBuffer, bitCount); - tagSize = bitCount; + if ((24 == bitCount) || (26 == bitCount) || (32 == bitCount) || (34 == bitCount)) { + // 24, 26, 32, 34-bit Wiegand codes + rfid = CheckAndConvertRfid(rfidBuffer, 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; - } - 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 { - // Time reached but unknown bitCount, clear and start again - tagSize = 0; bRet = false; } + tagSize = bitCount; + } else { + // Time reached but unknown bitCount, clear and start again + tagSize = 0; + bRet = false; + } #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 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 - 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 (GetOption(WIEGAND_OPTION_KEYPAD_TO_TAG) == 0) { // handle all key pad inputs as ONE Tag until # is recognized + if ((tagSize == 4) || (tagSize == 8)) { //only handle Keypad strokes if it is requested 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. @@ -372,7 +365,7 @@ void Wiegand::HandleKeyPad(void) { // will be called if a valid key pad input wa mqttRFIDKeypadBuffer = 0; } else { - mqttRFIDKeypadBuffer = (mqttRFIDKeypadBuffer*10)+rfid; //left shift + new key + mqttRFIDKeypadBuffer = (mqttRFIDKeypadBuffer * 10) + rfid; //left shift + new key webRFIDKeypadBuffer = mqttRFIDKeypadBuffer; // visualising the current typed keys rfid = 0; tagSize = 0; @@ -386,38 +379,33 @@ void Wiegand::HandleKeyPad(void) { // will be called if a valid key pad input wa } void Wiegand::ScanForTag() { - unsigned long startTime = micros(); + uint32_t startTime = micros(); handleDxInterrupt(3); - if (currentFoundRFIDcount > 0) { - unsigned int lastFoundRFIDcount = currentFoundRFIDcount; - #if (DEV_WIEGAND_TEST_MODE)>0 - AddLog(LOG_LEVEL_INFO, PSTR("WIE: ScanForTag(). bitTime: %0lu lastFoundTime: %0lu RFIDS in buffer: %lu"), bitTime, lastFoundTime, currentFoundRFIDcount); - #endif - // format MQTT output -// setOutputFormat(); -// char sFormat[50]; -// 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; + if (currentFoundRFIDcount > 0) { + uint32_t lastFoundRFIDcount = currentFoundRFIDcount; +#if (DEV_WIEGAND_TEST_MODE)>0 + AddLog(LOG_LEVEL_INFO, PSTR("WIE: ScanForTag(). bitTime: %u lastFoundTime: %u RFIDS in buffer: %u"), bitTime, lastFoundTime, currentFoundRFIDcount); +#endif + for (uint32_t i = 0; i < WIEGAND_RFID_ARRAY_SIZE; i++) { + if (rfid_found[i].RFID != 0 || (rfid_found[i].RFID == 0 && i == 0)) { + uint32_t oldTag = rfid; bool validKey = WiegandConversion(rfid_found[i].RFID, rfid_found[i].bitCount); - #if (DEV_WIEGAND_TEST_MODE)>0 - AddLog(LOG_LEVEL_INFO, PSTR("WIE: ValidKey: %d Previous tag %llu"), validKey, oldTag); - #endif // DEV_WIEGAND_TEST_MODE>0 +#if (DEV_WIEGAND_TEST_MODE)>0 + AddLog(LOG_LEVEL_INFO, PSTR("WIE: ValidKey %d, Previous tag %u"), validKey, oldTag); +#endif // DEV_WIEGAND_TEST_MODE>0 if (validKey) { // Only in case of valid key do action. Issue#10585 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) { AddLog(LOG_LEVEL_DEBUG, PSTR("WIE: Old tag")); } -// ResponseTime_P(sFormat, rfid, tagSize); -// Tasmota does not support 64-bit decimal output specifier (%llu) saving 60k code + ResponseTime_P(PSTR(",\"Wiegand\":{\"UID\":")); 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 { - ResponseTime_P(PSTR(",\"Wiegand\":{\"UID\":\"%1_X" WIEGAND_OPTION_HEX_POSTFIX "\",\"" D_JSON_SIZE "\":%d}}"), &rfid, tagSize); + ResponseAppend_P(PSTR("\"%X" WIEGAND_OPTION_HEX_POSTFIX "\""), rfid); } + ResponseAppend_P(PSTR(",\"" D_JSON_SIZE "\":%d}}"), tagSize); MqttPublishTeleSensor(); } } @@ -426,33 +414,29 @@ void Wiegand::ScanForTag() { if (currentFoundRFIDcount > lastFoundRFIDcount) { // if that happens: we need to move the id found during the loop to top of the array // 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 - #if (DEV_WIEGAND_TEST_MODE)>0 - AddLog(LOG_LEVEL_INFO, PSTR("WIE: ScanForTag() time elapsed %lu"), (micros() - startTime)); - #endif +#if (DEV_WIEGAND_TEST_MODE)>0 + AddLog(LOG_LEVEL_INFO, PSTR("WIE: ScanForTag() time elapsed %u"), (micros() - startTime)); +#endif } - } #ifdef USE_WEBSERVER void Wiegand::Show(void) { -// setOutputFormat(); -// char sFormat [30]; -// snprintf( sFormat, 30,PSTR("{s}Wiegand UID{m}%%ll%s {e}"), outFormat); -// if (tagSize>0) { WSContentSend_PD(sFormat, rfid); } -// else { WSContentSend_PD(sFormat, webRFIDKeypadBuffer); } -// Tasmota does not support 64-bit decimal output specifier (%llu) saving 60k code - if (GetOption(WIEGAND_OPTION_HEX) == 0) { - 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}%1_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 + WSContentSend_P(PSTR("{s}Wiegand UID{m}")); + if (GetOption(WIEGAND_OPTION_HEX) == 0) { + WSContentSend_P(PSTR("%u"), (tagSize > 0) ? rfid : webRFIDKeypadBuffer); + } else { + WSContentSend_P(PSTR("%X" WIEGAND_OPTION_HEX_POSTFIX), (tagSize > 0) ? rfid : webRFIDKeypadBuffer); + } + WSContentSend_P(PSTR("{e}")); + +#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 From b75919c487e4fb3017f7d313b6beb59c2a557b55 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 15 Feb 2022 20:02:31 +0100 Subject: [PATCH 10/25] remove not needed code which will conflict with next Arduino core build --- lib/lib_basic/OneWire-Stickbreaker/OneWire.h | 52 ++++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/lib/lib_basic/OneWire-Stickbreaker/OneWire.h b/lib/lib_basic/OneWire-Stickbreaker/OneWire.h index 2747bea4e..5f4b613c2 100644 --- a/lib/lib_basic/OneWire-Stickbreaker/OneWire.h +++ b/lib/lib_basic/OneWire-Stickbreaker/OneWire.h @@ -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].pullup | rtc_gpio_desc[pin].pulldown); } -#elif ESP_IDF_VERSION_MAJOR > 3 // ESP32-S2 needs IDF 4.2 or later - int8_t rtc_io = esp32_gpioMux[pin].rtc; - uint32_t rtc_reg = (rtc_io != -1)?rtc_io_desc[rtc_io].reg:0; - 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].pullup | rtc_io_desc[rtc_io].pulldown); - } +//#elif ESP_IDF_VERSION_MAJOR > 3 // ESP32-S2 needs IDF 4.2 or later +// int8_t rtc_io = esp32_gpioMux[pin].rtc; +// uint32_t rtc_reg = (rtc_io != -1)?rtc_io_desc[rtc_io].reg:0; +// 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].pullup | rtc_io_desc[rtc_io].pulldown); +// } #endif // Input if ( pin < 32 ) @@ -225,13 +225,13 @@ void directModeInput(IO_REG_TYPE pin) else GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32)); - 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 |= ((uint32_t)PIN_FUNC_GPIO << MCU_SEL_S); +// 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 |= ((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 } @@ -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].pullup | rtc_gpio_desc[pin].pulldown); } -#elif ESP_IDF_VERSION_MAJOR > 3 // ESP32-S2 needs IDF 4.2 or later - int8_t rtc_io = esp32_gpioMux[pin].rtc; - uint32_t rtc_reg = (rtc_io != -1)?rtc_io_desc[rtc_io].reg:0; - 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].pullup | rtc_io_desc[rtc_io].pulldown); - } +//#elif ESP_IDF_VERSION_MAJOR > 3 // ESP32-S2 needs IDF 4.2 or later +// int8_t rtc_io = esp32_gpioMux[pin].rtc; +// uint32_t rtc_reg = (rtc_io != -1)?rtc_io_desc[rtc_io].reg:0; +// 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].pullup | rtc_io_desc[rtc_io].pulldown); +// } #endif // Output if ( pin < 32 ) @@ -267,13 +267,13 @@ void directModeOutput(IO_REG_TYPE pin) else // already validated to pins <= 33 GPIO.enable1_w1ts.val = ((uint32_t)1 << (pin - 32)); - 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 |= ((uint32_t)PIN_FUNC_GPIO << MCU_SEL_S); +// 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 |= ((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 } From ecd4ec76f3cd74115703e1c3b065d234006a7836 Mon Sep 17 00:00:00 2001 From: stefanbode Date: Tue, 15 Feb 2022 20:26:49 +0100 Subject: [PATCH 11/25] prevent deepsleep if teleperiod <> 100 or 300 because teleperiod is send directly after start, deepsleep will wait for the second teleperiod in cases where it is defined e.g. to 60. #14860 --- tasmota/xdrv_29_deepsleep.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_29_deepsleep.ino b/tasmota/xdrv_29_deepsleep.ino index 144327d85..ae987ba69 100644 --- a/tasmota/xdrv_29_deepsleep.ino +++ b/tasmota/xdrv_29_deepsleep.ino @@ -178,7 +178,7 @@ bool Xdrv29(uint8_t function) DeepSleepEverySecond(); break; 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 } break; From 0ab3dd8edd5b096faaa2545207f8bfad2e0f1496 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Tue, 15 Feb 2022 21:44:45 +0100 Subject: [PATCH 12/25] Berry add hue_bridge.light_to_id() --- lib/libesp32/berry/generate/be_const_strtab.h | 1 + .../berry/generate/be_const_strtab_def.h | 5 +- .../berry_tasmota/src/be_hue_bridge_lib.c | 681 ++++++++++-------- .../berry_tasmota/src/embedded/hue_bridge.be | 9 + 4 files changed, 378 insertions(+), 318 deletions(-) diff --git a/lib/libesp32/berry/generate/be_const_strtab.h b/lib/libesp32/berry/generate/be_const_strtab.h index 834714ee9..b6fb90f13 100644 --- a/lib/libesp32/berry/generate/be_const_strtab.h +++ b/lib/libesp32/berry/generate/be_const_strtab.h @@ -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_X20must_X20be_X20of_X20class_X20_X27light_state_X27; 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_line_dsc; extern const bcstring be_const_str_list; diff --git a/lib/libesp32/berry/generate/be_const_strtab_def.h b/lib/libesp32/berry/generate/be_const_strtab_def.h index 777e7d55a..30fb8e581 100644 --- a/lib/libesp32/berry/generate/be_const_strtab_def.h +++ b/lib/libesp32/berry/generate/be_const_strtab_def.h @@ -518,6 +518,7 @@ be_define_const_str(length_X20in_X20bits_X20must_X20be_X20between_X200_X20and_X2 be_define_const_str(light, "light", 3801947695u, 0, 5, NULL); be_define_const_str(light_X20must_X20be_X20of_X20class_X20_X27light_state_X27, "light must be of class 'light_state'", 3669350396u, 0, 36, NULL); be_define_const_str(light_state, "light_state", 905783845u, 0, 11, NULL); +be_define_const_str(light_to_id, "light_to_id", 1117015647u, 0, 11, &be_const_str_signal_arcs); be_define_const_str(lights, "lights", 425118420u, 0, 6, &be_const_str_success); be_define_const_str(line_dsc, "line_dsc", 4094490978u, 0, 8, &be_const_str_web_add_button); be_define_const_str(list, "list", 217798785u, 0, 4, &be_const_str_url_encode); @@ -890,7 +891,7 @@ static const bstring* const m_string_table[] = { (const bstring *)&be_const_str_SERIAL_6N2, (const bstring *)&be_const_str__drivers, (const bstring *)&be_const_str__X28_X29, - (const bstring *)&be_const_str_signal_arcs, + (const bstring *)&be_const_str_light_to_id, (const bstring *)&be_const_str_AudioGeneratorMP3, (const bstring *)&be_const_str_BRY_X3A_X20ERROR_X2C_X20bad_X20json_X3A_X20, (const bstring *)&be_const_str_clear_to, @@ -1287,6 +1288,6 @@ static const bstring* const m_string_table[] = { static const struct bconststrtab m_const_string_table = { .size = 420, - .count = 863, + .count = 864, .table = m_string_table }; diff --git a/lib/libesp32/berry_tasmota/src/be_hue_bridge_lib.c b/lib/libesp32/berry_tasmota/src/be_hue_bridge_lib.c index bda0f8ca7..eaffff5b2 100644 --- a/lib/libesp32/berry_tasmota/src/be_hue_bridge_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_hue_bridge_lib.c @@ -6,6 +6,363 @@ #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 ********************************************************************/ @@ -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 ********************************************************************/ @@ -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 ********************************************************************/ be_local_class(hue_bridge_monad, 1, NULL, - be_nested_map(9, + be_nested_map(10, ( (struct bmapnode*) &(const bmapnode[]) { - { 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(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(lights, -1), be_const_var(0) }, + { be_const_key(groups, 6), be_const_closure(hue_bridge_monad_groups_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(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(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") ); diff --git a/lib/libesp32/berry_tasmota/src/embedded/hue_bridge.be b/lib/libesp32/berry_tasmota/src/embedded/hue_bridge.be index a4054b923..eb19de84d 100644 --- a/lib/libesp32/berry_tasmota/src/embedded/hue_bridge.be +++ b/lib/libesp32/berry_tasmota/src/embedded/hue_bridge.be @@ -28,6 +28,15 @@ hue_bridge.init = def (m) self.lights.remove(id) 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 def hue_status(id) import hue_ntv From 42b73ecfce6bc11d33320b8c586bffb7c85bf922 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Tue, 15 Feb 2022 21:58:05 +0100 Subject: [PATCH 13/25] Berry add module mqtt --- lib/libesp32/berry/default/be_modtab.c | 2 + lib/libesp32/berry/generate/be_const_strtab.h | 2 + .../berry/generate/be_const_strtab_def.h | 2105 +++++++++-------- lib/libesp32/berry/generate/be_fixed_mqtt.h | 19 + .../berry_tasmota/src/be_mqtt_lib.cpp | 21 + tasmota/xdrv_52_3_berry_mqtt.ino | 89 + tasmota/xdrv_52_3_berry_tasmota.ino | 43 - 7 files changed, 1187 insertions(+), 1094 deletions(-) create mode 100644 lib/libesp32/berry/generate/be_fixed_mqtt.h create mode 100644 lib/libesp32/berry_tasmota/src/be_mqtt_lib.cpp create mode 100644 tasmota/xdrv_52_3_berry_mqtt.ino diff --git a/lib/libesp32/berry/default/be_modtab.c b/lib/libesp32/berry/default/be_modtab.c index e09106849..f5102c224 100644 --- a/lib/libesp32/berry/default/be_modtab.c +++ b/lib/libesp32/berry/default/be_modtab.c @@ -30,6 +30,7 @@ be_extern_native_module(cb); /* Tasmota specific */ be_extern_native_module(python_compat); be_extern_native_module(re); +be_extern_native_module(mqtt); be_extern_native_module(persist); be_extern_native_module(autoconf); 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(re), &be_native_module(path), + &be_native_module(mqtt), &be_native_module(persist), #ifdef USE_AUTOCONF &be_native_module(autoconf), diff --git a/lib/libesp32/berry/generate/be_const_strtab.h b/lib/libesp32/berry/generate/be_const_strtab.h index b6fb90f13..0ca3362ad 100644 --- a/lib/libesp32/berry/generate/be_const_strtab.h +++ b/lib/libesp32/berry/generate/be_const_strtab.h @@ -760,6 +760,7 @@ extern const bcstring be_const_str_strftime; extern const bcstring be_const_str_string; extern const bcstring be_const_str_strip; 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_super; extern const bcstring be_const_str_sys; @@ -796,6 +797,7 @@ extern const bcstring be_const_str_type; extern const bcstring be_const_str_type_error; extern const bcstring be_const_str_udp; 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_upper; extern const bcstring be_const_str_url_encode; diff --git a/lib/libesp32/berry/generate/be_const_strtab_def.h b/lib/libesp32/berry/generate/be_const_strtab_def.h index 30fb8e581..ad5ef334d 100644 --- a/lib/libesp32/berry/generate/be_const_strtab_def.h +++ b/lib/libesp32/berry/generate/be_const_strtab_def.h @@ -1,747 +1,747 @@ -be_define_const_str(, "", 2166136261u, 0, 0, &be_const_str__def); -be_define_const_str(_X0A, "\n", 252472541u, 0, 1, &be_const_str__X2D_X2D_X3A_X2D_X2D); -be_define_const_str(_X20, " ", 621580159u, 0, 1, NULL); -be_define_const_str(_X21_X3D, "!=", 2428715011u, 0, 2, &be_const_str_send); -be_define_const_str(_X21_X3D_X3D, "!==", 559817114u, 0, 3, &be_const_str_yield); -be_define_const_str(_X22, "\"", 655135397u, 0, 1, &be_const_str__X23autoexec_X2Ebat); -be_define_const_str(_X22_X3A, "\":", 399167565u, 0, 2, &be_const_str_TAP_X3A_X20Loaded_X20Tasmota_X20App_X20_X27_X25s_X27); -be_define_const_str(_X23, "#", 638357778u, 0, 1, &be_const_str_delete_all_configs); -be_define_const_str(_X23autoexec_X2Ebat, "#autoexec.bat", 3382890497u, 0, 13, &be_const_str_constructor_cb); -be_define_const_str(_X23autoexec_X2Ebe, "#autoexec.be", 1181757091u, 0, 12, &be_const_str__X3Clegend_X3E_X3Cb_X20title_X3D_X27New_X20autoconf_X27_X3E_X26nbsp_X3BSelect_X20new_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E); -be_define_const_str(_X23display_X2Eini, "#display.ini", 182218220u, 0, 12, &be_const_str_public_key); -be_define_const_str(_X23init_X2Ebat, "#init.bat", 3297595077u, 0, 9, &be_const_str__X3D_X3C_X3E_X21); -be_define_const_str(_X23preinit_X2Ebe, "#preinit.be", 687035716u, 0, 11, &be_const_str_eth); +be_define_const_str(, "", 2166136261u, 0, 0, &be_const_str_SERIAL_6E1); +be_define_const_str(_X0A, "\n", 252472541u, 0, 1, NULL); +be_define_const_str(_X20, " ", 621580159u, 0, 1, &be_const_str_Unknown); +be_define_const_str(_X21_X3D, "!=", 2428715011u, 0, 2, &be_const_str_LVG_X3A_X20object_X3A); +be_define_const_str(_X21_X3D_X3D, "!==", 559817114u, 0, 3, &be_const_str_SERIAL_7O1); +be_define_const_str(_X22, "\"", 655135397u, 0, 1, &be_const_str__X2Ep); +be_define_const_str(_X22_X3A, "\":", 399167565u, 0, 2, NULL); +be_define_const_str(_X23, "#", 638357778u, 0, 1, &be_const_str_a); +be_define_const_str(_X23autoexec_X2Ebat, "#autoexec.bat", 3382890497u, 0, 13, &be_const_str_min); +be_define_const_str(_X23autoexec_X2Ebe, "#autoexec.be", 1181757091u, 0, 12, &be_const_str__X3Coption_X20value_X3D_X27reset_X27_X3E_X26lt_X3BRemove_X20autoconf_X26gt_X3B_X3C_X2Foption_X3E); +be_define_const_str(_X23display_X2Eini, "#display.ini", 182218220u, 0, 12, NULL); +be_define_const_str(_X23init_X2Ebat, "#init.bat", 3297595077u, 0, 9, &be_const_str_bool); +be_define_const_str(_X23preinit_X2Ebe, "#preinit.be", 687035716u, 0, 11, &be_const_str_setitem); be_define_const_str(_X2502d_X25s_X2502d, "%02d%s%02d", 1587999717u, 0, 10, NULL); -be_define_const_str(_X2504d_X2D_X2502d_X2D_X2502dT_X2502d_X3A_X2502d_X3A_X2502d, "%04d-%02d-%02dT%02d:%02d:%02d", 3425528601u, 0, 29, &be_const_str_CFG_X3A_X20downloading_X20_X27_X25s_X27); -be_define_const_str(_X2508x_X2D_X2504x_X2D_X2504x_X2D_X2504x_X2D_X2504x_X2508x, "%08x-%04x-%04x-%04x-%04x%08x", 1670063141u, 0, 28, NULL); -be_define_const_str(_X25s_X2Eautoconf, "%s.autoconf", 3560383524u, 0, 11, NULL); -be_define_const_str(_X26lt_X3BError_X3A_X20apply_X20new_X20or_X20remove_X26gt_X3B, "<Error: apply new or remove>", 2855507949u, 0, 34, &be_const_str_EXTERNAL_I2S); -be_define_const_str(_X26lt_X3BNone_X26gt_X3B, "<None>", 2602165498u, 0, 12, &be_const_str_isinstance); -be_define_const_str(_X28_X29, "()", 685372826u, 0, 2, &be_const_str_find_key_i); -be_define_const_str(_X2B, "+", 772578730u, 0, 1, &be_const_str_lower); -be_define_const_str(_X2C, ",", 688690635u, 0, 1, &be_const_str_leds); -be_define_const_str(_X2C_X22AXP192_X22_X3A_X7B_X22VBusVoltage_X22_X3A_X25_X2E3f_X2C_X22VBusCurrent_X22_X3A_X25_X2E1f_X2C_X22BattVoltage_X22_X3A_X25_X2E3f_X2C_X22BattCurrent_X22_X3A_X25_X2E1f_X2C_X22Temperature_X22_X3A_X25_X2E1f_X7D, ",\"AXP192\":{\"VBusVoltage\":%.3f,\"VBusCurrent\":%.1f,\"BattVoltage\":%.3f,\"BattCurrent\":%.1f,\"Temperature\":%.1f}", 2598755376u, 0, 106, &be_const_str_files); -be_define_const_str(_X2D_X2D_X3A_X2D_X2D, "--:--", 1370615441u, 0, 5, &be_const_str_lv_coord_arr); -be_define_const_str(_X2E, ".", 722245873u, 0, 1, &be_const_str_json_fdump_list); -be_define_const_str(_X2E_X2E, "..", 2748622605u, 0, 2, &be_const_str_list); -be_define_const_str(_X2Eautoconf, ".autoconf", 2524679088u, 0, 9, &be_const_str_get_current_module_path); -be_define_const_str(_X2Ebe, ".be", 1325797348u, 0, 3, &be_const_str_BRY_X3A_X20argument_X20must_X20be_X20a_X20function); -be_define_const_str(_X2Ebec, ".bec", 3985273221u, 0, 4, &be_const_str_get_vbus_voltage); -be_define_const_str(_X2Elen, ".len", 850842136u, 0, 4, &be_const_str_rtc); -be_define_const_str(_X2Ep, ".p", 1171526419u, 0, 2, &be_const_str_create_segment); -be_define_const_str(_X2Ep1, ".p1", 249175686u, 0, 3, &be_const_str_draw_line_dsc_init); -be_define_const_str(_X2Ep2, ".p2", 232398067u, 0, 3, &be_const_str_set); -be_define_const_str(_X2Esize, ".size", 1965188224u, 0, 5, NULL); -be_define_const_str(_X2Etapp, ".tapp", 1363391594u, 0, 5, &be_const_str_clear); -be_define_const_str(_X2Ew, ".w", 1255414514u, 0, 2, &be_const_str_set_huesat); -be_define_const_str(_X2F, "/", 705468254u, 0, 1, NULL); -be_define_const_str(_X2F_X2Eautoconf, "/.autoconf", 2212074393u, 0, 10, &be_const_str_CFG_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s); -be_define_const_str(_X2F_X3Frst_X3D, "/?rst=", 580074707u, 0, 6, &be_const_str_ctypes_bytes_dyn); -be_define_const_str(_X2Fac, "/ac", 3904651978u, 0, 3, &be_const_str__X3Cp_X3E_X3Cform_X20id_X3Dreapply_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20); -be_define_const_str(_X2Flights_X2F, "/lights/", 2370247908u, 0, 8, &be_const_str_init_draw_arc_dsc); -be_define_const_str(_X2Fstate_X2F, "/state/", 4226179876u, 0, 7, &be_const_str__X3Cselect_X20name_X3D_X27zip_X27_X3E); -be_define_const_str(_X3A, ":", 1057798253u, 0, 1, &be_const_str_day); -be_define_const_str(_X3C, "<", 957132539u, 0, 1, &be_const_str_LVG_X3A_X20call_X20to_X20unsupported_X20callback); -be_define_const_str(_X3C_X2Fform_X3E_X3C_X2Fp_X3E, "

", 3546571739u, 0, 11, &be_const_str_full_status); -be_define_const_str(_X3C_X2Fselect_X3E_X3Cp_X3E_X3C_X2Fp_X3E, "

", 1863865923u, 0, 16, &be_const_str_file); -be_define_const_str(_X3C_X3D, "<=", 2499223986u, 0, 2, &be_const_str__X3Cp_X3E_X3Cform_X20id_X3Dzip_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20); -be_define_const_str(_X3Cbutton_X20name_X3D_X27reapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3ERe_X2Dapply_X20current_X20configuration_X3C_X2Fbutton_X3E, "", 3147934216u, 0, 82, &be_const_str_False); -be_define_const_str(_X3Cbutton_X20name_X3D_X27zipapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3EApply_X20configuration_X3C_X2Fbutton_X3E, "", 1205771629u, 0, 72, &be_const_str_erase); -be_define_const_str(_X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E, "
", 842307168u, 0, 77, &be_const_str_add_anim); -be_define_const_str(_X3Cinstance_X3A_X20_X25s_X28_X25s_X2C_X20_X25s_X2C_X20_X25s_X29, "Choose a device configuration:
", 1336654704u, 0, 49, &be_const_str_HTTP_POST); -be_define_const_str(_X3Clambda_X3E, "", 607256038u, 0, 8, &be_const_str__X3F); -be_define_const_str(_X3Clegend_X3E_X3Cb_X20title_X3D_X27Autoconfiguration_X27_X3E_X26nbsp_X3BCurrent_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, " Current auto-configuration", 4212500780u, 0, 82, &be_const_str_get_width); -be_define_const_str(_X3Clegend_X3E_X3Cb_X20title_X3D_X27New_X20autoconf_X27_X3E_X26nbsp_X3BSelect_X20new_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, " Select new auto-configuration", 1926223891u, 0, 80, &be_const_str_assert); -be_define_const_str(_X3Coption_X20value_X3D_X27_X25s_X27_X3E_X25s_X3C_X2Foption_X3E, "", 510303524u, 0, 30, NULL); -be_define_const_str(_X3Coption_X20value_X3D_X27reset_X27_X3E_X26lt_X3BRemove_X20autoconf_X26gt_X3B_X3C_X2Foption_X3E, "", 3994619755u, 0, 54, &be_const_str_SERIAL_5E1); -be_define_const_str(_X3Cp_X20style_X3D_X27width_X3A340px_X3B_X27_X3E_X3Cb_X3EException_X3A_X3C_X2Fb_X3E_X3Cbr_X3E_X27_X25s_X27_X3Cbr_X3E_X25s_X3C_X2Fp_X3E, "

Exception:
'%s'
%s

", 4252565082u, 0, 59, &be_const_str_to_gamma); -be_define_const_str(_X3Cp_X3E_X3C_X2Fp_X3E_X3C_X2Ffieldset_X3E_X3Cp_X3E_X3C_X2Fp_X3E, "

", 2052843416u, 0, 25, &be_const_str__X3E_X3D); -be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27ac_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3EAuto_X2Dconfiguration_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E, "

", 2058443583u, 0, 110, &be_const_str_pixel_count); -be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dreapply_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20, "

 (This feature requires an internet connection)

", 2719266486u, 0, 74, NULL); -be_define_const_str(_X3Cp_X3ECurrent_X20configuration_X3A_X20_X3C_X2Fp_X3E_X3Cp_X3E_X3Cb_X3E_X25s_X3C_X2Fb_X3E_X3C_X2Fp_X3E, "

Current configuration:

%s

", 4115655761u, 0, 46, &be_const_str_f); -be_define_const_str(_X3Cselect_X20name_X3D_X27zip_X27_X3E, "

", 1863865923u, 0, 16, &be_const_str_srand); +be_define_const_str(_X3C_X3D, "<=", 2499223986u, 0, 2, &be_const_str_detect); +be_define_const_str(_X3Cbutton_X20name_X3D_X27reapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3ERe_X2Dapply_X20current_X20configuration_X3C_X2Fbutton_X3E, "", 3147934216u, 0, 82, &be_const_str_consume_mono); +be_define_const_str(_X3Cbutton_X20name_X3D_X27zipapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3EApply_X20configuration_X3C_X2Fbutton_X3E, "", 1205771629u, 0, 72, &be_const_str__X3Cp_X3E_X3C_X2Fp_X3E_X3C_X2Ffieldset_X3E_X3Cp_X3E_X3C_X2Fp_X3E); +be_define_const_str(_X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E, "
", 842307168u, 0, 77, NULL); +be_define_const_str(_X3Cinstance_X3A_X20_X25s_X28_X25s_X2C_X20_X25s_X2C_X20_X25s_X29, "Choose a device configuration:
", 1336654704u, 0, 49, &be_const_str__X3F); +be_define_const_str(_X3Clambda_X3E, "", 607256038u, 0, 8, &be_const_str_AudioOutput); +be_define_const_str(_X3Clegend_X3E_X3Cb_X20title_X3D_X27Autoconfiguration_X27_X3E_X26nbsp_X3BCurrent_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, " Current auto-configuration", 4212500780u, 0, 82, &be_const_str_lv_point); +be_define_const_str(_X3Clegend_X3E_X3Cb_X20title_X3D_X27New_X20autoconf_X27_X3E_X26nbsp_X3BSelect_X20new_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, " Select new auto-configuration", 1926223891u, 0, 80, &be_const_str_OPTION_A); +be_define_const_str(_X3Coption_X20value_X3D_X27_X25s_X27_X3E_X25s_X3C_X2Foption_X3E, "", 510303524u, 0, 30, &be_const_str_AXP192); +be_define_const_str(_X3Coption_X20value_X3D_X27reset_X27_X3E_X26lt_X3BRemove_X20autoconf_X26gt_X3B_X3C_X2Foption_X3E, "", 3994619755u, 0, 54, &be_const_str_gc); +be_define_const_str(_X3Cp_X20style_X3D_X27width_X3A340px_X3B_X27_X3E_X3Cb_X3EException_X3A_X3C_X2Fb_X3E_X3Cbr_X3E_X27_X25s_X27_X3Cbr_X3E_X25s_X3C_X2Fp_X3E, "

Exception:
'%s'
%s

", 4252565082u, 0, 59, &be_const_str_RGBW); +be_define_const_str(_X3Cp_X3E_X3C_X2Fp_X3E_X3C_X2Ffieldset_X3E_X3Cp_X3E_X3C_X2Fp_X3E, "

", 2052843416u, 0, 25, &be_const_str_energy_struct); +be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27ac_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3EAuto_X2Dconfiguration_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E, "

", 2058443583u, 0, 110, &be_const_str_loop); +be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dreapply_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20, "

 (This feature requires an internet connection)

", 2719266486u, 0, 74, &be_const_str_connected); +be_define_const_str(_X3Cp_X3ECurrent_X20configuration_X3A_X20_X3C_X2Fp_X3E_X3Cp_X3E_X3Cb_X3E_X25s_X3C_X2Fb_X3E_X3C_X2Fp_X3E, "

Current configuration:

%s

", 4115655761u, 0, 46, &be_const_str_set_matrix_pixel_color); +be_define_const_str(_X3Cselect_X20name_X3D_X27zip_X27_X3E, "

", 1863865923u, 0, 16, &be_const_str_srand); -be_define_const_str(_X3C_X3D, "<=", 2499223986u, 0, 2, &be_const_str_detect); -be_define_const_str(_X3Cbutton_X20name_X3D_X27reapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3ERe_X2Dapply_X20current_X20configuration_X3C_X2Fbutton_X3E, "", 3147934216u, 0, 82, &be_const_str_consume_mono); -be_define_const_str(_X3Cbutton_X20name_X3D_X27zipapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3EApply_X20configuration_X3C_X2Fbutton_X3E, "", 1205771629u, 0, 72, &be_const_str__X3Cp_X3E_X3C_X2Fp_X3E_X3C_X2Ffieldset_X3E_X3Cp_X3E_X3C_X2Fp_X3E); -be_define_const_str(_X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E, "
", 842307168u, 0, 77, NULL); -be_define_const_str(_X3Cinstance_X3A_X20_X25s_X28_X25s_X2C_X20_X25s_X2C_X20_X25s_X29, "Choose a device configuration:
", 1336654704u, 0, 49, &be_const_str__X3F); -be_define_const_str(_X3Clambda_X3E, "", 607256038u, 0, 8, &be_const_str_AudioOutput); -be_define_const_str(_X3Clegend_X3E_X3Cb_X20title_X3D_X27Autoconfiguration_X27_X3E_X26nbsp_X3BCurrent_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, " Current auto-configuration", 4212500780u, 0, 82, &be_const_str_lv_point); -be_define_const_str(_X3Clegend_X3E_X3Cb_X20title_X3D_X27New_X20autoconf_X27_X3E_X26nbsp_X3BSelect_X20new_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, " Select new auto-configuration", 1926223891u, 0, 80, &be_const_str_OPTION_A); -be_define_const_str(_X3Coption_X20value_X3D_X27_X25s_X27_X3E_X25s_X3C_X2Foption_X3E, "", 510303524u, 0, 30, &be_const_str_AXP192); -be_define_const_str(_X3Coption_X20value_X3D_X27reset_X27_X3E_X26lt_X3BRemove_X20autoconf_X26gt_X3B_X3C_X2Foption_X3E, "", 3994619755u, 0, 54, &be_const_str_gc); -be_define_const_str(_X3Cp_X20style_X3D_X27width_X3A340px_X3B_X27_X3E_X3Cb_X3EException_X3A_X3C_X2Fb_X3E_X3Cbr_X3E_X27_X25s_X27_X3Cbr_X3E_X25s_X3C_X2Fp_X3E, "

Exception:
'%s'
%s

", 4252565082u, 0, 59, &be_const_str_RGBW); -be_define_const_str(_X3Cp_X3E_X3C_X2Fp_X3E_X3C_X2Ffieldset_X3E_X3Cp_X3E_X3C_X2Fp_X3E, "

", 2052843416u, 0, 25, &be_const_str_energy_struct); -be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27ac_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3EAuto_X2Dconfiguration_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E, "

", 2058443583u, 0, 110, &be_const_str_loop); -be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dreapply_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20, "

 (This feature requires an internet connection)

", 2719266486u, 0, 74, &be_const_str_connected); -be_define_const_str(_X3Cp_X3ECurrent_X20configuration_X3A_X20_X3C_X2Fp_X3E_X3Cp_X3E_X3Cb_X3E_X25s_X3C_X2Fb_X3E_X3C_X2Fp_X3E, "

Current configuration:

%s

", 4115655761u, 0, 46, &be_const_str_set_matrix_pixel_color); -be_define_const_str(_X3Cselect_X20name_X3D_X27zip_X27_X3E, "

", 1863865923u, 0, 16, &be_const_str_lv_module_init); +be_define_const_str(_X3C_X3D, "<=", 2499223986u, 0, 2, &be_const_str_invalidate); +be_define_const_str(_X3Cbutton_X20name_X3D_X27reapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3ERe_X2Dapply_X20current_X20configuration_X3C_X2Fbutton_X3E, "", 3147934216u, 0, 82, &be_const_str_AudioFileSource); +be_define_const_str(_X3Cbutton_X20name_X3D_X27zipapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3EApply_X20configuration_X3C_X2Fbutton_X3E, "", 1205771629u, 0, 72, NULL); +be_define_const_str(_X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E, "
", 842307168u, 0, 77, &be_const_str_back_forth); +be_define_const_str(_X3Cinstance_X3A_X20_X25s_X28_X25s_X2C_X20_X25s_X2C_X20_X25s_X29, "Choose a device configuration:
", 1336654704u, 0, 49, &be_const_str_detected_X20on_X20bus); +be_define_const_str(_X3Clambda_X3E, "", 607256038u, 0, 8, NULL); +be_define_const_str(_X3Clegend_X3E_X3Cb_X20title_X3D_X27Autoconfiguration_X27_X3E_X26nbsp_X3BCurrent_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, " Current auto-configuration", 4212500780u, 0, 82, &be_const_str__read); +be_define_const_str(_X3Clegend_X3E_X3Cb_X20title_X3D_X27New_X20autoconf_X27_X3E_X26nbsp_X3BSelect_X20new_X20auto_X2Dconfiguration_X3C_X2Fb_X3E_X3C_X2Flegend_X3E, " Select new auto-configuration", 1926223891u, 0, 80, &be_const_str__X3Coption_X20value_X3D_X27reset_X27_X3E_X26lt_X3BRemove_X20autoconf_X26gt_X3B_X3C_X2Foption_X3E); +be_define_const_str(_X3Coption_X20value_X3D_X27_X25s_X27_X3E_X25s_X3C_X2Foption_X3E, "", 510303524u, 0, 30, &be_const_str_fast_loop); +be_define_const_str(_X3Coption_X20value_X3D_X27reset_X27_X3E_X26lt_X3BRemove_X20autoconf_X26gt_X3B_X3C_X2Foption_X3E, "", 3994619755u, 0, 54, &be_const_str__X3D_X3D); +be_define_const_str(_X3Cp_X20style_X3D_X27width_X3A340px_X3B_X27_X3E_X3Cb_X3EException_X3A_X3C_X2Fb_X3E_X3Cbr_X3E_X27_X25s_X27_X3Cbr_X3E_X25s_X3C_X2Fp_X3E, "

Exception:
'%s'
%s

", 4252565082u, 0, 59, NULL); +be_define_const_str(_X3Cp_X3E_X3C_X2Fp_X3E_X3C_X2Ffieldset_X3E_X3Cp_X3E_X3C_X2Fp_X3E, "

", 2052843416u, 0, 25, &be_const_str_reverse_gamma10); +be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27ac_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3EAuto_X2Dconfiguration_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E, "

", 2058443583u, 0, 110, NULL); +be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dreapply_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20, "

 (This feature requires an internet connection)

", 2719266486u, 0, 74, &be_const_str_log10); +be_define_const_str(_X3Cp_X3ECurrent_X20configuration_X3A_X20_X3C_X2Fp_X3E_X3Cp_X3E_X3Cb_X3E_X25s_X3C_X2Fb_X3E_X3C_X2Fp_X3E, "

Current configuration:

%s

", 4115655761u, 0, 46, &be_const_str_p2); +be_define_const_str(_X3Cselect_X20name_X3D_X27zip_X27_X3E, "