From a2756dca595e88e5ab26cfbd649747420ea42a03 Mon Sep 17 00:00:00 2001 From: Azrael-Kun Date: Sat, 30 Jul 2022 19:49:17 +1000 Subject: [PATCH] Add support for SONOFF SNZB-01 (#376) * Add support for SONOFF SNZB-01 * add note for long press, bump versions to 2022.07.30 Co-authored-by: Matteo Agnoletto <30753195+EPMatt@users.noreply.github.com> --- .../sonoff_snzb01/sonoff_snzb01.yaml | 205 ++++++++++++++++++ blueprints/hooks/cover/cover.yaml | 7 +- blueprints/hooks/light/light.yaml | 6 +- .../hooks/media_player/media_player.yaml | 7 +- website/docs/blueprints/controllers.mdx | 3 +- .../blueprints/controllers/sonoff_snzb01.mdx | 134 ++++++++++++ website/docs/blueprints/hooks/cover.mdx | 2 + website/docs/blueprints/hooks/light.mdx | 2 + .../docs/blueprints/hooks/media_player.mdx | 2 + .../static/img/controllers/sonoff_snzb01.png | Bin 0 -> 31866 bytes 10 files changed, 364 insertions(+), 4 deletions(-) create mode 100644 blueprints/controllers/sonoff_snzb01/sonoff_snzb01.yaml create mode 100644 website/docs/blueprints/controllers/sonoff_snzb01.mdx create mode 100644 website/static/img/controllers/sonoff_snzb01.png diff --git a/blueprints/controllers/sonoff_snzb01/sonoff_snzb01.yaml b/blueprints/controllers/sonoff_snzb01/sonoff_snzb01.yaml new file mode 100644 index 00000000..a12a4dc4 --- /dev/null +++ b/blueprints/controllers/sonoff_snzb01/sonoff_snzb01.yaml @@ -0,0 +1,205 @@ +# Blueprint metadata +blueprint: + name: Controller - SONOFF SNZB-01 Wireless Switch + description: | + # Controller - SONOFF SNZB-01 Wireless Switch + + Controller automation for executing any kind of action triggered by the provided SONOFF SNZB-01 Wireless Switch. + Supports deCONZ, ZHA, Zigbee2MQTT. + + Automations created with this blueprint can be connected with one or more [Hooks](https://epmatt.github.io/awesome-ha-blueprints/docs/blueprints/hooks) supported by this controller. + Hooks allow to easily create controller-based automations for interacting with media players, lights, covers and more. + See the list of [Hooks available for this controller](https://epmatt.github.io/awesome-ha-blueprints/docs/blueprints/controllers/sonoff_snzb01#available-hooks) for additional details. + + 📕 Full documentation regarding this blueprint is available [here](https://epmatt.github.io/awesome-ha-blueprints/docs/blueprints/controllers/sonoff_snzb01). + + 🚀 This blueprint is part of the **[Awesome HA Blueprints](https://epmatt.github.io/awesome-ha-blueprints) project**. + + ℹ️ Version 2022.07.30 + source_url: https://github.com/EPMatt/awesome-ha-blueprints/blob/main/blueprints/controllers/sonoff_snzb01/sonoff_snzb01.yaml + domain: automation + input: + integration: + name: (Required) Integration + description: Integration used for connecting the remote with Home Assistant. Select one of the available values. + selector: + select: + options: + - deCONZ + - ZHA + - Zigbee2MQTT + controller_device: + name: (deCONZ, ZHA) Controller Device + description: The controller device to use for the automation. Choose a value only if the remote is integrated with deCONZ, ZHA. + default: '' + selector: + device: + controller_entity: + name: (Zigbee2MQTT) Controller Entity + description: The action sensor of the controller to use for the automation. Choose a value only if the remote is integrated with Zigbee2MQTT. + default: '' + selector: + entity: + domain: sensor + helper_last_controller_event: + name: (Required) Helper - Last Controller Event + description: Input Text used to store the last event fired by the controller. You will need to manually create a text input entity for this, please read the blueprint Additional Notes for more info. + default: '' + selector: + entity: + domain: input_text + # inputs for custom actions + action_button_short: + name: (Optional) Button short press + description: Action to run on short button press. + default: [] + selector: + action: + action_button_long: + name: (Optional) Button long press + description: Action to run on long button press. + default: [] + selector: + action: + action_button_double: + name: (Optional) Button double press + description: Action to run on double button press. + default: [] + selector: + action: + # helpers used to properly recognize the remote button events + helper_debounce_delay: + name: (Optional) Helper - Debounce delay + description: + Delay used for debouncing RAW controller events, by default set to 0. A value of 0 disables the debouncing feature. Increase this value if you notice custom actions or linked Hooks running multiple times when interacting with the device. When the controller needs to be debounced, + usually a value of 100 is enough to remove all duplicate events. + default: 0 + selector: + number: + min: 0 + max: 1000 + unit_of_measurement: milliseconds + mode: box + step: 10 +# Automation schema +variables: + # convert input tags to variables, to be used in templates + integration: !input integration + helper_last_controller_event: !input helper_last_controller_event + helper_debounce_delay: !input helper_debounce_delay + # integration id used to select items in the action mapping + integration_id: '{{ integration | lower }}' + # mapping between actions and integrations + actions_mapping: + deconz: + button_short: ['1002'] + button_long: ['1001'] + button_double: ['1004'] + zha: + button_short: [toggle] + button_long: ['off'] + button_double: ['on'] + zigbee2mqtt: + button_short: [single] + button_long: [long] + button_double: [double] + # pre-choose actions for buttons based on configured integration + # no need to perform this task at automation runtime + button_short: '{{ actions_mapping[integration_id]["button_short"] }}' + button_long: '{{ actions_mapping[integration_id]["button_long"] }}' + button_double: '{{ actions_mapping[integration_id]["button_double"] }}' + # build data to send within a controller event + controller_entity: !input controller_entity + controller_device: !input controller_device + controller_id: '{% if integration_id=="zigbee2mqtt" %}{{controller_entity}}{% else %}{{controller_device}}{% endif %}' +mode: restart +max_exceeded: silent +trigger: + # trigger for zigbee2mqtt + - platform: event + event_type: state_changed + event_data: + entity_id: !input controller_entity + # trigger for other integrations + - platform: event + event_type: + - deconz_event + - zha_event + event_data: + device_id: !input controller_device +condition: + - condition: and + conditions: + # check that the button event is not empty + - >- + {%- set trigger_action -%} + {%- if integration_id == "zigbee2mqtt" -%} + {{ trigger.event.data.new_state.state }} + {%- elif integration_id == "deconz" -%} + {{ trigger.event.data.event }} + {%- elif integration_id == "zha" -%} + {{ trigger.event.data.command }}{{"_" if trigger.event.data.args|length > 0}}{{ trigger.event.data.args|join("_") }} + {%- endif -%} + {%- endset -%} + {{ trigger_action not in ["","None"] }} + # only for zigbee2mqtt, check if the event is relative to a real state change, and not only some minor changes in the sensor attributes + # this is required since multiple state_changed events are fired for a single button press, with the result of the automation being triggered multiple times + - '{{ integration_id != "zigbee2mqtt" or trigger.event.data.new_state.state != trigger.event.data.old_state.state }}' +action: + # debouncing - when automation is triggered multiple times, the last automation run is the one which completes execution, due to mode restart + # therefore previous runs must wait for the debounce delay before executing any other action + # if the delay expires and the automation is still running it means it's the last run and execution can continue + - delay: + milliseconds: !input helper_debounce_delay + # extract button event from the trigger + # provide a single string value to check against + - variables: + trigger_action: >- + {%- if integration_id == "zigbee2mqtt" -%} + {{ trigger.event.data.new_state.state }} + {%- elif integration_id == "deconz" -%} + {{ trigger.event.data.event }} + {%- elif integration_id == "zha" -%} + {{ trigger.event.data.command }}{{"_" if trigger.event.data.args|length > 0}}{{ trigger.event.data.args|join("_") }} + {%- endif -%} + trigger_delta: '{{ (as_timestamp(now()) - as_timestamp((states(helper_last_controller_event) | from_json).last_triggered if helper_last_controller_event is not none and (states(helper_last_controller_event) | regex_match("^\{(\".*\": \".*\"(, )?)*\}$")) else "1970-01-01 00:00:00")) * 1000 }}' + # update helper + - service: input_text.set_value + data: + entity_id: !input helper_last_controller_event + value: '{{ {"trigger_action":trigger_action,"last_triggered":now()|string} | to_json }}' + # choose the sequence to run based on the received button event + - choose: + - conditions: '{{ trigger_action | string in button_short }}' + sequence: + # fire the event + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_short + # run the custom action + - choose: + - conditions: [] + sequence: !input action_button_short + - conditions: '{{ trigger_action | string in button_long }}' + sequence: + # fire the event + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_long + # run the custom action + - choose: + - conditions: [] + sequence: !input action_button_long + - conditions: '{{ trigger_action | string in button_double }}' + sequence: + # fire the event + - event: ahb_controller_event + event_data: + controller: '{{ controller_id }}' + action: button_double + # run the custom action + - choose: + - conditions: [] + sequence: !input action_button_double diff --git a/blueprints/hooks/cover/cover.yaml b/blueprints/hooks/cover/cover.yaml index 06c075f4..36c246fa 100644 --- a/blueprints/hooks/cover/cover.yaml +++ b/blueprints/hooks/cover/cover.yaml @@ -16,7 +16,7 @@ blueprint: 🚀 This blueprint is part of the **[Awesome HA Blueprints](https://epmatt.github.io/awesome-ha-blueprints) project**. - ℹ️ Version 2022.07.22 + ℹ️ Version 2022.07.30 source_url: https://github.com/EPMatt/awesome-ha-blueprints/blob/main/blueprints/hooks/cover/cover.yaml domain: automation input: @@ -43,6 +43,7 @@ blueprint: - IKEA E1743 TRÅDFRI On/Off Switch & Dimmer - IKEA E1766 TRÅDFRI Open/Close Remote - IKEA E1812 TRÅDFRI Shortcut button + - SONOFF SNZB-01 Wireless Switch - Xiaomi WXCJKG11LM Aqara Opple 2 button remote - Xiaomi WXCJKG12LM Aqara Opple 4 button remote - Xiaomi WXCJKG12LM Aqara Opple 4 button remote (#2) @@ -82,6 +83,10 @@ variables: open_cover: button_short stop_cover_all: button_long close_cover: button_double + SONOFF SNZB-01 Wireless Switch: + open_cover: button_short + stop_cover_all: button_long + close_cover: button_double Xiaomi WXCJKG11LM Aqara Opple 2 button remote: open_cover: button_1_short open_cover_tilt: button_1_long diff --git a/blueprints/hooks/light/light.yaml b/blueprints/hooks/light/light.yaml index a1b58fcb..e4b537b5 100644 --- a/blueprints/hooks/light/light.yaml +++ b/blueprints/hooks/light/light.yaml @@ -16,7 +16,7 @@ blueprint: 🚀 This blueprint is part of the **[Awesome HA Blueprints](https://epmatt.github.io/awesome-ha-blueprints) project**. - ℹ️ Version 2022.07.22 + ℹ️ Version 2022.07.30 source_url: https://github.com/EPMatt/awesome-ha-blueprints/blob/main/blueprints/hooks/light/light.yaml domain: automation input: @@ -53,6 +53,7 @@ blueprint: - Philips 324131092621 Hue Dimmer switch - Philips 8718699693985 Hue Smart Button - Philips 929002398602 Hue Dimmer switch v2 + - SONOFF SNZB-01 Wireless Switch - Xiaomi WXCJKG11LM Aqara Opple 2 button remote - Xiaomi WXCJKG12LM Aqara Opple 4 button remote - Xiaomi WXCJKG12LM Aqara Opple 4 button remote (#2) @@ -261,6 +262,9 @@ variables: brightness_up_repeat: button_up_long brightness_down: button_down_short brightness_down_repeat: button_down_long + SONOFF SNZB-01 Wireless Switch: + toggle: button_short + color_up: button_double Xiaomi WXCJKG11LM Aqara Opple 2 button remote: turn_on: button_1_short brightness_up_repeat: button_1_long diff --git a/blueprints/hooks/media_player/media_player.yaml b/blueprints/hooks/media_player/media_player.yaml index 4be16c2e..95117dc1 100644 --- a/blueprints/hooks/media_player/media_player.yaml +++ b/blueprints/hooks/media_player/media_player.yaml @@ -16,7 +16,7 @@ blueprint: 🚀 This blueprint is part of the **[Awesome HA Blueprints](https://epmatt.github.io/awesome-ha-blueprints) project**. - ℹ️ Version 2022.07.22 + ℹ️ Version 2022.07.30 source_url: https://github.com/EPMatt/awesome-ha-blueprints/blob/main/blueprints/hooks/media_player/media_player.yaml domain: automation input: @@ -50,6 +50,7 @@ blueprint: - Philips 324131092621 Hue Dimmer switch - Philips 8718699693985 Hue Smart Button - Philips 929002398602 Hue Dimmer switch v2 + - SONOFF SNZB-01 Wireless Switch - Xiaomi WXCJKG11LM Aqara Opple 2 button remote - Xiaomi WXCJKG12LM Aqara Opple 4 button remote - Xiaomi WXCJKG12LM Aqara Opple 4 button remote (#2) @@ -161,6 +162,10 @@ variables: volume_up_repeat: button_up_long volume_down: button_down_short volume_down_repeat: button_down_long + SONOFF SNZB-01 Wireless Switch: + play_pause: button_short + stop: button_long + next_track: button_double Xiaomi WXCJKG11LM Aqara Opple 2 button remote: volume_up: button_1_short volume_up_repeat: button_1_long diff --git a/website/docs/blueprints/controllers.mdx b/website/docs/blueprints/controllers.mdx index 2597c59d..4f90483e 100644 --- a/website/docs/blueprints/controllers.mdx +++ b/website/docs/blueprints/controllers.mdx @@ -15,7 +15,7 @@ You can integrate Controllers with [Hooks](hooks) and create controller-based au ### Supported Controllers -Currently **15** devices are supported from **4** different vendors. +Currently **16** devices are supported from **5** different vendors. _Can't find the controller you're looking for in this list? [Submit a new blueprint proposal for your controller here.](https://github.com/EPMatt/awesome-ha-blueprints/issues/new?assignees=&labels=blueprint%2Cnew%2Ccontroller&template=new-controller-support.md&title=New+Controller+-+)_ @@ -32,6 +32,7 @@ _Can't find the controller you're looking for in this list? [Submit a new bluepr | Philips | [324131092621](/docs/blueprints/controllers/philips_324131092621) | Philips 324131092621 Hue Dimmer switch | deCONZ,ZHA,Zigbee2MQTT | ![philips_324131092621](/img/controllers/philips_324131092621.png) | | Philips | [8718699693985](/docs/blueprints/controllers/philips_8718699693985) | Philips 8718699693985 Hue Smart Button | deCONZ,ZHA | ![philips_8718699693985](/img/controllers/philips_8718699693985.png) | | Philips | [929002398602](/docs/blueprints/controllers/philips_929002398602) | Philips 929002398602 Hue Dimmer switch v2 | ZHA,Zigbee2MQTT | ![philips_929002398602](/img/controllers/philips_929002398602.png) | +| SONOFF | [SNZB-01](/docs/blueprints/controllers/sonoff_snzb01) | SONOFF SNZB-01 Wireless Switch | deCONZ,ZHA,Zigbee2MQTT | ![sonoff_snzb01](/img/controllers/sonoff_snzb01.png) | | Xiaomi | [WXCJKG11LM](/docs/blueprints/controllers/xiaomi_wxcjkg11lm) | Xiaomi WXCJKG11LM Aqara Opple 2 button remote | deCONZ,ZHA,Zigbee2MQTT | ![xiaomi_wxcjkg11lm](/img/controllers/xiaomi_wxcjkg11lm.png) | | Xiaomi | [WXCJKG12LM](/docs/blueprints/controllers/xiaomi_wxcjkg12lm) | Xiaomi WXCJKG12LM Aqara Opple 4 button remote | deCONZ,ZHA,Zigbee2MQTT | ![xiaomi_wxcjkg12lm](/img/controllers/xiaomi_wxcjkg12lm.png) | | Xiaomi | [WXCJKG13LM](/docs/blueprints/controllers/xiaomi_wxcjkg13lm) | Xiaomi WXCJKG13LM Aqara Opple 6 button remote | deCONZ,ZHA,Zigbee2MQTT | ![xiaomi_wxcjkg13lm](/img/controllers/xiaomi_wxcjkg13lm.png) | diff --git a/website/docs/blueprints/controllers/sonoff_snzb01.mdx b/website/docs/blueprints/controllers/sonoff_snzb01.mdx new file mode 100644 index 00000000..e7bfca1d --- /dev/null +++ b/website/docs/blueprints/controllers/sonoff_snzb01.mdx @@ -0,0 +1,134 @@ +--- +title: Controller - SONOFF SNZB-01 Wireless Switch +description: Controller automation for executing any kind of action triggered by the provided SONOFF SNZB-01 Wireless Switch. Supports deCONZ, ZHA, Zigbee2MQTT. +--- + +import { Input, Requirement, ImportCard } from '/src/components/blueprints_docs' + + + +
+ +:::tip +This blueprint is part of the **Controllers-Hooks Ecosystem**. You can read more about this topic [here](/docs/controllers-hooks-ecosystem). +::: + +## Description + +This blueprint provides universal support for running any custom action when a button is pressed on the provided SONOFF SNZB-01 Wireless Switch. Supports controllers integrated with deCONZ, ZHA, Zigbee2MQTT. Just specify the integration used to connect the remote to Home Assistant when setting up the automation, and the blueprint will take care of all the rest. + +:::tip +Automations created with this blueprint can be connected with one or more [Hooks](/docs/blueprints/hooks) supported by this controller. +Hooks allow to easily create controller-based automations for interacting with media players, lights, covers and more. See the list of [Hooks available for this controller](/docs/blueprints/controllers/sonoff_snzb01#available-hooks) for additional details. +::: + +## Requirements + + + + + + +This integration provides the entity which must be provided to the blueprint in the **Helper - Last Controller Event** input. Learn more about this helper by reading the dedicated section in the [Additional Notes](#helper---last-controller-event). + +[Input Text Integration Docs](https://www.home-assistant.io/integrations/input_text/) + + + +## Inputs + + + + + + + + + + +## Available Hooks + +### Light + +This Hook blueprint allows to build a controller-based automation to control a light. Supports brightness and color control both for white temperature and rgb lights. + +#### Default Mapping + +- Button short press -> Toggle +- Button double press -> Color up + +[Light Hook docs](/docs/blueprints/hooks/light) + +### Media Player + +This Hook blueprint allows to build a controller-based automation to control a media player. Supports volume setting, play/pause and track selection. + +#### Default Mapping + +- Button short press -> Play/Pause +- Button long press -> Stop +- Button double press -> Next track + +[Media Player Hook docs](/docs/blueprints/hooks/media_player) + +### Cover + +This Hook blueprint allows to build a controller-based automation to control a cover. Supports opening, closing and tilting the cover. + +#### Default Mapping + +- Button short press -> Open cover +- Button long press -> Stop cover and cover tilt +- Button double press -> Close cover + +[Cover Hook docs](/docs/blueprints/hooks/cover) + +## Additional Notes + +### Helper - Last Controller Event + +The `helper_last_controller_event` (Helper - Last Controller Event) input serves as a permanent storage area for the automation. The stored info is used to implement the blueprint's core functionality. To learn more about the helper, how it's used and why it's required, you can read the dedicated section in the [Controllers-Hooks Ecosystem documentation](/docs/controllers-hooks-ecosystem#helper---last-controller-event-input). + +### Behaviour of button long press + +Please note that the long press action for this controller is triggered after the button is pressed and held for approximately 3 seconds. Since the device does not fire an event when the button is released, the blueprint does not support looping an action over a long press. + +## Changelog + +- **2022-07-30**: first blueprint version :tada: diff --git a/website/docs/blueprints/hooks/cover.mdx b/website/docs/blueprints/hooks/cover.mdx index aa01f0f1..f9ac38c4 100644 --- a/website/docs/blueprints/hooks/cover.mdx +++ b/website/docs/blueprints/hooks/cover.mdx @@ -66,6 +66,7 @@ This integration provides the entity which represents a cover in Home Assistant. - [IKEA E1743 TRÅDFRI On/Off Switch & Dimmer](/docs/blueprints/controllers/ikea_e1743) - [IKEA E1766 TRÅDFRI Open/Close Remote](/docs/blueprints/controllers/ikea_e1766) - [IKEA E1812 TRÅDFRI Shortcut button](/docs/blueprints/controllers/ikea_e1812) +- [SONOFF SNZB-01 Wireless Switch](/docs/blueprints/controllers/sonoff_snzb01) - [Xiaomi WXCJKG11LM Aqara Opple 2 button remote](/docs/blueprints/controllers/xiaomi_wxcjkg11lm) - [Xiaomi WXCJKG12LM Aqara Opple 4 button remote](/docs/blueprints/controllers/xiaomi_wxcjkg12lm) - [Xiaomi WXCJKG13LM Aqara Opple 6 button remote](/docs/blueprints/controllers/xiaomi_wxcjkg13lm) @@ -88,3 +89,4 @@ If you want to link multiple covers to the same controller you can either use [C - **2021-10-29**: Add support for IKEA E1766 TRÅDFRI Open/Close Remote. - **2021-12-03**: Add support for Xiaomi WXCJKG11LM, WXCJKG12LM, WXCJKG13LM. - **2022-07-22**: Add support for Xiaomi WXKG11LM. +- **2022-07-30**: Add support for SONOFF SNZB-01. diff --git a/website/docs/blueprints/hooks/light.mdx b/website/docs/blueprints/hooks/light.mdx index 921323df..64dfc837 100644 --- a/website/docs/blueprints/hooks/light.mdx +++ b/website/docs/blueprints/hooks/light.mdx @@ -123,6 +123,7 @@ This integration provides the entity which represents a light in Home Assistant. - [Philips 324131092621 Hue Dimmer switch](/docs/blueprints/controllers/philips_324131092621) - [Philips 8718699693985 Hue Smart Button](/docs/blueprints/controllers/philips_8718699693985) - [Philips 929002398602 Hue Dimmer switch v2](/docs/blueprints/controllers/philips_929002398602) +- [SONOFF SNZB-01 Wireless Switch](/docs/blueprints/controllers/sonoff_snzb01) - [Xiaomi WXCJKG11LM Aqara Opple 2 button remote](/docs/blueprints/controllers/xiaomi_wxcjkg11lm) - [Xiaomi WXCJKG12LM Aqara Opple 4 button remote](/docs/blueprints/controllers/xiaomi_wxcjkg12lm) - [Xiaomi WXCJKG13LM Aqara Opple 6 button remote](/docs/blueprints/controllers/xiaomi_wxcjkg13lm) @@ -168,3 +169,4 @@ If you want to link multiple lights to the same controller you can either use [L - **2021-12-03**: Add support for Xiaomi WXCJKG11LM, WXCJKG12LM, WXCJKG13LM. - **2021-12-05**: Added secondary mapping for IKEA E2001/E2002 - **2022-07-22**: Add support for Xiaomi WXKG11LM. +- **2022-07-30**: Add support for SONOFF SNZB-01. diff --git a/website/docs/blueprints/hooks/media_player.mdx b/website/docs/blueprints/hooks/media_player.mdx index 952e2b2b..af848271 100644 --- a/website/docs/blueprints/hooks/media_player.mdx +++ b/website/docs/blueprints/hooks/media_player.mdx @@ -83,6 +83,7 @@ This integration provides the entity which represents a media player in Home Ass - [Philips 324131092621 Hue Dimmer switch](/docs/blueprints/controllers/philips_324131092621) - [Philips 8718699693985 Hue Smart Button](/docs/blueprints/controllers/philips_8718699693985) - [Philips 929002398602 Hue Dimmer switch v2](/docs/blueprints/controllers/philips_929002398602) +- [SONOFF SNZB-01 Wireless Switch](/docs/blueprints/controllers/sonoff_snzb01) - [Xiaomi WXCJKG11LM Aqara Opple 2 button remote](/docs/blueprints/controllers/xiaomi_wxcjkg11lm) - [Xiaomi WXCJKG12LM Aqara Opple 4 button remote](/docs/blueprints/controllers/xiaomi_wxcjkg12lm) - [Xiaomi WXCJKG13LM Aqara Opple 6 button remote](/docs/blueprints/controllers/xiaomi_wxcjkg13lm) @@ -115,3 +116,4 @@ Not all media players support the customization of the number of steps for volum - **2021-11-21**: Add support for Philips 929002398602 Hue Dimmer switch v2. - **2021-12-03**: Add support for Xiaomi WXCJKG11LM, WXCJKG12LM, WXCJKG13LM. - **2022-07-22**: Add support for Xiaomi WXKG11LM. +- **2022-07-30**: Add support for SONOFF SNZB-01. diff --git a/website/static/img/controllers/sonoff_snzb01.png b/website/static/img/controllers/sonoff_snzb01.png new file mode 100644 index 0000000000000000000000000000000000000000..4238ee76f26d8a28edee5487ec48498cf055974b GIT binary patch literal 31866 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