diff --git a/BUILDS.md b/BUILDS.md index b6e267c2c..2f55cc8a8 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -142,6 +142,7 @@ | USE_EZOORP | - | - | - | - | - | - | - | | USE_EZOPH | - | - | - | - | - | - | - | | USE_EZOPRS | - | - | - | - | - | - | - | +| USE_EZORGB | - | - | - | - | - | - | - | | USE_EZORTD | - | - | - | - | - | - | - | | | | | | | | | | | Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks diff --git a/CHANGELOG.md b/CHANGELOG.md index e4be63081..2b4451ec8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,17 +16,20 @@ All notable changes to this project will be documented in this file. - Support for EZO PRS sensors by Christopher Tremblay (#9659) - Support for EZO FLO sensors by Christopher Tremblay (#9697) - Support for EZO DO sensors by Christopher Tremblay (#9707) +- Support for EZO RGB sensors by Christopher Tremblay (#9723) - Zigbee reduce battery drain (#9642) - Zigbee command ``ZbMap`` to describe Zigbee topology (#9651) - Zigbee command ``ZbOccupancy`` to configure the time-out for PIR - Command ``Gpios 255`` to show all possible GPIO configurations - Command ``SwitchText`` to change JSON switch names by barbudor (#9691) +- Command ``SetOption114 1`` to detach Swiches from Relays and enable MQTT action state for all the SwitchModes returning `{"Switch1":{"Action":"ON"}}` - HM10 Beacon support and refactoring by Christian Baars (#9702) ### Changed - PlatformIO library structure redesigned for compilation speed by Jason2866 - Zigbee flash storage refactor adding commands ``ZbProbe``, ``ZbStatus2`` and ``ZbRestore`` (#9641) - Default otaurl in my_user_config.h to http://ota.tasmota.com/tasmota/release/tasmota.bin.gz +- When ``SetOption73 1`` JSON result from `{"ACTION":"SINGLE"}` to `{"Button1":{"Action":"SINGLE"}}` ### Fixed - Rule Break not working as expected when ONCE is enabled (#9245) diff --git a/I2CDEVICES.md b/I2CDEVICES.md index cbd00b950..f7cbe820b 100644 --- a/I2CDEVICES.md +++ b/I2CDEVICES.md @@ -87,3 +87,4 @@ Index | Define | Driver | Device | Address(es) | Description 55 | USE_EZOPRS | xsns_78 | EZOPRS | 0x61 - 0x70 | Pressure sensor 55 | USE_EZOFLO | xsns_78 | EZOFLO | 0x61 - 0x70 | Flow meter sensor 55 | USE_EZODO | xsns_78 | EZODO | 0x61 - 0x70 | Disolved Oxygen sensor + 55 | USE_EZORGB | xsns_78 | EZORGB | 0x61 - 0x70 | Color sensor diff --git a/RELEASENOTES.md b/RELEASENOTES.md index ec3dfc013..f15095462 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -61,9 +61,10 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota ### Added - Command ``Gpios 255`` to show all possible GPIO configurations - Command ``NoDelay`` for immediate backlog command execution by Erik Montnemery (#9544) -- Command ``SwitchMode 15`` sending only MQTT message on switch change (#9593) - Command ``ShutterChange`` to increment change position (#9594) +- Command ``SwitchMode 15`` sending only MQTT message on switch change (#9593) - Command ``SetOption113 1`` to set dimmer low on rotary dial after power off +- Command ``SetOption114 1`` to detach Swiches from Relays and enable MQTT action state for all the SwitchModes - Command ``SwitchText`` to change JSON switch names by barbudor (#9691) - Zigbee command ``ZbData`` for better support of device specific data - Zigbee command ``ZbOccupancy`` to configure the time-out for PIR @@ -89,6 +90,7 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota - TLS fingerprint ``#define MQTT_FINGERPRINT`` from string to hexnumbers (#9570) - Command ``Status`` output for disabled status types now returns {"Command":"Error"} - MAX31865 driver to support up to 6 thermocouples selected by ``MX31865 CS`` instead of ``SSPI CS`` (#9103) +- When ``SetOption73 1`` JSON result from `{"ACTION":"SINGLE"}` to `{"Button1":{"Action":"SINGLE"}}` ### Changed - Command ``Gpio17`` replaces command ``Adc`` diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 33359eb29..4a2a03281 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -37,9 +37,11 @@ #define D_JSON_BAUDRATE "Baudrate" #define D_JSON_BLINK "Blink" #define D_JSON_BLOCKED_LOOP "Blocked Loop" +#define D_JSON_BLUE "Blue" #define D_JSON_BOOTVERSION "Boot" #define D_JSON_BOOTCOUNT "BootCount" #define D_JSON_BSSID "BSSId" +#define D_JSON_BUTTON "Button" #define D_JSON_BUILDDATETIME "BuildDateTime" #define D_JSON_CHANNEL "Channel" #define D_JSON_CO2 "CarbonDioxide" @@ -82,6 +84,7 @@ #define D_JSON_FROM "from" #define D_JSON_GAS "Gas" #define D_JSON_GATEWAY "Gateway" +#define D_JSON_GREEN "Green" #define D_JSON_GROUPS "Groups" #define D_JSON_HALTING "Halting" #define D_JSON_HEAPSIZE "Heap" @@ -132,6 +135,7 @@ #define D_JSON_PROGRAMSIZE "ProgramSize" #define D_JSON_PSRMAXMEMORY "PsrMax" #define D_JSON_PSRFREEMEMORY "PsrFree" +#define D_JSON_RED "Red" #define D_JSON_REFERENCETEMPERATURE "ReferenceTemperature" #define D_JSON_REMAINING "Remaining" #define D_JSON_RESET "Reset" @@ -728,6 +732,8 @@ const char S_JSON_SENSOR_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_SENSO const char S_JSON_DRIVER_INDEX_NVALUE[] PROGMEM = "{\"" D_CMND_DRIVER "%d\":%d}"; const char S_JSON_DRIVER_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_DRIVER "%d\":\"%s\"}"; +const char S_JSON_SVALUE_ACTION_SVALUE[] PROGMEM = "{\"%s\":{\"Action\":\"%s\"}}"; + const char JSON_SNS_TEMP[] PROGMEM = ",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"; const char JSON_SNS_ILLUMINANCE[] PROGMEM = ",\"%s\":{\"" D_JSON_ILLUMINANCE "\":%d}"; @@ -787,6 +793,9 @@ const char HTTP_SNS_O2[] PROGMEM = "{s}%s " D_O2 "{ const char HTTP_SNS_LITERS[] PROGMEM = "{s}%s " D_VOLUME "{m}%s " D_UNIT_LITERS "{e}"; const char HTTP_SNS_LPM[] PROGMEM = "{s}%s " D_FLOW_RATE "{m}%s " D_UNIT_LITERS_PER_MIN "{e}"; const char HTTP_SNS_DO[] PROGMEM = "{s}%s " D_DO "{m}%s " D_UNIT_PARTS_PER_MILLION "{e}"; +const char HTTP_SNS_COLOR_RED[] PROGMEM = "{s}%s " D_COLOR_RED "{m}%u " "{e}"; +const char HTTP_SNS_COLOR_GREEN[] PROGMEM = "{s}%s " D_COLOR_GREEN "{m}%u " "{e}"; +const char HTTP_SNS_COLOR_BLUE[] PROGMEM = "{s}%s " D_COLOR_BLUE "{m}%u " "{e}"; const char S_MAIN_MENU[] PROGMEM = D_MAIN_MENU; const char S_CONFIGURATION[] PROGMEM = D_CONFIGURATION; diff --git a/tasmota/language/it_IT.h b/tasmota/language/it_IT.h index 75dfb3ff1..8f70895cd 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) 2020 Gennaro Tortone - some mods by Antonio Fragola - Updated by bovirus - rev. 30.10.2020 + Copyright (C) 2020 Gennaro Tortone - some mods by Antonio Fragola - Updated by bovirus - rev. 02.11.2020 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 @@ -84,7 +84,7 @@ #define D_DISABLED "Disabilitato/a" #define D_DISTANCE "Distanza" #define D_DNS_SERVER "Server DNS" -#define D_DO "Disolved Oxygen" +#define D_DO "Ossigeno dissolto" #define D_DONE "Completato" #define D_DST_TIME "DST" #define D_EC "EC" diff --git a/tasmota/language/zh_CN.h b/tasmota/language/zh_CN.h index a93ca3262..f2392e13f 100644 --- a/tasmota/language/zh_CN.h +++ b/tasmota/language/zh_CN.h @@ -501,9 +501,9 @@ // xsns_27_apds9960.ino #define D_GESTURE "Gesture" -#define D_COLOR_RED "Red" -#define D_COLOR_GREEN "Green" -#define D_COLOR_BLUE "Blue" +#define D_COLOR_RED "红" +#define D_COLOR_GREEN "绿" +#define D_COLOR_BLUE "蓝" #define D_CCT "CCT" #define D_PROXIMITY "Proximity" diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 8e5d8ecd4..b2200e29c 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -572,6 +572,7 @@ // #define USE_EZOPRS // [I2cDriver55] Enable support for EZO's PRS sensor (+0k7 code) - Shared EZO code required for any EZO device (+1k2 code) // #define USE_EZOFLO // [I2cDriver55] Enable support for EZO's FLO sensor (+0k4 code) - Shared EZO code required for any EZO device (+1k2 code) // #define USE_EZODO // [I2cDriver55] Enable support for EZO's DO sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) +// #define USE_EZORGB // [I2cDriver55] Enable support for EZO's RGB sensor (+0k5 code) - Shared EZO code required for any EZO device (+1k2 code) // #define USE_DISPLAY // Add I2C Display Support (+2k code) #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 diff --git a/tasmota/settings.h b/tasmota/settings.h index d75c40bcd..d2227d050 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -44,7 +44,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t ws_clock_reverse : 1; // bit 16 (v5.8.1) - SetOption16 - Switch between clockwise or counter-clockwise uint32_t decimal_text : 1; // bit 17 (v5.8.1) - SetOption17 - Switch between decimal or hexadecimal output (0 = hexadecimal, 1 = decimal) uint32_t light_signal : 1; // bit 18 (v5.10.0c) - SetOption18 - Pair light signal with CO2 sensor - uint32_t hass_discovery : 1; // bit 19 (v5.11.1a) - SetOption19 - Control Home Assistantautomatic discovery (See SetOption59) + uint32_t hass_discovery : 1; // bit 19 (v5.11.1a) - SetOption19 - Control Home Assistant automatic discovery (See SetOption59) uint32_t not_power_linked : 1; // bit 20 (v5.11.1f) - SetOption20 - Control power in relation to Dimmer/Color/Ct changes uint32_t no_power_on_check : 1; // bit 21 (v5.11.1i) - SetOption21 - Show voltage even if powered off uint32_t mqtt_serial : 1; // bit 22 (v5.12.0f) - CMND_SERIALSEND and CMND_SERIALLOG @@ -139,7 +139,8 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu typedef union { // Restricted by MISRA-C Rule 18.4 but so useful... uint32_t data; // Allow bit manipulation using SetOption struct { // SetOption114 .. SetOption145 - uint32_t spare00 : 1; // bit 0 + uint32_t mqtt_switches : 1; // bit 0 (V9.0.0.3) - SetOption114 - Detach Swiches from relays and enable MQTT action state for all the SwitchModes + //uint32_t spare00 : 1; // bit 0 uint32_t spare01 : 1; // bit 1 uint32_t spare02 : 1; // bit 2 uint32_t spare03 : 1; // bit 3 diff --git a/tasmota/support_button.ino b/tasmota/support_button.ino index 811767aae..39fdc407c 100644 --- a/tasmota/support_button.ino +++ b/tasmota/support_button.ino @@ -61,23 +61,21 @@ struct TOUCH_BUTTON { /********************************************************************************************/ -void ButtonPullupFlag(uint8 button_bit) -{ +void ButtonPullupFlag(uint32_t button_bit) { bitSet(Button.no_pullup_mask, button_bit); } -void ButtonInvertFlag(uint8 button_bit) -{ +void ButtonInvertFlag(uint32_t button_bit) { bitSet(Button.inverted_mask, button_bit); } + #ifdef ESP32 -void ButtonTouchFlag(uint8 button_bit) -{ +void ButtonTouchFlag(uint32_t button_bit) { bitSet(Button.touch_mask, button_bit); } #endif // ESP32 -void ButtonInit(void) -{ + +void ButtonInit(void) { Button.present = 0; #ifdef ESP8266 if ((SONOFF_DUAL == TasmotaGlobal.module_type) || (CH4 == TasmotaGlobal.module_type)) { @@ -101,8 +99,7 @@ void ButtonInit(void) } } -uint8_t ButtonSerial(uint8_t serial_in_byte) -{ +uint8_t ButtonSerial(uint8_t serial_in_byte) { if (Button.dual_receive_count) { Button.dual_receive_count--; if (Button.dual_receive_count) { @@ -133,8 +130,7 @@ uint8_t ButtonSerial(uint8_t serial_in_byte) * SetOption73 (0) - Decouple button from relay and send just mqtt topic \*********************************************************************************************/ -void ButtonHandler(void) -{ +void ButtonHandler(void) { if (TasmotaGlobal.uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit uint8_t hold_time_extent = IMMINENT_RESET_FACTOR; // Extent hold time factor in case of iminnent Reset command @@ -355,8 +351,8 @@ void ButtonHandler(void) } } -void MqttButtonTopic(uint8_t button_id, uint8_t action, uint8_t hold) -{ +/* +void MqttButtonTopic(uint8_t button_id, uint8_t action, uint8_t hold) { char scommand[CMDSZ]; char stopic[TOPSZ]; char mqttstate[7]; @@ -371,9 +367,21 @@ void MqttButtonTopic(uint8_t button_id, uint8_t action, uint8_t hold) MqttPublish(stopic); } } +*/ -void ButtonLoop(void) -{ +void MqttButtonTopic(uint32_t button_id, uint32_t action, uint32_t hold) { + SendKey(KEY_BUTTON, button_id, (hold) ? 3 : action +9); + + if (!Settings.flag.hass_discovery) { // SetOption19 - Control Home Assistant automatic discovery (See SetOption59) + char scommand[10]; + snprintf_P(scommand, sizeof(scommand), PSTR(D_JSON_BUTTON "%d"), button_id); + char mqttstate[7]; + Response_P(S_JSON_SVALUE_ACTION_SVALUE, scommand, (hold) ? SettingsText(SET_STATE_TXT4) : GetTextIndexed(mqttstate, sizeof(mqttstate), action, kMultiPress)); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, scommand); + } +} + +void ButtonLoop(void) { if (Button.present) { if (TimeReached(Button.debounce)) { SetNextTimeInterval(Button.debounce, Settings.button_debounce); // ButtonDebounce (50) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index c4deba6ce..cbeab8d0f 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -391,7 +391,7 @@ void CmndPower(void) void CmndStatus(void) { - uint32_t payload = XdrvMailbox.payload; + int32_t payload = XdrvMailbox.payload; if (payload > MAX_STATUS) { return; } // {"Command":"Error"} if (!Settings.flag.mqtt_enabled && (6 == payload)) { return; } // SetOption3 - Enable MQTT @@ -402,7 +402,7 @@ void CmndStatus(void) char stemp[200]; char stemp2[TOPSZ]; - if (0 == payload) { + if ((0 == payload) || (-99 == payload)) { uint32_t maxfn = (TasmotaGlobal.devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!TasmotaGlobal.devices_present) ? 1 : TasmotaGlobal.devices_present; #ifdef USE_SONOFF_IFAN if (IsModuleIfan()) { maxfn = 1; } diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index 41e63799f..f636752e7 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -652,7 +652,9 @@ void ResponseAppendFeatures(void) #if defined(USE_I2C) && defined(USE_EZODO) feature7 |= 0x00000100; #endif -// feature7 |= 0x00000200; +#if defined(USE_I2C) && defined(USE_EZORGB) + feature7 |= 0x00000200; +#endif // feature7 |= 0x00000400; // feature7 |= 0x00000800; diff --git a/tasmota/support_switch.ino b/tasmota/support_switch.ino index b1822a1b0..313b45408 100644 --- a/tasmota/support_switch.ino +++ b/tasmota/support_switch.ino @@ -34,6 +34,10 @@ const uint8_t AC_PERIOD = (20 + SWITCH_FAST_PROBE_INTERVAL - 1) / SWITCH_FAST_PR #define SM_NO_TIMER_MASK 0xFF #define SM_FIRST_PRESS 0x40 #define SM_SECOND_PRESS 0x80 +#define POWER_NONE 99 + +const char kSwitchPressStates[] PROGMEM = + "||||POWER_INCREMENT|POWER_INV|POWER_CLEAR|POWER_RELEASE|POWER_100|"; #include @@ -52,28 +56,23 @@ struct SWITCH { /********************************************************************************************/ -void SwitchPullupFlag(uint16 switch_bit) -{ +void SwitchPullupFlag(uint32 switch_bit) { bitSet(Switch.no_pullup_mask, switch_bit); } -void SwitchSetVirtual(uint32_t index, uint8_t state) -{ +void SwitchSetVirtual(uint32_t index, uint32_t state) { Switch.virtual_state[index] = state; } -uint8_t SwitchGetVirtual(uint32_t index) -{ +uint8_t SwitchGetVirtual(uint32_t index) { return Switch.virtual_state[index]; } -uint8_t SwitchLastState(uint32_t index) -{ +uint8_t SwitchLastState(uint32_t index) { return Switch.last_state[index]; } -bool SwitchState(uint32_t index) -{ +bool SwitchState(uint32_t index) { uint32_t switchmode = Settings.switchmode[index]; return ((FOLLOW_INV == switchmode) || (PUSHBUTTON_INV == switchmode) || @@ -86,17 +85,16 @@ bool SwitchState(uint32_t index) /*********************************************************************************************/ -void SwitchProbe(void) -{ - if (TasmotaGlobal.uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit +void SwitchProbe(void) { + if (TasmotaGlobal.uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit - uint8_t state_filter; - uint8_t debounce_flags = Settings.switch_debounce % 10; - uint8_t force_high = debounce_flags &1; // 51, 101, 151 etc - uint8_t force_low = debounce_flags &2; // 52, 102, 152 etc - uint8_t ac_detect = debounce_flags == 9; - uint8_t switch_probe_interval; - uint8_t first_change = Switch.first_change; + uint32_t state_filter; + uint32_t switch_probe_interval; + uint32_t first_change = Switch.first_change; + uint32_t debounce_flags = Settings.switch_debounce % 10; + bool force_high = (debounce_flags &1); // 51, 101, 151 etc + bool force_low = (debounce_flags &2); // 52, 102, 152 etc + bool ac_detect = (debounce_flags == 9); if (ac_detect) { switch_probe_interval = SWITCH_FAST_PROBE_INTERVAL; @@ -117,7 +115,7 @@ void SwitchProbe(void) // Olimex user_switch2.c code to fix 50Hz induced pulses if (1 == digitalRead(Pin(GPIO_SWT1, i))) { - if (ac_detect) { // Enabled with SwitchDebounce x9 + if (ac_detect) { // Enabled with SwitchDebounce x9 Switch.state[i] |= 0x80; if (Switch.state[i] > 0x80) { Switch.state[i]--; @@ -128,9 +126,9 @@ void SwitchProbe(void) } } else { - if (force_high) { // Enabled with SwitchDebounce x1 + if (force_high) { // Enabled with SwitchDebounce x1 if (1 == Switch.virtual_state[i]) { - Switch.state[i] = state_filter; // With noisy input keep current state 1 unless constant 0 + Switch.state[i] = state_filter; // With noisy input keep current state 1 unless constant 0 } } @@ -143,7 +141,7 @@ void SwitchProbe(void) } } else { - if (ac_detect) { // Enabled with SwitchDebounce x9 + if (ac_detect) { // Enabled with SwitchDebounce x9 /* * Moes MS-104B and similar devices using an AC detection circuitry * on their switch inputs generating an ~4 ms long low pulse every @@ -174,9 +172,9 @@ void SwitchProbe(void) } } else { - if (force_low) { // Enabled with SwitchDebounce x2 + if (force_low) { // Enabled with SwitchDebounce x2 if (0 == Switch.virtual_state[i]) { - Switch.state[i] = 0; // With noisy input keep current state 0 unless constant 1 + Switch.state[i] = 0; // With noisy input keep current state 0 unless constant 1 } } @@ -193,9 +191,8 @@ void SwitchProbe(void) TickerSwitch.attach_ms(switch_probe_interval, SwitchProbe); // Re-arm as core 2.3.0 does only support ONCE mode } -void SwitchInit(void) -{ - uint8_t ac_detect = Settings.switch_debounce % 10 == 9; +void SwitchInit(void) { + bool ac_detect = (Settings.switch_debounce % 10 == 9); Switch.present = 0; for (uint32_t i = 0; i < MAX_SWITCHES; i++) { @@ -230,58 +227,64 @@ void SwitchInit(void) * Switch handler \*********************************************************************************************/ -void SwitchHandler(uint8_t mode) -{ - if (TasmotaGlobal.uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit +void SwitchHandler(uint32_t mode) { + if (TasmotaGlobal.uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit - uint16_t loops_per_second = 1000 / Settings.switch_debounce; + uint32_t loops_per_second = 1000 / Settings.switch_debounce; for (uint32_t i = 0; i < MAX_SWITCHES; i++) { if (PinUsed(GPIO_SWT1, i) || (mode)) { - uint8_t button = Switch.virtual_state[i]; - uint8_t switchflag = POWER_TOGGLE +1; + uint32_t button = Switch.virtual_state[i]; + uint32_t switchflag = POWER_TOGGLE +1; + uint32_t mqtt_action = POWER_NONE; if (Switch.hold_timer[i] & (((Settings.switchmode[i] == PUSHHOLDMULTI) | (Settings.switchmode[i] == PUSHHOLDMULTI_INV)) ? SM_TIMER_MASK: SM_NO_TIMER_MASK)) { Switch.hold_timer[i]--; if ((Switch.hold_timer[i] & SM_TIMER_MASK) == loops_per_second * Settings.param[P_HOLD_TIME] / 25) { if ((Settings.switchmode[i] == PUSHHOLDMULTI) & (NOT_PRESSED == Switch.last_state[i])) { - SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); // Execute command via MQTT + SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); // Execute command via MQTT } if ((Settings.switchmode[i] == PUSHHOLDMULTI_INV) & (PRESSED == Switch.last_state[i])) { - SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); // Execute command via MQTT + SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); // Execute command via MQTT } } if (0 == (Switch.hold_timer[i] & (((Settings.switchmode[i] == PUSHHOLDMULTI) | (Settings.switchmode[i] == PUSHHOLDMULTI_INV)) ? SM_TIMER_MASK: SM_NO_TIMER_MASK))) { switch (Settings.switchmode[i]) { case TOGGLEMULTI: - switchflag = POWER_TOGGLE; // Toggle after hold + switchflag = POWER_TOGGLE; // Toggle after hold break; case FOLLOWMULTI: - switchflag = button &1; // Follow wall switch state after hold + switchflag = button &1; // Follow wall switch state after hold break; case FOLLOWMULTI_INV: - switchflag = ~button &1; // Follow inverted wall switch state after hold + switchflag = ~button &1; // Follow inverted wall switch state after hold break; case PUSHHOLDMULTI: if (NOT_PRESSED == button) { Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 25; SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); // Execute command via MQTT + mqtt_action = POWER_INCREMENT; } else { Switch.hold_timer[i]= 0; - SendKey(KEY_SWITCH, i +1, POWER_CLEAR); // Execute command via MQTT + SendKey(KEY_SWITCH, i +1, POWER_CLEAR); // Execute command via MQTT + mqtt_action = POWER_CLEAR; } break; case PUSHHOLDMULTI_INV: if (PRESSED == button) { Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 25; SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); // Execute command via MQTT + mqtt_action = POWER_INCREMENT; + } else { Switch.hold_timer[i]= 0; - SendKey(KEY_SWITCH, i +1, POWER_CLEAR); // Execute command via MQTT + SendKey(KEY_SWITCH, i +1, POWER_CLEAR); // Execute command via MQTT + mqtt_action = POWER_CLEAR; } break; default: - SendKey(KEY_SWITCH, i +1, POWER_HOLD); // Execute command via MQTT + SendKey(KEY_SWITCH, i +1, POWER_HOLD); // Execute command via MQTT + mqtt_action = POWER_HOLD; break; } } @@ -291,22 +294,22 @@ void SwitchHandler(uint8_t mode) switch (Settings.switchmode[i]) { case TOGGLE: case PUSHBUTTON_TOGGLE: - switchflag = POWER_TOGGLE; // Toggle + switchflag = POWER_TOGGLE; // Toggle break; case FOLLOW: - switchflag = button &1; // Follow wall switch state + switchflag = button &1; // Follow wall switch state break; case FOLLOW_INV: - switchflag = ~button &1; // Follow inverted wall switch state + switchflag = ~button &1; // Follow inverted wall switch state break; case PUSHBUTTON: if (PRESSED == button) { - switchflag = POWER_TOGGLE; // Toggle with pushbutton to Gnd + switchflag = POWER_TOGGLE; // Toggle with pushbutton to Gnd } break; case PUSHBUTTON_INV: if (NOT_PRESSED == button) { - switchflag = POWER_TOGGLE; // Toggle with releasing pushbutton from Gnd + switchflag = POWER_TOGGLE; // Toggle with releasing pushbutton from Gnd } break; case PUSHBUTTONHOLD: @@ -314,8 +317,8 @@ void SwitchHandler(uint8_t mode) Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; // Start timer on button press } if ((NOT_PRESSED == button) && (Switch.hold_timer[i])) { - Switch.hold_timer[i] = 0; // Button released and hold timer not expired : stop timer... - switchflag = POWER_TOGGLE; // ...and Toggle + Switch.hold_timer[i] = 0; // Button released and hold timer not expired : stop timer... + switchflag = POWER_TOGGLE; // ...and Toggle } break; case PUSHBUTTONHOLD_INV: @@ -323,8 +326,8 @@ void SwitchHandler(uint8_t mode) Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; // Start timer on button press... } if ((PRESSED == button) && (Switch.hold_timer[i])) { - Switch.hold_timer[i] = 0; // Button released and hold timer not expired : stop timer. - switchflag = POWER_TOGGLE; // ...and Toggle + Switch.hold_timer[i] = 0; // Button released and hold timer not expired : stop timer. + switchflag = POWER_TOGGLE; // ...and Toggle } break; case TOGGLEMULTI: @@ -332,30 +335,34 @@ void SwitchHandler(uint8_t mode) case FOLLOWMULTI_INV: if (Switch.hold_timer[i]) { Switch.hold_timer[i] = 0; - SendKey(KEY_SWITCH, i +1, POWER_HOLD); // Execute command via MQTT + SendKey(KEY_SWITCH, i +1, POWER_HOLD); // Execute command via MQTT + mqtt_action = POWER_HOLD; } else { - Switch.hold_timer[i] = loops_per_second / 2; // 0.5 second multi press window + Switch.hold_timer[i] = loops_per_second / 2; // 0.5 second multi press window } break; case PUSHHOLDMULTI: if (NOT_PRESSED == button) { if ((Switch.hold_timer[i] & SM_TIMER_MASK) != 0) { Switch.hold_timer[i] = ((Switch.hold_timer[i] & ~SM_TIMER_MASK) == SM_FIRST_PRESS) ? SM_SECOND_PRESS : 0; - SendKey(KEY_SWITCH, i +1, POWER_INV); // Execute command via MQTT + SendKey(KEY_SWITCH, i +1, POWER_INV); // Execute command via MQTT + mqtt_action = POWER_INV; } } else { if ((Switch.hold_timer[i] & SM_TIMER_MASK) > loops_per_second * Settings.param[P_HOLD_TIME] / 25) { if((Switch.hold_timer[i] & ~SM_TIMER_MASK) != SM_SECOND_PRESS) { Switch.hold_timer[i]= SM_FIRST_PRESS; - switchflag = POWER_TOGGLE; // Toggle with pushbutton + switchflag = POWER_TOGGLE; // Toggle with pushbutton } else{ - SendKey(KEY_SWITCH, i +1, POWER_100); // Execute command via MQTT + SendKey(KEY_SWITCH, i +1, POWER_100); // Execute command via MQTT + mqtt_action = POWER_100; Switch.hold_timer[i]= 0; } } else { Switch.hold_timer[i]= 0; - SendKey(KEY_SWITCH, i +1, POWER_RELEASE); // Execute command via MQTT + SendKey(KEY_SWITCH, i +1, POWER_RELEASE); // Execute command via MQTT + mqtt_action = POWER_RELEASE; } } Switch.hold_timer[i] = (Switch.hold_timer[i] & ~SM_TIMER_MASK) | loops_per_second * Settings.param[P_HOLD_TIME] / 10; @@ -364,33 +371,36 @@ void SwitchHandler(uint8_t mode) if (PRESSED == button) { if ((Switch.hold_timer[i] & SM_TIMER_MASK) != 0) { Switch.hold_timer[i] = ((Switch.hold_timer[i] & ~SM_TIMER_MASK) == SM_FIRST_PRESS) ? SM_SECOND_PRESS : 0; - SendKey(KEY_SWITCH, i +1, POWER_INV); // Execute command via MQTT + SendKey(KEY_SWITCH, i +1, POWER_INV); // Execute command via MQTT + mqtt_action = POWER_INV; } } else { if ((Switch.hold_timer[i] & SM_TIMER_MASK)> loops_per_second * Settings.param[P_HOLD_TIME] / 25) { if((Switch.hold_timer[i] & ~SM_TIMER_MASK) != SM_SECOND_PRESS) { Switch.hold_timer[i]= SM_FIRST_PRESS; - switchflag = POWER_TOGGLE; // Toggle with pushbutton + switchflag = POWER_TOGGLE; // Toggle with pushbutton } else{ - SendKey(KEY_SWITCH, i +1, POWER_100); // Execute command via MQTT + SendKey(KEY_SWITCH, i +1, POWER_100); // Execute command via MQTT + mqtt_action = POWER_100; Switch.hold_timer[i]= 0; } } else { Switch.hold_timer[i]= 0; - SendKey(KEY_SWITCH, i +1, POWER_RELEASE); // Execute command via MQTT + SendKey(KEY_SWITCH, i +1, POWER_RELEASE); // Execute command via MQTT + mqtt_action = POWER_RELEASE; } } Switch.hold_timer[i] = (Switch.hold_timer[i] & ~SM_TIMER_MASK) | loops_per_second * Settings.param[P_HOLD_TIME] / 10; break; case PUSHON: if (PRESSED == button) { - switchflag = POWER_ON; // Power ON with pushbutton to Gnd + switchflag = POWER_ON; // Power ON with pushbutton to Gnd } break; case PUSHON_INV: if (NOT_PRESSED == button) { - switchflag = POWER_ON; // Power ON with releasing pushbutton from Gnd + switchflag = POWER_ON; // Power ON with releasing pushbutton from Gnd } break; case PUSH_IGNORE: @@ -400,16 +410,34 @@ void SwitchHandler(uint8_t mode) Switch.last_state[i] = button; } if (switchflag <= POWER_TOGGLE) { - if (!SendKey(KEY_SWITCH, i +1, switchflag)) { // Execute command via MQTT - ExecuteCommandPower(i +1, switchflag, SRC_SWITCH); // Execute command internally (if i < TasmotaGlobal.devices_present) + if (!Settings.flag5.mqtt_switches) { // SetOption114 (0) - Detach Swiches from relays and enable MQTT action state for all the SwitchModes + if (!SendKey(KEY_SWITCH, i +1, switchflag)) { // Execute command via MQTT + ExecuteCommandPower(i +1, switchflag, SRC_SWITCH); // Execute command internally (if i < TasmotaGlobal.devices_present) + } + } else { mqtt_action = switchflag; } + } + if ((mqtt_action != POWER_NONE) && Settings.flag5.mqtt_switches) { // SetOption114 (0) - Detach Swiches from relays and enable MQTT action state for all the SwitchModes + if (!Settings.flag.hass_discovery) { // SetOption19 - Control Home Assistant automatic discovery (See SetOption59) + char mqtt_state_str[16]; + char *mqtt_state = mqtt_state_str; + if (mqtt_action <= 3) { + if (mqtt_action != 3) { SendKey(KEY_SWITCH, i +1, mqtt_action); } + mqtt_state = SettingsText(SET_STATE_TXT1 + mqtt_action); + } else { + GetTextIndexed(mqtt_state_str, sizeof(mqtt_state_str), mqtt_action, kSwitchPressStates); + } + Response_P(S_JSON_SVALUE_ACTION_SVALUE, GetSwitchText(i).c_str(), mqtt_state); + char scommand[10]; + snprintf_P(scommand, sizeof(scommand), PSTR(D_JSON_SWITCH "%d"), i +1); + MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, scommand); } + mqtt_action = POWER_NONE; } } } } -void SwitchLoop(void) -{ +void SwitchLoop(void) { if (Switch.present) { if (TimeReached(Switch.debounce)) { SetNextTimeInterval(Switch.debounce, Settings.switch_debounce); diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 6304562b9..f805ee57e 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -497,7 +497,7 @@ bool SendKey(uint32_t key, uint32_t device, uint32_t state) XdrvCall(FUNC_ANY_KEY); XdrvMailbox.payload = payload_save; #ifdef USE_PWM_DIMMER - result = true; + if (PWM_DIMMER == TasmotaGlobal.module_type) result = true; } #endif // USE_PWM_DIMMER return result; diff --git a/tasmota/tasmota_configurations.h b/tasmota/tasmota_configurations.h index 773a2e32e..2d9df7c00 100644 --- a/tasmota/tasmota_configurations.h +++ b/tasmota/tasmota_configurations.h @@ -136,7 +136,8 @@ //#define USE_EZOO2 // [I2cDriver55] Enable support for EZO's O2 sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) //#define USE_EZOPRS // [I2cDriver55] Enable support for EZO's PRS sensor (+0k7 code) - Shared EZO code required for any EZO device (+1k2 code) //#define USE_EZOFLO // [I2cDriver55] Enable support for EZO's FLO sensor (+0k4 code) - Shared EZO code required for any EZO device (+1k2 code) -// #define USE_EZODO // [I2cDriver55] Enable support for EZO's DO sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) +// #define USE_EZODO // [I2cDriver55] Enable support for EZO's DO sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) +// #define USE_EZORGB // [I2cDriver55] Enable support for EZO's RGB sensor (+0k5 code) - Shared EZO code required for any EZO device (+1k2 code) #define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code) #define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code) diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index b976dd843..857857d5f 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -352,13 +352,11 @@ void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic, bool retain * prefix 6 = tele using subtopic or RESULT */ char romram[64]; - char stopic[TOPSZ]; - snprintf_P(romram, sizeof(romram), ((prefix > 3) && !Settings.flag.mqtt_response) ? S_RSLT_RESULT : subtopic); // SetOption4 - Switch between MQTT RESULT or COMMAND - for (uint32_t i = 0; i < strlen(romram); i++) { - romram[i] = toupper(romram[i]); - } + UpperCase(romram, romram); + prefix &= 3; + char stopic[TOPSZ]; GetTopic_P(stopic, prefix, TasmotaGlobal.mqtt_topic, romram); MqttPublish(stopic, retained); diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index 5fceb4533..d87f06055 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -1618,8 +1618,8 @@ int32_t EZ_IncomingMessage(int32_t res, const class SBuffer &buf) { if ((0x0000 == profileid) && (0x00 == srcendpoint)) { // ZDO request // Report LQI - Z_Device & device = zigbee_devices.getShortAddr(srcaddr); if (srcaddr != localShortAddr) { + Z_Device & device = zigbee_devices.getShortAddr(srcaddr); device.setLQI(linkquality); device.setLastSeenNow(); } diff --git a/tasmota/xsns_27_apds9960.ino b/tasmota/xsns_27_apds9960.ino index e9ec54bef..780680262 100644 --- a/tasmota/xsns_27_apds9960.ino +++ b/tasmota/xsns_27_apds9960.ino @@ -86,9 +86,6 @@ const char HTTP_SNS_GESTURE[] PROGMEM = "{s}%s " D_GESTURE "{m}%s{e}"; #endif // USE_APDS9960_GESTURE #ifdef USE_APDS9960_COLOR -const char HTTP_SNS_COLOR_RED[] PROGMEM = "{s}%s " D_COLOR_RED "{m}%u{e}"; -const char HTTP_SNS_COLOR_GREEN[] PROGMEM = "{s}%s " D_COLOR_GREEN "{m}%u{e}"; -const char HTTP_SNS_COLOR_BLUE[] PROGMEM = "{s}%s " D_COLOR_BLUE "{m}%u{e}"; const char HTTP_SNS_CCT[] PROGMEM = "{s}%s " D_CCT "{m}%u " D_UNIT_KELVIN "{e}"; #endif // USE_APDS9960_COLOR diff --git a/tasmota/xsns_62_MI_ESP32.ino b/tasmota/xsns_62_MI_ESP32.ino index ef047c36c..d69ae4a90 100644 --- a/tasmota/xsns_62_MI_ESP32.ino +++ b/tasmota/xsns_62_MI_ESP32.ino @@ -373,6 +373,7 @@ class MI32SensorCallback : public NimBLEClientCallbacks { } void onDisconnect(NimBLEClient* pclient) { MI32.mode.connected = 0; + MI32.mode.willReadBatt = 0; AddLog_P2(LOG_LEVEL_DEBUG,PSTR("disconnected %s"), kMI32DeviceType[(MIBLEsensors[MI32.state.sensor].type)-1]); } bool onConnParamsUpdateRequest(NimBLEClient* MI32Client, const ble_gap_upd_params* params) { @@ -859,7 +860,7 @@ void MI32StartScanTask(){ xTaskCreatePinnedToCore( MI32ScanTask, /* Function to implement the task */ "MI32ScanTask", /* Name of the task */ - 4096, /* Stack size in words */ + 2048, /* Stack size in words */ NULL, /* Task input parameter */ 0, /* Priority of the task */ NULL, /* Task handle. */ @@ -1660,7 +1661,7 @@ void MI32EverySecond(bool restart){ if(_beacon.active == false) continue; _activeBeacons++; _beacon.time++; - Response_P(PSTR("{\"Beacon%u\":{\"Time\":%u}}"), _beacon.time); + Response_P(PSTR("{\"Beacon%u\":{\"Time\":%u}}"), _idx, _beacon.time); XdrvRulesProcess(); } if(_activeBeacons==0) MI32.mode.activeBeacon = 0; @@ -1843,7 +1844,7 @@ bool MI32Cmd(void) { switch(XdrvMailbox.index){ case 0: MI32.state.beaconScanCounter = 8; - Response_P(S_JSON_MI32_BCOMMAND_SVALUE, command, XdrvMailbox.index,PSTR("\"scanning\"")); + Response_P(S_JSON_MI32_BCOMMAND_SVALUE, command, XdrvMailbox.index,PSTR("scanning")); break; case 1: case 2: case 3: case 4: char _MAC[18]; @@ -1880,7 +1881,7 @@ bool MI32Cmd(void) { * Presentation \*********************************************************************************************/ -const char HTTP_MI32[] PROGMEM = "{s}MI ESP32 v0916{m}%u%s / %u{e}"; +const char HTTP_MI32[] PROGMEM = "{s}MI ESP32 v0916a{m}%u%s / %u{e}"; const char HTTP_MI32_MAC[] PROGMEM = "{s}%s %s{m}%s{e}"; const char HTTP_RSSI[] PROGMEM = "{s}%s " D_RSSI "{m}%d dBm{e}"; const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u %%{e}"; diff --git a/tasmota/xsns_78_ezo.ino b/tasmota/xsns_78_ezo.ino index 409b55d11..0593ed200 100644 --- a/tasmota/xsns_78_ezo.ino +++ b/tasmota/xsns_78_ezo.ino @@ -18,13 +18,13 @@ */ #ifdef USE_I2C -#if defined(USE_EZOPH) || defined(USE_EZOORP) || defined(USE_EZORTD) || defined(USE_EZOHUM) || defined(USE_EZOEC) || defined(USE_EZOCO2) || defined(USE_EZOO2) || defined(USE_EZOPRS) || defined(USE_EZOFLO) || defined(USE_EZODO) +#if defined(USE_EZOPH) || defined(USE_EZOORP) || defined(USE_EZORTD) || defined(USE_EZOHUM) || defined(USE_EZOEC) || defined(USE_EZOCO2) || defined(USE_EZOO2) || defined(USE_EZOPRS) || defined(USE_EZOFLO) || defined(USE_EZODO) || defined(USE_EZORGB) #define USE_EZO #endif #if defined(USE_EZO) #define D_EZO_DELAY 300 // Minimum delay for any instruction -#define D_EZO_MAX_BUF 40 // Maximum response +#define D_EZO_MAX_BUF 52 // Maximum response const char D_EZO_NAME[] PROGMEM = "EZO"; diff --git a/tasmota/xsns_78_ezorgb.ino b/tasmota/xsns_78_ezorgb.ino new file mode 100644 index 000000000..5bbb49d79 --- /dev/null +++ b/tasmota/xsns_78_ezorgb.ino @@ -0,0 +1,82 @@ +/* + xsns_78_ezorgb.ino - EZO RGB I2C RGB sensor support for Tasmota + + Copyright (C) 2020 Christopher Tremblay + + 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_I2C +#ifdef USE_EZORGB + +#define EZO_RGB_READ_LATENCY 400 + +struct EZORGB : public EZOStruct { + EZORGB(uint32_t addr) : EZOStruct(addr), R(-1), G(-1), B(-6), Lux(0), hasLux(false) {} + + virtual void ProcessMeasurement(void) + { + char data[D_EZO_MAX_BUF]; + char *next; + // R, G, B, Lux + + EZOStruct::ProcessMeasurement(data, sizeof(data), EZO_RGB_READ_LATENCY); + + R = atoi(data); + next = strchr(data, ',') + 1; + G = atoi(next); + next = strchr(next, ',') + 1; + B = atoi(next); + + next = strstr_P(next, PSTR(",Lux")); + hasLux = (next != nullptr); + if (hasLux) { + Lux = atoi(next + sizeof(",Lux") - 1); + } + } + + virtual void Show(bool json, const char *name) + { + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_RED "\":%d,\"" D_JSON_GREEN "\":%d,\"" D_JSON_BLUE "\":%d"), name, R, G, B); + if (hasLux) { + ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%d"), Lux); + } + ResponseJsonEnd(); + +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_COLOR_RED, name, R); + WSContentSend_PD(HTTP_SNS_COLOR_GREEN, name, G); + WSContentSend_PD(HTTP_SNS_COLOR_BLUE, name, B); + + if (hasLux) { + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, name, Lux); + } +#endif + } + } + + static const char id[] PROGMEM; + +private: + uint16_t R, G, B; + uint16_t Lux; + bool hasLux; +}; + +const char EZORGB::id[] PROGMEM = "RGB"; + +#endif // USE_EZORGB +#endif // USE_I2C diff --git a/tasmota/xsns_78_xezo.ino b/tasmota/xsns_78_xezo.ino index 784475ab5..6bb745dc4 100644 --- a/tasmota/xsns_78_xezo.ino +++ b/tasmota/xsns_78_xezo.ino @@ -106,7 +106,11 @@ const char *const EZOSupport[EZO_ADDR_n] PROGMEM = { #else EZOStruct::id, #endif - EZOStruct::id, // "RGB" +#ifdef USE_EZORGB + EZORGB::id, +#else + EZOStruct::id, +#endif }; #define CREATE_EZO_CLASS(CLASS) \ @@ -267,6 +271,9 @@ private: #endif #ifdef USE_EZOHUM CREATE_EZO_CLASS(HUM) +#endif +#ifdef USE_EZORGB + CREATE_EZO_CLASS(RGB) #endif } count++; diff --git a/tools/decode-status.py b/tools/decode-status.py index 719c03061..aa324d6b3 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -168,7 +168,8 @@ a_setoption = [[ "Use friendly name in zigbee topic (use with SetOption89)", "Set dimmer low on rotary dial after power off" ],[ - "","","","", + "Detach Swiches from Relays and enable MQTT action state for all the SwitchModes", + "","","", "","","","", "","","","", "","","","", @@ -235,7 +236,7 @@ a_features = [[ ],[ "USE_EZOORP","USE_EZORTD","USE_EZOHUM","USE_EZOEC", "USE_EZOCO2","USE_EZOO2","USE_EZOPRS","USE_EZOFLO", - "USE_EZODO","","","", + "USE_EZODO","USE_EZORGB","","", "","","","", "","","","", "","","","",