From c6673d4081ca4052668a91554c68363cb46ff635 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bub=C3=ADk?= Date: Sat, 27 Feb 2021 22:28:29 +0100 Subject: [PATCH 01/11] new feature: LCD/DLP Projector Serial Control - implemented as XDRV53 - user must configure GPIO pins "DLP Rx" and "DLP Tx" for serial communication - emulates an additional RELAY by sending ON/OFF commands to Projector - continually polls the Projector's state to update virtual RELAY state - blocks RELAY1 in ON state while Projector is running (to protect the lamp) - serial codes for NEC and OPTOMA, ready for more manufacturers - tested with NEC V300W --- BUILDS.md | 1 + 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/my_user_config.h | 3 + tasmota/support_features.ino | 4 +- tasmota/tasmota_configurations.h | 8 + tasmota/tasmota_template.h | 6 + tasmota/xdrv_53_projector_ctrl.h | 66 +++++ tasmota/xdrv_53_projector_ctrl.ino | 455 +++++++++++++++++++++++++++++ tools/decode-status.py | 2 +- 34 files changed, 595 insertions(+), 2 deletions(-) create mode 100644 tasmota/xdrv_53_projector_ctrl.h create mode 100644 tasmota/xdrv_53_projector_ctrl.ino diff --git a/BUILDS.md b/BUILDS.md index 9e4e847d0..f510ee046 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -172,6 +172,7 @@ | USE_TASMOTA_CLIENT | - | - | - | - | - | - | - | | USE_OPENTHERM | - | - | - | - | - | - | - | | USE_MIEL_HVAC | - | - | - | - | - | - | - | +| USE_PROJECTOR_CTRL | - | - | - | - | - | - | - | | USE_AS608 | - | - | - | - | - | - | - | | USE_TCP_BRIDGE | - | - | - | - | - | - | - | zbbridge | | | | | | | | | diff --git a/tasmota/language/af_AF.h b/tasmota/language/af_AF.h index 07e8a88fa..5d5c923b5 100644 --- a/tasmota/language/af_AF.h +++ b/tasmota/language/af_AF.h @@ -769,6 +769,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Herstel" #define D_SENSOR_RC522_RST "RC522 Herstel" diff --git a/tasmota/language/bg_BG.h b/tasmota/language/bg_BG.h index 9f222a84c..a45e9ea27 100644 --- a/tasmota/language/bg_BG.h +++ b/tasmota/language/bg_BG.h @@ -768,6 +768,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset" #define D_SENSOR_RC522_RST "RC522 Rst" diff --git a/tasmota/language/cs_CZ.h b/tasmota/language/cs_CZ.h index 1e9382216..02eaacc0c 100644 --- a/tasmota/language/cs_CZ.h +++ b/tasmota/language/cs_CZ.h @@ -769,6 +769,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset" #define D_SENSOR_RC522_RST "RC522 Rst" diff --git a/tasmota/language/de_DE.h b/tasmota/language/de_DE.h index cde12947c..5f8a42d78 100644 --- a/tasmota/language/de_DE.h +++ b/tasmota/language/de_DE.h @@ -769,6 +769,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset" #define D_SENSOR_RC522_RST "RC522 Rst" diff --git a/tasmota/language/el_GR.h b/tasmota/language/el_GR.h index 7ba39fa04..6d1ecfacf 100644 --- a/tasmota/language/el_GR.h +++ b/tasmota/language/el_GR.h @@ -769,6 +769,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset" #define D_SENSOR_RC522_RST "RC522 Rst" diff --git a/tasmota/language/en_GB.h b/tasmota/language/en_GB.h index 16d37c32c..e1b006c62 100644 --- a/tasmota/language/en_GB.h +++ b/tasmota/language/en_GB.h @@ -769,6 +769,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset" #define D_SENSOR_RC522_RST "RC522 Rst" diff --git a/tasmota/language/es_ES.h b/tasmota/language/es_ES.h index f5e3e8d2a..19b9a9ecb 100644 --- a/tasmota/language/es_ES.h +++ b/tasmota/language/es_ES.h @@ -769,6 +769,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset" #define D_SENSOR_RC522_RST "RC522 Rst" diff --git a/tasmota/language/fr_FR.h b/tasmota/language/fr_FR.h index 1a8eb94fe..bedcdc94b 100644 --- a/tasmota/language/fr_FR.h +++ b/tasmota/language/fr_FR.h @@ -765,6 +765,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset" #define D_SENSOR_RC522_RST "RC522 Rst" diff --git a/tasmota/language/fy_NL.h b/tasmota/language/fy_NL.h index fcb977be1..0a201c9f8 100644 --- a/tasmota/language/fy_NL.h +++ b/tasmota/language/fy_NL.h @@ -769,6 +769,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset" #define D_SENSOR_RC522_RST "RC522 Rst" diff --git a/tasmota/language/he_HE.h b/tasmota/language/he_HE.h index 79cc2c3b8..95636505d 100644 --- a/tasmota/language/he_HE.h +++ b/tasmota/language/he_HE.h @@ -769,6 +769,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset" #define D_SENSOR_RC522_RST "RC522 Rst" diff --git a/tasmota/language/hu_HU.h b/tasmota/language/hu_HU.h index 360a4c17c..cc5ed8cb5 100644 --- a/tasmota/language/hu_HU.h +++ b/tasmota/language/hu_HU.h @@ -769,6 +769,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset" #define D_SENSOR_RC522_RST "RC522 Rst" diff --git a/tasmota/language/it_IT.h b/tasmota/language/it_IT.h index 20b1957f0..066510664 100644 --- a/tasmota/language/it_IT.h +++ b/tasmota/language/it_IT.h @@ -769,6 +769,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 - RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC - TX" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC - RX" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP - Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP - Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD - Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD - Reset" #define D_SENSOR_RC522_RST "RC522 - Reset" diff --git a/tasmota/language/ko_KO.h b/tasmota/language/ko_KO.h index 22f98997b..2d29d9f83 100644 --- a/tasmota/language/ko_KO.h +++ b/tasmota/language/ko_KO.h @@ -769,6 +769,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset" #define D_SENSOR_RC522_RST "RC522 Rst" diff --git a/tasmota/language/nl_NL.h b/tasmota/language/nl_NL.h index 875f25551..0bc949743 100644 --- a/tasmota/language/nl_NL.h +++ b/tasmota/language/nl_NL.h @@ -769,6 +769,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset" #define D_SENSOR_RC522_RST "RC522 Rst" diff --git a/tasmota/language/pl_PL.h b/tasmota/language/pl_PL.h index 825448a04..e29ae3442 100644 --- a/tasmota/language/pl_PL.h +++ b/tasmota/language/pl_PL.h @@ -769,6 +769,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset" #define D_SENSOR_RC522_RST "RC522 Rst" diff --git a/tasmota/language/pt_BR.h b/tasmota/language/pt_BR.h index 68e4e4df1..1d78796da 100644 --- a/tasmota/language/pt_BR.h +++ b/tasmota/language/pt_BR.h @@ -769,6 +769,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset" #define D_SENSOR_RC522_RST "RC522 Rst" diff --git a/tasmota/language/pt_PT.h b/tasmota/language/pt_PT.h index 2f26b2e64..111cefb87 100644 --- a/tasmota/language/pt_PT.h +++ b/tasmota/language/pt_PT.h @@ -769,6 +769,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset" #define D_SENSOR_RC522_RST "RC522 Rst" diff --git a/tasmota/language/ro_RO.h b/tasmota/language/ro_RO.h index e00935295..68c7d66a3 100644 --- a/tasmota/language/ro_RO.h +++ b/tasmota/language/ro_RO.h @@ -769,6 +769,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset" #define D_SENSOR_RC522_RST "RC522 Rst" diff --git a/tasmota/language/ru_RU.h b/tasmota/language/ru_RU.h index c9d8c1166..fb6e9983d 100644 --- a/tasmota/language/ru_RU.h +++ b/tasmota/language/ru_RU.h @@ -769,6 +769,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset" #define D_SENSOR_RC522_RST "RC522 Rst" diff --git a/tasmota/language/sk_SK.h b/tasmota/language/sk_SK.h index b752d20fe..b0360781d 100644 --- a/tasmota/language/sk_SK.h +++ b/tasmota/language/sk_SK.h @@ -769,6 +769,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset" #define D_SENSOR_RC522_RST "RC522 Rst" diff --git a/tasmota/language/sv_SE.h b/tasmota/language/sv_SE.h index 7105f64a9..29c9ec03c 100644 --- a/tasmota/language/sv_SE.h +++ b/tasmota/language/sv_SE.h @@ -769,6 +769,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset" #define D_SENSOR_RC522_RST "RC522 Rst" diff --git a/tasmota/language/tr_TR.h b/tasmota/language/tr_TR.h index a23f686fe..ee6414694 100644 --- a/tasmota/language/tr_TR.h +++ b/tasmota/language/tr_TR.h @@ -769,6 +769,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset" #define D_SENSOR_RC522_RST "RC522 Rst" diff --git a/tasmota/language/uk_UA.h b/tasmota/language/uk_UA.h index 83c78b23f..898550b21 100644 --- a/tasmota/language/uk_UA.h +++ b/tasmota/language/uk_UA.h @@ -769,6 +769,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset" #define D_SENSOR_RC522_RST "RC522 Rst" diff --git a/tasmota/language/vi_VN.h b/tasmota/language/vi_VN.h index 329f7ebe8..6c9a7c671 100644 --- a/tasmota/language/vi_VN.h +++ b/tasmota/language/vi_VN.h @@ -769,6 +769,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset" #define D_SENSOR_RC522_RST "RC522 Rst" diff --git a/tasmota/language/zh_CN.h b/tasmota/language/zh_CN.h index 85e7381c4..3d92dcf30 100644 --- a/tasmota/language/zh_CN.h +++ b/tasmota/language/zh_CN.h @@ -769,6 +769,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset" #define D_SENSOR_RC522_RST "RC522 Rst" diff --git a/tasmota/language/zh_TW.h b/tasmota/language/zh_TW.h index 34ff54547..40abf06f7 100644 --- a/tasmota/language/zh_TW.h +++ b/tasmota/language/zh_TW.h @@ -769,6 +769,8 @@ #define D_SENSOR_IEM3000_RX "iEM3000 RX" #define D_SENSOR_MIEL_HVAC_TX "MiEl HVAC Tx" #define D_SENSOR_MIEL_HVAC_RX "MiEl HVAC Rx" +#define D_SENSOR_PROJECTOR_CTRL_TX "DLP Tx" +#define D_SENSOR_PROJECTOR_CTRL_RX "DLP Rx" #define D_SENSOR_SHELLY_DIMMER_BOOT0 "SHD Boot 0" #define D_SENSOR_SHELLY_DIMMER_RST_INV "SHD Reset" #define D_SENSOR_RC522_RST "RC522 Rst" diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index b35a1c475..188d09343 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -677,6 +677,9 @@ #define USE_TASMOTA_CLIENT_SERIAL_SPEED 57600 // Depends on the sketch that is running on the Uno/Pro Mini //#define USE_OPENTHERM // Add support for OpenTherm (+15k code) //#define USE_MIEL_HVAC // Add support for Mitsubishi Electric HVAC serial interface (+5k code) +//#define USE_PROJECTOR_CTRL // Add support for LCD/DLP Projector serial control interface (+1k code) +//#define USE_PROJECTOR_CTRL_NEC // Use codes for NEC +//#define USE_PROJECTOR_CTRL_OPTOMA // Use codes for OPTOMA //#define USE_AS608 // Add support for AS608 optical and R503 capacitive fingerprint sensor (+3k code) // #define USE_AS608_MESSAGES // Add verbose error messages (+0k4 code) diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index 45ec475fc..04acd2e07 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -718,7 +718,9 @@ void ResponseAppendFeatures(void) #if defined(USE_DISPLAY) && defined(USE_DISPLAY_TM1637) feature7 |= 0x40000000; #endif -// feature7 |= 0x80000000; +#ifdef USE_PROJECTOR_CTRL + feature7 |= 0x80000000; // xdrv_53_projector_ctrl.ino +#endif } static uint32_t feature8 = 0x00000000; diff --git a/tasmota/tasmota_configurations.h b/tasmota/tasmota_configurations.h index e0bf0100e..3838c6126 100644 --- a/tasmota/tasmota_configurations.h +++ b/tasmota/tasmota_configurations.h @@ -178,6 +178,9 @@ //#define USE_TASMOTA_CLIENT // Add support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem) //#define USE_OPENTHERM // Add support for OpenTherm (+15k code) //#define USE_MIEL_HVAC // Add support for Mitsubishi Electric HVAC serial interface (+5k code) +//#define USE_PROJECTOR_CTRL // Add support for LCD/DLP Projector serial control interface (+1k code) +//#define USE_PROJECTOR_CTRL_NEC // Use codes for NEC +//#define USE_PROJECTOR_CTRL_OPTOMA // Use codes for OPTOMA //#define USE_AS608 // Add support for AS608 optical and R503 capacitive fingerprint sensor (+3k4 code) #define USE_ENERGY_SENSOR // Add energy sensors (-14k code) @@ -431,6 +434,8 @@ #undef USE_TASMOTA_CLIENT // Disable support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem) #undef USE_OPENTHERM // Disable support for OpenTherm (+15k code) #undef USE_MIEL_HVAC // Disable support for Mitsubishi Electric HVAC serial interface (+5k code) +#undef USE_PROJECTOR_CTRL // Disable support for LCD/DLP Projector serial control interface + #undef USE_DHT // Disable support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI @@ -560,6 +565,7 @@ #undef USE_TASMOTA_CLIENT // Disable support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem) #undef USE_OPENTHERM // Disable support for OpenTherm (+15k code) #undef USE_MIEL_HVAC // Disable support for Mitsubishi Electric HVAC serial interface (+5k code) +#undef USE_PROJECTOR_CTRL // Disable support for LCD/DLP Projector serial control interface #undef USE_ENERGY_SENSOR // Disable energy sensors #undef USE_ADE7953 // Disable ADE7953 Energy monitor as used on Shelly 2.5 (I2C address 0x38) (+1k5) @@ -699,6 +705,7 @@ #undef USE_TASMOTA_CLIENT // Disable support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem) #undef USE_OPENTHERM // Disable support for OpenTherm (+15k code) #undef USE_MIEL_HVAC // Disable support for Mitsubishi Electric HVAC serial interface (+5k code) +#undef USE_PROJECTOR_CTRL // Disable support for LCD/DLP Projector serial control interface //#undef USE_ENERGY_SENSOR // Disable energy sensors #undef USE_PZEM004T // Disable PZEM004T energy sensor @@ -840,6 +847,7 @@ #undef USE_TASMOTA_CLIENT // Disable support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem) #undef USE_OPENTHERM // Disable support for OpenTherm (+15k code) #undef USE_MIEL_HVAC // Disable support for Mitsubishi Electric HVAC serial interface (+5k code) +#undef USE_PROJECTOR_CTRL // Disable support for LCD/DLP Projector serial control interface #undef USE_AS608 // Disable support for AS608 optical and R503 capacitive fingerprint sensor (+3k4 code) #undef USE_ENERGY_SENSOR // Disable energy sensors diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index 6221c833c..286ebc118 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -150,6 +150,7 @@ enum UserSelectablePins { GPIO_NEOPOOL_TX, GPIO_NEOPOOL_RX, // Sugar Valley RS485 interface GPIO_SDM72_TX, GPIO_SDM72_RX, // SDM72 Serial interface GPIO_TM1637CLK, GPIO_TM1637DIO, // TM1637 interface + GPIO_PROJECTOR_CTRL_TX, GPIO_PROJECTOR_CTRL_RX, // LCD/DLP Projector Serial Control GPIO_SENSOR_END }; enum ProgramSelectablePins { @@ -320,6 +321,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_NEOPOOL_TX "|" D_SENSOR_NEOPOOL_RX "|" D_SENSOR_SDM72_TX "|" D_SENSOR_SDM72_RX "|" D_SENSOR_TM1637_CLK "|" D_SENSOR_TM1637_DIO "|" + D_SENSOR_PROJECTOR_CTRL_TX "|" D_SENSOR_PROJECTOR_CTRL_RX "|" ; const char kSensorNamesFixed[] PROGMEM = @@ -760,6 +762,10 @@ const uint16_t kGpioNiceList[] PROGMEM = { AGPIO(GPIO_NEOPOOL_TX), // Sugar Valley RS485 Interface AGPIO(GPIO_NEOPOOL_RX), // Sugar Valley RS485 Interface #endif +#ifdef USE_PROJECTOR_CTRL + AGPIO(GPIO_PROJECTOR_CTRL_TX), // LCD/DLP Projector Serial Control + AGPIO(GPIO_PROJECTOR_CTRL_RX), // LCD/DLP Projector Serial Control +#endif /*-------------------------------------------------------------------------------------------*\ * ESP32 specifics diff --git a/tasmota/xdrv_53_projector_ctrl.h b/tasmota/xdrv_53_projector_ctrl.h new file mode 100644 index 000000000..71683b8c9 --- /dev/null +++ b/tasmota/xdrv_53_projector_ctrl.h @@ -0,0 +1,66 @@ +#ifndef _XDRV53_PROJECTOR_CTRL_H_ +#define _XDRV53_PROJECTOR_CTRL_H_ + +//define RELAY that is forced ON while projector is running +#ifndef PROJECTOR_CTRL_PWR_BY_RELAY +#define PROJECTOR_CTRL_PWR_BY_RELAY 1 +#endif //PROJECTOR_CTRL_PWR_BY_RELAY + +#define PROJECTOR_CTRL_SERIAL_TIMEOUT 10 //up to 254 seconds +#define PROJECTOR_CTRL_SERIAL_BAUDRATE 9600 + +#ifdef USE_PROJECTOR_CTRL_NEC +/* see the serial codes in + * https://www.sharpnecdisplays.eu/p/download/v/5e14a015e26cacae3ae64a422f7f8af4/cp/Products/Projectors/Shared/CommandLists/PDF-ExternalControlManual-english.pdf#page=5 + * tested with NEC V300W + * final cksum byte is appended automatically + */ +#define PROJECTOR_CTRL_LOGNAME "DLP[NEC]" +static const uint8_t projector_ctrl_msg_qry_typ[] = { 0x00, 0xBF, 0x00, 0x00, 0x01, 0x00 }; //page81 +static const uint8_t projector_ctrl_msg_qry_pwr[] = { 0x00, 0xBF, 0x00, 0x00, 0x01, 0x02 }; //page83 +static const uint8_t projector_ctrl_msg_pwr_on[] = { 0x02, 0x00, 0x00, 0x00, 0x00 }; //page15 +static const uint8_t projector_ctrl_msg_pwr_off[] = { 0x02, 0x01, 0x00, 0x00, 0x00 }; //page16 +static const struct projector_ctrl_command_info_s projector_ctrl_commands[] = { + {PROJECTOR_CTRL_S_QRY_TYPE, &projector_ctrl_msg_qry_typ[0], sizeof(projector_ctrl_msg_qry_typ), + PROJECTOR_CTRL_SERIAL_TIMEOUT, 0x20, 22, 8, 4, 0xA0, 8, 5, 2}, + {PROJECTOR_CTRL_S_QRY_PWR, &projector_ctrl_msg_qry_pwr[0], sizeof(projector_ctrl_msg_qry_pwr), + PROJECTOR_CTRL_SERIAL_TIMEOUT, 0x20, 22, 6, 1, 0xA0, 8, 5, 2}, + {PROJECTOR_CTRL_S_PWR_ON, &projector_ctrl_msg_pwr_on[0], sizeof(projector_ctrl_msg_pwr_on), + PROJECTOR_CTRL_SERIAL_TIMEOUT, 0x22, 6, 0, 1, 0xA2, 8, 5, 2}, + {PROJECTOR_CTRL_S_PWR_OFF, &projector_ctrl_msg_pwr_off[0], sizeof(projector_ctrl_msg_pwr_off), + PROJECTOR_CTRL_SERIAL_TIMEOUT, 0x22, 6, 0, 1, 0xA2, 8, 5, 2} +}; +#define PROJECTOR_CTRL_QRYPWR_ON 0x04 +#define PROJECTOR_CTRL_QRYPWR_COOLING 0x05 + + +#elif defined(USE_PROJECTOR_CTRL_OPTOMA) +/* see the serial codes in + * https://www.optoma.co.uk/uploads/manuals/hd36-m-en-gb.pdf#page=56 + * not really tested with OPTOMA devices + */ +#define PROJECTOR_CTRL_LOGNAME "DLP[OPTOMA]" +static const uint8_t projector_ctrl_msg_qry_typ[] = { 0x7e, 0x30, 0x30, 0x31, 0x32, 0x32, 0x20, 0x31, 0x0d }; //page59 +static const uint8_t projector_ctrl_msg_qry_pwr[] = { 0x7e, 0x30, 0x30, 0x31, 0x32, 0x34, 0x20, 0x31, 0x0d }; //page59 +static const uint8_t projector_ctrl_msg_pwr_on[] = { 0x7e, 0x30, 0x30, 0x30, 0x30, 0x20, 0x31, 0x0d }; //page56 +static const uint8_t projector_ctrl_msg_pwr_off[] = { 0x7e, 0x30, 0x30, 0x30, 0x30, 0x20, 0x30, 0x0d }; //page56 +static const struct projector_ctrl_command_info_s projector_ctrl_commands[] = { + {PROJECTOR_CTRL_S_QRY_TYPE, &projector_ctrl_msg_qry_typ[0], sizeof(projector_ctrl_msg_qry_typ), + PROJECTOR_CTRL_SERIAL_TIMEOUT, 'O', 6, 2, 4, 'I', 5, 4, 1}, + {PROJECTOR_CTRL_S_QRY_PWR, &projector_ctrl_msg_qry_pwr[0], sizeof(projector_ctrl_msg_qry_pwr), + PROJECTOR_CTRL_SERIAL_TIMEOUT, 'O', 3, 2, 1, 'I', 5, 4, 1}, + {PROJECTOR_CTRL_S_PWR_ON, &projector_ctrl_msg_pwr_on[0], sizeof(projector_ctrl_msg_pwr_on), + PROJECTOR_CTRL_SERIAL_TIMEOUT, 'P', 1, 0, 1, 'F', 1, 0, 1}, + {PROJECTOR_CTRL_S_PWR_OFF, &projector_ctrl_msg_pwr_off[0], sizeof(projector_ctrl_msg_pwr_off), + PROJECTOR_CTRL_SERIAL_TIMEOUT, 'P', 1, 0, 1, 'F', 1, 0, 1} +}; +#define PROJECTOR_CTRL_QRYPWR_ON 0x31 +#define PROJECTOR_CTRL_QRYPWR_COOLING 0x31 //placebo + + +#else +#error USE_PROJECTOR_CTRL: No projector type defined +#endif + + +#endif //_XDRV53_PROJECTOR_CTRL_H_ \ No newline at end of file diff --git a/tasmota/xdrv_53_projector_ctrl.ino b/tasmota/xdrv_53_projector_ctrl.ino new file mode 100644 index 000000000..5b3e6849a --- /dev/null +++ b/tasmota/xdrv_53_projector_ctrl.ino @@ -0,0 +1,455 @@ +/* + xdrv_53_projector_ctrl.ino - LCD/DLP Projector Serial Control support for Tasmota + + Copyright (C) 2021 Jan Bubík + Written with the gifts I got from Jesus. + + 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_PROJECTOR_CTRL +/*********************************************************************************************\ + * LCD/DLP Projector Control via serial interface + * https://www.sharpnecdisplays.eu/p/download/v/5e14a015e26cacae3ae64a422f7f8af4/cp/Products/Projectors/Shared/CommandLists/PDF-ExternalControlManual-english.pdf#page=5 + * https://www.optoma.co.uk/uploads/manuals/hd36-m-en-gb.pdf#page=56 +\*********************************************************************************************/ + +#define XDRV_53 53 + +#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) +#define xxstr(s) xstr(s) +#define xstr(s) #s + +enum projector_ctrl_dev_state_e : uint8_t { + PROJECTOR_CTRL_DEV_UNKNOWN=0, + PROJECTOR_CTRL_DEV_PWR_OFF, + PROJECTOR_CTRL_DEV_PWR_ON +}; + +enum projector_ctrl_serial_state_e : uint8_t { + PROJECTOR_CTRL_S_UNCONNECTED=0, + PROJECTOR_CTRL_S_QRY_PWR, + PROJECTOR_CTRL_S_QRY_TYPE, + PROJECTOR_CTRL_S_IDLE, + PROJECTOR_CTRL_S_PWR_ON, + PROJECTOR_CTRL_S_PWR_OFF +}; + +enum projector_ctrl_serial_result_e : uint8_t { + PROJECTOR_CTRL_R_UNKNOWN=0, + PROJECTOR_CTRL_R_PASS, + PROJECTOR_CTRL_R_FAIL +}; + +struct projector_ctrl_command_info_s { + const enum projector_ctrl_serial_state_e command; + const uint8_t *send_codes; + const uint8_t send_len; + const uint8_t timeout_ticks; + const uint8_t pass_first_byte; + const uint8_t pass_len; + const uint8_t pass_value_offset; + const uint8_t pass_value_bytes; + const uint8_t fail_first_byte; + const uint8_t fail_len; + const uint8_t fail_value_offset; + const uint8_t fail_value_bytes; +} __packed; + +#include "xdrv_53_projector_ctrl.h" + +struct projector_ctrl_softc_s { + TasmotaSerial *sc_serial; + uint8_t sc_device; + uint8_t sc_ticks; + enum projector_ctrl_dev_state_e sc_dev_state; + enum projector_ctrl_serial_state_e sc_ser_state; + enum projector_ctrl_serial_result_e sc_ser_result; + enum projector_ctrl_serial_state_e sc_ser_next_cmd; + const struct projector_ctrl_command_info_s *sc_cmd_info; + uint8_t sc_ser_sum; + uint8_t sc_ser_len; + uint32_t sc_ser_value; +} __packed; + +static struct projector_ctrl_softc_s *projector_ctrl_sc = nullptr; + + + +static void +projector_ctrl_pre_init(void) +{ + struct projector_ctrl_softc_s *sc; + int baudrate = PROJECTOR_CTRL_SERIAL_BAUDRATE; + + if (!PinUsed(GPIO_PROJECTOR_CTRL_TX) || !PinUsed(GPIO_PROJECTOR_CTRL_RX)) + return; + + sc = (struct projector_ctrl_softc_s *)malloc(sizeof(*sc)); + if (sc == NULL) { + AddLog_P(LOG_LEVEL_ERROR, PSTR(PROJECTOR_CTRL_LOGNAME ": unable to allocate state")); + return; + } + + memset(sc, 0, sizeof(*sc)); + + sc->sc_serial = new TasmotaSerial(Pin(GPIO_PROJECTOR_CTRL_RX), + Pin(GPIO_PROJECTOR_CTRL_TX), 2); + + if (!sc->sc_serial->begin(baudrate, 2)) { + AddLog_P(LOG_LEVEL_ERROR, PSTR(PROJECTOR_CTRL_LOGNAME ": unable to begin serial " + "(baudrate %d)"), baudrate); + goto del; + } + + if (sc->sc_serial->hardwareSerial()) { + ClaimSerial(); + SetSerial(baudrate, TS_SERIAL_8N1); + } + + sc->sc_device = ++(TasmotaGlobal.devices_present); /* claim a POWER device slot */ + + AddLog_P(LOG_LEVEL_INFO, PSTR(PROJECTOR_CTRL_LOGNAME ": new RELAY%d, polling serial for Projector status"), sc->sc_device); + + projector_ctrl_sc = sc; + return; +del: + delete sc->sc_serial; +free: + free(sc); +} + + + +static void +projector_ctrl_write(struct projector_ctrl_softc_s *sc, const uint8_t *bytes, const size_t len) +{ + TasmotaSerial *serial; + uint8_t cksum; + size_t i; + + cksum = 0; + serial = sc->sc_serial; + + for (i = 0; i < len; i++) { + uint8_t b = bytes[i]; + serial->write(b); + cksum += b; + } +#ifdef USE_PROJECTOR_CTRL_NEC + serial->write(cksum); +#endif +#ifdef DEBUG_PROJECTOR_CTRL + char hex_b[(len + 1) * 2]; + AddLog_P(LOG_LEVEL_DEBUG,PSTR(PROJECTOR_CTRL_LOGNAME ": RAW bytes %s %02x"), + ToHex_P((uint8_t *)bytes, len, hex_b, sizeof(hex_b)), cksum); +#endif //DEBUG_PROJECTOR_CTRL + + serial->flush(); + return; +} + + + +static void +projector_ctrl_request(struct projector_ctrl_softc_s *sc, const uint8_t command) +{ + const struct projector_ctrl_command_info_s *e; + size_t i; + + if ((sc->sc_dev_state!=PROJECTOR_CTRL_DEV_UNKNOWN)&&(sc->sc_ser_state!=PROJECTOR_CTRL_S_IDLE)) { + if ((command!=PROJECTOR_CTRL_S_QRY_PWR)&&(command!=PROJECTOR_CTRL_S_QRY_TYPE)) { + sc->sc_ser_next_cmd=(projector_ctrl_serial_state_e)command; + AddLog_P(LOG_LEVEL_INFO, PSTR(PROJECTOR_CTRL_LOGNAME + ": Serial CMD %02x already running, enqueueing next (%02x)"), sc->sc_ser_state, command); + }; + return; + }; + + for (i = 0; i < nitems(projector_ctrl_commands); i++) { + e = &projector_ctrl_commands[i]; + if (command == e->command){ + sc->sc_cmd_info=e; + sc->sc_ser_len=0; + sc->sc_ser_result=PROJECTOR_CTRL_R_UNKNOWN; + sc->sc_ser_state=(projector_ctrl_serial_state_e)command; + sc->sc_ser_sum=0; + sc->sc_ser_next_cmd=PROJECTOR_CTRL_S_UNCONNECTED; + sc->sc_ticks=0; +#ifdef DEBUG_PROJECTOR_CTRL + AddLog_P(LOG_LEVEL_DEBUG, PSTR(PROJECTOR_CTRL_LOGNAME + ": Sending CMD %02x"), command); +#endif //DEBUG_PROJECTOR_CTRL + projector_ctrl_write(sc,e->send_codes,e->send_len); + return; + } + }; +#ifdef DEBUG_PROJECTOR_CTRL + AddLog_P(LOG_LEVEL_DEBUG, PSTR(PROJECTOR_CTRL_LOGNAME + ": Undefined serial command %02x"), command); +#endif //DEBUG_PROJECTOR_CTRL + return; +} + + + +static uint8_t +projector_ctrl_parse(struct projector_ctrl_softc_s *sc, const uint8_t byte) +{ + enum projector_ctrl_serial_state_e nstate; + const struct projector_ctrl_command_info_s *cmd; + + nstate = sc->sc_ser_state; + + switch (nstate) { + case PROJECTOR_CTRL_S_IDLE: + case PROJECTOR_CTRL_S_UNCONNECTED: +#ifdef DEBUG_PROJECTOR_CTRL + AddLog_P(LOG_LEVEL_DEBUG, PSTR(PROJECTOR_CTRL_LOGNAME + ": Spurious input in state %02x, got %02x, going UNCONNECTED"), nstate, byte); +#endif //DEBUG_PROJECTOR_CTRL + return(PROJECTOR_CTRL_S_UNCONNECTED); + + default: + cmd=sc->sc_cmd_info; + sc->sc_ser_len++; + if (sc->sc_ser_len==1) { + if (byte==cmd->pass_first_byte){ + sc->sc_ser_result=PROJECTOR_CTRL_R_PASS; +#ifdef DEBUG_PROJECTOR_CTRL + AddLog_P(LOG_LEVEL_DEBUG, PSTR(PROJECTOR_CTRL_LOGNAME + ": CMD %02x PASS, 1st byte %02x"), nstate, byte); +#endif //DEBUG_PROJECTOR_CTRL + }else if (byte==cmd->fail_first_byte){ + sc->sc_ser_result=PROJECTOR_CTRL_R_FAIL; +#ifdef DEBUG_PROJECTOR_CTRL + AddLog_P(LOG_LEVEL_DEBUG, PSTR(PROJECTOR_CTRL_LOGNAME + ": CMD %02x FAIL, 1st byte %02x"), nstate, byte); +#endif //DEBUG_PROJECTOR_CTRL + }else{ +#ifdef DEBUG_PROJECTOR_CTRL + AddLog_P(LOG_LEVEL_DEBUG, PSTR(PROJECTOR_CTRL_LOGNAME + ": CMD %02x UNKNOWN, 1st byte %02x, going UNCONNECTED"), nstate, byte); +#endif //DEBUG_PROJECTOR_CTRL + return(PROJECTOR_CTRL_S_UNCONNECTED); + }; + }; + if (sc->sc_ser_result==PROJECTOR_CTRL_R_PASS){ + if (sc->sc_ser_len==(cmd->pass_value_offset+1)) + sc->sc_ser_value=byte; + if ((sc->sc_ser_len>(cmd->pass_value_offset+1))&&(sc->sc_ser_len<=(cmd->pass_value_offset+cmd->pass_value_bytes))) + sc->sc_ser_value=(sc->sc_ser_value<<8)|byte; + if (sc->sc_ser_len==cmd->pass_len){ +#ifdef USE_PROJECTOR_CTRL_NEC + if(sc->sc_ser_sum!=byte){ +#ifdef DEBUG_PROJECTOR_CTRL + AddLog_P(LOG_LEVEL_DEBUG, PSTR(PROJECTOR_CTRL_LOGNAME + ": Failed cksum for CMD %02x. Got %02x bytes, computed cksum: %02x, recevied cksum: %02x, going UNCONNECTED"), + nstate, sc->sc_ser_len, sc->sc_ser_sum, byte); +#endif //DEBUG_PROJECTOR_CTRL + nstate=PROJECTOR_CTRL_S_UNCONNECTED; + } else +#endif //USE_PROJECTOR_CTRL_NEC + { +#ifdef DEBUG_PROJECTOR_CTRL + AddLog_P(LOG_LEVEL_DEBUG, PSTR(PROJECTOR_CTRL_LOGNAME + ": CMD %02x PASS, got %02x bytes, retval %02x, going IDLE"), nstate, sc->sc_ser_len, sc->sc_ser_value); +#endif //DEBUG_PROJECTOR_CTRL + nstate=PROJECTOR_CTRL_S_IDLE; + }; + }; + }; + + if (sc->sc_ser_result==PROJECTOR_CTRL_R_FAIL) { + if (sc->sc_ser_len==(cmd->fail_value_offset+1)) + sc->sc_ser_value=byte; + if ((sc->sc_ser_len>(cmd->fail_value_offset+1))&&(sc->sc_ser_len<=(cmd->fail_value_offset+cmd->fail_value_bytes))) + sc->sc_ser_value=(sc->sc_ser_value<<8)|byte; + if(sc->sc_ser_len==cmd->fail_len){ +#ifdef USE_PROJECTOR_CTRL_NEC + if(sc->sc_ser_sum!=byte){ +#ifdef DEBUG_PROJECTOR_CTRL + AddLog_P(LOG_LEVEL_DEBUG, PSTR(PROJECTOR_CTRL_LOGNAME + ": Failed cksum for CMD %02x. Got %02x bytes, computed cksum: %02x, receied cksum: %02x, going UNCONNECTED"), + nstate, sc->sc_ser_len, sc->sc_ser_sum, byte); +#endif //DEBUG_PROJECTOR_CTRL + nstate=PROJECTOR_CTRL_S_UNCONNECTED; + } else +#endif //USE_PROJECTOR_CTRL_NEC + { +#ifdef DEBUG_PROJECTOR_CTRL + AddLog_P(LOG_LEVEL_DEBUG, PSTR(PROJECTOR_CTRL_LOGNAME + ": CMD %02x FAIL, got %02x bytes, retval %02x, going idle"), nstate, sc->sc_ser_len, sc->sc_ser_value); +#endif //DEBUG_PROJECTOR_CTRL + nstate=PROJECTOR_CTRL_S_IDLE; + }; + }; + }; + +#ifdef USE_PROJECTOR_CTRL_NEC + sc->sc_ser_sum += byte; +#endif //USE_PROJECTOR_CTRL_NEC + + break; + } + return (nstate); +} + + + +static void +projector_ctrl_loop(struct projector_ctrl_softc_s *sc) +{ + TasmotaSerial *serial; + uint8_t oldstate; + serial = sc->sc_serial; + + while (serial->available()) { + yield(); + oldstate = sc->sc_ser_state; + switch (sc->sc_ser_state = (projector_ctrl_serial_state_e)projector_ctrl_parse(sc, serial->read())) { + case PROJECTOR_CTRL_S_UNCONNECTED: + sc->sc_dev_state=PROJECTOR_CTRL_DEV_UNKNOWN; + break; + case PROJECTOR_CTRL_S_IDLE: + if ((oldstate==PROJECTOR_CTRL_S_QRY_PWR)&&(sc->sc_ser_result==PROJECTOR_CTRL_R_PASS)){ + if(((sc->sc_ser_value==PROJECTOR_CTRL_QRYPWR_ON)||(sc->sc_ser_value==PROJECTOR_CTRL_QRYPWR_COOLING))&&(sc->sc_dev_state!=PROJECTOR_CTRL_DEV_PWR_ON)){ + sc->sc_dev_state=PROJECTOR_CTRL_DEV_PWR_ON; + ExecuteCommandPower(sc->sc_device, POWER_ON, SRC_IGNORE); + }; + if(((sc->sc_ser_value!=PROJECTOR_CTRL_QRYPWR_ON)&&(sc->sc_ser_value!=PROJECTOR_CTRL_QRYPWR_COOLING))&&(sc->sc_dev_state!=PROJECTOR_CTRL_DEV_PWR_OFF)){ + sc->sc_dev_state=PROJECTOR_CTRL_DEV_PWR_OFF; + ExecuteCommandPower(sc->sc_device, POWER_OFF, SRC_IGNORE); + }; + }; + if ((oldstate==PROJECTOR_CTRL_S_PWR_ON)&&(sc->sc_ser_result==PROJECTOR_CTRL_R_PASS)) + sc->sc_dev_state=PROJECTOR_CTRL_DEV_PWR_ON; + if ((oldstate==PROJECTOR_CTRL_S_PWR_OFF)&&(sc->sc_ser_result==PROJECTOR_CTRL_R_PASS)) + sc->sc_dev_state=PROJECTOR_CTRL_DEV_PWR_OFF; + if(sc->sc_ser_next_cmd!=PROJECTOR_CTRL_S_UNCONNECTED){ + oldstate=sc->sc_ser_next_cmd; + sc->sc_ser_next_cmd=PROJECTOR_CTRL_S_UNCONNECTED; + projector_ctrl_request(sc,oldstate); + }; + break; + }; + } +} + + + +static void +projector_ctrl_connect(struct projector_ctrl_softc_s *sc) +{ + projector_ctrl_request(sc,PROJECTOR_CTRL_S_QRY_PWR); +} + + + +static void +projector_ctrl_tick(struct projector_ctrl_softc_s *sc) +{ + if(sc->sc_ser_state==PROJECTOR_CTRL_S_IDLE){ + switch (TasmotaGlobal.uptime&0xf) { + case 0: + projector_ctrl_request(sc,PROJECTOR_CTRL_S_QRY_PWR); + break; + case 8: + projector_ctrl_request(sc,PROJECTOR_CTRL_S_QRY_TYPE); + break; + }; + }else if(sc->sc_ticks > sc->sc_cmd_info->timeout_ticks){ + //current CMD has ran out of time, drop connection + AddLog_P(LOG_LEVEL_INFO,PSTR(PROJECTOR_CTRL_LOGNAME ": DISCONNECTED")); + sc->sc_dev_state=PROJECTOR_CTRL_DEV_UNKNOWN; + sc->sc_ser_state=PROJECTOR_CTRL_S_UNCONNECTED; + }; +} + + + +static bool +projector_ctrl_set_power(struct projector_ctrl_softc_s *sc) +{ + if (TasmotaGlobal.active_device==PROJECTOR_CTRL_PWR_BY_RELAY){ + if ((sc->sc_dev_state == PROJECTOR_CTRL_DEV_PWR_ON) && (0==bitRead(XdrvMailbox.index, PROJECTOR_CTRL_PWR_BY_RELAY -1))) { + TasmotaGlobal.power = bitSet(TasmotaGlobal.power,PROJECTOR_CTRL_PWR_BY_RELAY -1); + AddLog_P(LOG_LEVEL_INFO,PSTR(PROJECTOR_CTRL_LOGNAME ": Keep RELAY" xxstr(PROJECTOR_CTRL_PWR_BY_RELAY) " ON")); + } else { + return(false); + }; + } else if (TasmotaGlobal.active_device==sc->sc_device){ + if (bitRead(XdrvMailbox.index, sc->sc_device -1)) { + switch (sc->sc_dev_state) { + case PROJECTOR_CTRL_DEV_UNKNOWN: + TasmotaGlobal.power = bitClear(TasmotaGlobal.power,sc->sc_device -1); + break; + case PROJECTOR_CTRL_DEV_PWR_OFF: + projector_ctrl_request(sc,PROJECTOR_CTRL_S_PWR_ON); + break; + }; + }else{ + if (sc->sc_dev_state == PROJECTOR_CTRL_DEV_PWR_ON) + projector_ctrl_request(sc,PROJECTOR_CTRL_S_PWR_OFF); + }; + } else { + return(false); + }; + return (true); +} + + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xdrv53(uint8_t function) { + bool result; + struct projector_ctrl_softc_s *sc; + + result = false; + sc = projector_ctrl_sc; + + switch (function) { + case FUNC_PRE_INIT: + projector_ctrl_pre_init(); + return (false); + } + + if (sc == NULL) + return (false); + + switch (function) { + case FUNC_LOOP: + projector_ctrl_loop(sc); + break; + + case FUNC_EVERY_SECOND: + sc->sc_ticks++; + if (sc->sc_dev_state!=PROJECTOR_CTRL_DEV_UNKNOWN) + projector_ctrl_tick(sc); + else if ((TasmotaGlobal.uptime&0x7)==0) //each 8 seconds + projector_ctrl_connect(sc); + break; + + case FUNC_SET_DEVICE_POWER: + result = projector_ctrl_set_power(sc); + break; + + } + + return (result); +} + +#endif // USE_PROJECTOR_CTRL \ No newline at end of file diff --git a/tools/decode-status.py b/tools/decode-status.py index bd1f959a8..4e12be5d5 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -247,7 +247,7 @@ a_features = [[ "USE_DISPLAY_ILI9488","USE_DISPLAY_SSD1351","USE_DISPLAY_RA8876","USE_DISPLAY_ST7789", "USE_DISPLAY_SSD1331","USE_UFILESYS","USE_TIMEPROP","USE_PID", "USE_BS814A2","USE_SEESAW_SOIL","USE_WIEGAND","USE_NEOPOOL", - "USE_TOF10120","USE_SDM72","USE_DISPLAY_TM1637","" + "USE_TOF10120","USE_SDM72","USE_DISPLAY_TM1637","USE_PROJECTOR_CTRL" ],[ "","","","", "","","","", From 4d3fda5a745693d471835a7bc97e1442dd9c6fb2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 28 Feb 2021 12:37:02 +0100 Subject: [PATCH 02/11] Add support for NEC and OPTOMA LCD/DLP Projector serial power control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for NEC and OPTOMA LCD/DLP Projector serial power control by Jan Bubík (#11145) --- CHANGELOG.md | 1 + RELEASENOTES.md | 5 +++-- tasmota/my_user_config.h | 6 +++--- tasmota/tasmota_configurations.h | 7 +++---- tasmota/xdrv_53_projector_ctrl.ino | 4 ++++ 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8762f4b97..7ed373e37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file. - Allow MCP230xx pinmode from output to input (#11104) - SML VBUS support (#11125) - Command ``Sensor80 1 <0..7>`` to control MFRC522 RFID antenna gain from 18dB (0) to 48dB (7) (#11073) +- Support for NEC and OPTOMA LCD/DLP Projector serial power control by Jan Bubík (#11145) ### Changed - TuyaMcu dimmer timeout (#11121) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index aebea7960..be8fe4f20 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -80,9 +80,10 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota ## Changelog v9.3.1.1 ### Added -- Allow MCP230xx pinmode from output to input [#11104](https://github.com/arendst/Tasmota/issues/11104) -- SML VBUS support [#11125](https://github.com/arendst/Tasmota/issues/11125) - Command ``Sensor80 1 <0..7>`` to control MFRC522 RFID antenna gain from 18dB (0) to 48dB (7) [#11073](https://github.com/arendst/Tasmota/issues/11073) +- Support for SML VBUS [#11125](https://github.com/arendst/Tasmota/issues/11125) +- Support for NEC and OPTOMA LCD/DLP Projector serial power control by Jan Bubík [#11145](https://github.com/arendst/Tasmota/issues/11145) +- Allow MCP230xx pinmode from output to input [#11104](https://github.com/arendst/Tasmota/issues/11104) ### Changed - TuyaMcu dimmer timeout [#11121](https://github.com/arendst/Tasmota/issues/11121) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 188d09343..33ced12ed 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -677,9 +677,9 @@ #define USE_TASMOTA_CLIENT_SERIAL_SPEED 57600 // Depends on the sketch that is running on the Uno/Pro Mini //#define USE_OPENTHERM // Add support for OpenTherm (+15k code) //#define USE_MIEL_HVAC // Add support for Mitsubishi Electric HVAC serial interface (+5k code) -//#define USE_PROJECTOR_CTRL // Add support for LCD/DLP Projector serial control interface (+1k code) -//#define USE_PROJECTOR_CTRL_NEC // Use codes for NEC -//#define USE_PROJECTOR_CTRL_OPTOMA // Use codes for OPTOMA +//#define USE_PROJECTOR_CTRL // Add support for LCD/DLP Projector serial control interface (+2k code) +// #define USE_PROJECTOR_CTRL_NEC // Use codes for NEC +// #define USE_PROJECTOR_CTRL_OPTOMA // Use codes for OPTOMA //#define USE_AS608 // Add support for AS608 optical and R503 capacitive fingerprint sensor (+3k code) // #define USE_AS608_MESSAGES // Add verbose error messages (+0k4 code) diff --git a/tasmota/tasmota_configurations.h b/tasmota/tasmota_configurations.h index 3838c6126..c4956bdbd 100644 --- a/tasmota/tasmota_configurations.h +++ b/tasmota/tasmota_configurations.h @@ -178,9 +178,9 @@ //#define USE_TASMOTA_CLIENT // Add support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem) //#define USE_OPENTHERM // Add support for OpenTherm (+15k code) //#define USE_MIEL_HVAC // Add support for Mitsubishi Electric HVAC serial interface (+5k code) -//#define USE_PROJECTOR_CTRL // Add support for LCD/DLP Projector serial control interface (+1k code) -//#define USE_PROJECTOR_CTRL_NEC // Use codes for NEC -//#define USE_PROJECTOR_CTRL_OPTOMA // Use codes for OPTOMA +//#define USE_PROJECTOR_CTRL // Add support for LCD/DLP Projector serial control interface (+2k code) +// #define USE_PROJECTOR_CTRL_NEC // Use codes for NEC +// #define USE_PROJECTOR_CTRL_OPTOMA // Use codes for OPTOMA //#define USE_AS608 // Add support for AS608 optical and R503 capacitive fingerprint sensor (+3k4 code) #define USE_ENERGY_SENSOR // Add energy sensors (-14k code) @@ -436,7 +436,6 @@ #undef USE_MIEL_HVAC // Disable support for Mitsubishi Electric HVAC serial interface (+5k code) #undef USE_PROJECTOR_CTRL // Disable support for LCD/DLP Projector serial control interface - #undef USE_DHT // Disable support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI #undef USE_MAX31865 // Disable support for MAX31865 RTD sensors using softSPI diff --git a/tasmota/xdrv_53_projector_ctrl.ino b/tasmota/xdrv_53_projector_ctrl.ino index 5b3e6849a..7f0c28bf5 100644 --- a/tasmota/xdrv_53_projector_ctrl.ino +++ b/tasmota/xdrv_53_projector_ctrl.ino @@ -27,6 +27,10 @@ #define XDRV_53 53 +#ifndef USE_PROJECTOR_CTRL_NEC +#define USE_PROJECTOR_CTRL_NEC // Use at least one projector +#endif + #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) #define xxstr(s) xstr(s) #define xstr(s) #s From 89d8fbb0ec756290ddc422e08b209c586f59dca4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 28 Feb 2021 12:50:02 +0100 Subject: [PATCH 03/11] Change ARRAY_SIZE() to nitems() --- tasmota/settings.ino | 2 +- tasmota/support.ino | 26 +++++++++---------- tasmota/support_command.ino | 18 ++++++------- tasmota/support_tasmota.ino | 10 ++++---- tasmota/tasmota.ino | 2 +- tasmota/tasmota_ca.ino | 2 +- tasmota/tasmota_globals.h | 6 ++--- tasmota/xdrv_01_webserver.ino | 20 +++++++-------- tasmota/xdrv_02_mqtt.ino | 4 +-- tasmota/xdrv_10_scripter.ino | 2 +- tasmota/xdrv_16_tuyamcu.ino | 10 ++++---- tasmota/xdrv_23_zigbee_2_devices.ino | 8 +++--- tasmota/xdrv_23_zigbee_4_persistence.ino | 2 +- tasmota/xdrv_23_zigbee_5_converters.ino | 20 +++++++-------- tasmota/xdrv_23_zigbee_7_0_statemachine.ino | 6 ++--- tasmota/xdrv_23_zigbee_8_parsers.ino | 14 +++++------ tasmota/xdrv_23_zigbee_A_impl.ino | 4 +-- tasmota/xdrv_41_tcp_bridge.ino | 12 ++++----- tasmota/xnrg_18_sdm72.ino | 2 +- tasmota/xsns_53_sml.ino | 2 +- tasmota/xsns_83_neopool.ino | 28 ++++++++++----------- 21 files changed, 99 insertions(+), 101 deletions(-) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index d4857bb15..fe5316e9f 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -744,7 +744,7 @@ void SettingsDefaultSet2(void) { Settings.module = MODULE; Settings.fallback_module = FALLBACK_MODULE; ModuleDefault(WEMOS); -// for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) { Settings.my_gp.io[i] = GPIO_NONE; } +// for (uint32_t i = 0; i < nitems(Settings.my_gp.io); i++) { Settings.my_gp.io[i] = GPIO_NONE; } SettingsUpdateText(SET_FRIENDLYNAME1, PSTR(FRIENDLY_NAME)); SettingsUpdateText(SET_FRIENDLYNAME2, PSTR(FRIENDLY_NAME"2")); SettingsUpdateText(SET_FRIENDLYNAME3, PSTR(FRIENDLY_NAME"3")); diff --git a/tasmota/support.ino b/tasmota/support.ino index 0cb0daf5a..d5ba2d914 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -1237,7 +1237,7 @@ int ResponseJsonEndEnd(void) #ifdef ESP8266 uint16_t GpioConvert(uint8_t gpio) { - if (gpio >= ARRAY_SIZE(kGpioConvert)) { + if (gpio >= nitems(kGpioConvert)) { return AGPIO(GPIO_USER); } return pgm_read_word(kGpioConvert + gpio); @@ -1285,7 +1285,7 @@ void ConvertGpios(void) { void DumpConvertTable(void) { bool jsflg = false; uint32_t lines = 1; - for (uint32_t i = 0; i < ARRAY_SIZE(kGpioConvert); i++) { + for (uint32_t i = 0; i < nitems(kGpioConvert); i++) { uint32_t data = pgm_read_word(kGpioConvert + i); if (!jsflg) { Response_P(PSTR("{\"GPIOConversion%d\":{"), lines); @@ -1293,14 +1293,14 @@ void DumpConvertTable(void) { ResponseAppend_P(PSTR(",")); } jsflg = true; - if ((ResponseAppend_P(PSTR("\"%d\":\"%d\""), i, data) > (MAX_LOGSZ - TOPSZ)) || (i == ARRAY_SIZE(kGpioConvert) -1)) { + if ((ResponseAppend_P(PSTR("\"%d\":\"%d\""), i, data) > (MAX_LOGSZ - TOPSZ)) || (i == nitems(kGpioConvert) -1)) { ResponseJsonEndEnd(); MqttPublishPrefixTopic_P(RESULT_OR_STAT, XdrvMailbox.command); jsflg = false; lines++; } } - for (uint32_t i = 0; i < ARRAY_SIZE(kAdcNiceList); i++) { + for (uint32_t i = 0; i < nitems(kAdcNiceList); i++) { uint32_t data = pgm_read_word(kAdcNiceList + i); if (!jsflg) { Response_P(PSTR("{\"ADC0Conversion%d\":{"), lines); @@ -1308,7 +1308,7 @@ void DumpConvertTable(void) { ResponseAppend_P(PSTR(",")); } jsflg = true; - if ((ResponseAppend_P(PSTR("\"%d\":\"%d\""), i, data) > (MAX_LOGSZ - TOPSZ)) || (i == ARRAY_SIZE(kAdcNiceList) -1)) { + if ((ResponseAppend_P(PSTR("\"%d\":\"%d\""), i, data) > (MAX_LOGSZ - TOPSZ)) || (i == nitems(kAdcNiceList) -1)) { ResponseJsonEndEnd(); MqttPublishPrefixTopic_P(RESULT_OR_STAT, XdrvMailbox.command); jsflg = false; @@ -1328,7 +1328,7 @@ int ICACHE_RAM_ATTR Pin(uint32_t gpio, uint32_t index) { real_gpio += index; mask = 0xFFFF; } - for (uint32_t i = 0; i < ARRAY_SIZE(TasmotaGlobal.gpio_pin); i++) { + for (uint32_t i = 0; i < nitems(TasmotaGlobal.gpio_pin); i++) { if ((TasmotaGlobal.gpio_pin[i] & mask) == real_gpio) { return i; // Pin number configured for gpio } @@ -1342,7 +1342,7 @@ bool PinUsed(uint32_t gpio, uint32_t index) { } uint32_t GetPin(uint32_t lpin) { - if (lpin < ARRAY_SIZE(TasmotaGlobal.gpio_pin)) { + if (lpin < nitems(TasmotaGlobal.gpio_pin)) { return TasmotaGlobal.gpio_pin[lpin]; } else { return GPIO_NONE; @@ -1466,7 +1466,7 @@ void GetInternalTemplate(void* ptr, uint32_t module, uint32_t option) { void TemplateGpios(myio *gp) { uint16_t *dest = (uint16_t *)gp; - uint16_t src[ARRAY_SIZE(Settings.user_template.gp.io)]; + uint16_t src[nitems(Settings.user_template.gp.io)]; memset(dest, GPIO_NONE, sizeof(myio)); if (USER_MODULE == Settings.module) { @@ -1484,7 +1484,7 @@ void TemplateGpios(myio *gp) // AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t *)&src, sizeof(mycfgio)); uint32_t j = 0; - for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) { + for (uint32_t i = 0; i < nitems(Settings.user_template.gp.io); i++) { if (6 == i) { j = 9; } if (8 == i) { j = 12; } dest[j] = src[i]; @@ -1600,7 +1600,7 @@ bool JsonTemplate(char* dataBuf) uint8_t template8[sizeof(mytmplt8285)] = { GPIO_NONE }; if (13 == arr.size()) { // Possible old template uint32_t gpio = 0; - for (uint32_t i = 0; i < ARRAY_SIZE(template8) -1; i++) { + for (uint32_t i = 0; i < nitems(template8) -1; i++) { gpio = arr[i].getUInt(); if (gpio > 255) { // New templates might have values above 255 break; @@ -1615,13 +1615,13 @@ bool JsonTemplate(char* dataBuf) val = root[PSTR(D_JSON_FLAG)]; if (val) { - template8[ARRAY_SIZE(template8) -1] = val.getUInt() & 0x0F; + template8[nitems(template8) -1] = val.getUInt() & 0x0F; } TemplateConvert(template8, Settings.user_template.gp.io); Settings.user_template.flag.data = 0; } else { #endif - for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) { + for (uint32_t i = 0; i < nitems(Settings.user_template.gp.io); i++) { JsonParserToken val = arr[i]; if (!val) { break; } uint16_t gpio = val.getUInt(); @@ -1657,7 +1657,7 @@ void TemplateJson(void) // AddLogBufferSize(LOG_LEVEL_DEBUG, (uint8_t*)&Settings.user_template, sizeof(Settings.user_template) / 2, 2); Response_P(PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), SettingsText(SET_TEMPLATE_NAME)); - for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) { + for (uint32_t i = 0; i < nitems(Settings.user_template.gp.io); i++) { uint16_t gpio = Settings.user_template.gp.io[i]; if (gpio == AGPIO(GPIO_USER)) { gpio = AGPIO(GPIO_NONE) +1; diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 5dc9e9eaa..1a16279ad 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -1156,7 +1156,7 @@ void CmndModule(void) Settings.module = XdrvMailbox.payload; SetModuleType(); if (Settings.last_module != XdrvMailbox.payload) { - for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) { + for (uint32_t i = 0; i < nitems(Settings.my_gp.io); i++) { Settings.my_gp.io[i] = GPIO_NONE; } } @@ -1200,12 +1200,12 @@ void CmndModules(void) void CmndGpio(void) { - if (XdrvMailbox.index < ARRAY_SIZE(Settings.my_gp.io)) { + if (XdrvMailbox.index < nitems(Settings.my_gp.io)) { myio template_gp; TemplateGpios(&template_gp); if (ValidGPIO(XdrvMailbox.index, template_gp.io[XdrvMailbox.index]) && (XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < AGPIO(GPIO_SENSOR_END))) { bool present = false; - for (uint32_t i = 0; i < ARRAY_SIZE(kGpioNiceList); i++) { + for (uint32_t i = 0; i < nitems(kGpioNiceList); i++) { uint32_t midx = pgm_read_word(kGpioNiceList + i); uint32_t max_midx = ((midx & 0x001F) > 0) ? midx : midx +1; if ((XdrvMailbox.payload >= (midx & 0xFFE0)) && (XdrvMailbox.payload < max_midx)) { @@ -1214,7 +1214,7 @@ void CmndGpio(void) } } if (present) { - for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) { + for (uint32_t i = 0; i < nitems(Settings.my_gp.io); i++) { if (ValidGPIO(i, template_gp.io[i]) && (Settings.my_gp.io[i] == XdrvMailbox.payload)) { Settings.my_gp.io[i] = GPIO_NONE; } @@ -1225,7 +1225,7 @@ void CmndGpio(void) } bool jsflg = false; bool jsflg2 = false; - for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) { + for (uint32_t i = 0; i < nitems(Settings.my_gp.io); i++) { if (ValidGPIO(i, template_gp.io[i]) || ((255 == XdrvMailbox.payload) && !FlashPin(i))) { if (!jsflg) { Response_P(PSTR("{")); @@ -1243,7 +1243,7 @@ void CmndGpio(void) char sindex[4] = { 0 }; uint32_t sensor_name_idx = BGPIO(sensor_type); uint32_t nice_list_search = sensor_type & 0xFFE0; - for (uint32_t j = 0; j < ARRAY_SIZE(kGpioNiceList); j++) { + for (uint32_t j = 0; j < nitems(kGpioNiceList); j++) { uint32_t nls_idx = pgm_read_word(kGpioNiceList + j); if (((nls_idx & 0xFFE0) == nice_list_search) && ((nls_idx & 0x001F) > 0)) { snprintf_P(sindex, sizeof(sindex), PSTR("%d"), (sensor_type & 0x001F) +1); @@ -1310,10 +1310,10 @@ void CmndGpios(void) // DumpConvertTable(); ShowGpios(nullptr, GPIO_SENSOR_END, 0, lines); } else { - ShowGpios(kGpioNiceList, ARRAY_SIZE(kGpioNiceList), 0, lines); + ShowGpios(kGpioNiceList, nitems(kGpioNiceList), 0, lines); #ifdef ESP8266 #ifndef USE_ADC_VCC - ShowGpios(kAdcNiceList, ARRAY_SIZE(kAdcNiceList), 1, lines); + ShowGpios(kAdcNiceList, nitems(kAdcNiceList), 1, lines); #endif // USE_ADC_VCC #endif // ESP8266 } @@ -1345,7 +1345,7 @@ void CmndTemplate(void) } SettingsUpdateText(SET_TEMPLATE_NAME, PSTR("Merged")); uint32_t j = 0; - for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) { + for (uint32_t i = 0; i < nitems(Settings.user_template.gp.io); i++) { if (6 == i) { j = 9; } if (8 == i) { j = 12; } if (TasmotaGlobal.my_module.io[j] > GPIO_NONE) { diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 1e57256e6..9556f5aee 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -1556,7 +1556,7 @@ void GpioInit(void) ConvertGpios(); #endif // ESP8266 - for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) { + for (uint32_t i = 0; i < nitems(Settings.user_template.gp.io); i++) { if ((Settings.user_template.gp.io[i] >= AGPIO(GPIO_SENSOR_END)) && (Settings.user_template.gp.io[i] < AGPIO(GPIO_USER))) { Settings.user_template.gp.io[i] = AGPIO(GPIO_USER); // Fix not supported sensor ids in template } @@ -1564,7 +1564,7 @@ void GpioInit(void) myio template_gp; TemplateGpios(&template_gp); - for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) { + for (uint32_t i = 0; i < nitems(Settings.my_gp.io); i++) { if ((Settings.my_gp.io[i] >= AGPIO(GPIO_SENSOR_END)) && (Settings.my_gp.io[i] < AGPIO(GPIO_USER))) { Settings.my_gp.io[i] = GPIO_NONE; // Fix not supported sensor ids in module } @@ -1576,7 +1576,7 @@ void GpioInit(void) } } - for (uint32_t i = 0; i < ARRAY_SIZE(TasmotaGlobal.my_module.io); i++) { + for (uint32_t i = 0; i < nitems(TasmotaGlobal.my_module.io); i++) { uint32_t mpin = ValidPin(i, TasmotaGlobal.my_module.io[i]); DEBUG_CORE_LOG(PSTR("INI: gpio pin %d, mpin %d"), i, mpin); @@ -1648,7 +1648,7 @@ void GpioInit(void) if (mpin) { SetPin(i, mpin); } // Anything above GPIO_NONE and below GPIO_SENSOR_END } -// AddLogBufferSize(LOG_LEVEL_DEBUG, (uint8_t*)TasmotaGlobal.gpio_pin, ARRAY_SIZE(TasmotaGlobal.gpio_pin), sizeof(TasmotaGlobal.gpio_pin[0])); +// AddLogBufferSize(LOG_LEVEL_DEBUG, (uint8_t*)TasmotaGlobal.gpio_pin, nitems(TasmotaGlobal.gpio_pin), sizeof(TasmotaGlobal.gpio_pin[0])); analogWriteRange(Settings.pwm_range); // Default is 1023 (Arduino.h) analogWriteFreq(Settings.pwm_frequency); // Default is 1000 (core_esp8266_wiring_pwm.c) @@ -1715,7 +1715,7 @@ void GpioInit(void) AddLogSpi(1, Pin(GPIO_SPI_CLK), Pin(GPIO_SPI_MOSI), Pin(GPIO_SPI_MISO)); #endif // USE_SPI - for (uint32_t i = 0; i < ARRAY_SIZE(TasmotaGlobal.my_module.io); i++) { + for (uint32_t i = 0; i < nitems(TasmotaGlobal.my_module.io); i++) { uint32_t mpin = ValidPin(i, TasmotaGlobal.my_module.io[i]); // AddLog(LOG_LEVEL_DEBUG, PSTR("INI: gpio pin %d, mpin %d"), i, mpin); if (AGPIO(GPIO_OUTPUT_HI) == mpin) { diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index c0b7b4669..637d2b84b 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -307,7 +307,7 @@ void setup(void) { TasmotaGlobal.no_autoexec = true; } if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +3) { // Restarted 5 times - for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) { + for (uint32_t i = 0; i < nitems(Settings.my_gp.io); i++) { Settings.my_gp.io[i] = GPIO_NONE; // Reset user defined GPIO disabling sensors } } diff --git a/tasmota/tasmota_ca.ino b/tasmota/tasmota_ca.ino index 97b79614b..f4982c688 100644 --- a/tasmota/tasmota_ca.ino +++ b/tasmota/tasmota_ca.ino @@ -245,7 +245,7 @@ const br_x509_trust_anchor PROGMEM Tasmota_TA[] = { } }; -const size_t Tasmota_TA_size = ARRAY_SIZE(Tasmota_TA); +const size_t Tasmota_TA_size = nitems(Tasmota_TA); // we add a separate CA for telegram /*********************************************************************************************\ diff --git a/tasmota/tasmota_globals.h b/tasmota/tasmota_globals.h index 9c05574d7..52149943c 100644 --- a/tasmota/tasmota_globals.h +++ b/tasmota/tasmota_globals.h @@ -461,15 +461,13 @@ const char kWebColors[] PROGMEM = #define tmin(a,b) ((a)<(b)?(a):(b)) #define tmax(a,b) ((a)>(b)?(a):(b)) +#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) + #define STR_HELPER(x) #x #ifndef STR #define STR(x) STR_HELPER(x) #endif -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) -#endif - #define AGPIO(x) ((x)<<5) #define BGPIO(x) ((x)>>5) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 4ded970b9..4595f50a2 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -453,7 +453,7 @@ void StartWebserver(int type, IPAddress ipweb) if (!Webserver) { Webserver = new ESP8266WebServer((HTTP_MANAGER == type || HTTP_MANAGER_RESET_ONLY == type) ? 80 : WEB_PORT); // call `Webserver->on()` on each entry - for (uint32_t i=0; iNone (0)}3}2'17'>Button1 (17)}3... + for (uint32_t i = 0; i < nitems(kGpioNiceList); i++) { // GPIO: }2'0'>None (0)}3}2'17'>Button1 (17)}3... if (option && (1 == i)) { WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX, AGPIO(GPIO_USER), PSTR(D_SENSOR_USER)); // }2'255'>User}3 } @@ -1338,7 +1338,7 @@ void WSContentSendNiceLists(uint32_t option) { WSContentSend_P(PSTR("hs=[")); uint32_t midx; bool first_done = false; - for (uint32_t i = 0; i < ARRAY_SIZE(kGpioNiceList); i++) { // hs=[36,68,100,132,168,200,232,264,292,324,356,388,421,453]; + for (uint32_t i = 0; i < nitems(kGpioNiceList); i++) { // hs=[36,68,100,132,168,200,232,264,292,324,356,388,421,453]; midx = pgm_read_word(kGpioNiceList + i); if (midx & 0x001F) { if (first_done) { WSContentSend_P(PSTR(",")); } @@ -1348,7 +1348,7 @@ void WSContentSendNiceLists(uint32_t option) { } #ifdef ESP8266 #ifdef USE_ADC - for (uint32_t i = 0; i < ARRAY_SIZE(kAdcNiceList); i++) { // hs=[36,68,100,132,168,200,232,264,292,324,356,388,421,453]; + for (uint32_t i = 0; i < nitems(kAdcNiceList); i++) { // hs=[36,68,100,132,168,200,232,264,292,324,356,388,421,453]; midx = pgm_read_word(kAdcNiceList + i); if (midx & 0x001F) { if (first_done) { WSContentSend_P(PSTR(",")); } @@ -1366,7 +1366,7 @@ void WSContentSendNiceLists(uint32_t option) { void WSContentSendAdcNiceList(uint32_t option) { char stemp[30]; // Template number and Sensor name WSContentSend_P(PSTR("os=\"")); - for (uint32_t i = 0; i < ARRAY_SIZE(kAdcNiceList); i++) { // GPIO: }2'0'>None}3}2'17'>Analog}3... + for (uint32_t i = 0; i < nitems(kAdcNiceList); i++) { // GPIO: }2'0'>None}3}2'17'>Analog}3... if (option && (1 == i)) { WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX, AGPIO(GPIO_USER), PSTR(D_SENSOR_USER)); // }2'15'>User}3 } @@ -1404,7 +1404,7 @@ void HandleTemplateConfiguration(void) WSContentBegin(200, CT_PLAIN); WSContentSend_P(PSTR("%s}1"), AnyModuleName(module).c_str()); // NAME: Generic - for (uint32_t i = 0; i < ARRAY_SIZE(template_gp.io); i++) { // 17,148,29,149,7,255,255,255,138,255,139,255,255 + for (uint32_t i = 0; i < nitems(template_gp.io); i++) { // 17,148,29,149,7,255,255,255,138,255,139,255,255 if (!FlashPin(i)) { WSContentSend_P(PSTR("%s%d"), (i>0)?",":"", template_gp.io[i]); } @@ -1490,7 +1490,7 @@ void TemplateSaveSettings(void) snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_TEMPLATE " {\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), tmp); uint32_t j = 0; - for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) { + for (uint32_t i = 0; i < nitems(Settings.user_template.gp.io); i++) { if (6 == i) { j = 9; } if (8 == i) { j = 12; } snprintf_P(svalue, sizeof(svalue), PSTR("%s%s%d"), svalue, (i>0)?",":"", WebGetGpioArg(j)); @@ -1549,7 +1549,7 @@ void HandleModuleConfiguration(void) WSContentSendNiceLists(0); - for (uint32_t i = 0; i < ARRAY_SIZE(template_gp.io); i++) { + for (uint32_t i = 0; i < nitems(template_gp.io); i++) { if (ValidGPIO(i, template_gp.io[i])) { WSContentSend_P(PSTR("sk(%d,%d);"), TasmotaGlobal.my_module.io[i], i); // g0 - g17 } @@ -1566,7 +1566,7 @@ void HandleModuleConfiguration(void) WSContentSendStyle(); WSContentSend_P(HTTP_FORM_MODULE, AnyModuleName(MODULE).c_str()); - for (uint32_t i = 0; i < ARRAY_SIZE(template_gp.io); i++) { + for (uint32_t i = 0; i < nitems(template_gp.io); i++) { if (ValidGPIO(i, template_gp.io[i])) { snprintf_P(stemp, 3, PINS_WEMOS +i*2); WSContentSend_P(PSTR("%s " D_GPIO "%d"), @@ -1592,7 +1592,7 @@ void ModuleSaveSettings(void) myio template_gp; TemplateGpios(&template_gp); String gpios = ""; - for (uint32_t i = 0; i < ARRAY_SIZE(template_gp.io); i++) { + for (uint32_t i = 0; i < nitems(template_gp.io); i++) { if (Settings.last_module != new_module) { Settings.my_gp.io[i] = GPIO_NONE; } else { diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index b90007e44..6be10eb70 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -33,7 +33,7 @@ WiFiClient EspClient; // Wifi Client - non-TLS const char kMqttCommands[] PROGMEM = "|" // No prefix // SetOption synonyms - D_SO_MQTTJSONONLY "|" + D_SO_MQTTJSONONLY "|" #ifdef USE_MQTT_TLS D_SO_MQTTTLS "|" #endif @@ -195,7 +195,7 @@ void MqttInit(void) { #endif #ifdef USE_MQTT_TLS_CA_CERT - tlsClient->setTrustAnchor(Tasmota_TA, ARRAY_SIZE(Tasmota_TA)); + tlsClient->setTrustAnchor(Tasmota_TA, nitems(Tasmota_TA)); #endif // USE_MQTT_TLS_CA_CERT MqttClient.setClient(*tlsClient); diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index 83fd386b8..10a7db17f 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -2676,7 +2676,7 @@ chknext: } } */ - if ((gpiopin < ARRAY_SIZE(TasmotaGlobal.gpio_pin)) && (TasmotaGlobal.gpio_pin[gpiopin] > 0)) { + if ((gpiopin < nitems(TasmotaGlobal.gpio_pin)) && (TasmotaGlobal.gpio_pin[gpiopin] > 0)) { fvar = TasmotaGlobal.gpio_pin[gpiopin]; // skip ] bracket len++; diff --git a/tasmota/xdrv_16_tuyamcu.ino b/tasmota/xdrv_16_tuyamcu.ino index fc2cd861c..22eba70f2 100644 --- a/tasmota/xdrv_16_tuyamcu.ino +++ b/tasmota/xdrv_16_tuyamcu.ino @@ -330,11 +330,11 @@ float TuyaAdjustedTemperature(int16_t packetValue, uint8_t res) break; case 3: return (float)packetValue / 1000.0; - break; + break; default: return (float)packetValue; break; - } + } } /*********************************************************************************************\ * Internal Functions @@ -622,10 +622,10 @@ void LightSerialDuty(uint16_t duty, char *hex_char, uint8_t TuyaIdx) dpid = TuyaGetDpId(TUYA_MCU_FUNC_CT); } else { dpid = TuyaGetDpId(TUYA_MCU_FUNC_DIMMER2); } } - + if (Tuya.ignore_dim && Tuya.ignore_dimmer_cmd_timeout < millis()) { Tuya.ignore_dim = false; - } + } if (duty > 0 && !Tuya.ignore_dim && TuyaSerial && dpid > 0) { if (TuyaIdx == 2 && CTLight) { @@ -955,7 +955,7 @@ void TuyaNormalPowerModePacketProcess(void) uint8_t key1_gpio = Tuya.buffer[7]; bool key1_set = false; bool led1_set = false; - for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) { + for (uint32_t i = 0; i < nitems(Settings.my_gp.io); i++) { if (Settings.my_gp.io[i] == AGPIO(GPIO_LED1)) led1_set = true; else if (Settings.my_gp.io[i] == AGPIO(GPIO_KEY1)) key1_set = true; } diff --git a/tasmota/xdrv_23_zigbee_2_devices.ino b/tasmota/xdrv_23_zigbee_2_devices.ino index 6a6b60655..e349691c7 100644 --- a/tasmota/xdrv_23_zigbee_2_devices.ino +++ b/tasmota/xdrv_23_zigbee_2_devices.ino @@ -100,7 +100,7 @@ Z_Data_Type Z_Data::CharToDataType(char c) { if (c == '_') { return Z_Data_Type::Z_Device; } else { - for (uint32_t i=0; iname_offset)) { continue; } // avoid strcasecmp_P() from crashing if (0 == strcasecmp_P(command, Z_strings + pgm_read_word(&converter->name_offset))) { @@ -690,7 +690,7 @@ const __FlashStringHelper* zigbeeFindAttributeByName(const char *command, // const __FlashStringHelper* zigbeeFindAttributeById(uint16_t cluster, uint16_t attr_id, uint8_t *attr_type, int8_t *multiplier) { - for (uint32_t i = 0; i < ARRAY_SIZE(Z_PostProcess); i++) { + for (uint32_t i = 0; i < nitems(Z_PostProcess); i++) { const Z_AttributeConverter *converter = &Z_PostProcess[i]; uint16_t conv_cluster = CxToCluster(pgm_read_byte(&converter->cluster_short)); uint16_t conv_attr_id = pgm_read_word(&converter->attribute); @@ -1458,7 +1458,7 @@ void ZCLFrame::parseReadAttributes(Z_attribute_list& attr_list) { read_attr_ids[i/2] = attrid; // find the attribute name - for (uint32_t i = 0; i < ARRAY_SIZE(Z_PostProcess); i++) { + for (uint32_t i = 0; i < nitems(Z_PostProcess); i++) { const Z_AttributeConverter *converter = &Z_PostProcess[i]; uint16_t conv_cluster = CxToCluster(pgm_read_byte(&converter->cluster_short)); uint16_t conv_attribute = pgm_read_word(&converter->attribute); @@ -1527,7 +1527,7 @@ void ZCLFrame::parseReadConfigAttributes(Z_attribute_list& attr_list) { // find the attribute name int8_t multiplier = 1; - for (uint32_t i = 0; i < ARRAY_SIZE(Z_PostProcess); i++) { + for (uint32_t i = 0; i < nitems(Z_PostProcess); i++) { const Z_AttributeConverter *converter = &Z_PostProcess[i]; uint16_t conv_cluster = CxToCluster(pgm_read_byte(&converter->cluster_short)); uint16_t conv_attribute = pgm_read_word(&converter->attribute); @@ -1997,7 +1997,7 @@ void Z_postProcessAttributes(uint16_t shortaddr, uint16_t src_ep, class Z_attrib uint8_t map_offset = 0; uint8_t zigbee_type = Znodata; int8_t conv_multiplier; - for (uint32_t i = 0; i < ARRAY_SIZE(Z_PostProcess); i++) { + for (uint32_t i = 0; i < nitems(Z_PostProcess); i++) { const Z_AttributeConverter *converter = &Z_PostProcess[i]; uint16_t conv_cluster = CxToCluster(pgm_read_byte(&converter->cluster_short)); uint16_t conv_attribute = pgm_read_word(&converter->attribute); @@ -2088,7 +2088,7 @@ void Z_postProcessAttributes(uint16_t shortaddr, uint16_t src_ep, class Z_attrib // Internal search function void Z_parseAttributeKey_inner(class Z_attribute & attr, uint16_t preferred_cluster) { // scan attributes to find by name, and retrieve type - for (uint32_t i = 0; i < ARRAY_SIZE(Z_PostProcess); i++) { + for (uint32_t i = 0; i < nitems(Z_PostProcess); i++) { const Z_AttributeConverter *converter = &Z_PostProcess[i]; uint16_t local_attr_id = pgm_read_word(&converter->attribute); uint16_t local_cluster_id = CxToCluster(pgm_read_byte(&converter->cluster_short)); @@ -2177,7 +2177,7 @@ bool Z_parseAttributeKey(class Z_attribute & attr, uint16_t preferred_cluster) { void Z_Data::toAttributes(Z_attribute_list & attr_list) const { Z_Data_Type type = getType(); // iterate through attributes to see which ones need to be exported - for (uint32_t i = 0; i < ARRAY_SIZE(Z_PostProcess); i++) { + for (uint32_t i = 0; i < nitems(Z_PostProcess); i++) { const Z_AttributeConverter *converter = &Z_PostProcess[i]; uint8_t conv_export = pgm_read_byte(&converter->multiplier_idx) & Z_EXPORT_DATA; uint8_t conv_mapping = pgm_read_byte(&converter->mapping); diff --git a/tasmota/xdrv_23_zigbee_7_0_statemachine.ino b/tasmota/xdrv_23_zigbee_7_0_statemachine.ino index bb50d300c..a9afb9764 100644 --- a/tasmota/xdrv_23_zigbee_7_0_statemachine.ino +++ b/tasmota/xdrv_23_zigbee_7_0_statemachine.ino @@ -438,7 +438,7 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = { 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) @@ -947,7 +947,7 @@ void ZigbeeGotoLabel(uint8_t label) { uint8_t cur_d8 = 0; uint8_t cur_instr_len = 1; // size of current instruction in words - for (uint32_t i = 0; i < ARRAY_SIZE(zb_prog); i += cur_instr_len) { + for (uint32_t i = 0; i < nitems(zb_prog); i += cur_instr_len) { const Zigbee_Instruction *cur_instr_line = &zb_prog[i]; cur_instr = pgm_read_byte(&cur_instr_line->i.i); cur_d8 = pgm_read_byte(&cur_instr_line->i.d8); @@ -1006,7 +1006,7 @@ void ZigbeeStateMachine_Run(void) { zigbee.recv_until = false; zigbee.state_no_timeout = false; // reset the no_timeout for next instruction - if (zigbee.pc > ARRAY_SIZE(zb_prog)) { + if (zigbee.pc > nitems(zb_prog)) { AddLog(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Invalid pc: %d, aborting"), zigbee.pc); zigbee.pc = -1; } diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index 04fed0f57..39db75771 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -207,7 +207,7 @@ void EnergyScanResults(void) { uint32_t bars = changeUIntScale(energy_unsigned, bar_min + 0x80, bar_max + 0x80, 0, bar_count); for (uint32_t j = 0; j < bars; j++) { bar_str[j] = '#'; } bar_str[bars] = 0; - + AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Channel %2d: %s"), i + USE_ZIGBEE_CHANNEL_MIN, bar_str); } ResponseAppend_P(PSTR("]}")); @@ -667,7 +667,7 @@ const uint8_t Z_bindings[] PROGMEM = { int32_t Z_ClusterToCxBinding(uint16_t cluster) { uint8_t cx = ClusterToCx(cluster); - for (uint32_t i=0; i 0xFEFF) ? uxy[i] : 0xFEFF; } diff --git a/tasmota/xdrv_23_zigbee_A_impl.ino b/tasmota/xdrv_23_zigbee_A_impl.ino index 870315055..fc8bfdc3c 100644 --- a/tasmota/xdrv_23_zigbee_A_impl.ino +++ b/tasmota/xdrv_23_zigbee_A_impl.ino @@ -622,7 +622,7 @@ void ZbSendRead(JsonParserToken val_attr, ZCLMessage & zcl) { bool found = false; // scan attributes to find by name, and retrieve type - for (uint32_t i = 0; i < ARRAY_SIZE(Z_PostProcess); i++) { + for (uint32_t i = 0; i < nitems(Z_PostProcess); i++) { const Z_AttributeConverter *converter = &Z_PostProcess[i]; uint16_t local_attr_id = pgm_read_word(&converter->attribute); uint16_t local_cluster_id = CxToCluster(pgm_read_byte(&converter->cluster_short)); @@ -1463,7 +1463,7 @@ void CmndZbPermitJoin(void) { } if (0 == zigbee.permit_end_time) { zigbee.permit_end_time = 1; } // avoid very rare case where timer collides with timestamp equals to zero } - + ResponseCmndDone(); } diff --git a/tasmota/xdrv_41_tcp_bridge.ino b/tasmota/xdrv_41_tcp_bridge.ino index aeadfde61..44a686e77 100644 --- a/tasmota/xdrv_41_tcp_bridge.ino +++ b/tasmota/xdrv_41_tcp_bridge.ino @@ -62,15 +62,15 @@ void TCPLoop(void) if ((server_tcp) && (server_tcp->hasClient())) { // find an empty slot uint32_t i; - for (i=0; iavailable(); break; } } - if (i >= ARRAY_SIZE(client_tcp)) { - i = client_next++ % ARRAY_SIZE(client_tcp); + if (i >= nitems(client_tcp)) { + i = client_next++ % nitems(client_tcp); WiFiClient &client = client_tcp[i]; client.stop(); client = server_tcp->available(); @@ -92,14 +92,14 @@ void TCPLoop(void) if (buf_len > 0) { AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_TCP "from MCU: %*_H"), buf_len, tcp_buf); - for (uint32_t i=0; i 0)) { + if ((gpiopin < nitems(TasmotaGlobal.gpio_pin)) && (TasmotaGlobal.gpio_pin[gpiopin] > 0)) { return true; } return false; diff --git a/tasmota/xsns_83_neopool.ino b/tasmota/xsns_83_neopool.ino index eb7ac25d4..22fc9489b 100644 --- a/tasmota/xsns_83_neopool.ino +++ b/tasmota/xsns_83_neopool.ino @@ -767,7 +767,7 @@ void NeoPool250ms(void) // Every 250 mSec } #endif // DEBUG_TASMOTA_SENSOR - ++neopool_read_state %= ARRAY_SIZE(NeoPoolReg); + ++neopool_read_state %= nitems(NeoPoolReg); #ifdef NEOPOOL_OPTIMIZE_READINGS if (0 == neopool_read_state) { neopool_first_read = false; @@ -795,7 +795,7 @@ void NeoPool250ms(void) // Every 250 mSec #ifdef DEBUG_TASMOTA_SENSOR AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("NEO: notify 0x%04X - addr block 0x%04X ignored"), NeoPoolGetData(MBF_NOTIFICATION), NeoPoolReg[neopool_read_state].addr); #endif // DEBUG_TASMOTA_SENSOR - ++neopool_read_state %= ARRAY_SIZE(NeoPoolReg); + ++neopool_read_state %= nitems(NeoPoolReg); } } #endif // NEOPOOL_OPTIMIZE_READINGS @@ -840,7 +840,7 @@ bool NeoPoolInitData(void) bool res = false; neopool_error = true; - for(uint32_t i=0; i= NeoPoolReg[i].addr && addr < NeoPoolReg[i].addr+NeoPoolReg[i].cnt) { return NeoPoolReg[i].data[addr - NeoPoolReg[i].addr]; } @@ -1206,14 +1206,14 @@ void NeoPoolShow(bool json) } // Filtration mode - GetTextIndexed(stemp, sizeof(stemp), NeoPoolGetData(MBF_PAR_FILT_MODE) < MBV_PAR_FILT_INTELLIGENT ? NeoPoolGetData(MBF_PAR_FILT_MODE) : ARRAY_SIZE(kNeoPoolFiltrationMode)-1, kNeoPoolFiltrationMode); + GetTextIndexed(stemp, sizeof(stemp), NeoPoolGetData(MBF_PAR_FILT_MODE) < MBV_PAR_FILT_INTELLIGENT ? NeoPoolGetData(MBF_PAR_FILT_MODE) : nitems(kNeoPoolFiltrationMode)-1, kNeoPoolFiltrationMode); WSContentSend_PD(HTTP_SNS_NEOPOOL_FILT_MODE, neopool_type, stemp); // Relays for(uint32_t i=0; i<8; i++) { char sdesc[24]; - memset(sdesc, 0, ARRAY_SIZE(sdesc)); - memset(stemp, 0, ARRAY_SIZE(stemp)); + memset(sdesc, 0, nitems(sdesc)); + memset(stemp, 0, nitems(stemp)); if (0 != NeoPoolGetData(MBF_PAR_PH_ACID_RELAY_GPIO) && i == NeoPoolGetData(MBF_PAR_PH_ACID_RELAY_GPIO)-1) { strncpy_P(sdesc, PSTR(D_NEOPOOL_RELAY_PH_ACID), sizeof(sdesc)); } @@ -1306,14 +1306,14 @@ void CmndNeopoolReadReg(void) { uint16_t addr, data[30] = { 0 }, cnt=1; uint32_t value[2] = { 0 }; - uint32_t params_cnt = ParseParameters(ARRAY_SIZE(value), value); + uint32_t params_cnt = ParseParameters(nitems(value), value); bool fbits32 = !strcasecmp_P(XdrvMailbox.command, PSTR(D_PRFX_NEOPOOL D_CMND_NP_READL)); cnt = 1; if (2 == params_cnt) { cnt = value[1]; } - if (params_cnt && cnt < (fbits32 ? (ARRAY_SIZE(data)/2) : ARRAY_SIZE(data))) { + if (params_cnt && cnt < (fbits32 ? (nitems(data)/2) : nitems(data))) { addr = value[0]; if (NEOPOOL_OK != NeoPoolReadRegister(addr, data, fbits32 ? (cnt*2) : cnt)) { NeopoolResponseError(); @@ -1326,8 +1326,8 @@ void CmndNeopoolReadReg(void) void CmndNeopoolWriteReg(void) { uint16_t addr, data[20] = { 0 }, cnt; - uint32_t value[(ARRAY_SIZE(data)/2)+1] = { 0 }; - uint32_t params_cnt = ParseParameters(ARRAY_SIZE(value), value); + uint32_t value[(nitems(data)/2)+1] = { 0 }; + uint32_t params_cnt = ParseParameters(nitems(value), value); bool fbits32 = !strcasecmp_P(XdrvMailbox.command, PSTR(D_PRFX_NEOPOOL D_CMND_NP_WRITEL)); if (params_cnt > 1) { @@ -1359,7 +1359,7 @@ void CmndNeopoolBit(void) uint16_t addr, data; int8_t bit; uint32_t value[3] = { 0 }; - uint32_t params_cnt = ParseParameters(ARRAY_SIZE(value), value); + uint32_t params_cnt = ParseParameters(nitems(value), value); bool fbits32 = !strcasecmp_P(XdrvMailbox.command, PSTR(D_PRFX_NEOPOOL D_CMND_NP_BITL)); uint16_t tempdata[2]; @@ -1457,7 +1457,7 @@ void CmndNeopoolFiltrationMode(void) NeopoolResponseError(); return; } - ResponseCmndChar(GetTextIndexed(stemp, sizeof(stemp), data < MBV_PAR_FILT_INTELLIGENT ? data : ARRAY_SIZE(kNeoPoolFiltrationMode)-1, kNeoPoolFiltrationMode)); + ResponseCmndChar(GetTextIndexed(stemp, sizeof(stemp), data < MBV_PAR_FILT_INTELLIGENT ? data : nitems(kNeoPoolFiltrationMode)-1, kNeoPoolFiltrationMode)); } void CmndNeopoolTime(void) @@ -1508,7 +1508,7 @@ void CmndNeopoolLight(void) return; } if (relay >=1 && relay <=8) { - if (XdrvMailbox.data_len && XdrvMailbox.payload >= 0 && XdrvMailbox.payload < ARRAY_SIZE(timer_val)) { + if (XdrvMailbox.data_len && XdrvMailbox.payload >= 0 && XdrvMailbox.payload < nitems(timer_val)) { addr = MBF_PAR_TIMER_BLOCK_LIGHT_INT + MBV_TIMER_OFFMB_TIMER_ENABLE; data = timer_val[XdrvMailbox.payload]; NeoPoolWriteRegister(MBF_PAR_TIMER_BLOCK_LIGHT_INT + MBV_TIMER_OFFMB_TIMER_ENABLE, &data, 1); From 947c8ccf0ff6f9e9ecdef0011a1e9db820be331d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 28 Feb 2021 15:11:29 +0100 Subject: [PATCH 04/11] Fix light scheme related color changes Fix light scheme related color changes (#11041) --- CHANGELOG.md | 1 + RELEASENOTES.md | 1 + tasmota/xdrv_04_light.ino | 25 ++++++++++++++++++------- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ed373e37..30b7395a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ All notable changes to this project will be documented in this file. - Timer loop when console is scrolled up regression from v9.3.0 (#11108) - Display exception when no file system is present (#11125) - PN532 on ESP32 Serial flush both Tx and Rx buffers (#10910) +- Light scheme related color changes (#11041) ## [Released] diff --git a/RELEASENOTES.md b/RELEASENOTES.md index be8fe4f20..f02d78da4 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -94,3 +94,4 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota - Timer loop when console is scrolled up regression from v9.3.0 [#11108](https://github.com/arendst/Tasmota/issues/11108) - Display exception when no file system is present [#11125](https://github.com/arendst/Tasmota/issues/11125) - PN532 on ESP32 Serial flush both Tx and Rx buffers [#10910](https://github.com/arendst/Tasmota/issues/10910) +- Light scheme related color changes [#11041](https://github.com/arendst/Tasmota/issues/11041) diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 1d78df359..ef13d91eb 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -1083,6 +1083,17 @@ void LightCalcPWMRange(void) { //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LightCalcPWMRange %d %d - %d %d"), Settings.dimmer_hw_min, Settings.dimmer_hw_max, Light.pwm_min, Light.pwm_max); } +void LightSetScheme(uint32_t scheme) { + if (!scheme && Settings.light_scheme) { + if (Light.last_color[0] < 255) { + Light.last_color[0]++; + } else { + Light.last_color[0]--; + } + } + Settings.light_scheme = scheme; +} + void LightInit(void) { // move white blend mode from deprecated `RGBWWTable` to `SetOption105` @@ -1149,7 +1160,7 @@ void LightInit(void) max_scheme = LS_POWER; } if ((LS_WAKEUP == Settings.light_scheme) || (Settings.light_scheme > max_scheme)) { - Settings.light_scheme = LS_POWER; + LightSetScheme(LS_POWER); } Light.power = 0; Light.update = true; @@ -1308,7 +1319,7 @@ void LightSetSignal(uint16_t lo, uint16_t hi, uint16_t value) uint16_t signal = changeUIntScale(value, lo, hi, 0, 255); // 0..255 // AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "Light signal %d"), signal); light_controller.changeRGB(signal, 255 - signal, 0, true); // keep bri - Settings.light_scheme = 0; + LightSetScheme(LS_POWER); if (0 == light_state.getBri()) { light_controller.changeBri(50); } @@ -1668,7 +1679,7 @@ void LightAnimate(void) MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_CMND_WAKEUP)); Light.wakeup_active = 0; - Settings.light_scheme = LS_POWER; + LightSetScheme(LS_POWER); } } break; @@ -2288,7 +2299,7 @@ void LightHandleDevGroupItem(void) uint32_t old_bri = light_state.getBri(); light_controller.changeChannels(Light.entry_color); light_controller.changeBri(old_bri); - Settings.light_scheme = 0; + LightSetScheme(LS_POWER); if (!restore_power && !Light.power) { Light.old_power = Light.power; Light.power = 0xff; @@ -2448,7 +2459,7 @@ void CmndSupportColor(void) #ifdef USE_LIGHT_PALETTE } #endif // USE_LIGHT_PALETTE - Settings.light_scheme = 0; + LightSetScheme(LS_POWER); coldim = true; } else { // Color3, 4, 5 and 6 for (uint32_t i = 0; i < LST_RGB; i++) { @@ -2617,7 +2628,7 @@ void CmndScheme(void) Light.wheel--; #endif // USE_LIGHT_PALETTE } - Settings.light_scheme = XdrvMailbox.payload; + LightSetScheme(XdrvMailbox.payload); if (LS_WAKEUP == Settings.light_scheme) { Light.wakeup_active = 3; } @@ -2640,7 +2651,7 @@ void CmndWakeup(void) light_controller.changeDimmer(XdrvMailbox.payload); } Light.wakeup_active = 3; - Settings.light_scheme = LS_WAKEUP; + LightSetScheme(LS_WAKEUP); LightPowerOn(); ResponseCmndChar(PSTR(D_JSON_STARTED)); } From fd1eb08b6e626fe376f6b392328b24665cd4818e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 28 Feb 2021 15:27:12 +0100 Subject: [PATCH 05/11] Refactor fix light scheme related color changes --- tasmota/xdrv_04_light.ino | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index ef13d91eb..70390e67a 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -1085,11 +1085,7 @@ void LightCalcPWMRange(void) { void LightSetScheme(uint32_t scheme) { if (!scheme && Settings.light_scheme) { - if (Light.last_color[0] < 255) { - Light.last_color[0]++; - } else { - Light.last_color[0]--; - } + Light.update = true; } Settings.light_scheme = scheme; } From 5f75f4619cccdb51613ef38af48c764b8722846e Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Sun, 28 Feb 2021 16:09:57 +0100 Subject: [PATCH 06/11] ssd1351 support for 4 wire spi --- .../Adafruit_SSD1351-gemu-1.0/SSD1351.cpp | 248 ++++++++++-------- .../Adafruit_SSD1351-gemu-1.0/SSD1351.h | 5 +- tasmota/language/af_AF.h | 1 + tasmota/language/bg_BG.h | 1 + tasmota/language/cs_CZ.h | 1 + tasmota/language/de_DE.h | 1 + tasmota/language/el_GR.h | 1 + tasmota/language/en_GB.h | 1 + tasmota/language/es_ES.h | 1 + tasmota/language/fr_FR.h | 1 + tasmota/language/fy_NL.h | 1 + tasmota/language/he_HE.h | 1 + tasmota/language/hu_HU.h | 1 + tasmota/language/it_IT.h | 1 + tasmota/language/ko_KO.h | 1 + tasmota/language/nl_NL.h | 1 + tasmota/language/pl_PL.h | 1 + tasmota/language/pt_BR.h | 1 + tasmota/language/pt_PT.h | 1 + tasmota/language/ro_RO.h | 1 + tasmota/language/ru_RU.h | 1 + tasmota/language/sk_SK.h | 1 + tasmota/language/sv_SE.h | 1 + tasmota/language/tr_TR.h | 1 + tasmota/language/uk_UA.h | 1 + tasmota/language/vi_VN.h | 1 + tasmota/language/zh_CN.h | 1 + tasmota/language/zh_TW.h | 1 + tasmota/tasmota_template.h | 4 +- tasmota/xdsp_09_SSD1351.ino | 17 +- 30 files changed, 192 insertions(+), 108 deletions(-) diff --git a/lib/lib_display/Adafruit_SSD1351-gemu-1.0/SSD1351.cpp b/lib/lib_display/Adafruit_SSD1351-gemu-1.0/SSD1351.cpp index 891a573d5..274b030b2 100644 --- a/lib/lib_display/Adafruit_SSD1351-gemu-1.0/SSD1351.cpp +++ b/lib/lib_display/Adafruit_SSD1351-gemu-1.0/SSD1351.cpp @@ -22,11 +22,12 @@ const uint16_t ssd1351_colors[]={SSD1351_BLACK,SSD1351_WHITE,SSD1351_RED,SSD1351 SSD1351_LIGHTGREY,SSD1351_DARKGREY,SSD1351_ORANGE,SSD1351_GREENYELLOW,SSD1351_PINK}; // Constructor when using software SPI. All output pins are configurable. -SSD1351::SSD1351(int8_t cs,int8_t mosi,int8_t sclk) : Renderer(SSD1351_WIDTH, SSD1351_HEIGHT) { +SSD1351::SSD1351(int8_t cs,int8_t mosi,int8_t sclk, int8_t dc) : Renderer(SSD1351_WIDTH, SSD1351_HEIGHT) { _cs = cs; _mosi = mosi; _sclk = sclk; _hwspi = 0; + _dc = dc; } #ifndef ESP32 @@ -70,27 +71,30 @@ uint32_t ssd1351_mtdo_prev; void SSD1351::spi_lcd_mode_init(void) { uint32 regvalue; - ssd1351_clock_prev=SPI1CLK; - ssd1351_usr_prev=SPI1U; - ssd1351_usr1_prev=SPI1U1; - ssd1351_usr2_prev=SPI1U2; - ssd1351_spi1c_prev=SPI1C; - ssd1351_spi1p_prev=SPI1P; - //ssd1351_gpmux_prev=GPMUX; - ssd1351_mtdo_prev=READ_PERI_REG(PERIPHS_IO_MUX_MTDO_U); + if (_dc >= 0) { + spis = SPISettings(40000000, MSBFIRST, SPI_MODE0); + } else { + ssd1351_clock_prev=SPI1CLK; + ssd1351_usr_prev=SPI1U; + ssd1351_usr1_prev=SPI1U1; + ssd1351_usr2_prev=SPI1U2; + ssd1351_spi1c_prev=SPI1C; + ssd1351_spi1p_prev=SPI1P; + //ssd1351_gpmux_prev=GPMUX; + ssd1351_mtdo_prev=READ_PERI_REG(PERIPHS_IO_MUX_MTDO_U); - SPI1U = SPIUMOSI | SPIUDUPLEX | SPIUSSE; - SPI1U1=0; - SPI1C = 0; + SPI1U = SPIUMOSI | SPIUDUPLEX | SPIUSSE; + SPI1U1=0; + SPI1C = 0; - //bit9 of PERIPHS_IO_MUX should be cleared when HSPI clock doesn't equal CPU clock - //bit8 of PERIPHS_IO_MUX should be cleared when SPI clock doesn't equal CPU clock + //bit9 of PERIPHS_IO_MUX should be cleared when HSPI clock doesn't equal CPU clock + //bit8 of PERIPHS_IO_MUX should be cleared when SPI clock doesn't equal CPU clock - WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105); //clear bit9 + WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105); //clear bit9 //PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);//configure miso to spi mode - PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);//configure mosi to spi mode - PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);//configure sclk to spi mode - PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);//configure cs to spi mode + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);//configure mosi to spi mode + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);//configure sclk to spi mode + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);//configure cs to spi mode // the current implementation leaves about 1 us between transfers ???? // due to lack of documentation i could not find the reason @@ -98,9 +102,9 @@ void SSD1351::spi_lcd_mode_init(void) { //SET_PERI_REG_MASK(SPI_USER(1), SPI_CS_SETUP|SPI_CS_HOLD|SPI_USR_COMMAND); - SET_PERI_REG_MASK(SPI_USER(1), SPI_USR_COMMAND); + SET_PERI_REG_MASK(SPI_USER(1), SPI_USR_COMMAND); - CLEAR_PERI_REG_MASK(SPI_USER(1), SPI_FLASH_MODE); + CLEAR_PERI_REG_MASK(SPI_USER(1), SPI_FLASH_MODE); // SPI clock=CPU clock/8 => 10 Mhz /* WRITE_PERI_REG(SPI_CLOCK(1), @@ -110,47 +114,58 @@ void SSD1351::spi_lcd_mode_init(void) { ((3&SPI_CLKCNT_L)<= 0) { + SPI.beginTransaction(spis); + } else { + while(READ_PERI_REG(SPI_CMD(1))&SPI_USR); + SPI1CLK=ssd1351_clock; + SPI1U=ssd1351_usr; + SPI1U1=ssd1351_usr1; + SPI1U2=ssd1351_usr2; + SPI1C=ssd1351_spi1c; + SPI1P=ssd1351_spi1p; + //GPMUX=ssd1351_gpmux; + WRITE_PERI_REG(PERIPHS_IO_MUX_MTDO_U,ssd1351_mtdo); + } + ssd131_start = 1; } void SSD1351::stop(void) { if (!ssd131_start) return; - //while(SPI1CMD & SPIBUSY) {} - while(READ_PERI_REG(SPI_CMD(1))&SPI_USR); - SPI1CLK=ssd1351_clock_prev; - SPI1U=ssd1351_usr_prev; - SPI1U1=ssd1351_usr1_prev; - SPI1U2=ssd1351_usr2_prev; - SPI1C=ssd1351_spi1c_prev; - SPI1P=ssd1351_spi1p_prev; - //GPMUX=ssd1351_gpmux_prev; - WRITE_PERI_REG(PERIPHS_IO_MUX_MTDO_U,ssd1351_mtdo_prev); - ssd131_start=0; + + if (_dc >= 0) { + SPI.endTransaction(); + } else { + //while(SPI1CMD & SPIBUSY) {} + while(READ_PERI_REG(SPI_CMD(1))&SPI_USR); + SPI1CLK=ssd1351_clock_prev; + SPI1U=ssd1351_usr_prev; + SPI1U1=ssd1351_usr1_prev; + SPI1U2=ssd1351_usr2_prev; + SPI1C=ssd1351_spi1c_prev; + SPI1P=ssd1351_spi1p_prev; + //GPMUX=ssd1351_gpmux_prev; + WRITE_PERI_REG(PERIPHS_IO_MUX_MTDO_U,ssd1351_mtdo_prev); + } + ssd131_start = 0; } // dc = 0 @@ -158,19 +173,23 @@ void SSD1351::writecommand(uint8_t c) { if (_hwspi) { uint32_t regvalue; uint8_t bytetemp; - bytetemp=(c>>1)&0x7f; - start(); - //#define SPI_USR_COMMAND_BITLEN 0x0000000F //#define SPI_USR_COMMAND_BITLEN_S 28 - - regvalue= ((8&SPI_USR_COMMAND_BITLEN)<= 0) { + digitalWrite(_dc, LOW); + SPI.transfer(c); + } else { + bytetemp = (c >> 1) & 0x7f; + regvalue= ((8&SPI_USR_COMMAND_BITLEN)<>1)|0x80; - start(); - regvalue= ((8&SPI_USR_COMMAND_BITLEN)<= 0) { + digitalWrite(_dc, HIGH); + SPI.transfer(d); + } else { + bytetemp = (d >> 1) | 0x80; + regvalue= ((8&SPI_USR_COMMAND_BITLEN)<>= 1) { + if (_dc >= 0) { + digitalWrite(_dc, dc); WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); - if(d&bit) WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); + for(uint8_t bit = 0x80; bit; bit >>= 1) { + WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); + if(d&bit) WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); + else WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_mosi); + WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); + } + } else { + WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); + if(dc) WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); else WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_mosi); WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); + for(uint8_t bit = 0x80; bit; bit >>= 1) { + WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_sclk); + if(d&bit) WRITE_PERI_REG( PIN_OUT_SET, 1<<_mosi); + else WRITE_PERI_REG( PIN_OUT_CLEAR, 1<<_mosi); + WRITE_PERI_REG( PIN_OUT_SET, 1<<_sclk); + } } - WRITE_PERI_REG( PIN_OUT_SET, 1<<_cs); + WRITE_PERI_REG( PIN_OUT_SET, 1 << _cs); } - #else // ESP32 section uint8_t ssd131_start; void SSD1351::writedata(uint8_t d) { - fastSPIwrite(d,1); + fastSPIwrite(d, 1); } void SSD1351::writecommand(uint8_t c) { - fastSPIwrite(c,0); + fastSPIwrite(c, 0); } #include "soc/spi_reg.h" @@ -227,12 +262,10 @@ void SSD1351::writecommand(uint8_t c) { #include "esp32-hal.h" #include "soc/spi_struct.h" -SPISettings oled_spiSettings; - // diconnect from spi void SSD1351::start(void) { if (ssd131_start) return; - SPI.beginTransaction(oled_spiSettings); + SPI.beginTransaction(spis); ssd131_start = 1; } @@ -245,21 +278,25 @@ void SSD1351::stop(void) { // since ardunio transferBits ia completely disfunctional // we use our own hardware driver for 9 bit spi -void SSD1351::fastSPIwrite(uint8_t d,uint8_t dc) { +void SSD1351::fastSPIwrite(uint8_t d, uint8_t dc) { + digitalWrite( _cs, LOW); + if (_dc >= 0) { + digitalWrite(_dc, dc); + SPI.transfer(d); + } else { + uint32_t regvalue = d >> 1; + if (dc) regvalue |= 0x80; + else regvalue &= 0x7f; + if (d & 1) regvalue |= 0x8000; - uint32_t regvalue=d>>1; - if (dc) regvalue|=0x80; - else regvalue&=0x7f; - if (d&1) regvalue|=0x8000; - - REG_SET_BIT(SPI_USER_REG(3), SPI_USR_MOSI); - REG_WRITE(SPI_MOSI_DLEN_REG(3), 9 - 1); - uint32_t *dp=(uint32_t*)SPI_W0_REG(3); - *dp=regvalue; - REG_SET_BIT(SPI_CMD_REG(3), SPI_USR); - while (REG_GET_FIELD(SPI_CMD_REG(3), SPI_USR)); - + REG_SET_BIT(SPI_USER_REG(3), SPI_USR_MOSI); + REG_WRITE(SPI_MOSI_DLEN_REG(3), 9 - 1); + uint32_t *dp=(uint32_t*)SPI_W0_REG(3); + *dp = regvalue; + REG_SET_BIT(SPI_CMD_REG(3), SPI_USR); + while (REG_GET_FIELD(SPI_CMD_REG(3), SPI_USR)); + } digitalWrite( _cs, HIGH); } @@ -312,21 +349,26 @@ void SSD1351::begin(void) { pinMode(_mosi, OUTPUT); digitalWrite(_mosi, LOW); + if (_dc >= 0) { + pinMode(_dc, OUTPUT); + digitalWrite(_dc, LOW); + } + #ifndef ESP32 - if ((_sclk==14) && (_mosi==13) && (_cs==15)) { + if ((_sclk == 14) && (_mosi == 13) && (_cs == 15)) { // we use hardware spi - _hwspi=1; + _hwspi = 1; SPI.begin(); spi_lcd_mode_init(); } else { // we must use software spi - _hwspi=0; + _hwspi = 0; } #else - _hwspi=1; - SPI.begin(_sclk,-1,_mosi, -1); - oled_spiSettings = SPISettings(4500000, MSBFIRST, SPI_MODE3); + _hwspi = 1; + SPI.begin(_sclk, -1, _mosi, -1); + spis = SPISettings(4500000, MSBFIRST, SPI_MODE3); #endif const uint8_t *addr = (const uint8_t *)initList; diff --git a/lib/lib_display/Adafruit_SSD1351-gemu-1.0/SSD1351.h b/lib/lib_display/Adafruit_SSD1351-gemu-1.0/SSD1351.h index d9b05ad0f..ad81fc240 100644 --- a/lib/lib_display/Adafruit_SSD1351-gemu-1.0/SSD1351.h +++ b/lib/lib_display/Adafruit_SSD1351-gemu-1.0/SSD1351.h @@ -93,7 +93,7 @@ class SSD1351 : public Renderer { public: - SSD1351(int8_t cs,int8_t mosi,int8_t sclk); + SSD1351(int8_t cs,int8_t mosi,int8_t sclk, int8_t dc); void begin(void); void DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font); @@ -119,10 +119,11 @@ class SSD1351 : public Renderer { private: uint8_t tabcolor; + SPISettings spis; void fastSPIwrite(uint8_t d,uint8_t dc); void start(void); void stop(void); - int8_t _cs, _mosi, _sclk, _hwspi; + int8_t _cs, _mosi, _sclk, _hwspi, _dc; }; diff --git a/tasmota/language/af_AF.h b/tasmota/language/af_AF.h index 5d5c923b5..1232634c0 100644 --- a/tasmota/language/af_AF.h +++ b/tasmota/language/af_AF.h @@ -783,6 +783,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/language/bg_BG.h b/tasmota/language/bg_BG.h index a45e9ea27..885b5581c 100644 --- a/tasmota/language/bg_BG.h +++ b/tasmota/language/bg_BG.h @@ -782,6 +782,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/language/cs_CZ.h b/tasmota/language/cs_CZ.h index 02eaacc0c..0a529953d 100644 --- a/tasmota/language/cs_CZ.h +++ b/tasmota/language/cs_CZ.h @@ -783,6 +783,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/language/de_DE.h b/tasmota/language/de_DE.h index 5f8a42d78..7372e7ace 100644 --- a/tasmota/language/de_DE.h +++ b/tasmota/language/de_DE.h @@ -783,6 +783,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/language/el_GR.h b/tasmota/language/el_GR.h index 6d1ecfacf..2f8703296 100644 --- a/tasmota/language/el_GR.h +++ b/tasmota/language/el_GR.h @@ -783,6 +783,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/language/en_GB.h b/tasmota/language/en_GB.h index e1b006c62..76001a80f 100644 --- a/tasmota/language/en_GB.h +++ b/tasmota/language/en_GB.h @@ -783,6 +783,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/language/es_ES.h b/tasmota/language/es_ES.h index 19b9a9ecb..7faf7732a 100644 --- a/tasmota/language/es_ES.h +++ b/tasmota/language/es_ES.h @@ -783,6 +783,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/language/fr_FR.h b/tasmota/language/fr_FR.h index bedcdc94b..d77d60dd2 100644 --- a/tasmota/language/fr_FR.h +++ b/tasmota/language/fr_FR.h @@ -779,6 +779,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/language/fy_NL.h b/tasmota/language/fy_NL.h index 0a201c9f8..7edab6b21 100644 --- a/tasmota/language/fy_NL.h +++ b/tasmota/language/fy_NL.h @@ -783,6 +783,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/language/he_HE.h b/tasmota/language/he_HE.h index 95636505d..3898d6c8b 100644 --- a/tasmota/language/he_HE.h +++ b/tasmota/language/he_HE.h @@ -783,6 +783,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/language/hu_HU.h b/tasmota/language/hu_HU.h index cc5ed8cb5..4a12ed438 100644 --- a/tasmota/language/hu_HU.h +++ b/tasmota/language/hu_HU.h @@ -783,6 +783,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/language/it_IT.h b/tasmota/language/it_IT.h index 066510664..db152893a 100644 --- a/tasmota/language/it_IT.h +++ b/tasmota/language/it_IT.h @@ -783,6 +783,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 - CS" #define D_SENSOR_EPAPER42_CS "EPaper42 - CS" #define D_SENSOR_SSD1351_CS "SSD1351 - CS" +#define D_SENSOR_SSD1351_DC "SSD1351 - DC" #define D_SENSOR_RA8876_CS "RA8876 - CS" #define D_SENSOR_ST7789_CS "ST7789 - CS" #define D_SENSOR_ST7789_DC "ST7789 - DC" diff --git a/tasmota/language/ko_KO.h b/tasmota/language/ko_KO.h index 2d29d9f83..679e4860f 100644 --- a/tasmota/language/ko_KO.h +++ b/tasmota/language/ko_KO.h @@ -783,6 +783,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/language/nl_NL.h b/tasmota/language/nl_NL.h index 0bc949743..8c626e06c 100644 --- a/tasmota/language/nl_NL.h +++ b/tasmota/language/nl_NL.h @@ -783,6 +783,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/language/pl_PL.h b/tasmota/language/pl_PL.h index e29ae3442..52fc2a264 100644 --- a/tasmota/language/pl_PL.h +++ b/tasmota/language/pl_PL.h @@ -783,6 +783,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/language/pt_BR.h b/tasmota/language/pt_BR.h index 1d78796da..2612a9b61 100644 --- a/tasmota/language/pt_BR.h +++ b/tasmota/language/pt_BR.h @@ -783,6 +783,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/language/pt_PT.h b/tasmota/language/pt_PT.h index 111cefb87..785ff78a6 100644 --- a/tasmota/language/pt_PT.h +++ b/tasmota/language/pt_PT.h @@ -783,6 +783,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/language/ro_RO.h b/tasmota/language/ro_RO.h index 68c7d66a3..6966df535 100644 --- a/tasmota/language/ro_RO.h +++ b/tasmota/language/ro_RO.h @@ -783,6 +783,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/language/ru_RU.h b/tasmota/language/ru_RU.h index fb6e9983d..a6cae93e6 100644 --- a/tasmota/language/ru_RU.h +++ b/tasmota/language/ru_RU.h @@ -783,6 +783,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/language/sk_SK.h b/tasmota/language/sk_SK.h index b0360781d..b975fd064 100644 --- a/tasmota/language/sk_SK.h +++ b/tasmota/language/sk_SK.h @@ -783,6 +783,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/language/sv_SE.h b/tasmota/language/sv_SE.h index 29c9ec03c..5075803d9 100644 --- a/tasmota/language/sv_SE.h +++ b/tasmota/language/sv_SE.h @@ -783,6 +783,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/language/tr_TR.h b/tasmota/language/tr_TR.h index ee6414694..7591b0d53 100644 --- a/tasmota/language/tr_TR.h +++ b/tasmota/language/tr_TR.h @@ -783,6 +783,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/language/uk_UA.h b/tasmota/language/uk_UA.h index 898550b21..0da2f4f61 100644 --- a/tasmota/language/uk_UA.h +++ b/tasmota/language/uk_UA.h @@ -783,6 +783,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/language/vi_VN.h b/tasmota/language/vi_VN.h index 6c9a7c671..292d8eda4 100644 --- a/tasmota/language/vi_VN.h +++ b/tasmota/language/vi_VN.h @@ -783,6 +783,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/language/zh_CN.h b/tasmota/language/zh_CN.h index 3d92dcf30..03059e7c7 100644 --- a/tasmota/language/zh_CN.h +++ b/tasmota/language/zh_CN.h @@ -783,6 +783,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/language/zh_TW.h b/tasmota/language/zh_TW.h index 40abf06f7..c43366aff 100644 --- a/tasmota/language/zh_TW.h +++ b/tasmota/language/zh_TW.h @@ -783,6 +783,7 @@ #define D_SENSOR_EPAPER29_CS "EPaper29 CS" #define D_SENSOR_EPAPER42_CS "EPaper42 CS" #define D_SENSOR_SSD1351_CS "SSD1351 CS" +#define D_SENSOR_SSD1351_DC "SSD1351 DC" #define D_SENSOR_RA8876_CS "RA8876 CS" #define D_SENSOR_ST7789_CS "ST7789 CS" #define D_SENSOR_ST7789_DC "ST7789 DC" diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index 286ebc118..aee95f754 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -151,6 +151,7 @@ enum UserSelectablePins { GPIO_SDM72_TX, GPIO_SDM72_RX, // SDM72 Serial interface GPIO_TM1637CLK, GPIO_TM1637DIO, // TM1637 interface GPIO_PROJECTOR_CTRL_TX, GPIO_PROJECTOR_CTRL_RX, // LCD/DLP Projector Serial Control + GPIO_SSD1351_DC, GPIO_SENSOR_END }; enum ProgramSelectablePins { @@ -322,6 +323,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_SDM72_TX "|" D_SENSOR_SDM72_RX "|" D_SENSOR_TM1637_CLK "|" D_SENSOR_TM1637_DIO "|" D_SENSOR_PROJECTOR_CTRL_TX "|" D_SENSOR_PROJECTOR_CTRL_RX "|" + D_SENSOR_SSD1351_DC "|" ; const char kSensorNamesFixed[] PROGMEM = @@ -423,6 +425,7 @@ const uint16_t kGpioNiceList[] PROGMEM = { #endif // USE_DISPLAY_EPAPER_42 #ifdef USE_DISPLAY_SSD1351 AGPIO(GPIO_SSD1351_CS), + AGPIO(GPIO_SSD1351_DC), #endif // USE_DISPLAY_SSD1351 #ifdef USE_DISPLAY_RA8876 AGPIO(GPIO_RA8876_CS), @@ -766,7 +769,6 @@ const uint16_t kGpioNiceList[] PROGMEM = { AGPIO(GPIO_PROJECTOR_CTRL_TX), // LCD/DLP Projector Serial Control AGPIO(GPIO_PROJECTOR_CTRL_RX), // LCD/DLP Projector Serial Control #endif - /*-------------------------------------------------------------------------------------------*\ * ESP32 specifics \*-------------------------------------------------------------------------------------------*/ diff --git a/tasmota/xdsp_09_SSD1351.ino b/tasmota/xdsp_09_SSD1351.ino index 0a1957e3a..ea0e5a2fd 100644 --- a/tasmota/xdsp_09_SSD1351.ino +++ b/tasmota/xdsp_09_SSD1351.ino @@ -59,12 +59,25 @@ void SSD1351_InitDriver() { fg_color = SSD1351_WHITE; bg_color = SSD1351_BLACK; + +#ifdef SSD1351_DC + int8_t dcpin = SSD1351_DC; +#else + int8_t dcpin = -1; +#endif + +#ifdef GPIO_SSD1351_DC + if (PinUsed(GPIO_SSD1351_DC)) { + dcpin = Pin(GPIO_SSD1351_DC); + } +#endif + // init renderer if (TasmotaGlobal.soft_spi_enabled){ - ssd1351 = new SSD1351(Pin(GPIO_SSD1351_CS), Pin(GPIO_SSPI_MOSI), Pin(GPIO_SSPI_SCLK)); + ssd1351 = new SSD1351(Pin(GPIO_SSD1351_CS), Pin(GPIO_SSPI_MOSI), Pin(GPIO_SSPI_SCLK), dcpin); } else if (TasmotaGlobal.spi_enabled) { - ssd1351 = new SSD1351(Pin(GPIO_SSD1351_CS), Pin(GPIO_SPI_MOSI), Pin(GPIO_SPI_CLK)); + ssd1351 = new SSD1351(Pin(GPIO_SSD1351_CS), Pin(GPIO_SPI_MOSI), Pin(GPIO_SPI_CLK), dcpin); } delay(100); From ed5dcbe6162dc1fc2e3edab7505180bedc5f35f0 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Sun, 28 Feb 2021 16:19:09 +0100 Subject: [PATCH 07/11] Update xdsp_09_SSD1351.ino --- tasmota/xdsp_09_SSD1351.ino | 2 -- 1 file changed, 2 deletions(-) diff --git a/tasmota/xdsp_09_SSD1351.ino b/tasmota/xdsp_09_SSD1351.ino index ea0e5a2fd..ba8b92c2e 100644 --- a/tasmota/xdsp_09_SSD1351.ino +++ b/tasmota/xdsp_09_SSD1351.ino @@ -66,11 +66,9 @@ void SSD1351_InitDriver() { int8_t dcpin = -1; #endif -#ifdef GPIO_SSD1351_DC if (PinUsed(GPIO_SSD1351_DC)) { dcpin = Pin(GPIO_SSD1351_DC); } -#endif // init renderer if (TasmotaGlobal.soft_spi_enabled){ From 94ab68aed0912d6b3a8f4632e983562af1786ea0 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Sun, 28 Feb 2021 17:08:43 +0100 Subject: [PATCH 08/11] Update xdsp_09_SSD1351.ino --- tasmota/xdsp_09_SSD1351.ino | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/tasmota/xdsp_09_SSD1351.ino b/tasmota/xdsp_09_SSD1351.ino index ba8b92c2e..2b6301449 100644 --- a/tasmota/xdsp_09_SSD1351.ino +++ b/tasmota/xdsp_09_SSD1351.ino @@ -59,23 +59,12 @@ void SSD1351_InitDriver() { fg_color = SSD1351_WHITE; bg_color = SSD1351_BLACK; - -#ifdef SSD1351_DC - int8_t dcpin = SSD1351_DC; -#else - int8_t dcpin = -1; -#endif - - if (PinUsed(GPIO_SSD1351_DC)) { - dcpin = Pin(GPIO_SSD1351_DC); - } - // init renderer if (TasmotaGlobal.soft_spi_enabled){ - ssd1351 = new SSD1351(Pin(GPIO_SSD1351_CS), Pin(GPIO_SSPI_MOSI), Pin(GPIO_SSPI_SCLK), dcpin); + ssd1351 = new SSD1351(Pin(GPIO_SSD1351_CS), Pin(GPIO_SSPI_MOSI), Pin(GPIO_SSPI_SCLK), Pin(GPIO_SSD1351_DC)); } else if (TasmotaGlobal.spi_enabled) { - ssd1351 = new SSD1351(Pin(GPIO_SSD1351_CS), Pin(GPIO_SPI_MOSI), Pin(GPIO_SPI_CLK), dcpin); + ssd1351 = new SSD1351(Pin(GPIO_SSD1351_CS), Pin(GPIO_SPI_MOSI), Pin(GPIO_SPI_CLK), Pin(GPIO_SSD1351_DC)); } delay(100); From b2bc701518f51ef10cb35b0b16d29f3d9ee555e7 Mon Sep 17 00:00:00 2001 From: bovirus <1262554+bovirus@users.noreply.github.com> Date: Sun, 28 Feb 2021 19:02:36 +0100 Subject: [PATCH 09/11] Update Italian language --- tasmota/language/it_IT.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tasmota/language/it_IT.h b/tasmota/language/it_IT.h index db152893a..c522b7981 100644 --- a/tasmota/language/it_IT.h +++ b/tasmota/language/it_IT.h @@ -1,7 +1,7 @@ /* it-IT.h - localization for Italian - Italy for Tasmota - Copyright (C) 2021 Gennaro Tortone - some mods by Antonio Fragola - Updated by bovirus - rev. 12.02.2021 + Copyright (C) 2021 Gennaro Tortone - some mods by Antonio Fragola - Updated by bovirus - rev. 27.02.2021 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 @@ -792,8 +792,8 @@ #define D_SENSOR_SDCARD_CS "Scheda SD - CS" #define D_SENSOR_WIEGAND_D0 "Wiegand - D0" #define D_SENSOR_WIEGAND_D1 "Wiegand - D1" -#define D_SENSOR_NEOPOOL_TX "NeoPool Tx" -#define D_SENSOR_NEOPOOL_RX "NeoPool Rx" +#define D_SENSOR_NEOPOOL_TX "NeoPool - TX" +#define D_SENSOR_NEOPOOL_RX "NeoPool - RX" // Units #define D_UNIT_AMPERE "A" @@ -1001,7 +1001,7 @@ #define D_NEOPOOL_RELAY_FILTRATION "Filtrazione" #define D_NEOPOOL_RELAY_LIGHT "Luce" #define D_NEOPOOL_RELAY_PH_ACID "Pompa per acido" -#define D_NEOPOOL_RELAY_PH_BASE "Popa base" +#define D_NEOPOOL_RELAY_PH_BASE "Pompa base" #define D_NEOPOOL_RELAY_RX "Livello Redox" #define D_NEOPOOL_RELAY_CL "Pompa cloro" #define D_NEOPOOL_RELAY_CD "Pompa salamoia" @@ -1013,7 +1013,7 @@ #define D_NEOPOOL_COVER "Copertura" #define D_NEOPOOL_SHOCK "Shock" #define D_NEOPOOL_ALARM "! " -#define D_NEOPOOL_LOW "Low" +#define D_NEOPOOL_LOW "Bassa" #define D_NEOPOOL_FLOW1 "FL1" #define D_NEOPOOL_FLOW2 "FL2" #define D_NEOPOOL_PH_HIGH "troppo alto" // ph Alarms From 3a3e77215b1372bc88c9db9b6836ce06918b971b Mon Sep 17 00:00:00 2001 From: Simon Hailes Date: Sun, 28 Feb 2021 18:17:38 +0000 Subject: [PATCH 10/11] Align protocol interpretation with MI docs (16 bit payload type). Add ref to MI docs. Add light sense for DOOR. Add HASS discovery for MOST sensor types. --- tasmota/xsns_62_esp32_mi_ble.ino | 418 +++++++++++++++++++++++-------- 1 file changed, 316 insertions(+), 102 deletions(-) diff --git a/tasmota/xsns_62_esp32_mi_ble.ino b/tasmota/xsns_62_esp32_mi_ble.ino index 8b7b760ba..27198c961 100644 --- a/tasmota/xsns_62_esp32_mi_ble.ino +++ b/tasmota/xsns_62_esp32_mi_ble.ino @@ -182,8 +182,7 @@ struct mi_beacon_mac_data_t{ // e.g. 28/08 uint8_t mac[6]; }; struct mi_beacon_payload_data_t{ // - uint8_t type; - uint8_t ten; + uint16_t type; uint8_t size; uint8_t data[16]; }; @@ -286,6 +285,7 @@ struct mi_sensor_t{ uint32_t Btn:1; uint32_t events:1; uint32_t pairing:1; + uint32_t light:1; // binary light sensor }; uint32_t raw; } feature; @@ -303,12 +303,16 @@ struct mi_sensor_t{ uint32_t noMotion:1; uint32_t Btn:1; uint32_t PairBtn:1; + uint32_t light:1; // binary light sensor }; uint32_t raw; } eventType; int RSSI; uint8_t pairing; + int8_t light; // binary light sensor - initialise to -1 + int16_t Btn; // moved so we can initialise to -1 + uint32_t lastTime; uint32_t lux; float temp; //Flora, MJ_HT_V1, LYWSD0x, CGx @@ -325,7 +329,6 @@ struct mi_sensor_t{ uint16_t events; //"alarms" since boot uint32_t NMT; // no motion time in seconds for the MJYD2S }; - uint16_t Btn; }; union { uint8_t bat; // many values seem to be hard-coded garbage (LYWSD0x, GCD1) @@ -1152,6 +1155,21 @@ int MIDecryptPayload(const uint8_t *macin, const uint8_t *nonce, uint32_t tag, u // xxyy FFEEDDCCBBAA 0104 TTTTHHHH // xxyy FFEEDDCCBBAA 0201 BB +const char *MIaddrStr(const uint8_t *addr, int useAlias = 0){ + static char addrstr[32]; + + const char *id = nullptr; + if (useAlias){ + id = BLE_ESP32::getAlias(addr); + } + if (!id || !(*id)){ + id = addrstr; + BLE_ESP32::dump(addrstr, 13, addr, 6); + } else { + } + + return id; +} int MIParsePacket(const uint8_t* slotmac, struct mi_beacon_data_t *parsed, const uint8_t *datain, int len){ uint8_t data[32]; @@ -1189,6 +1207,10 @@ int MIParsePacket(const uint8_t* slotmac, struct mi_beacon_data_t *parsed, const parsed->framedata.bindingvalidreq = (data[byteindex] & 0x02)>>1; //Byte 0: ......x. parsed->framedata.registeredflag = (data[byteindex] & 0x01); //Byte 0: .......x + // note: + // if bindingvalidreq, we should connect and establish a key. + // However, how do we determine WHICH TAS should do this? + byteindex++; parsed->devicetype = *((uint16_t *)(data + byteindex)); @@ -1243,17 +1265,17 @@ int MIParsePacket(const uint8_t* slotmac, struct mi_beacon_data_t *parsed, const break; case 0: // suceeded parsed->needkey = KEY_REQUIRED_AND_FOUND; - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Payload decrypted")); + if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32 %s: Payload decrypted"), MIaddrStr(slotmac)); break; case -1: // key failed to work parsed->needkey = KEY_REQUIRED_AND_INVALID; - AddLog(LOG_LEVEL_ERROR,PSTR("M32: Payload decrypt failed")); + AddLog(LOG_LEVEL_ERROR,PSTR("M32 %s: Payload decrypt failed"), MIaddrStr(slotmac)); parsed->payloadpresent = 0; return 0; break; case -2: // key not present parsed->needkey = KEY_REQUIRED_BUT_NOT_FOUND; - AddLog(LOG_LEVEL_ERROR,PSTR("M32: Payload encrypted but no key")); + AddLog(LOG_LEVEL_ERROR,PSTR("M32 %s: Payload encrypted but no key"), MIaddrStr(slotmac)); parsed->payloadpresent = 0; return 0; break; @@ -1288,7 +1310,7 @@ int MIParsePacket(const uint8_t* slotmac, struct mi_beacon_data_t *parsed, const } if ((len - byteindex) == 0){ - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: No payload")); + if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32 %s: No payload"), MIaddrStr(slotmac)); parsed->payload.size = 0; parsed->payloadpresent = 0; return 0; @@ -1297,14 +1319,14 @@ int MIParsePacket(const uint8_t* slotmac, struct mi_beacon_data_t *parsed, const // we have payload which did not need decrypt. if (decres == 1){ parsed->needkey = KEY_NOT_REQUIRED; - if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Payload unencrypted")); + if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32 %s: Payload unencrypted"), MIaddrStr(slotmac)); } // already decrypted if required parsed->payloadpresent = 1; memcpy(&parsed->payload, (data + byteindex), (len - byteindex)); if (parsed->payload.size != (len - byteindex) - 3){ - AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Payload length mismatch")); + AddLog(LOG_LEVEL_DEBUG,PSTR("M32 %s: Payload length mismatch"), MIaddrStr(slotmac)); } return 1; @@ -1399,6 +1421,8 @@ uint32_t MIBLEgetSensorSlot(const uint8_t *mac, uint16_t _type, uint8_t counter) _newSensor.bat = 0x00; _newSensor.RSSI = 0xffff; _newSensor.lux = 0x00ffffff; + _newSensor.light = -1; + _newSensor.Btn = -1; switch (_type) { @@ -1428,9 +1452,13 @@ uint32_t MIBLEgetSensorSlot(const uint8_t *mac, uint16_t _type, uint8_t counter) _newSensor.feature.events=1; break; case MI_YEERC: - case MI_DOOR: _newSensor.feature.Btn=1; break; + case MI_DOOR: // MCCGQ02HL + _newSensor.feature.Btn=1; + _newSensor.feature.light=1; + _newSensor.feature.bat=1; + break; default: _newSensor.hum=NAN; _newSensor.feature.temp=1; @@ -1651,26 +1679,49 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){ MIBLEsensors[_slot].pairing = 0; MIBLEsensors[_slot].eventType.PairBtn = 0; + //https://iot.mi.com/new/doc/embedded-development/ble/object-definition + switch(parsed->payload.type){ - case 0x01: // button press - MIBLEsensors[_slot].Btn = pld->Btn.num + (pld->Btn.longPress/2)*6; - MIBLEsensors[_slot].feature.Btn = 1; - MIBLEsensors[_slot].eventType.Btn = 1; - MI32.mode.shallTriggerTele = 1; - MIBLEsensors[_slot].shallSendMQTT = 1; - break; - case 0x02: // related to pair button? + case 0x0002: // related to pair button? 'easypairing' MIBLEsensors[_slot].pairing = 1; MIBLEsensors[_slot].eventType.PairBtn = 1; MIBLEsensors[_slot].feature.pairing = 1; MI32.mode.shallTriggerTele = 1; MIBLEsensors[_slot].shallSendMQTT = 1; break; - case 0x03: {// motion? 1 byte + case 0x0003: {// motion? 1 byte 'near' uint8_t motion = parsed->payload.data[0]; res = 0; }break; - case 0x04:{ + case 0x000f: // 'Someone is moving (with light)' + MIBLEsensors[_slot].eventType.motion = 1; + MIBLEsensors[_slot].lastTime = millis(); + MIBLEsensors[_slot].events++; + MIBLEsensors[_slot].lux = pld->lux; + MIBLEsensors[_slot].eventType.lux = 1; + MIBLEsensors[_slot].NMT = 0; + MI32.mode.shallTriggerTele = 1; + MIBLEsensors[_slot].shallSendMQTT = 1; + MIBLEsensors[_slot].feature.lux = 1; + MIBLEsensors[_slot].feature.NMT = 1; + MIBLEsensors[_slot].feature.events=1; + + // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: PIR: primary"),MIBLEsensors[_slot].lux ); + break; + + + + case 0x1001: // button press + MIBLEsensors[_slot].Btn = pld->Btn.num + (pld->Btn.longPress/2)*6; + MIBLEsensors[_slot].feature.Btn = 1; + MIBLEsensors[_slot].eventType.Btn = 1; + MI32.mode.shallTriggerTele = 1; + MIBLEsensors[_slot].shallSendMQTT = 1; + break; + //case 0x1002: // 'sleep' + //case 0x1003: // 'RSSI' + + case 0x1004:{ // 'temperature' float _tempFloat=(float)(pld->temp)/10.0f; if(_tempFloat<60){ MIBLEsensors[_slot].temp=_tempFloat; @@ -1682,7 +1733,8 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){ } // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Mode 4: U16: %u Temp"), _beacon.temp ); } break; - case 0x06: { + // 0x1005 - not documented + case 0x1006: { // 'humidity' float _tempFloat=(float)(pld->hum)/10.0f; if(_tempFloat<101){ MIBLEsensors[_slot].hum=_tempFloat; @@ -1694,7 +1746,7 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){ } // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Mode 6: U16: %u Hum"), _beacon.hum); } break; - case 0x07: + case 0x1007: // 'Light illuminance' MIBLEsensors[_slot].lux=pld->lux & 0x00ffffff; if(MIBLEsensors[_slot].type==MI_MJYD2S){ MIBLEsensors[_slot].eventType.noMotion = 1; @@ -1703,21 +1755,21 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){ MIBLEsensors[_slot].feature.lux = 1; // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Mode 7: U24: %u Lux"), _beacon.lux & 0x00ffffff); break; - case 0x08: + case 0x1008: //'Soil moisture' MIBLEsensors[_slot].moisture=pld->moist; MIBLEsensors[_slot].eventType.moist = 1; MIBLEsensors[_slot].feature.moist = 1; if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode 8: moisture updated")); // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Mode 8: U8: %u Moisture"), _beacon.moist); break; - case 0x09: // 'conductivity' + case 0x1009: // 'conductivity' / 'Soil EC value' MIBLEsensors[_slot].fertility=pld->fert; MIBLEsensors[_slot].eventType.fert = 1; MIBLEsensors[_slot].feature.fert = 1; if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: Mode 9: fertility updated")); // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Mode 9: U16: %u Fertility"), _beacon.fert); break; - case 0x0a: + case 0x100a:// 'Electricity' if(MI32.option.ignoreBogusBattery){ if(MIBLEsensors[_slot].type==MI_LYWSD03MMC || MIBLEsensors[_slot].type==MI_MHOC401){ res = 0; @@ -1736,7 +1788,8 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){ } // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Mode a: U8: %u %%"), _beacon.bat); break; - case 0x0d:{ + // 100b-100d -> undefioend in docs. + case 0x100d:{ // is this right???? MIBLEsensors[_slot].feature.tempHum = 1; float _tempFloat=(float)(pld->HT.temp)/10.0f; if(_tempFloat < 60){ @@ -1755,36 +1808,26 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){ MIBLEsensors[_slot].eventType.tempHum = 1; // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Mode d: U16: %x Temp U16: %x Hum"), _beacon.HT.temp, _beacon.HT.hum); } break; - case 0x0f: - if (parsed->payload.ten != 0) break; - MIBLEsensors[_slot].eventType.motion = 1; - MIBLEsensors[_slot].lastTime = millis(); - MIBLEsensors[_slot].events++; - MIBLEsensors[_slot].lux = pld->lux; - MIBLEsensors[_slot].eventType.lux = 1; - MIBLEsensors[_slot].NMT = 0; - MI32.mode.shallTriggerTele = 1; - MIBLEsensors[_slot].shallSendMQTT = 1; - MIBLEsensors[_slot].feature.lux = 1; - MIBLEsensors[_slot].feature.NMT = 1; - MIBLEsensors[_slot].feature.events=1; - - // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: PIR: primary"),MIBLEsensors[_slot].lux ); - break; - case 0x10:{ // 'formaldehide' + // 100e = 'lock' + // 100f = 'door' + case 0x1010:{ // 'formaldehide' const uint16_t f = uint16_t(parsed->payload.data[0]) | (uint16_t(parsed->payload.data[1]) << 8); float formaldehyde = (float)f / 100.0f; res = 0; } break; - case 0x12:{ // 'active' + // 1011 = 'bind' + case 0x1012:{ // 'switch' int active = parsed->payload.data[0]; res = 0; } break; - case 0x13:{ //mosquito tablet + case 0x1013:{ // 'Remaining amount of consumables' - mosquito tablet int tablet = parsed->payload.data[0]; res = 0; } break; - case 0x17:{ + //Flooding 0x1014 1 1 + //smoke 0x1015 1 1 + //Gas 0x1016 + case 0x1017:{ // 'No one moves' const uint32_t idle_time = uint32_t(parsed->payload.data[0]) | (uint32_t(parsed->payload.data[1]) << 8) | (uint32_t(parsed->payload.data[2]) << 16) | (uint32_t(parsed->payload.data[2]) << 24); float idlemins = (float)idle_time / 60.0f; @@ -1798,17 +1841,29 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){ // AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Mode 17: NMT: %u seconds"), _beacon.NMT); } break; - - case 0x19:{ - MIBLEsensors[_slot].Btn = uint8_t(parsed->payload.data[0]); // just an 8 bit value in a union. + //Light intensity 0x1018 + case 0x1018:{ //'Light intensity' - 0=dark, 1=light? - MCCGQ02HL + MIBLEsensors[_slot].light = parsed->payload.data[0]; + MIBLEsensors[_slot].eventType.light = 1; + MI32.mode.shallTriggerTele = 1; + MIBLEsensors[_slot].shallSendMQTT = 1; + MIBLEsensors[_slot].feature.light = 1; + } break; + case 0x1019:{ //'Door sensor' - 0=open, 1=closed, 2=timeout? - MCCGQ02HL + MIBLEsensors[_slot].Btn = (uint8_t) parsed->payload.data[0]; // just an 8 bit value in a union. MIBLEsensors[_slot].eventType.Btn = 1; MI32.mode.shallTriggerTele = 1; MIBLEsensors[_slot].shallSendMQTT = 1; MIBLEsensors[_slot].feature.Btn = 1; } break; + //Weight attributes 0x101A 600 0 + //No one moves over time 0x101B 1 1 + //Smart pillow 0x101C 60 1 + //Formaldehyde (new) 0x101D + default: { - AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Unknown MI pld")); + AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Unknown MI pld type %x %s"), parsed->payload.type, tmp); res = 0; } break; } @@ -2179,45 +2234,65 @@ void CmndMi32Block(void){ } void CmndMi32Option(void){ - bool onOff = atoi(XdrvMailbox.data); + bool set = false; + if (strlen(XdrvMailbox.data)){ + set = true; + } + int onOff = atoi(XdrvMailbox.data); switch(XdrvMailbox.index) { case 0: - MI32.option.allwaysAggregate = onOff; - ResponseCmndIdxNumber(onOff); - return; + if (set){ + MI32.option.allwaysAggregate = onOff; + } else { + onOff = MI32.option.allwaysAggregate; + } break; case 1: - MI32.option.noSummary = onOff; - ResponseCmndIdxNumber(onOff); - return; + if (set){ + MI32.option.noSummary = onOff; + } else { + onOff = MI32.option.noSummary; + } break; case 2: - MI32.option.directBridgeMode = onOff; - ResponseCmndIdxNumber(onOff); - return; + if (set){ + MI32.option.directBridgeMode = onOff; + } else { + onOff = MI32.option.directBridgeMode; + } break; case 4:{ - MI32.option.ignoreBogusBattery = onOff; - ResponseCmndIdxNumber(onOff); - return; + if (set){ + MI32.option.ignoreBogusBattery = onOff; + } else { + onOff = MI32.option.ignoreBogusBattery; + } } break; case 5:{ - MI32.option.onlyAliased = onOff; - if (MI32.option.onlyAliased){ - // discard all sensors for a restart - MIBLEsensors.clear(); + if (set){ + MI32.option.onlyAliased = onOff; + if (MI32.option.onlyAliased){ + // discard all sensors for a restart + MIBLEsensors.clear(); + } + } else { + onOff = MI32.option.onlyAliased; } - ResponseCmndIdxNumber(onOff); - return; } break; case 6:{ - MI32.option.MQTTType = onOff; - ResponseCmndIdxNumber(onOff); + if (set){ + MI32.option.MQTTType = onOff; + } else { + onOff = MI32.option.MQTTType; + } + } break; + default:{ + ResponseCmndIdxError(); return; } break; - } - ResponseCmndIdxError(); + ResponseCmndIdxNumber(onOff); + return; } void MI32KeyListResp(){ @@ -2325,6 +2400,7 @@ const char HTTP_EVENTS[] PROGMEM = "{s}%s Events{m}%u {e}"; const char HTTP_NMT[] PROGMEM = "{s}%s No motion{m}> %u seconds{e}"; const char HTTP_MI32_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%u us/cm{e}"; const char HTTP_MI32_HL[] PROGMEM = "{s}
{m}
{e}"; +const char HTTP_MI32_LIGHT[] PROGMEM = "{s}%s" " Light" "{m}%d{e}"; //const char HTTP_NEEDKEY[] PROGMEM = "{s}%s MAC[3], p->MAC[4], p->MAC[5]); } + const char *alias = BLE_ESP32::getAlias(p->MAC); + if (alias && alias[0]){ + ResponseAppend_P(PSTR("\"alias\":\"%s\","), + alias); + } + ResponseAppend_P(PSTR("\"mac\":\"%02x%02x%02x%02x%02x%02x\""), p->MAC[0], p->MAC[1], p->MAC[2], p->MAC[3], p->MAC[4], p->MAC[5]); @@ -2475,6 +2557,15 @@ void MI32GetOneSensorJson(int slot, int hidename){ } } } + if (p->feature.light){ + if(p->eventType.light || !MI32.mode.triggeredTele || MI32.option.allwaysAggregate +#ifdef USE_HOME_ASSISTANT + ||(hass_mode==2) +#endif //USE_HOME_ASSISTANT + ){ + ResponseAppend_P(PSTR(",\"Light\":%d"), p->light); + } + } if (p->feature.moist){ if(p->eventType.moist || !MI32.mode.triggeredTele || MI32.option.allwaysAggregate){ if (p->moisture!=0xff @@ -2504,12 +2595,12 @@ void MI32GetOneSensorJson(int slot, int hidename){ } } if (p->feature.Btn){ - if(p->eventType.Btn + if(p->eventType.Btn || !MI32.mode.triggeredTele || MI32.option.allwaysAggregate #ifdef USE_HOME_ASSISTANT ||(hass_mode==2) #endif //USE_HOME_ASSISTANT ){ - ResponseAppend_P(PSTR(",\"Btn\":%u"),p->Btn); + ResponseAppend_P(PSTR(",\"Btn\":%d"),p->Btn); } } if(p->eventType.PairBtn && p->pairing){ @@ -2685,14 +2776,74 @@ const char MI_HA_DISCOVERY_TEMPLATE[] PROGMEM = "\"model\":\"%s\"," "\"via_device\":\"%s\"" "}," - "\"dev_cla\":\"%s\"," + "%s%s%s" "\"expire_after\":600," "\"json_attr_t\":\"%s\"," "\"name\":\"%s_%s\"," "\"state_topic\":\"%s\"," "\"uniq_id\":\"%s_%s\"," - "\"unit_of_meas\":\"%s\"," - "\"val_tpl\":\"{{ value_json.%s }}\"}"; + "%s%s%s" + "\"val_tpl\":\"{{ %s%s%s }}\"}"; + +// careful - a missing comma causes a crash!!!! +// because of the way we loop? +const char *classes[] = { + // 0 + "temperature", + "Temperature", + "°C", + + // 1 + "humidity", + "Humidity", + "%", + + // 2 + "temperature", + "DewPoint", + "°C", + + // 3 + "battery", + "Battery", + "%", + + // 4 + "signal_strength", + "RSSI", + "dB", + + // 5 + "",//- empty device class + "Btn", + "", + + // 6 + "", //- empty device class + "Light", + "", + + // 7 + "", //- empty device class + "Moisture", + "", + + // 8 + "", //- empty device class + "Illuminance", + "", + + // 9 + "", //- empty device class + "Fertility", + "", + + // 10 + "", //- empty device class + "Firmware", + "", +}; + void MI32DiscoveryOneMISensor(){ // don't detect half-added ones here @@ -2708,25 +2859,7 @@ void MI32DiscoveryOneMISensor(){ p = &MIBLEsensors[MI32.mqttCurrentSingleSlot]; - // careful - a missing comma causes a crash!!!! - // because of the way we loop? - const char *classes[] = { - "temperature", - "Temperature", - "°C", - "humidity", - "Humidity", - "%", - "temperature", - "DewPoint", - "°C", - "battery", - "Battery", - "%", - "signal_strength", - "RSSI", - "dB" - }; + int datacount = (sizeof(classes)/sizeof(*classes))/3; @@ -2758,9 +2891,72 @@ void MI32DiscoveryOneMISensor(){ if (!classes[i] || !classes[i+1] || !classes[i+2]){ return; } - + uint8_t isBinary = 0; + ResponseClear(); + switch(i/3){ + case 0: // temp + if (!p->feature.temp && !p->feature.tempHum){ + continue; + } + break; + case 1:// hum + if (!p->feature.hum && !p->feature.tempHum){ + continue; + } + break; + case 2: //dew + if (!p->feature.tempHum && !(p->feature.temp && p->feature.hum)){ + continue; + } + break; + + case 3: //bat + if (!p->feature.bat){ + continue; + } + break; + + case 4: //rssi - all + break; + + case 5: // button + if (!p->feature.Btn){ + continue; + } + //isBinary = 2; // invert payload + break; + + case 6: // binary light sense + if (!p->feature.light){ + continue; + } + //isBinary = 1; + break; + case 7: // moisture + if (!p->feature.moist){ + continue; + } + //isBinary = 1; + break; + case 8: // lux + if (!p->feature.lux){ + continue; + } + break; + case 9: // fertility + if (!p->feature.fert){ + continue; + } + break; + case 10: // firmware + if (!p->feature.fert){ // Flora only + continue; + } + break; + } + /* {"availability":[],"device":{"identifiers":["TasmotaBLEa4c1387fc1e1"],"manufacturer":"simon","model":"someBLEsensor","name":"TASBLEa4c1387fc1e1","sw_version":"0.0.0"},"dev_cla":"temperature","json_attr_t":"tele/tasmota_esp32/SENSOR","name":"TASLYWSD037fc1e1Temp","state_topic":"tele/tasmota_esp32/SENSOR","uniq_id":"Tasmotaa4c1387fc1e1temp","unit_of_meas":"°C","val_tpl":"{{ value_json.LYWSD037fc1e1.Temperature }}"} {"availability":[],"device":{"identifiers":["TasmotaBLEa4c1387fc1e1"], @@ -2781,7 +2977,9 @@ void MI32DiscoveryOneMISensor(){ //\"via_device\":\"%s\" host, //"\"dev_cla\":\"%s\"," + (classes[i][0]?"\"dev_cla\":\"":""), classes[i], + (classes[i][0]?"\",":""), //"\"json_attr_t\":\"%s\"," - the topic the sensor publishes on SensorTopic, //"\"name\":\"%s_%s\"," - the name of this DATA @@ -2791,14 +2989,26 @@ void MI32DiscoveryOneMISensor(){ //"\"uniq_id\":\"%s_%s\"," - unique for this data, id, classes[i+1], //"\"unit_of_meas\":\"%s\"," - the measure of this type of data + (classes[i+2][0]?"\"unit_of_meas\":\"":""), classes[i+2], - //"\"val_tpl\":\"{{ value_json.%s }}") // e.g. Temperature - classes[i+1] + (classes[i+2][0]?"\",":""), + //"\"val_tpl\":\"{{ %s%s }}") // e.g. Temperature + // inverted binary - {{ 'off' if value_json.posn else 'on' }} + // binary - {{ 'on' if value_json.posn else 'off' }} + + ((isBinary < 1)?"value_json.": + ((isBinary < 2)?"value_json.":"'off' if value_json.") + ), + classes[i+1], + ((isBinary < 1)?"": + ((isBinary < 2)?"":" else 'on'") + ) + // ); - sprintf(DiscoveryTopic, "homeassistant/sensor/%s/%s/config", - id, classes[i+1]); + sprintf(DiscoveryTopic, "homeassistant/%ssensor/%s/%s/config", + (isBinary? "binary_":""), id, classes[i+1]); MqttPublish(DiscoveryTopic); p->nextDiscoveryData++; @@ -3013,6 +3223,10 @@ void MI32Show(bool json) WSContentSend_PD(HTTP_SNS_ILLUMINANCE, typeName, p->lux); } } + if (p->feature.light){ + WSContentSend_PD(HTTP_MI32_LIGHT, typeName, p->light); + } + if(p->bat!=0x00){ WSContentSend_PD(HTTP_BATTERY, typeName, p->bat); } From b613e1db37fcfbfe558e713b976e4c14ccb2855e Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 28 Feb 2021 20:50:37 +0100 Subject: [PATCH 11/11] Berry improvements --- .../Berry-0.1.10/generate/be_const_strtab.h | 233 +++---- .../generate/be_const_strtab_def.h | 335 +++++---- .../Berry-0.1.10/generate/be_fixed_debug.h | 13 +- .../Berry-0.1.10/generate/be_fixed_os.h | 22 - .../Berry-0.1.10/generate/be_fixed_path.h | 2 + .../Berry-0.1.10/generate/be_fixed_sys.h | 15 - .../Berry-0.1.10/generate/be_fixed_time.h | 17 - lib/libesp32/Berry-0.1.10/src/be_gc.c | 2 +- lib/libesp32/Berry-0.1.10/src/be_gc.h | 8 +- lib/libesp32/Berry-0.1.10/src/be_lexer.c | 3 +- lib/libesp32/Berry-0.1.10/src/be_object.h | 31 - lib/libesp32/Berry-0.1.10/src/be_parser.c | 2 +- lib/libesp32/Berry-0.1.10/src/be_string.c | 19 +- lib/libesp32/Berry-0.1.10/src/be_string.h | 2 +- lib/libesp32/Berry-0.1.10/src/be_strlib.c | 6 +- lib/libesp32/Berry-0.1.10/src/be_vector.c | 8 +- .../Berry-0.1.10/src/port/be_modtab.c | 6 +- .../Berry-0.1.10/src/port/be_tasmotalib.c | 19 +- .../Berry-0.1.10/src/port/be_wirelib.c | 36 + .../Berry-0.1.10/src/port/berry_conf.h | 25 +- tasmota/berry/tasmota.be | 20 + tasmota/xdrv_52_3_berry_native.ino | 323 +++++++++ tasmota/xdrv_52_7_berry_embedded.ino | 281 ++++++++ tasmota/xdrv_52_9_berry.ino | 354 ++++++++++ tasmota/xdrv_52_berry.ino | 650 ------------------ 25 files changed, 1335 insertions(+), 1097 deletions(-) create mode 100644 lib/libesp32/Berry-0.1.10/generate/be_fixed_path.h create mode 100644 lib/libesp32/Berry-0.1.10/src/port/be_wirelib.c create mode 100644 tasmota/xdrv_52_3_berry_native.ino create mode 100644 tasmota/xdrv_52_7_berry_embedded.ino create mode 100644 tasmota/xdrv_52_9_berry.ino delete mode 100644 tasmota/xdrv_52_berry.ino diff --git a/lib/libesp32/Berry-0.1.10/generate/be_const_strtab.h b/lib/libesp32/Berry-0.1.10/generate/be_const_strtab.h index 9234199bb..d3ad809d7 100644 --- a/lib/libesp32/Berry-0.1.10/generate/be_const_strtab.h +++ b/lib/libesp32/Berry-0.1.10/generate/be_const_strtab.h @@ -1,128 +1,111 @@ -extern const bcstring be_const_str_calldepth; -extern const bcstring be_const_str_clock; -extern const bcstring be_const_str_size; -extern const bcstring be_const_str_system; -extern const bcstring be_const_str_type; -extern const bcstring be_const_str_if; -extern const bcstring be_const_str_int; -extern const bcstring be_const_str_isfile; -extern const bcstring be_const_str_log; -extern const bcstring be_const_str_raise; -extern const bcstring be_const_str_concat; -extern const bcstring be_const_str_list; -extern const bcstring be_const_str_map; -extern const bcstring be_const_str_for; -extern const bcstring be_const_str_dot_p; -extern const bcstring be_const_str_isdir; -extern const bcstring be_const_str_mkdir; -extern const bcstring be_const_str_remove; -extern const bcstring be_const_str_cosh; -extern const bcstring be_const_str_abs; -extern const bcstring be_const_str_reverse; -extern const bcstring be_const_str_sinh; -extern const bcstring be_const_str_hex; -extern const bcstring be_const_str_tostring; -extern const bcstring be_const_str_opt_add; -extern const bcstring be_const_str_atan; -extern const bcstring be_const_str_real; -extern const bcstring be_const_str_iter; -extern const bcstring be_const_str_top; -extern const bcstring be_const_str_except; -extern const bcstring be_const_str_getcwd; -extern const bcstring be_const_str_listdir; -extern const bcstring be_const_str_log10; -extern const bcstring be_const_str_allocated; -extern const bcstring be_const_str_init; -extern const bcstring be_const_str_module; -extern const bcstring be_const_str_ceil; -extern const bcstring be_const_str_clear; -extern const bcstring be_const_str_collect; -extern const bcstring be_const_str_find; -extern const bcstring be_const_str_item; -extern const bcstring be_const_str_format; -extern const bcstring be_const_str_sqrt; -extern const bcstring be_const_str_classname; -extern const bcstring be_const_str_byte; -extern const bcstring be_const_str_else; -extern const bcstring be_const_str_deinit; -extern const bcstring be_const_str_end; -extern const bcstring be_const_str_true; -extern const bcstring be_const_str___upper__; -extern const bcstring be_const_str_char; -extern const bcstring be_const_str_load; -extern const bcstring be_const_str_resize; -extern const bcstring be_const_str_sethook; -extern const bcstring be_const_str_varname; -extern const bcstring be_const_str_deg; -extern const bcstring be_const_str_srand; -extern const bcstring be_const_str_str; -extern const bcstring be_const_str_range; -extern const bcstring be_const_str_toupper; -extern const bcstring be_const_str_; -extern const bcstring be_const_str_copy; -extern const bcstring be_const_str_exp; -extern const bcstring be_const_str_time; -extern const bcstring be_const_str_break; -extern const bcstring be_const_str_opt_neq; -extern const bcstring be_const_str_assert; -extern const bcstring be_const_str_attrdump; -extern const bcstring be_const_str_chdir; -extern const bcstring be_const_str_isinstance; -extern const bcstring be_const_str_continue; -extern const bcstring be_const_str_do; -extern const bcstring be_const_str_lower; -extern const bcstring be_const_str_pow; -extern const bcstring be_const_str_false; -extern const bcstring be_const_str_count; -extern const bcstring be_const_str_exit; -extern const bcstring be_const_str_print; -extern const bcstring be_const_str_def; -extern const bcstring be_const_str_pop; -extern const bcstring be_const_str_tolower; -extern const bcstring be_const_str_classof; -extern const bcstring be_const_str_cos; -extern const bcstring be_const_str_dump; -extern const bcstring be_const_str_join; -extern const bcstring be_const_str_push; -extern const bcstring be_const_str_sin; -extern const bcstring be_const_str_return; -extern const bcstring be_const_str_path; -extern const bcstring be_const_str_rand; -extern const bcstring be_const_str_class; -extern const bcstring be_const_str_nil; -extern const bcstring be_const_str_input; -extern const bcstring be_const_str_floor; -extern const bcstring be_const_str_keys; -extern const bcstring be_const_str_number; -extern const bcstring be_const_str_rad; -extern const bcstring be_const_str_imin; -extern const bcstring be_const_str_pi; -extern const bcstring be_const_str_splitext; -extern const bcstring be_const_str_compile; -extern const bcstring be_const_str_setrange; -extern const bcstring be_const_str_traceback; -extern const bcstring be_const_str_upper; -extern const bcstring be_const_str_var; -extern const bcstring be_const_str_opt_eq; -extern const bcstring be_const_str_codedump; -extern const bcstring be_const_str_tan; -extern const bcstring be_const_str_setitem; -extern const bcstring be_const_str_tanh; -extern const bcstring be_const_str_as; -extern const bcstring be_const_str_issubclass; -extern const bcstring be_const_str_upvname; -extern const bcstring be_const_str_opt_connect; -extern const bcstring be_const_str_try; -extern const bcstring be_const_str_while; -extern const bcstring be_const_str_import; -extern const bcstring be_const_str___lower__; -extern const bcstring be_const_str_open; extern const bcstring be_const_str_acos; extern const bcstring be_const_str_asin; -extern const bcstring be_const_str_imax; -extern const bcstring be_const_str_insert; -extern const bcstring be_const_str_split; -extern const bcstring be_const_str___iterator__; -extern const bcstring be_const_str_exists; -extern const bcstring be_const_str_super; +extern const bcstring be_const_str_list; +extern const bcstring be_const_str_module; +extern const bcstring be_const_str_pop; +extern const bcstring be_const_str_int; +extern const bcstring be_const_str_push; +extern const bcstring be_const_str_setrange; +extern const bcstring be_const_str_sinh; extern const bcstring be_const_str_elif; +extern const bcstring be_const_str_iter; +extern const bcstring be_const_str_load; +extern const bcstring be_const_str_class; +extern const bcstring be_const_str_if; +extern const bcstring be_const_str_opt_eq; +extern const bcstring be_const_str_ceil; +extern const bcstring be_const_str_floor; +extern const bcstring be_const_str_map; +extern const bcstring be_const_str_print; +extern const bcstring be_const_str_else; +extern const bcstring be_const_str_find; +extern const bcstring be_const_str_str; +extern const bcstring be_const_str___upper__; +extern const bcstring be_const_str_dump; +extern const bcstring be_const_str_atan; +extern const bcstring be_const_str_size; +extern const bcstring be_const_str_tolower; +extern const bcstring be_const_str_opt_add; +extern const bcstring be_const_str_abs; +extern const bcstring be_const_str_lower; +extern const bcstring be_const_str_end; +extern const bcstring be_const_str_import; +extern const bcstring be_const_str_classof; +extern const bcstring be_const_str_concat; +extern const bcstring be_const_str_byte; +extern const bcstring be_const_str_top; +extern const bcstring be_const_str_clear; +extern const bcstring be_const_str_opt_connect; +extern const bcstring be_const_str_collect; +extern const bcstring be_const_str_init; +extern const bcstring be_const_str_log10; +extern const bcstring be_const_str_nil; +extern const bcstring be_const_str_; +extern const bcstring be_const_str_real; +extern const bcstring be_const_str_calldepth; +extern const bcstring be_const_str_format; +extern const bcstring be_const_str_pi; +extern const bcstring be_const_str_do; +extern const bcstring be_const_str___iterator__; +extern const bcstring be_const_str_number; +extern const bcstring be_const_str_type; +extern const bcstring be_const_str_dot_p; +extern const bcstring be_const_str_traceback; +extern const bcstring be_const_str_as; +extern const bcstring be_const_str___lower__; +extern const bcstring be_const_str_exp; +extern const bcstring be_const_str_hex; +extern const bcstring be_const_str_char; +extern const bcstring be_const_str_split; +extern const bcstring be_const_str_toupper; +extern const bcstring be_const_str_deinit; +extern const bcstring be_const_str_tan; +extern const bcstring be_const_str_srand; +extern const bcstring be_const_str_imin; +extern const bcstring be_const_str_input; +extern const bcstring be_const_str_issubclass; +extern const bcstring be_const_str_tostring; +extern const bcstring be_const_str_break; +extern const bcstring be_const_str_insert; +extern const bcstring be_const_str_var; +extern const bcstring be_const_str_open; +extern const bcstring be_const_str_tanh; +extern const bcstring be_const_str_upper; +extern const bcstring be_const_str_allocated; +extern const bcstring be_const_str_rad; +extern const bcstring be_const_str_attrdump; +extern const bcstring be_const_str_copy; +extern const bcstring be_const_str_sqrt; +extern const bcstring be_const_str_for; +extern const bcstring be_const_str_raise; +extern const bcstring be_const_str_opt_neq; +extern const bcstring be_const_str_assert; +extern const bcstring be_const_str_item; +extern const bcstring be_const_str_reverse; +extern const bcstring be_const_str_sin; +extern const bcstring be_const_str_super; +extern const bcstring be_const_str_try; +extern const bcstring be_const_str_range; +extern const bcstring be_const_str_return; +extern const bcstring be_const_str_compile; +extern const bcstring be_const_str_false; +extern const bcstring be_const_str_resize; +extern const bcstring be_const_str_continue; +extern const bcstring be_const_str_log; +extern const bcstring be_const_str_true; +extern const bcstring be_const_str_while; +extern const bcstring be_const_str_pow; +extern const bcstring be_const_str_cos; +extern const bcstring be_const_str_count; +extern const bcstring be_const_str_remove; +extern const bcstring be_const_str_imax; +extern const bcstring be_const_str_rand; +extern const bcstring be_const_str_codedump; +extern const bcstring be_const_str_deg; +extern const bcstring be_const_str_keys; +extern const bcstring be_const_str_setitem; +extern const bcstring be_const_str_def; +extern const bcstring be_const_str_except; +extern const bcstring be_const_str_classname; +extern const bcstring be_const_str_isinstance; +extern const bcstring be_const_str_cosh; diff --git a/lib/libesp32/Berry-0.1.10/generate/be_const_strtab_def.h b/lib/libesp32/Berry-0.1.10/generate/be_const_strtab_def.h index 25b5b9221..b967bc818 100644 --- a/lib/libesp32/Berry-0.1.10/generate/be_const_strtab_def.h +++ b/lib/libesp32/Berry-0.1.10/generate/be_const_strtab_def.h @@ -1,190 +1,165 @@ -be_define_const_str(calldepth, "calldepth", 3122364302u, 0, 9, &be_const_str_clock); -be_define_const_str(clock, "clock", 363073373u, 0, 5, &be_const_str_size); -be_define_const_str(size, "size", 597743964u, 0, 4, &be_const_str_system); -be_define_const_str(system, "system", 1226705564u, 0, 6, &be_const_str_type); -be_define_const_str(type, "type", 1361572173u, 0, 4, &be_const_str_if); -be_define_const_str(if, "if", 959999494u, 50, 2, NULL); -be_define_const_str(int, "int", 2515107422u, 0, 3, &be_const_str_isfile); -be_define_const_str(isfile, "isfile", 3131505107u, 0, 6, &be_const_str_log); -be_define_const_str(log, "log", 1062293841u, 0, 3, &be_const_str_raise); -be_define_const_str(raise, "raise", 1593437475u, 70, 5, NULL); -be_define_const_str(concat, "concat", 4124019837u, 0, 6, &be_const_str_list); -be_define_const_str(list, "list", 217798785u, 0, 4, &be_const_str_map); -be_define_const_str(map, "map", 3751997361u, 0, 3, &be_const_str_for); -be_define_const_str(for, "for", 2901640080u, 54, 3, NULL); -be_define_const_str(dot_p, ".p", 1171526419u, 0, 2, &be_const_str_isdir); -be_define_const_str(isdir, "isdir", 2340917412u, 0, 5, &be_const_str_mkdir); -be_define_const_str(mkdir, "mkdir", 2883839448u, 0, 5, &be_const_str_remove); -be_define_const_str(remove, "remove", 3683784189u, 0, 6, NULL); -be_define_const_str(cosh, "cosh", 4099687964u, 0, 4, NULL); -be_define_const_str(abs, "abs", 709362235u, 0, 3, &be_const_str_reverse); -be_define_const_str(reverse, "reverse", 558918661u, 0, 7, &be_const_str_sinh); -be_define_const_str(sinh, "sinh", 282220607u, 0, 4, NULL); -be_define_const_str(hex, "hex", 4273249610u, 0, 3, NULL); -be_define_const_str(tostring, "tostring", 2299708645u, 0, 8, NULL); -be_define_const_str(opt_add, "+", 772578730u, 0, 1, &be_const_str_atan); -be_define_const_str(atan, "atan", 108579519u, 0, 4, &be_const_str_real); -be_define_const_str(real, "real", 3604983901u, 0, 4, NULL); -be_define_const_str(iter, "iter", 3124256359u, 0, 4, &be_const_str_top); -be_define_const_str(top, "top", 2802900028u, 0, 3, &be_const_str_except); -be_define_const_str(except, "except", 950914032u, 69, 6, NULL); -be_define_const_str(getcwd, "getcwd", 652026575u, 0, 6, &be_const_str_listdir); -be_define_const_str(listdir, "listdir", 2005220720u, 0, 7, &be_const_str_log10); -be_define_const_str(log10, "log10", 2346846000u, 0, 5, NULL); -be_define_const_str(allocated, "allocated", 429986098u, 0, 9, &be_const_str_init); -be_define_const_str(init, "init", 380752755u, 0, 4, &be_const_str_module); -be_define_const_str(module, "module", 3617558685u, 0, 6, NULL); -be_define_const_str(ceil, "ceil", 1659167240u, 0, 4, &be_const_str_clear); -be_define_const_str(clear, "clear", 1550717474u, 0, 5, &be_const_str_collect); -be_define_const_str(collect, "collect", 2399039025u, 0, 7, &be_const_str_find); -be_define_const_str(find, "find", 3186656602u, 0, 4, &be_const_str_item); -be_define_const_str(item, "item", 2671260646u, 0, 4, NULL); -be_define_const_str(format, "format", 3114108242u, 0, 6, &be_const_str_sqrt); -be_define_const_str(sqrt, "sqrt", 2112764879u, 0, 4, NULL); -be_define_const_str(classname, "classname", 1998589948u, 0, 9, NULL); -be_define_const_str(byte, "byte", 1683620383u, 0, 4, NULL); -be_define_const_str(else, "else", 3183434736u, 52, 4, NULL); -be_define_const_str(deinit, "deinit", 2345559592u, 0, 6, &be_const_str_end); -be_define_const_str(end, "end", 1787721130u, 56, 3, &be_const_str_true); -be_define_const_str(true, "true", 1303515621u, 61, 4, NULL); -be_define_const_str(__upper__, "__upper__", 3612202883u, 0, 9, NULL); -be_define_const_str(char, "char", 2823553821u, 0, 4, &be_const_str_load); -be_define_const_str(load, "load", 3859241449u, 0, 4, &be_const_str_resize); -be_define_const_str(resize, "resize", 3514612129u, 0, 6, &be_const_str_sethook); -be_define_const_str(sethook, "sethook", 3963967276u, 0, 7, &be_const_str_varname); -be_define_const_str(varname, "varname", 2273276445u, 0, 7, NULL); -be_define_const_str(deg, "deg", 3327754271u, 0, 3, &be_const_str_srand); -be_define_const_str(srand, "srand", 465518633u, 0, 5, &be_const_str_str); -be_define_const_str(str, "str", 3259748752u, 0, 3, NULL); -be_define_const_str(range, "range", 4208725202u, 0, 5, &be_const_str_toupper); -be_define_const_str(toupper, "toupper", 3691983576u, 0, 7, NULL); -be_define_const_str(, "", 2166136261u, 0, 0, &be_const_str_copy); -be_define_const_str(copy, "copy", 3848464964u, 0, 4, &be_const_str_exp); -be_define_const_str(exp, "exp", 1923516200u, 0, 3, &be_const_str_time); -be_define_const_str(time, "time", 1564253156u, 0, 4, &be_const_str_break); -be_define_const_str(break, "break", 3378807160u, 58, 5, NULL); -be_define_const_str(opt_neq, "!=", 2428715011u, 0, 2, &be_const_str_assert); -be_define_const_str(assert, "assert", 2774883451u, 0, 6, &be_const_str_attrdump); -be_define_const_str(attrdump, "attrdump", 1521571304u, 0, 8, &be_const_str_chdir); -be_define_const_str(chdir, "chdir", 806634853u, 0, 5, &be_const_str_isinstance); -be_define_const_str(isinstance, "isinstance", 3669352738u, 0, 10, &be_const_str_continue); -be_define_const_str(continue, "continue", 2977070660u, 59, 8, &be_const_str_do); -be_define_const_str(do, "do", 1646057492u, 65, 2, NULL); -be_define_const_str(lower, "lower", 3038577850u, 0, 5, &be_const_str_pow); -be_define_const_str(pow, "pow", 1479764693u, 0, 3, &be_const_str_false); -be_define_const_str(false, "false", 184981848u, 62, 5, NULL); -be_define_const_str(count, "count", 967958004u, 0, 5, NULL); -be_define_const_str(exit, "exit", 3454868101u, 0, 4, &be_const_str_print); -be_define_const_str(print, "print", 372738696u, 0, 5, &be_const_str_def); -be_define_const_str(def, "def", 3310976652u, 55, 3, NULL); -be_define_const_str(pop, "pop", 1362321360u, 0, 3, &be_const_str_tolower); -be_define_const_str(tolower, "tolower", 1042520049u, 0, 7, NULL); -be_define_const_str(classof, "classof", 1796577762u, 0, 7, &be_const_str_cos); -be_define_const_str(cos, "cos", 4220379804u, 0, 3, &be_const_str_dump); -be_define_const_str(dump, "dump", 3663001223u, 0, 4, &be_const_str_join); -be_define_const_str(join, "join", 3374496889u, 0, 4, &be_const_str_push); -be_define_const_str(push, "push", 2272264157u, 0, 4, &be_const_str_sin); -be_define_const_str(sin, "sin", 3761252941u, 0, 3, &be_const_str_return); -be_define_const_str(return, "return", 2246981567u, 60, 6, NULL); -be_define_const_str(path, "path", 2223459638u, 0, 4, &be_const_str_rand); -be_define_const_str(rand, "rand", 2711325910u, 0, 4, &be_const_str_class); -be_define_const_str(class, "class", 2872970239u, 57, 5, &be_const_str_nil); -be_define_const_str(nil, "nil", 228849900u, 63, 3, NULL); -be_define_const_str(input, "input", 4191711099u, 0, 5, NULL); -be_define_const_str(floor, "floor", 3102149661u, 0, 5, &be_const_str_keys); -be_define_const_str(keys, "keys", 4182378701u, 0, 4, &be_const_str_number); -be_define_const_str(number, "number", 467038368u, 0, 6, &be_const_str_rad); -be_define_const_str(rad, "rad", 1358899048u, 0, 3, NULL); -be_define_const_str(imin, "imin", 2714127864u, 0, 4, &be_const_str_pi); -be_define_const_str(pi, "pi", 1213090802u, 0, 2, NULL); -be_define_const_str(splitext, "splitext", 2150391934u, 0, 8, NULL); -be_define_const_str(compile, "compile", 1000265118u, 0, 7, &be_const_str_setrange); -be_define_const_str(setrange, "setrange", 3794019032u, 0, 8, &be_const_str_traceback); -be_define_const_str(traceback, "traceback", 3385188109u, 0, 9, &be_const_str_upper); -be_define_const_str(upper, "upper", 176974407u, 0, 5, &be_const_str_var); -be_define_const_str(var, "var", 2317739966u, 64, 3, NULL); -be_define_const_str(opt_eq, "==", 2431966415u, 0, 2, NULL); -be_define_const_str(codedump, "codedump", 1786337906u, 0, 8, &be_const_str_tan); -be_define_const_str(tan, "tan", 2633446552u, 0, 3, NULL); -be_define_const_str(setitem, "setitem", 1554834596u, 0, 7, NULL); -be_define_const_str(tanh, "tanh", 153638352u, 0, 4, &be_const_str_as); -be_define_const_str(as, "as", 1579491469u, 67, 2, NULL); -be_define_const_str(issubclass, "issubclass", 4078395519u, 0, 10, &be_const_str_upvname); -be_define_const_str(upvname, "upvname", 3848760617u, 0, 7, NULL); -be_define_const_str(opt_connect, "..", 2748622605u, 0, 2, NULL); -be_define_const_str(try, "try", 2887626766u, 68, 3, &be_const_str_while); -be_define_const_str(while, "while", 231090382u, 53, 5, NULL); -be_define_const_str(import, "import", 288002260u, 66, 6, NULL); -be_define_const_str(__lower__, "__lower__", 123855590u, 0, 9, &be_const_str_open); -be_define_const_str(open, "open", 3546203337u, 0, 4, NULL); be_define_const_str(acos, "acos", 1006755615u, 0, 4, &be_const_str_asin); -be_define_const_str(asin, "asin", 4272848550u, 0, 4, &be_const_str_imax); -be_define_const_str(imax, "imax", 3084515410u, 0, 4, &be_const_str_insert); -be_define_const_str(insert, "insert", 3332609576u, 0, 6, &be_const_str_split); -be_define_const_str(split, "split", 2276994531u, 0, 5, NULL); -be_define_const_str(__iterator__, "__iterator__", 3884039703u, 0, 12, &be_const_str_exists); -be_define_const_str(exists, "exists", 1002329533u, 0, 6, &be_const_str_super); -be_define_const_str(super, "super", 4152230356u, 0, 5, &be_const_str_elif); +be_define_const_str(asin, "asin", 4272848550u, 0, 4, &be_const_str_list); +be_define_const_str(list, "list", 217798785u, 0, 4, &be_const_str_module); +be_define_const_str(module, "module", 3617558685u, 0, 6, &be_const_str_pop); +be_define_const_str(pop, "pop", 1362321360u, 0, 3, NULL); +be_define_const_str(int, "int", 2515107422u, 0, 3, &be_const_str_push); +be_define_const_str(push, "push", 2272264157u, 0, 4, &be_const_str_setrange); +be_define_const_str(setrange, "setrange", 3794019032u, 0, 8, &be_const_str_sinh); +be_define_const_str(sinh, "sinh", 282220607u, 0, 4, &be_const_str_elif); be_define_const_str(elif, "elif", 3232090307u, 51, 4, NULL); +be_define_const_str(iter, "iter", 3124256359u, 0, 4, &be_const_str_load); +be_define_const_str(load, "load", 3859241449u, 0, 4, &be_const_str_class); +be_define_const_str(class, "class", 2872970239u, 57, 5, &be_const_str_if); +be_define_const_str(if, "if", 959999494u, 50, 2, NULL); +be_define_const_str(opt_eq, "==", 2431966415u, 0, 2, &be_const_str_ceil); +be_define_const_str(ceil, "ceil", 1659167240u, 0, 4, NULL); +be_define_const_str(floor, "floor", 3102149661u, 0, 5, &be_const_str_map); +be_define_const_str(map, "map", 3751997361u, 0, 3, &be_const_str_print); +be_define_const_str(print, "print", 372738696u, 0, 5, &be_const_str_else); +be_define_const_str(else, "else", 3183434736u, 52, 4, NULL); +be_define_const_str(find, "find", 3186656602u, 0, 4, &be_const_str_str); +be_define_const_str(str, "str", 3259748752u, 0, 3, NULL); +be_define_const_str(__upper__, "__upper__", 3612202883u, 0, 9, &be_const_str_dump); +be_define_const_str(dump, "dump", 3663001223u, 0, 4, NULL); +be_define_const_str(atan, "atan", 108579519u, 0, 4, &be_const_str_size); +be_define_const_str(size, "size", 597743964u, 0, 4, &be_const_str_tolower); +be_define_const_str(tolower, "tolower", 1042520049u, 0, 7, NULL); +be_define_const_str(opt_add, "+", 772578730u, 0, 1, &be_const_str_abs); +be_define_const_str(abs, "abs", 709362235u, 0, 3, &be_const_str_lower); +be_define_const_str(lower, "lower", 3038577850u, 0, 5, &be_const_str_end); +be_define_const_str(end, "end", 1787721130u, 56, 3, &be_const_str_import); +be_define_const_str(import, "import", 288002260u, 66, 6, NULL); +be_define_const_str(classof, "classof", 1796577762u, 0, 7, &be_const_str_concat); +be_define_const_str(concat, "concat", 4124019837u, 0, 6, NULL); +be_define_const_str(byte, "byte", 1683620383u, 0, 4, &be_const_str_top); +be_define_const_str(top, "top", 2802900028u, 0, 3, NULL); +be_define_const_str(clear, "clear", 1550717474u, 0, 5, NULL); +be_define_const_str(opt_connect, "..", 2748622605u, 0, 2, &be_const_str_collect); +be_define_const_str(collect, "collect", 2399039025u, 0, 7, &be_const_str_init); +be_define_const_str(init, "init", 380752755u, 0, 4, &be_const_str_log10); +be_define_const_str(log10, "log10", 2346846000u, 0, 5, &be_const_str_nil); +be_define_const_str(nil, "nil", 228849900u, 63, 3, NULL); +be_define_const_str(, "", 2166136261u, 0, 0, &be_const_str_real); +be_define_const_str(real, "real", 3604983901u, 0, 4, NULL); +be_define_const_str(calldepth, "calldepth", 3122364302u, 0, 9, &be_const_str_format); +be_define_const_str(format, "format", 3114108242u, 0, 6, &be_const_str_pi); +be_define_const_str(pi, "pi", 1213090802u, 0, 2, &be_const_str_do); +be_define_const_str(do, "do", 1646057492u, 65, 2, NULL); +be_define_const_str(__iterator__, "__iterator__", 3884039703u, 0, 12, &be_const_str_number); +be_define_const_str(number, "number", 467038368u, 0, 6, &be_const_str_type); +be_define_const_str(type, "type", 1361572173u, 0, 4, NULL); +be_define_const_str(dot_p, ".p", 1171526419u, 0, 2, &be_const_str_traceback); +be_define_const_str(traceback, "traceback", 3385188109u, 0, 9, &be_const_str_as); +be_define_const_str(as, "as", 1579491469u, 67, 2, NULL); +be_define_const_str(__lower__, "__lower__", 123855590u, 0, 9, &be_const_str_exp); +be_define_const_str(exp, "exp", 1923516200u, 0, 3, &be_const_str_hex); +be_define_const_str(hex, "hex", 4273249610u, 0, 3, NULL); +be_define_const_str(char, "char", 2823553821u, 0, 4, &be_const_str_split); +be_define_const_str(split, "split", 2276994531u, 0, 5, &be_const_str_toupper); +be_define_const_str(toupper, "toupper", 3691983576u, 0, 7, NULL); +be_define_const_str(deinit, "deinit", 2345559592u, 0, 6, &be_const_str_tan); +be_define_const_str(tan, "tan", 2633446552u, 0, 3, NULL); +be_define_const_str(srand, "srand", 465518633u, 0, 5, NULL); +be_define_const_str(imin, "imin", 2714127864u, 0, 4, &be_const_str_input); +be_define_const_str(input, "input", 4191711099u, 0, 5, &be_const_str_issubclass); +be_define_const_str(issubclass, "issubclass", 4078395519u, 0, 10, NULL); +be_define_const_str(tostring, "tostring", 2299708645u, 0, 8, &be_const_str_break); +be_define_const_str(break, "break", 3378807160u, 58, 5, NULL); +be_define_const_str(insert, "insert", 3332609576u, 0, 6, &be_const_str_var); +be_define_const_str(var, "var", 2317739966u, 64, 3, NULL); +be_define_const_str(open, "open", 3546203337u, 0, 4, &be_const_str_tanh); +be_define_const_str(tanh, "tanh", 153638352u, 0, 4, &be_const_str_upper); +be_define_const_str(upper, "upper", 176974407u, 0, 5, NULL); +be_define_const_str(allocated, "allocated", 429986098u, 0, 9, &be_const_str_rad); +be_define_const_str(rad, "rad", 1358899048u, 0, 3, NULL); +be_define_const_str(attrdump, "attrdump", 1521571304u, 0, 8, &be_const_str_copy); +be_define_const_str(copy, "copy", 3848464964u, 0, 4, &be_const_str_sqrt); +be_define_const_str(sqrt, "sqrt", 2112764879u, 0, 4, NULL); +be_define_const_str(for, "for", 2901640080u, 54, 3, &be_const_str_raise); +be_define_const_str(raise, "raise", 1593437475u, 70, 5, NULL); +be_define_const_str(opt_neq, "!=", 2428715011u, 0, 2, &be_const_str_assert); +be_define_const_str(assert, "assert", 2774883451u, 0, 6, &be_const_str_item); +be_define_const_str(item, "item", 2671260646u, 0, 4, &be_const_str_reverse); +be_define_const_str(reverse, "reverse", 558918661u, 0, 7, &be_const_str_sin); +be_define_const_str(sin, "sin", 3761252941u, 0, 3, &be_const_str_super); +be_define_const_str(super, "super", 4152230356u, 0, 5, &be_const_str_try); +be_define_const_str(try, "try", 2887626766u, 68, 3, NULL); +be_define_const_str(range, "range", 4208725202u, 0, 5, &be_const_str_return); +be_define_const_str(return, "return", 2246981567u, 60, 6, NULL); +be_define_const_str(compile, "compile", 1000265118u, 0, 7, &be_const_str_false); +be_define_const_str(false, "false", 184981848u, 62, 5, NULL); +be_define_const_str(resize, "resize", 3514612129u, 0, 6, NULL); +be_define_const_str(continue, "continue", 2977070660u, 59, 8, NULL); +be_define_const_str(log, "log", 1062293841u, 0, 3, &be_const_str_true); +be_define_const_str(true, "true", 1303515621u, 61, 4, NULL); +be_define_const_str(while, "while", 231090382u, 53, 5, NULL); +be_define_const_str(pow, "pow", 1479764693u, 0, 3, NULL); +be_define_const_str(cos, "cos", 4220379804u, 0, 3, &be_const_str_count); +be_define_const_str(count, "count", 967958004u, 0, 5, &be_const_str_remove); +be_define_const_str(remove, "remove", 3683784189u, 0, 6, NULL); +be_define_const_str(imax, "imax", 3084515410u, 0, 4, &be_const_str_rand); +be_define_const_str(rand, "rand", 2711325910u, 0, 4, NULL); +be_define_const_str(codedump, "codedump", 1786337906u, 0, 8, &be_const_str_deg); +be_define_const_str(deg, "deg", 3327754271u, 0, 3, &be_const_str_keys); +be_define_const_str(keys, "keys", 4182378701u, 0, 4, &be_const_str_setitem); +be_define_const_str(setitem, "setitem", 1554834596u, 0, 7, NULL); +be_define_const_str(def, "def", 3310976652u, 55, 3, &be_const_str_except); +be_define_const_str(except, "except", 950914032u, 69, 6, NULL); +be_define_const_str(classname, "classname", 1998589948u, 0, 9, &be_const_str_isinstance); +be_define_const_str(isinstance, "isinstance", 3669352738u, 0, 10, NULL); +be_define_const_str(cosh, "cosh", 4099687964u, 0, 4, NULL); static const bstring* const m_string_table[] = { - (const bstring *)&be_const_str_calldepth, - (const bstring *)&be_const_str_int, - (const bstring *)&be_const_str_concat, - (const bstring *)&be_const_str_dot_p, - NULL, - (const bstring *)&be_const_str_cosh, - (const bstring *)&be_const_str_abs, - (const bstring *)&be_const_str_hex, - (const bstring *)&be_const_str_tostring, - (const bstring *)&be_const_str_opt_add, - (const bstring *)&be_const_str_iter, - (const bstring *)&be_const_str_getcwd, - NULL, - (const bstring *)&be_const_str_allocated, - (const bstring *)&be_const_str_ceil, - (const bstring *)&be_const_str_format, - (const bstring *)&be_const_str_classname, - (const bstring *)&be_const_str_byte, - (const bstring *)&be_const_str_else, - (const bstring *)&be_const_str_deinit, - (const bstring *)&be_const_str___upper__, - (const bstring *)&be_const_str_char, - NULL, - (const bstring *)&be_const_str_deg, - NULL, - (const bstring *)&be_const_str_range, - (const bstring *)&be_const_str_, - NULL, - (const bstring *)&be_const_str_opt_neq, - (const bstring *)&be_const_str_lower, - (const bstring *)&be_const_str_count, - (const bstring *)&be_const_str_exit, - (const bstring *)&be_const_str_pop, - (const bstring *)&be_const_str_classof, - (const bstring *)&be_const_str_path, - (const bstring *)&be_const_str_input, - (const bstring *)&be_const_str_floor, - (const bstring *)&be_const_str_imin, - (const bstring *)&be_const_str_splitext, - NULL, - (const bstring *)&be_const_str_compile, - (const bstring *)&be_const_str_opt_eq, - (const bstring *)&be_const_str_codedump, - (const bstring *)&be_const_str_setitem, - (const bstring *)&be_const_str_tanh, - (const bstring *)&be_const_str_issubclass, - (const bstring *)&be_const_str_opt_connect, - (const bstring *)&be_const_str_try, - (const bstring *)&be_const_str_import, - (const bstring *)&be_const_str___lower__, - NULL, (const bstring *)&be_const_str_acos, - (const bstring *)&be_const_str___iterator__ + NULL, + (const bstring *)&be_const_str_int, + NULL, + (const bstring *)&be_const_str_iter, + (const bstring *)&be_const_str_opt_eq, + (const bstring *)&be_const_str_floor, + (const bstring *)&be_const_str_find, + (const bstring *)&be_const_str___upper__, + (const bstring *)&be_const_str_atan, + (const bstring *)&be_const_str_opt_add, + NULL, + (const bstring *)&be_const_str_classof, + (const bstring *)&be_const_str_byte, + (const bstring *)&be_const_str_clear, + (const bstring *)&be_const_str_opt_connect, + (const bstring *)&be_const_str_, + (const bstring *)&be_const_str_calldepth, + (const bstring *)&be_const_str___iterator__, + (const bstring *)&be_const_str_dot_p, + (const bstring *)&be_const_str___lower__, + (const bstring *)&be_const_str_char, + (const bstring *)&be_const_str_deinit, + (const bstring *)&be_const_str_srand, + (const bstring *)&be_const_str_imin, + (const bstring *)&be_const_str_tostring, + (const bstring *)&be_const_str_insert, + (const bstring *)&be_const_str_open, + (const bstring *)&be_const_str_allocated, + (const bstring *)&be_const_str_attrdump, + (const bstring *)&be_const_str_for, + (const bstring *)&be_const_str_opt_neq, + (const bstring *)&be_const_str_range, + (const bstring *)&be_const_str_compile, + (const bstring *)&be_const_str_resize, + (const bstring *)&be_const_str_continue, + (const bstring *)&be_const_str_log, + (const bstring *)&be_const_str_while, + (const bstring *)&be_const_str_pow, + (const bstring *)&be_const_str_cos, + (const bstring *)&be_const_str_imax, + (const bstring *)&be_const_str_codedump, + (const bstring *)&be_const_str_def, + (const bstring *)&be_const_str_classname, + (const bstring *)&be_const_str_cosh }; static const struct bconststrtab m_const_string_table = { - .size = 53, - .count = 107, + .size = 45, + .count = 90, .table = m_string_table }; diff --git a/lib/libesp32/Berry-0.1.10/generate/be_fixed_debug.h b/lib/libesp32/Berry-0.1.10/generate/be_fixed_debug.h index 4139381d9..d6ab2709c 100644 --- a/lib/libesp32/Berry-0.1.10/generate/be_fixed_debug.h +++ b/lib/libesp32/Berry-0.1.10/generate/be_fixed_debug.h @@ -1,19 +1,16 @@ #include "be_constobj.h" static be_define_const_map_slots(m_libdebug_map) { - { be_const_key(attrdump, -1), be_const_func(m_attrdump) }, - { be_const_key(upvname, -1), be_const_func(m_upvname) }, - { be_const_key(codedump, -1), be_const_func(m_codedump) }, - { be_const_key(top, -1), be_const_func(m_top) }, - { be_const_key(sethook, 3), be_const_func(m_sethook) }, - { be_const_key(varname, 7), be_const_func(m_varname) }, - { be_const_key(calldepth, -1), be_const_func(m_calldepth) }, { be_const_key(traceback, -1), be_const_func(m_traceback) }, + { be_const_key(codedump, -1), be_const_func(m_codedump) }, + { be_const_key(calldepth, -1), be_const_func(m_calldepth) }, + { be_const_key(top, -1), be_const_func(m_top) }, + { be_const_key(attrdump, 0), be_const_func(m_attrdump) }, }; static be_define_const_map( m_libdebug_map, - 8 + 5 ); static be_define_const_module( diff --git a/lib/libesp32/Berry-0.1.10/generate/be_fixed_os.h b/lib/libesp32/Berry-0.1.10/generate/be_fixed_os.h index 25022b87d..12eff88ab 100644 --- a/lib/libesp32/Berry-0.1.10/generate/be_fixed_os.h +++ b/lib/libesp32/Berry-0.1.10/generate/be_fixed_os.h @@ -1,24 +1,2 @@ #include "be_constobj.h" -static be_define_const_map_slots(m_libos_map) { - { be_const_key(listdir, 1), be_const_func(m_listdir) }, - { be_const_key(mkdir, -1), be_const_func(m_mkdir) }, - { be_const_key(chdir, -1), be_const_func(m_chdir) }, - { be_const_key(exit, 2), be_const_func(m_exit) }, - { be_const_key(system, -1), be_const_func(m_system) }, - { be_const_key(remove, 3), be_const_func(m_remove) }, - { be_const_key(path, -1), be_const_module(m_libpath) }, - { be_const_key(getcwd, -1), be_const_func(m_getcwd) }, -}; - -static be_define_const_map( - m_libos_map, - 8 -); - -static be_define_const_module( - m_libos, - "os" -); - -BE_EXPORT_VARIABLE be_define_const_native_module(os, NULL); diff --git a/lib/libesp32/Berry-0.1.10/generate/be_fixed_path.h b/lib/libesp32/Berry-0.1.10/generate/be_fixed_path.h new file mode 100644 index 000000000..12eff88ab --- /dev/null +++ b/lib/libesp32/Berry-0.1.10/generate/be_fixed_path.h @@ -0,0 +1,2 @@ +#include "be_constobj.h" + diff --git a/lib/libesp32/Berry-0.1.10/generate/be_fixed_sys.h b/lib/libesp32/Berry-0.1.10/generate/be_fixed_sys.h index 5fb85ceb0..12eff88ab 100644 --- a/lib/libesp32/Berry-0.1.10/generate/be_fixed_sys.h +++ b/lib/libesp32/Berry-0.1.10/generate/be_fixed_sys.h @@ -1,17 +1,2 @@ #include "be_constobj.h" -static be_define_const_map_slots(m_libsys_map) { - { be_const_key(path, -1), be_const_func(m_path) }, -}; - -static be_define_const_map( - m_libsys_map, - 1 -); - -static be_define_const_module( - m_libsys, - "sys" -); - -BE_EXPORT_VARIABLE be_define_const_native_module(sys, NULL); diff --git a/lib/libesp32/Berry-0.1.10/generate/be_fixed_time.h b/lib/libesp32/Berry-0.1.10/generate/be_fixed_time.h index 7c10c5fb9..12eff88ab 100644 --- a/lib/libesp32/Berry-0.1.10/generate/be_fixed_time.h +++ b/lib/libesp32/Berry-0.1.10/generate/be_fixed_time.h @@ -1,19 +1,2 @@ #include "be_constobj.h" -static be_define_const_map_slots(m_libtime_map) { - { be_const_key(dump, 1), be_const_func(m_dump) }, - { be_const_key(clock, -1), be_const_func(m_clock) }, - { be_const_key(time, 0), be_const_func(m_time) }, -}; - -static be_define_const_map( - m_libtime_map, - 3 -); - -static be_define_const_module( - m_libtime, - "time" -); - -BE_EXPORT_VARIABLE be_define_const_native_module(time, NULL); diff --git a/lib/libesp32/Berry-0.1.10/src/be_gc.c b/lib/libesp32/Berry-0.1.10/src/be_gc.c index 58a00f73a..37abd1f94 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_gc.c +++ b/lib/libesp32/Berry-0.1.10/src/be_gc.c @@ -310,7 +310,7 @@ static void free_ntvclos(bvm *vm, bgcobject *obj) while (count--) { be_free(vm, *uv++, sizeof(bupval)); } - be_free(vm, f, sizeof(bntvclos)); + be_free(vm, f, sizeof(bntvclos) + sizeof(bupval*) * f->nupvals); } } diff --git a/lib/libesp32/Berry-0.1.10/src/be_gc.h b/lib/libesp32/Berry-0.1.10/src/be_gc.h index 5943a7392..16ca7e766 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_gc.h +++ b/lib/libesp32/Berry-0.1.10/src/be_gc.h @@ -13,7 +13,7 @@ #define BE_GCOBJECT BE_STRING #define gc_object(o) cast(bgcobject*, o) -#define gc_cast(o, t, T) ((o) && pgm_read_byte(&(o)->type) == (t) ? (T*)(o) : NULL) +#define gc_cast(o, t, T) ((o) && (o)->type == (t) ? (T*)(o) : NULL) #define cast_proto(o) gc_cast(o, BE_PROTO, bproto) #define cast_closure(o) gc_cast(o, BE_CLOSURE, bclosure) #define cast_ntvclos(o) gc_cast(o, BE_NTVCLOS, bntvclos) @@ -38,11 +38,11 @@ if (!gc_isconst(o)) { \ #define gc_setwhite(o) gc_setmark((o), GC_WHITE) #define gc_setgray(o) gc_setmark((o), GC_GRAY) #define gc_setdark(o) gc_setmark((o), GC_DARK) -#define gc_isfixed(o) ((pgm_read_byte(&(o)->marked) & GC_FIXED) != 0) +#define gc_isfixed(o) (((o)->marked & GC_FIXED) != 0) #define gc_setfixed(o) ((o)->marked |= GC_FIXED) #define gc_clearfixed(o) ((o)->marked &= ~GC_FIXED) -#define gc_isconst(o) ((pgm_read_byte(&(o)->marked) & GC_CONST) != 0) -#define gc_exmark(o) ((pgm_read_byte(&(o)->marked) >> 4) & 0x0F) +#define gc_isconst(o) (((o)->marked & GC_CONST) != 0) +#define gc_exmark(o) (((o)->marked >> 4) & 0x0F) #define gc_setexmark(o, k) ((o)->marked |= (k) << 4) #define be_isgctype(t) ((t) >= BE_GCOBJECT) diff --git a/lib/libesp32/Berry-0.1.10/src/be_lexer.c b/lib/libesp32/Berry-0.1.10/src/be_lexer.c index b201e8df2..eea82109d 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_lexer.c +++ b/lib/libesp32/Berry-0.1.10/src/be_lexer.c @@ -105,8 +105,7 @@ static int next(blexer *lexer) lr->s = s ? s : &eos; --lr->len; } - // lexer->cursor = *lr->s++; // SH - lexer->cursor = pgm_read_byte(lr->s++); + lexer->cursor = *lr->s++; return lexer->cursor; } diff --git a/lib/libesp32/Berry-0.1.10/src/be_object.h b/lib/libesp32/Berry-0.1.10/src/be_object.h index dd73a8a87..d465138ec 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_object.h +++ b/lib/libesp32/Berry-0.1.10/src/be_object.h @@ -10,37 +10,6 @@ #include "berry.h" -/* support for PROGMEM on ESP8266 and AVR */ -#ifdef _PGMSPACE_H_ - #define strncmp strncmp_PP - #define strcmp(str1P, str2P) strncmp_PP((str1P), (str2P), SIZE_IRRELEVANT) - #define strncasecmp strncasecmp_P - #define strcasecmp_P(str1, str2P) strncasecmp_P((str1), (str2P), SIZE_IRRELEVANT) - #define strlen strlen_P - #define strchr strchr_P - #define strcat strcat_P - #define strncat strncat_P - #define strcpy strcpy_P - #define strncpy strncpy_P - #define memcpy memcpy_P - #define memccpy memccpy_P - #define memmove memmove_P - #define memcmp memcmp_P - #define memmem memmem_P - #define memchr memchr_P - #define sprintf sprintf_P - #define snprintf snprintf_P -#endif - -#ifndef pgm_read_byte -#define pgm_read_byte(addr) (*(const uint8_t*)(addr)) -#endif - -#ifndef pgm_read_word -#define pgm_read_word(addr) (*(const uint16_t*)(addr)) -#endif - - /* basic types, do not change value */ #define BE_NONE (-1) /* unknow type */ #define BE_COMPTR (-2) /* common pointer */ diff --git a/lib/libesp32/Berry-0.1.10/src/be_parser.c b/lib/libesp32/Berry-0.1.10/src/be_parser.c index bdfdcaf3d..1839e9392 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_parser.c +++ b/lib/libesp32/Berry-0.1.10/src/be_parser.c @@ -31,7 +31,7 @@ #define FUNC_ANONYMOUS 2 /* get binary operator priority */ -#define binary_op_prio(op) (pgm_read_byte(&binary_op_prio_tab[cast_int(op) - OptAdd])) +#define binary_op_prio(op) (binary_op_prio_tab[cast_int(op) - OptAdd]) #define scan_next_token(parser) (be_lexer_scan_next(&(parser)->lexer)) #define next_token(parser) ((parser)->lexer.token) diff --git a/lib/libesp32/Berry-0.1.10/src/be_string.c b/lib/libesp32/Berry-0.1.10/src/be_string.c index 0590fb396..db7dcaebf 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_string.c +++ b/lib/libesp32/Berry-0.1.10/src/be_string.c @@ -44,9 +44,9 @@ int be_eqstr(bstring *s1, bstring *s2) if (s1 == s2) { /* short string or the same string */ return 1; } - slen = pgm_read_byte(&s1->slen); + slen = s1->slen; /* long string */ - if (slen == 255 && slen == pgm_read_byte(&s2->slen)) { + if (slen == 255 && slen == s2->slen) { blstring *ls1 = cast(blstring*, s1); blstring *ls2 = cast(blstring*, s2); return ls1->llen == ls2->llen && !strcmp(lstr(ls1), lstr(ls2)); @@ -88,7 +88,7 @@ static void resize(bvm *vm, int size) static void free_sstring(bvm *vm, bstring *str) { - be_free(vm, str, sizeof(bsstring) + pgm_read_byte(&str->slen) + 1); + be_free(vm, str, sizeof(bsstring) + str->slen + 1); } /* FNV-1a Hash */ @@ -97,8 +97,7 @@ static uint32_t str_hash(const char *str, size_t len) uint32_t hash = 2166136261u; be_assert(str || len); while (len--) { - hash = (hash ^ (unsigned char)pgm_read_byte(str)) * 16777619u; - str++; + hash = (hash ^ (unsigned char)*str++) * 16777619u; } return hash; } @@ -150,7 +149,7 @@ static bstring* find_conststr(const char *str, size_t len) uint32_t hash = str_hash(str, len); bcstring *s = (bcstring*)tab->table[hash % tab->size]; for (; s != NULL; s = next(s)) { - if (len == pgm_read_byte(&s->slen) && !strncmp(str, s->s, len)) { + if (len == s->slen && !strncmp(str, s->s, len)) { return (bstring*)s; } } @@ -166,7 +165,7 @@ static bstring* newshortstr(bvm *vm, const char *str, size_t len) bstring **list = vm->strtab.table + (hash & (size - 1)); for (s = *list; s != NULL; s = next(s)) { - if (len == pgm_read_byte(&s->slen) && !strncmp(str, sstr(s), len)) { + if (len == s->slen && !strncmp(str, sstr(s), len)) { return s; } } @@ -253,7 +252,7 @@ uint32_t be_strhash(const bstring *s) return cast(bcstring*, s)->hash; } #if BE_USE_STR_HASH_CACHE - if (pgm_read_byte(&s->slen) != 255) { + if (s->slen != 255) { return cast(bsstring*, s)->hash; } #endif @@ -266,7 +265,7 @@ const char* be_str2cstr(const bstring *s) if (gc_isconst(s)) { return cstr(s); } - if (pgm_read_byte(&s->slen) == 255) { + if (s->slen == 255) { return lstr(s); } return sstr(s); @@ -277,4 +276,4 @@ void be_str_setextra(bstring *s, int extra) if (!gc_isconst(s)) { s->extra = cast(bbyte, extra); } -} \ No newline at end of file +} diff --git a/lib/libesp32/Berry-0.1.10/src/be_string.h b/lib/libesp32/Berry-0.1.10/src/be_string.h index 8d3fba49e..51b3fd016 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_string.h +++ b/lib/libesp32/Berry-0.1.10/src/be_string.h @@ -33,7 +33,7 @@ typedef struct { } bcstring; #define str_len(_s) \ - (pgm_read_byte(&(_s)->slen) == 255 ? cast(blstring*, _s)->llen : pgm_read_byte(&(_s)->slen)) + ((_s)->slen == 255 ? cast(blstring*, _s)->llen : (_s)->slen) #define str(_s) be_str2cstr(_s) #define str_extra(_s) ((_s)->extra) diff --git a/lib/libesp32/Berry-0.1.10/src/be_strlib.c b/lib/libesp32/Berry-0.1.10/src/be_strlib.c index 37fe8e12b..499383774 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_strlib.c +++ b/lib/libesp32/Berry-0.1.10/src/be_strlib.c @@ -176,7 +176,7 @@ const char* be_pushvfstr(bvm *vm, const char *format, va_list arg) } pushstr(vm, format, p - format); concat2(vm); - switch (pgm_read_byte(&p[1])) { + switch (p[1]) { case 's': { const char *s = va_arg(arg, char*); if (s == NULL) { @@ -339,8 +339,8 @@ bstring* be_strindex(bvm *vm, bstring *str, bvalue *idx) const char* be_splitpath(const char *path) { const char *p; - for (p = path - 1; pgm_read_byte(path) != '\0'; ++path) { - if (pgm_read_byte(path) == '/') { + for (p = path - 1; *path != '\0'; ++path) { + if (*path == '/') { p = path; } } diff --git a/lib/libesp32/Berry-0.1.10/src/be_vector.c b/lib/libesp32/Berry-0.1.10/src/be_vector.c index 2cd3f1e2e..b73479601 100644 --- a/lib/libesp32/Berry-0.1.10/src/be_vector.c +++ b/lib/libesp32/Berry-0.1.10/src/be_vector.c @@ -122,16 +122,16 @@ static int binary_search(int value) const uint16_t *high = tab + array_count(tab) - 1; while (low <= high) { const uint16_t *mid = low + ((high - low) >> 1); - if (pgm_read_word(mid) == value) { - return pgm_read_word(&mid[1]); + if (*mid == value) { + return mid[1]; } - if (pgm_read_word(mid) < value) { + if (*mid < value) { low = mid + 1; } else { high = mid - 1; } } - return pgm_read_word(low); + return *low; } static int nextpow(int value) diff --git a/lib/libesp32/Berry-0.1.10/src/port/be_modtab.c b/lib/libesp32/Berry-0.1.10/src/port/be_modtab.c index eb83cf5a2..b3e763fec 100644 --- a/lib/libesp32/Berry-0.1.10/src/port/be_modtab.c +++ b/lib/libesp32/Berry-0.1.10/src/port/be_modtab.c @@ -20,7 +20,8 @@ be_extern_native_module(debug); be_extern_native_module(gc); /* Tasmota specific */ -be_extern_native_module(tasmota); +be_extern_native_module(tasmota_ntv); +be_extern_native_module(wire); /* user-defined modules declare start */ @@ -55,7 +56,8 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = { #endif /* user-defined modules register start */ - &be_native_module(tasmota), + &be_native_module(tasmota_ntv), + &be_native_module(wire), /* user-defined modules register end */ NULL /* do not remove */ diff --git a/lib/libesp32/Berry-0.1.10/src/port/be_tasmotalib.c b/lib/libesp32/Berry-0.1.10/src/port/be_tasmotalib.c index 3e0736fd0..098cb3844 100644 --- a/lib/libesp32/Berry-0.1.10/src/port/be_tasmotalib.c +++ b/lib/libesp32/Berry-0.1.10/src/port/be_tasmotalib.c @@ -13,9 +13,16 @@ extern int l_millis(bvm *vm); extern int l_timereached(bvm *vm); extern int l_yield(bvm *vm); +extern int l_respCmnd(bvm *vm); +extern int l_respCmndStr(bvm *vm); +extern int l_respCmndDone(bvm *vm); +extern int l_respCmndError(bvm *vm); +extern int l_respCmndFailed(bvm *vm); + // #if !BE_USE_PRECOMPILED_OBJECT #if 1 // TODO we will do pre-compiled later -be_native_module_attr_table(tasmota) { + +be_native_module_attr_table(tasmota_ntv) { be_native_module_function("getfreeheap", l_getFreeHeap), be_native_module_function("publish", l_publish), be_native_module_function("cmd", l_cmd), @@ -23,9 +30,17 @@ be_native_module_attr_table(tasmota) { be_native_module_function("millis", l_millis), be_native_module_function("timereached", l_timereached), be_native_module_function("yield", l_yield), + + be_native_module_function("respcmnd", l_respCmnd), + be_native_module_function("respcmndstr", l_respCmndStr), + be_native_module_function("respcmnd_done", l_respCmndDone), + be_native_module_function("respcmnd_error", l_respCmndError), + be_native_module_function("respcmnd_failed", l_respCmndFailed), + + be_native_module_str("_operators", "=<>!|"), }; -be_define_native_module(tasmota, NULL); +be_define_native_module(tasmota_ntv, NULL); #else /* @const_object_info_begin module tasmota (scope: global, depend: 1) { diff --git a/lib/libesp32/Berry-0.1.10/src/port/be_wirelib.c b/lib/libesp32/Berry-0.1.10/src/port/be_wirelib.c new file mode 100644 index 000000000..b52865710 --- /dev/null +++ b/lib/libesp32/Berry-0.1.10/src/port/be_wirelib.c @@ -0,0 +1,36 @@ +/******************************************************************** + * Tasmota lib + * + * To use: `import wire` + * + * 2 wire communication - I2C + *******************************************************************/ +#include "be_object.h" + +extern int b_wire_begintransmission(bvm *vm); +extern int b_wire_endtransmission(bvm *vm); +extern int b_wire_requestfrom(bvm *vm); +extern int b_wire_available(bvm *vm); +extern int b_wire_write(bvm *vm); +extern int b_wire_read(bvm *vm); + +// #if !BE_USE_PRECOMPILED_OBJECT +#if 1 // TODO we will do pre-compiled later +be_native_module_attr_table(wire) { + be_native_module_function("begintransmission", b_wire_begintransmission), + be_native_module_function("endtransmission", b_wire_endtransmission), + be_native_module_function("requestfrom", b_wire_requestfrom), + be_native_module_function("available", b_wire_available), + be_native_module_function("write", b_wire_write), + be_native_module_function("read", b_wire_read), +}; + +be_define_native_module(wire, NULL); +#else +/* @const_object_info_begin +module tasmota (scope: global, depend: 1) { + getfreeheap, func(l_getFreeHeap) +} +@const_object_info_end */ +#include "../generate/be_fixed_tasmota.h" +#endif diff --git a/lib/libesp32/Berry-0.1.10/src/port/berry_conf.h b/lib/libesp32/Berry-0.1.10/src/port/berry_conf.h index 820207003..94f0c27b3 100644 --- a/lib/libesp32/Berry-0.1.10/src/port/berry_conf.h +++ b/lib/libesp32/Berry-0.1.10/src/port/berry_conf.h @@ -8,19 +8,6 @@ #ifndef BERRY_CONF_H #define BERRY_CONF_H -#include - -#ifdef __cplusplus -extern "C" { -#endif - - extern int strncmp_PP(const char * str1P, const char * str2P, size_t size); - extern char * strchr_P(const char *s, int c); - -#ifdef __cplusplus -} -#endif - #include /* Macro: BE_DEBUG @@ -53,12 +40,12 @@ extern "C" { * Use precompiled objects to avoid creating these objects at * runtime. Enable this macro can greatly optimize RAM usage. * Default: 1 - **/ -#ifdef ESP8266 -#define BE_USE_PRECOMPILED_OBJECT 0 -#else -#define BE_USE_PRECOMPILED_OBJECT 0 // will enable later when stabilized -#endif +// **/ +// #ifdef ESP8266 +// #define BE_USE_PRECOMPILED_OBJECT 0 +// #else +#define BE_USE_PRECOMPILED_OBJECT 1 // will enable later when stabilized +// #endif /* Macro: BE_DEBUG_RUNTIME_INFO * Set runtime error debugging information. diff --git a/tasmota/berry/tasmota.be b/tasmota/berry/tasmota.be index 8129b0a6e..213eb0be0 100644 --- a/tasmota/berry/tasmota.be +++ b/tasmota/berry/tasmota.be @@ -20,6 +20,26 @@ def charsinstring(s,c) return -1 end +### +class Tasmota + var _op, _operators, _rules + def init() + self._operators = "=<>!|" + self._op = [ + ['==', /s1,s2-> str(s1) == str(s2)], + ['!==',/s1,s2-> str(s1) != str(s2)], + ['=', /f1,f2-> real(f1) == real(f2)], + ['!=', /f1,f2-> real(f1) != real(f2)], + ['>=', /f1,f2-> real(f1) >= real(f2)], + ['<=', /f1,f2-> real(f1) <= real(f2)], + ['>', /f1,f2-> real(f1) > real(f2)], + ['<', /f1,f2-> real(f1) < real(f2)], + ] + self._rules = {} + end +end +### + tasmota._eqstr=/s1,s2-> str(s1) == str(s2) tasmota._neqstr=/s1,s2-> str(s1) != str(s2) tasmota._eq=/f1,f2-> real(f1) == real(f2) diff --git a/tasmota/xdrv_52_3_berry_native.ino b/tasmota/xdrv_52_3_berry_native.ino new file mode 100644 index 000000000..22cf0b9f1 --- /dev/null +++ b/tasmota/xdrv_52_3_berry_native.ino @@ -0,0 +1,323 @@ +/* + xdrv_52_3_berry_native.ino - Berry scripting language, native fucnctions + + Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +#ifdef USE_BERRY + +#include +#include + +/*********************************************************************************************\ + * Native functions mapped to Berry functions + * + * log(msg:string [,log_level:int]) ->nil + * + * import tasmota + * + * tasmota.getfreeheap() -> int + * tasmota.publish(topic:string, payload:string[, retain:bool]) -> nil + * tasmota.cmd(command:string) -> string + * tasmota.getoption(index:int) -> int + * tasmota.millis([delay:int]) -> int + * tasmota.timereached(timer:int) -> bool + * tasmota.yield() -> nil + * +\*********************************************************************************************/ +extern "C" { + // Berry: `tasmota.publish(topic, payload [,retain]) -> nil`` + // + int32_t l_publish(struct bvm *vm); + int32_t l_publish(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top >= 2 && be_isstring(vm, 1) && be_isstring(vm, 2)) { // 2 mandatory string arguments + if (top == 2 || (top == 3 && be_isbool(vm, 3))) { // 3rd optional argument must be bool + const char * topic = be_tostring(vm, 1); + const char * payload = be_tostring(vm, 2); + bool retain = false; + if (top == 3) { + retain = be_tobool(vm, 3); + } + strlcpy(TasmotaGlobal.mqtt_data, payload, sizeof(TasmotaGlobal.mqtt_data)); + MqttPublish(topic, retain); + be_return(vm); // Return + } + } + be_return_nil(vm); // Return nil when something goes wrong + } + + // Berry: `tasmota.cmd(command:string) -> string` + // + int32_t l_cmd(struct bvm *vm); + int32_t l_cmd(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 1 && be_isstring(vm, 1)) { // only 1 argument of type string accepted + const char * command = be_tostring(vm, 1); + ExecuteCommand(command, SRC_BERRY); + be_pushstring(vm, TasmotaGlobal.mqtt_data); + be_return(vm); // Return + } + be_return_nil(vm); // Return nil when something goes wrong + } + + // Berry: tasmota.millis([delay:int]) -> int + // + int32_t l_millis(struct bvm *vm); + int32_t l_millis(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 0 || (top == 1 && be_isint(vm, 1))) { // only 1 argument of type string accepted + uint32_t delay = 0; + if (top == 1) { + delay = be_toint(vm, 1); + } + uint32_t ret_millis = millis() + delay; + be_pushint(vm, ret_millis); + be_return(vm); // Return + } + be_return_nil(vm); // Return nil when something goes wrong + } + + // Berry: tasmota.getoption(index:int) -> int + // + int32_t l_getoption(struct bvm *vm); + int32_t l_getoption(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 1 && be_isint(vm, 1)) { + uint32_t opt = GetOption(be_toint(vm, 1)); + be_pushint(vm, opt); + be_return(vm); // Return + } + be_return_nil(vm); // Return nil when something goes wrong + } + + // Berry: tasmota.timereached(timer:int) -> bool + // + int32_t l_timereached(struct bvm *vm); + int32_t l_timereached(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 1 && be_isint(vm, 1)) { // only 1 argument of type string accepted + uint32_t timer = be_toint(vm, 1); + bool reached = TimeReached(timer); + be_pushbool(vm, reached); + be_return(vm); // Return + } + be_return_nil(vm); // Return nil when something goes wrong + } + + // Berry: `yield() -> nil` + // ESP object + int32_t l_yield(bvm *vm); + int32_t l_yield(bvm *vm) { + optimistic_yield(10); + be_return(vm); + } + + // Berry: `save(file:string, f:closure) -> bool` + int32_t l_save(struct bvm *vm); + int32_t l_save(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top ==2 && be_isstring(vm, 1) && be_isclosure(vm, 2)) { // only 1 argument of type string accepted + const char *fname = be_tostring(vm, 1); + int32_t ret = be_savecode(vm, fname); + be_pushint(vm, ret); + be_return(vm); // Return + } + be_return_nil(vm); // Return nil when something goes wrong + } + + int32_t l_respCmnd(bvm *vm); + int32_t l_respCmnd(bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 1) { + const char *msg = be_tostring(vm, 1); + Response_P("%s", msg); + } + be_return_nil(vm); // Return nil when something goes wrong + } + + int32_t l_respCmndStr(bvm *vm); + int32_t l_respCmndStr(bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 1) { + const char *msg = be_tostring(vm, 1); + ResponseCmndChar(msg); + } + be_return_nil(vm); // Return nil when something goes wrong + } + + int32_t l_respCmndDone(bvm *vm); + int32_t l_respCmndDone(bvm *vm) { + ResponseCmndDone(); + be_return_nil(vm); + } + + int32_t l_respCmndError(bvm *vm); + int32_t l_respCmndError(bvm *vm) { + ResponseCmndError(); + be_return_nil(vm); + } + + int32_t l_respCmndFailed(bvm *vm); + int32_t l_respCmndFailed(bvm *vm) { + ResponseCmndFailed(); + be_return_nil(vm); + } +} + +/*********************************************************************************************\ + * Native functions mapped to Berry functions + * + * import wire + * + * wire.getfreeheap() -> int + * +\*********************************************************************************************/ +extern "C" { + // Berry: `begintransmission(address:int) -> nil` + int32_t b_wire_begintransmission(struct bvm *vm); + int32_t b_wire_begintransmission(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 1 && be_isint(vm, 1)) { // only 1 argument of type string accepted + int32_t address = be_toint(vm, 1); + Wire.beginTransmission(address); + be_return(vm); // Return + } + be_return_nil(vm); // Return nil when something goes wrong + } + + // Berry: `endtransmission([stop:bool]) -> nil` + int32_t b_wire_endtransmission(struct bvm *vm); + int32_t b_wire_endtransmission(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 0 || (top == 1 && be_isbool(vm, 1))) { // only 1 argument of type string accepted + bool stop = true; + if (top == 1) { + stop = be_tobool(vm, 1); + } + uint32_t ret = Wire.endTransmission(stop); + be_pushint(vm, ret); + be_return(vm); // Return + } + be_return_nil(vm); // Return nil when something goes wrong + } + + // Berry: `requestfrom(address:int, quantity:int [stop:bool = true]) -> nil` + int32_t b_wire_requestfrom(struct bvm *vm); + int32_t b_wire_requestfrom(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if ( (top == 2 || (top == 3 && be_isbool(vm, 3))) + && be_isint(vm, 1) && be_isint(vm, 2) ) { + int32_t address = be_toint(vm, 1); + int32_t quantity = be_toint(vm, 2); + bool stop = true; + if (top == 3) { + stop = be_tobool(vm, 3); + } + Wire.requestFrom((uint16_t)address, (uint8_t)quantity, stop); + be_return(vm); // Return + } + be_return_nil(vm); // Return nil when something goes wrong + } + + // Berry: `available() -> bool` + int32_t b_wire_available(struct bvm *vm); + int32_t b_wire_available(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 0) { + size_t available = Wire.available(); + be_pushint(vm, available); + be_return(vm); // Return + } + be_return_nil(vm); // Return nil when something goes wrong + } + + // Berry: `write(value:int | s:string) -> nil` + int32_t b_wire_write(struct bvm *vm); + int32_t b_wire_write(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 1 && (be_isint(vm, 1) || be_isint(vm, 1))) { + if (be_isint(vm, 1)) { + int32_t value = be_toint(vm, 1); + Wire.write(value); + } else if (be_isstring(vm, 1)) { + const char * s = be_tostring(vm, 1); + Wire.write(s); + } else { + be_return_nil(vm); + } + be_return(vm); // Return + } + be_return_nil(vm); // Return nil when something goes wrong + } + + // Berry: `read() -> int` + int32_t b_wire_read(struct bvm *vm); + int32_t b_wire_read(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 0) { + int32_t value = Wire.read(); + be_pushint(vm, value); + be_return(vm); // Return + } + be_return_nil(vm); // Return nil when something goes wrong + } + +} + +/*********************************************************************************************\ + * Native functions mapped to Berry functions + * + * log(msg:string [,log_level:int]) ->nil + * +\*********************************************************************************************/ +extern "C" { + // Berry: `log(msg:string [,log_level:int]) ->nil` + // Logs the string at LOG_LEVEL_INFO (loglevel=2) + int32_t l_logInfo(struct bvm *vm); + int32_t l_logInfo(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top >= 1 && be_isstring(vm, 1)) { // only 1 argument of type string accepted + const char * msg = be_tostring(vm, 1); + uint32_t log_level = LOG_LEVEL_INFO; + if (top >= 2 && be_isint(vm, 2)) { + log_level = be_toint(vm, 2); + if (log_level > LOG_LEVEL_DEBUG_MORE) { log_level = LOG_LEVEL_DEBUG_MORE; } + } + AddLog(log_level, PSTR("%s"), msg); + be_return(vm); // Return + } + be_return_nil(vm); // Return nil when something goes wrong + } + + // Berry: `getFreeHeap() -> int` + // ESP object + int32_t l_getFreeHeap(bvm *vm); + int32_t l_getFreeHeap(bvm *vm) { + be_pushint(vm, ESP.getFreeHeap()); + be_return(vm); + } +} + +// called as a replacement to Berry `print()` +void berry_log(const char * berry_buf); +void berry_log(const char * berry_buf) { + AddLog(LOG_LEVEL_INFO, PSTR("%s"), berry_buf); +} + + +#endif // USE_BERRY diff --git a/tasmota/xdrv_52_7_berry_embedded.ino b/tasmota/xdrv_52_7_berry_embedded.ino new file mode 100644 index 000000000..4904210d1 --- /dev/null +++ b/tasmota/xdrv_52_7_berry_embedded.ino @@ -0,0 +1,281 @@ +/* + xdrv_52_3_berry_embedded.ino - Berry scripting language, embedded code + + Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +#ifdef USE_BERRY + +/*********************************************************************************************\ + * Handlers for Berry calls and async + * +\*********************************************************************************************/ + +const char berry_prog[] = + "" + //"def func(x) for i:1..x print('a') end end " + //"def testreal() return str(1.2+1) end " + //"def noop() log('noop before'); yield(); log('middle after'); yield(); log('noop after'); end " + //"log(\"foobar\") " + + // auto-import modules + // // import alias + "import wire " + + // Phase 1 + // Prepare the super class that will be eventually in Flash + "class Tasmota_ntv " + "var _op, _operators, _rules, _timers, _cmd " + + // Map all native functions to methods + // Again, this will be eventually pre-compiled + "var getfreeheap, publish, cmd, getoption, millis, timereached, yield " + "var respcmnd, respcmndstr, respcmnd_done, respcmnd_error, respcmnd_failed " + "def init_ntv() " + "import tasmota_ntv " + "self.getfreeheap = tasmota_ntv.getfreeheap " + "self.publish = tasmota_ntv.publish " + "self.cmd = tasmota_ntv.cmd " + "self.getoption = tasmota_ntv.getoption " + "self.millis = tasmota_ntv.millis " + "self.timereached = tasmota_ntv.timereached " + "self.yield = tasmota_ntv.yield " + "self._operators = tasmota_ntv._operators " + + "self.respcmnd = tasmota_ntv.respcmnd " + "self.respcmndstr = tasmota_ntv.respcmndstr " + "self.respcmnd_done = tasmota_ntv.respcmnd_done " + "self.respcmnd_error = tasmota_ntv.respcmnd_error " + "self.respcmnd_failed = tasmota_ntv.respcmnd_failed " + "end " + + "def init() " + "self._op = [ " + "['==', /s1,s2-> str(s1) == str(s2)]," + "['!==',/s1,s2-> str(s1) != str(s2)]," + "['=', /f1,f2-> real(f1) == real(f2)]," + "['!=', /f1,f2-> real(f1) != real(f2)]," + "['>=', /f1,f2-> real(f1) >= real(f2)]," + "['<=', /f1,f2-> real(f1) <= real(f2)]," + "['>', /f1,f2-> real(f1) > real(f2)]," + "['<', /f1,f2-> real(f1) < real(f2)]," + "] " + "self._rules = {} " + "self._timers = [] " + "self._cmd = {} " + "self.init_ntv() " + "end " + "end " + + "class Tasmota: Tasmota_ntv " + // add `charsinstring(s:string,c:string) -> int`` + // looks for any char in c, and return the position of the first chat + // or -1 if not found + "def charsinstring(s,c) " + "for i:0..size(s)-1 " + "for j:0..size(c)-1 " + "if s[i] == c[j] return i end " + "end " + "end " + "return -1 " + "end " + + // find a key in map, case insensitive, return actual key or nil if not found + "def findkeyi(m,keyi) " + "import string " + "var keyu = string.toupper(keyi) " + "if classof(m) == map " + "for k:m.keys() " + "if string.toupper(k)==keyu || keyi=='?' " + "return k " + "end " + "end " + "end " + "end " + + // Rules + "def addrule(pat,f) self._rules[pat] = f end " + + // # split the item when there is an operator, returns a list of (left,op,right) + // # ex: "Dimmer>50" -> ["Dimmer",tasmota_gt,"50"] + "def find_op(item) " + "import string " + "var pos = self.charsinstring(item, self._operators) " + "if pos>=0 " + "var op_split = string.split(item,pos) " + // #print(op_split) + "var op_left = op_split[0] " + "var op_rest = op_split[1] " + // # iterate through operators + "for op: self._op " + "if string.find(op_rest,op[0]) == 0 " + "var op_func = op[1] " + "var op_right = string.split(op_rest,size(op[0]))[1] " + "return [op_left,op_func,op_right] " + "end " + "end " + "end " + "return [item, nil, nil] " + "end " + + // Rules trigger if match. return true if match, false if not + // Note: condition is not yet managed + "def try_rule(ev, rule, f) " + "import string " + "var rl_list = self.find_op(rule) " + "var e=ev " + "var rl=string.split(rl_list[0],'#') " + "for it:rl " + "found=self.findkeyi(e,it) " + "if found == nil " + "return false " + "end " + "e=e[found] " + "end " + // # check if condition is true + "if rl_list[1] " + // # did we find a function + "if !rl_list[1](e,rl_list[2]) " + // # condition is not met + "return false " + "end " + "end " + "f(e,ev) " + "return true " + "end " + + // Run rules, i.e. check each individual rule + // Returns true if at least one rule matched, false if none + "def exec_rules(ev_json) " + "import json " + "var ev = json.load(ev_json) " + "var ret = false " + "if ev == nil " + "print('BRY: ERROR, bad json: '+ev_json, 3) " + "else " + "for r: self._rules.keys() " + "ret = self.try_rule(ev,r,self._rules[r]) || ret " + "end " + "end " + "return ret " + "end " + + "def settimer(delay,f) self._timers.push([self.millis(delay),f]) end " + + "def run_deferred() " + "var i=0 " + "while i. +*/ + + +#ifdef USE_BERRY + +#define XDRV_52 52 + +#include + +const char kBrCommands[] PROGMEM = D_PRFX_BR "|" // prefix + D_CMND_BR_RUN "|" D_CMND_BR_RESET + ; + +void (* const BerryCommand[])(void) PROGMEM = { + CmndBrRun, CmndBrReset, + }; + +class BerrySupport { +public: + bvm *vm = nullptr; // berry vm + bool rules_busy = false; // are we already processing rules, avoid infinite loop + const char *fname = nullptr; // name of berry function to call + int32_t fret = 0; +}; +BerrySupport berry; + +// +// Sanity Check for be_top() +// +// Checks that the Berry stack is empty, if not print a Warning and empty it +// +void checkBeTop(void) { + int32_t top = be_top(berry.vm); + if (top != 0) { + be_pop(berry.vm, top); // TODO should not be there + AddLog(LOG_LEVEL_ERROR, D_LOG_BERRY "Error be_top is non zero=%d", top); + } +} + +/*********************************************************************************************\ + * Handlers for Berry calls and async + * +\*********************************************************************************************/ +// // call a function (if exists) of type void -> void +// void callBerryFunctionVoid_berry(const char * fname) { +// berry.fret = 0; +// callBerryFunctionVoid(berry.fname); +// } + +bool callBerryRule(void) { + if (berry.rules_busy) { return false; } + berry.rules_busy = true; + char * json_event = TasmotaGlobal.mqtt_data; + bool serviced = false; + + checkBeTop(); + be_getglobal(berry.vm, "_exec_rules"); + if (!be_isnil(berry.vm, -1)) { + + // { + // String event_saved = TasmotaGlobal.mqtt_data; + // // json_event = {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089}} + // // json_event = {"System":{"Boot":1}} + // // json_event = {"SerialReceived":"on"} - invalid but will be expanded to {"SerialReceived":{"Data":"on"}} + // char *p = strchr(json_event, ':'); + // if ((p != NULL) && !(strchr(++p, ':'))) { // Find second colon + // event_saved.replace(F(":"), F(":{\"Data\":")); + // event_saved += F("}"); + // // event_saved = {"SerialReceived":{"Data":"on"}} + // } + // be_pushstring(berry.vm, event_saved.c_str()); + // } + be_pushstring(berry.vm, TasmotaGlobal.mqtt_data); + int ret = be_pcall(berry.vm, 1); + serviced = be_tobool(berry.vm, 1); + AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Event (%s) serviced=%d"), TasmotaGlobal.mqtt_data, serviced); + be_pop(berry.vm, 2); // remove function object + } else { + be_pop(berry.vm, 1); // remove nil object + } + checkBeTop(); + berry.rules_busy = false; + + return serviced; // TODO event not handled +} + +bool callBerryCommand(void) { + const char * command = nullptr; + + checkBeTop(); + be_getglobal(berry.vm, "_exec_cmd"); + if (!be_isnil(berry.vm, -1)) { + be_pushstring(berry.vm, XdrvMailbox.topic); + be_pushint(berry.vm, XdrvMailbox.index); + be_pushstring(berry.vm, XdrvMailbox.data); + int ret = be_pcall(berry.vm, 3); + command = be_tostring(berry.vm, 3); + strlcpy(XdrvMailbox.topic, command, CMDSZ); + // AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Command (%s) serviced=%d"), XdrvMailbox.command, serviced); + be_pop(berry.vm, 4); // remove function object + } else { + be_pop(berry.vm, 1); // remove nil object + } + checkBeTop(); + + return command != nullptr; // TODO event not handled +} + +size_t callBerryGC(void) { + size_t ram_used = 0; + checkBeTop(); + be_getglobal(berry.vm, "_gc"); + if (!be_isnil(berry.vm, -1)) { + int ret = be_pcall(berry.vm, 0); + ram_used = be_toint(berry.vm, 1); + be_pop(berry.vm, 1); // remove function object + } else { + be_pop(berry.vm, 1); // remove nil object + } + checkBeTop(); + + return ram_used; +} + +// void callBerryMqttData(void) { +// AddLog(LOG_LEVEL_INFO, D_LOG_BERRY "callBerryMqttData"); +// if (nullptr == berry.vm) { return; } +// if (XdrvMailbox.data_len < 1) { +// return; +// } +// const char * topic = XdrvMailbox.topic; +// const char * payload = XdrvMailbox.data; + +// checkBeTop(); +// be_getglobal(berry.vm, "mqtt_data_dispatch"); +// if (!be_isnil(berry.vm, -1)) { +// be_pushstring(berry.vm, topic); +// be_pushstring(berry.vm, payload); +// be_pcall(berry.vm, 0); +// be_pop(berry.vm, 3); // remove function object +// } else { +// be_pop(berry.vm, 1); // remove nil object +// } +// checkBeTop(); +// } + +// call a function (if exists) of type void -> void +void callBerryFunctionVoid(const char * fname) { + if (nullptr == berry.vm) { return; } + checkBeTop(); + be_getglobal(berry.vm, fname); + if (!be_isnil(berry.vm, -1)) { + be_pcall(berry.vm, 0); + } + be_pop(berry.vm, 1); // remove function or nil object + checkBeTop(); +} + +/*********************************************************************************************\ + * VM Init +\*********************************************************************************************/ +extern "C" { + extern size_t be_gc_memcount(bvm *vm); + extern void be_gc_collect(bvm *vm); +} +void BrReset(void) { + // clean previous VM if any + if (berry.vm != nullptr) { + be_vm_delete(berry.vm); + berry.vm = nullptr; + } + + int32_t ret_code1, ret_code2; + bool berry_init_ok = false; + do { + berry.vm = be_vm_new(); /* create a virtual machine instance */ + // AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry VM created, RAM used=%u"), be_gc_memcount(berry.vm)); + + // Register functions + be_regfunc(berry.vm, PSTR("log"), l_logInfo); + be_regfunc(berry.vm, PSTR("save"), l_save); + + // AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry function registered, RAM used=%u"), be_gc_memcount(berry.vm)); + + ret_code1 = be_loadstring(berry.vm, berry_prog); + if (ret_code1 != 0) { + AddLog(LOG_LEVEL_ERROR, PSTR(D_LOG_BERRY "ERROR: be_loadstring [%s] %s"), be_tostring(berry.vm, -2), be_tostring(berry.vm, -1)); + be_pop(berry.vm, 2); + break; + } + // AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry code loaded, RAM used=%u"), be_gc_memcount(berry.vm)); + ret_code2 = be_pcall(berry.vm, 0); + if (ret_code1 != 0) { + AddLog(LOG_LEVEL_ERROR, PSTR(D_LOG_BERRY "ERROR: be_pcall [%s] %s"), be_tostring(berry.vm, -2), be_tostring(berry.vm, -1)); + be_pop(berry.vm, 2); + break; + } + // AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Berry code ran, RAM used=%u"), be_gc_memcount(berry.vm)); + be_pop(berry.vm, 1); + + be_gc_collect(berry.vm); + AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_BERRY "Berry initialized, RAM used=%u"), callBerryGC()); + // AddLog(LOG_LEVEL_INFO, PSTR("Delete Berry VM")); + // be_vm_delete(vm); + // AddLog(LOG_LEVEL_INFO, PSTR("After Berry")); + + berry_init_ok = true; + } while (0); + + if (!berry_init_ok) { + // free resources + if (berry.vm != nullptr) { + be_vm_delete(berry.vm); + berry.vm = nullptr; + } + } +} + +/*********************************************************************************************\ + * Tasmota Commands +\*********************************************************************************************/ +// +// Command `BrRun` +// +void CmndBrRun(void) { + int32_t ret_code; + const char * ret_type, * ret_val; + + if (berry.vm == nullptr) { ResponseCmndChar_P(PSTR(D_BR_NOT_STARTED)); return; } + + char br_cmd[XdrvMailbox.data_len+12]; + // encapsulate into a function, copied from `be_repl.c` / `try_return()` + snprintf_P(br_cmd, sizeof(br_cmd), PSTR("return (%s)"), XdrvMailbox.data); + + checkBeTop(); + do { + // First try with the `return ()` wrapper + ret_code = be_loadbuffer(berry.vm, PSTR("input"), br_cmd, strlen(br_cmd)); + if (be_getexcept(berry.vm, ret_code) == BE_SYNTAX_ERROR) { + be_pop(berry.vm, 2); // remove exception values + // if fails, try the direct command + ret_code = be_loadbuffer(berry.vm, PSTR("input"), XdrvMailbox.data, strlen(XdrvMailbox.data)); + } + if (0 != ret_code) break; + + ret_code = be_pcall(berry.vm, 0); // execute code + } while (0); + + if (0 == ret_code) { + // code taken from REPL, look first at top, and if nil, look at return value + if (be_isnil(berry.vm, 0)) { + ret_val = be_tostring(berry.vm, -1); + } else { + ret_val = be_tostring(berry.vm, 0); + } + Response_P("{\"" D_PRFX_BR "\":\"%s\"}", ret_val); // can't use XdrvMailbox.command as it may have been overwritten by subcommand + be_pop(berry.vm, 1); + } else { + Response_P(PSTR("{\"" D_PRFX_BR "\":\"[%s] %s\"}"), be_tostring(berry.vm, -2), be_tostring(berry.vm, -1)); + be_pop(berry.vm, 2); + } + + checkBeTop(); +} + +// +// Command `BrReset` +// +void CmndBrReset(void) { + if (berry.vm == nullptr) { ResponseCmndChar_P(PSTR(D_BR_NOT_STARTED)); return; } + + BrReset(); +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ +bool Xdrv52(uint8_t function) +{ + bool result = false; + + switch (function) { + //case FUNC_PRE_INIT: + case FUNC_INIT: + BrReset(); + break; + case FUNC_EVERY_50_MSECOND: + callBerryFunctionVoid(PSTR("_run_deferred")); + break; + case FUNC_EVERY_100_MSECOND: + callBerryFunctionVoid(PSTR("every_100ms")); + break; + case FUNC_EVERY_SECOND: + callBerryFunctionVoid(PSTR("every_second")); + break; + case FUNC_COMMAND: + result = DecodeCommand(kBrCommands, BerryCommand); + if (!result) { + result = callBerryCommand(); + } + break; + // case FUNC_SET_POWER: + // break; + case FUNC_RULES_PROCESS: + result = callBerryRule(); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_ADD_BUTTON: + break; + case FUNC_WEB_ADD_MAIN_BUTTON: + + break; + case FUNC_WEB_ADD_HANDLER: + break; +#endif // USE_WEBSERVER + case FUNC_SAVE_BEFORE_RESTART: + break; + case FUNC_MQTT_DATA: + // callBerryMqttData(); + break; + case FUNC_WEB_SENSOR: + break; + + case FUNC_JSON_APPEND: + break; + + case FUNC_BUTTON_PRESSED: + break; + + case FUNC_LOOP: + break; + + } + return result; +} + +#endif // USE_BERRY diff --git a/tasmota/xdrv_52_berry.ino b/tasmota/xdrv_52_berry.ino deleted file mode 100644 index d6e4fa015..000000000 --- a/tasmota/xdrv_52_berry.ino +++ /dev/null @@ -1,650 +0,0 @@ -/* - xdrv_52_berry.ino - Berry scripting language - - Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - - -#ifdef USE_BERRY - -#define XDRV_52 52 - -#include -#include - -const char kBrCommands[] PROGMEM = D_PRFX_BR "|" // prefix - D_CMND_BR_RUN "|" D_CMND_BR_RESET - ; - -void (* const BerryCommand[])(void) PROGMEM = { - CmndBrRun, CmndBrReset, - }; - -class BerrySupport { -public: - bvm *vm = nullptr; // berry vm - bool rules_busy = false; // are we already processing rules, avoid infinite loop - const char *fname = nullptr; // name of berry function to call - int32_t fret = 0; -}; -BerrySupport berry; - -// -// Sanity Check for be_top() -// -// Checks that the Berry stack is empty, if not print a Warning and empty it -// -void checkBeTop(void) { - int32_t top = be_top(berry.vm); - if (top != 0) { - be_pop(berry.vm, top); // TODO should not be there - AddLog(LOG_LEVEL_ERROR, D_LOG_BERRY "Error be_top is non zero=%d", top); - } -} - -/*********************************************************************************************\ - * Native functions mapped to Berry functions - * - * log(msg:string [,log_level:int]) ->nil - * - * import tasmota - * - * tasmota.getfreeheap() -> int - * tasmota.publish(topic:string, payload:string[, retain:bool]) -> nil - * tasmota.cmd(command:string) -> string - * tasmota.getoption(index:int) -> int - * tasmota.millis([delay:int]) -> int - * tasmota.timereached(timer:int) -> bool - * tasmota.yield() -> nil - * -\*********************************************************************************************/ -extern "C" { - // Berry: `log(msg:string [,log_level:int]) ->nil` - // Logs the string at LOG_LEVEL_INFO (loglevel=2) - int32_t l_logInfo(struct bvm *vm); - int32_t l_logInfo(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top >= 1 && be_isstring(vm, 1)) { // only 1 argument of type string accepted - const char * msg = be_tostring(vm, 1); - uint32_t log_level = LOG_LEVEL_INFO; - if (top >= 2 && be_isint(vm, 2)) { - log_level = be_toint(vm, 2); - if (log_level > LOG_LEVEL_DEBUG_MORE) { log_level = LOG_LEVEL_DEBUG_MORE; } - } - AddLog(log_level, PSTR("%s"), msg); - be_return(vm); // Return - } - be_return_nil(vm); // Return nil when something goes wrong - } - - // Berry: `getFreeHeap() -> int` - // ESP object - int32_t l_getFreeHeap(bvm *vm); - int32_t l_getFreeHeap(bvm *vm) { - be_pushint(vm, ESP.getFreeHeap()); - be_return(vm); - } - - // Berry: `tasmota.publish(topic, payload [,retain]) -> nil`` - // - int32_t l_publish(struct bvm *vm); - int32_t l_publish(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top >= 2 && be_isstring(vm, 1) && be_isstring(vm, 2)) { // 2 mandatory string arguments - if (top == 2 || (top == 3 && be_isbool(vm, 3))) { // 3rd optional argument must be bool - const char * topic = be_tostring(vm, 1); - const char * payload = be_tostring(vm, 2); - bool retain = false; - if (top == 3) { - retain = be_tobool(vm, 3); - } - strlcpy(TasmotaGlobal.mqtt_data, payload, sizeof(TasmotaGlobal.mqtt_data)); - MqttPublish(topic, retain); - be_return(vm); // Return - } - } - be_return_nil(vm); // Return nil when something goes wrong - } - - // Berry: `tasmota.cmd(command:string) -> string` - // - int32_t l_cmd(struct bvm *vm); - int32_t l_cmd(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top == 1 && be_isstring(vm, 1)) { // only 1 argument of type string accepted - const char * command = be_tostring(vm, 1); - ExecuteCommand(command, SRC_BERRY); - be_pushstring(vm, TasmotaGlobal.mqtt_data); - be_return(vm); // Return - } - be_return_nil(vm); // Return nil when something goes wrong - } - - // Berry: tasmota.millis([delay:int]) -> int - // - int32_t l_millis(struct bvm *vm); - int32_t l_millis(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top == 0 || (top == 1 && be_isint(vm, 1))) { // only 1 argument of type string accepted - uint32_t delay = 0; - if (top == 1) { - delay = be_toint(vm, 1); - } - uint32_t ret_millis = millis() + delay; - be_pushint(vm, ret_millis); - be_return(vm); // Return - } - be_return_nil(vm); // Return nil when something goes wrong - } - - // Berry: tasmota.getoption(index:int) -> int - // - int32_t l_getoption(struct bvm *vm); - int32_t l_getoption(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top == 1 && be_isint(vm, 1)) { - uint32_t opt = GetOption(be_toint(vm, 1)); - be_pushint(vm, opt); - be_return(vm); // Return - } - be_return_nil(vm); // Return nil when something goes wrong - } - - // Berry: tasmota.timereached(timer:int) -> bool - // - int32_t l_timereached(struct bvm *vm); - int32_t l_timereached(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top == 1 && be_isint(vm, 1)) { // only 1 argument of type string accepted - uint32_t timer = be_toint(vm, 1); - bool reached = TimeReached(timer); - be_pushbool(vm, reached); - be_return(vm); // Return - } - be_return_nil(vm); // Return nil when something goes wrong - } - - // Berry: `yield() -> nil` - // ESP object - int32_t l_yield(bvm *vm); - int32_t l_yield(bvm *vm) { - optimistic_yield(10); - be_return(vm); - } - - // Berry: `save(file:string, f:closure) -> bool` - int32_t l_save(struct bvm *vm); - int32_t l_save(struct bvm *vm) { - int32_t top = be_top(vm); // Get the number of arguments - if (top ==2 && be_isstring(vm, 1) && be_isclosure(vm, 2)) { // only 1 argument of type string accepted - const char *fname = be_tostring(vm, 1); - int32_t ret = be_savecode(vm, fname); - be_pushint(vm, ret); - be_return(vm); // Return - } - be_return_nil(vm); // Return nil when something goes wrong - } - - -} - -// called as a replacement to Berry `print()` -void berry_log(const char * berry_buf); -void berry_log(const char * berry_buf) { - AddLog(LOG_LEVEL_INFO, PSTR("%s"), berry_buf); -} - -/*********************************************************************************************\ - * Handlers for Berry calls and async - * -\*********************************************************************************************/ -// // call a function (if exists) of type void -> void -// void callBerryFunctionVoid_berry(const char * fname) { -// berry.fret = 0; -// callBerryFunctionVoid(berry.fname); -// } - -bool callBerryRule(void) { - if (berry.rules_busy) { return false; } - berry.rules_busy = true; - char * json_event = TasmotaGlobal.mqtt_data; - bool serviced = false; - - checkBeTop(); - be_getglobal(berry.vm, "_exec_rules"); - if (!be_isnil(berry.vm, -1)) { - - // { - // String event_saved = TasmotaGlobal.mqtt_data; - // // json_event = {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089}} - // // json_event = {"System":{"Boot":1}} - // // json_event = {"SerialReceived":"on"} - invalid but will be expanded to {"SerialReceived":{"Data":"on"}} - // char *p = strchr(json_event, ':'); - // if ((p != NULL) && !(strchr(++p, ':'))) { // Find second colon - // event_saved.replace(F(":"), F(":{\"Data\":")); - // event_saved += F("}"); - // // event_saved = {"SerialReceived":{"Data":"on"}} - // } - // be_pushstring(berry.vm, event_saved.c_str()); - // } - be_pushstring(berry.vm, TasmotaGlobal.mqtt_data); - int ret = be_pcall(berry.vm, 1); - serviced = be_tobool(berry.vm, 1); - AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_BERRY "Event (%s) serviced=%d"), TasmotaGlobal.mqtt_data, serviced); - be_pop(berry.vm, 2); // remove function object - } else { - be_pop(berry.vm, 1); // remove nil object - } - checkBeTop(); - berry.rules_busy = false; - - return serviced; // TODO event not handled -} - -// void callBerryMqttData(void) { -// AddLog(LOG_LEVEL_INFO, D_LOG_BERRY "callBerryMqttData"); -// if (nullptr == berry.vm) { return; } -// if (XdrvMailbox.data_len < 1) { -// return; -// } -// const char * topic = XdrvMailbox.topic; -// const char * payload = XdrvMailbox.data; - -// checkBeTop(); -// be_getglobal(berry.vm, "mqtt_data_dispatch"); -// if (!be_isnil(berry.vm, -1)) { -// be_pushstring(berry.vm, topic); -// be_pushstring(berry.vm, payload); -// be_pcall(berry.vm, 0); -// be_pop(berry.vm, 3); // remove function object -// } else { -// be_pop(berry.vm, 1); // remove nil object -// } -// checkBeTop(); -// } - -// call a function (if exists) of type void -> void -void callBerryFunctionVoid(const char * fname) { - if (nullptr == berry.vm) { return; } - checkBeTop(); - be_getglobal(berry.vm, fname); - if (!be_isnil(berry.vm, -1)) { - be_pcall(berry.vm, 0); - } - be_pop(berry.vm, 1); // remove function or nil object - checkBeTop(); -} - -/*********************************************************************************************\ - * Handlers for Berry calls and async - * -\*********************************************************************************************/ - -const char berry_prog[] PROGMEM = - "" - //"def func(x) for i:1..x print('a') end end " - //"def testreal() return str(1.2+1) end " - //"def noop() log('noop before'); yield(); log('middle after'); yield(); log('noop after'); end " - //"log(\"foobar\") " - - // auto-import modules - "import string " - "import json " - "import gc " - "import tasmota " - // import alias - "import tasmota as t " - - // add `charsinstring(s:string,c:string) -> int`` - // looks for any char in c, and return the position of the first chat - // or -1 if not found - "def charsinstring(s,c) " - "for i:0..size(s)-1 " - "for j:0..size(c)-1 " - "if s[i] == c[j] return i end " - "end " - "end " - "return -1 " - "end " - - // find a key in map, case insensitive, return actual key or nil if not found - "def findkeyi(m,keyi) " - "var keyu = string.toupper(keyi) " - "if classof(m) == map " - "for k:m.keys() " - "if string.toupper(k)==keyu || keyi=='?' " - "return k " - "end " - "end " - "end " - "end " - - // Rules - - "tasmota._operators='=<>!' " // operators used in rules - // Rules comparisong functions - "tasmota._eqstr=/s1,s2-> str(s1) == str(s2) " - "tasmota._neqstr=/s1,s2-> str(s1) != str(s2) " - "tasmota._eq=/f1,f2-> real(f1) == real(f2) " - "tasmota._neq=/f1,f2-> real(f1) != real(f2) " - "tasmota._gt=/f1,f2-> real(f1) > real(f2) " - "tasmota._lt=/f1,f2-> real(f1) < real(f2) " - "tasmota._ge=/f1,f2-> real(f1) >= real(f2) " - "tasmota._le=/f1,f2-> real(f1) <= real(f2) " - - "tasmota._op=[" - "['==',tasmota._eqstr]," - "['!==',tasmota._neqstr]," - "['=',tasmota._eq]," - "['!=',tasmota._neq]," - "['>=',tasmota._ge]," - "['<=',tasmota._le]," - "['>',tasmota._gt]," - "['<',tasmota._lt]," - "] " - "tasmota_rules={} " - "tasmota.rule = def(pat,f) tasmota_rules[pat] = f end " - - // # split the item when there is an operator, returns a list of (left,op,right) - // # ex: "Dimmer>50" -> ["Dimmer",tasmota_gt,"50"] - "tasmota.find_op = def (item) " - "var pos = charsinstring(item, tasmota._operators) " - "if pos>=0 " - "var op_split = string.split(item,pos) " - // #print(op_split) - "var op_left = op_split[0] " - "var op_rest = op_split[1] " - // # iterate through operators - "for op:tasmota._op " - "if string.find(op_rest,op[0]) == 0 " - "var op_func = op[1] " - "var op_right = string.split(op_rest,size(op[0]))[1] " - "return [op_left,op_func,op_right] " - "end " - "end " - "end " - "return [item, nil, nil] " - "end " - - // Rules trigger if match. return true if match, false if not - // Note: condition is not yet managed - "tasmota.try_rule = def (ev, rule, f) " - "var rl_list = tasmota.find_op(rule) " - "var e=ev " - "var rl=string.split(rl_list[0],'#') " - "for it:rl " - "found=findkeyi(e,it) " - "if found == nil " - "return false " - "end " - "e=e[found] " - "end " - // # check if condition is true - "if rl_list[1] " - // # did we find a function - "if !rl_list[1](e,rl_list[2]) " - // # condition is not met - "return false " - "end " - "end " - "f(e,ev) " - "return true " - "end " - // Run rules, i.e. check each individual rule - // Returns true if at least one rule matched, false if none - "tasmota.exec_rules = def (ev_json) " - "var ev = json.load(ev_json) " - "var ret = false " - "if ev == nil " - "log('BRY: ERROR, bad json: '+ev_json, 3) " - "end " - "for r:tasmota_rules.keys() " - "ret = tasmota.try_rule(ev,r,tasmota_rules[r]) || ret " - "end " - "return ret " - "end " - // Not sure how to run `tasmota.exec_rules` from C code, so alias with `_exec_rules()`` - "def _exec_rules(e) return tasmota.exec_rules(e) end " - - // Timers - "tasmota_timers=[] " - "tasmota.timer = def (delay,f) tasmota_timers.push([tasmota.millis(delay),f]) end " - - "def _run_deferred() " - "var i=0 " - "while i