From 5ee17b9fd80f63964bb35e3e8e04f2a2b12d06fb Mon Sep 17 00:00:00 2001 From: theorlangur Date: Wed, 20 Dec 2023 03:25:23 +0100 Subject: [PATCH] Add device triggers for Sonoff SNZB-01P smart button (#2833) --- tests/test_sonoff.py | 30 ++++++++++++ zhaquirks/sonoff/snzb01p.py | 91 +++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 tests/test_sonoff.py create mode 100644 zhaquirks/sonoff/snzb01p.py diff --git a/tests/test_sonoff.py b/tests/test_sonoff.py new file mode 100644 index 0000000000..2e5b47a000 --- /dev/null +++ b/tests/test_sonoff.py @@ -0,0 +1,30 @@ +"""Tests for Sonoff quirks.""" + + +import zhaquirks +import zhaquirks.sonoff.snzb01p + +zhaquirks.setup() + + +def test_sonoff_snzb01p(assert_signature_matches_quirk): + """Test 'Sonoff SNZB-01P smart button' signature is matched to its quirk.""" + + signature = { + "node_descriptor": "NodeDescriptor(logical_type=, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=, mac_capability_flags=, manufacturer_code=4742, maximum_buffer_size=82, maximum_incoming_transfer_size=255, server_mask=11264, maximum_outgoing_transfer_size=255, descriptor_capability_field=, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=True, *is_full_function_device=False, *is_mains_powered=False, *is_receiver_on_when_idle=False, *is_router=False, *is_security_capable=False)", + "endpoints": { + "1": { + "profile_id": 260, + "device_type": "0x0000", + "in_clusters": ["0x0000", "0x0001", "0x0003", "0x0020", "0xfc57"], + "out_clusters": ["0x0003", "0x0006", "0x0019"], + } + }, + "manufacturer": "eWeLink", + "model": "SNZB-01P", + "class": "sonoff.snzb01p.SonoffSmartButtonSNZB01P", + } + + assert_signature_matches_quirk( + zhaquirks.sonoff.snzb01p.SonoffSmartButtonSNZB01P, signature + ) diff --git a/zhaquirks/sonoff/snzb01p.py b/zhaquirks/sonoff/snzb01p.py new file mode 100644 index 0000000000..5248f09d77 --- /dev/null +++ b/zhaquirks/sonoff/snzb01p.py @@ -0,0 +1,91 @@ +"""Sonoff Smart Button SNZB-01P""" +from zigpy.profiles import zha +from zigpy.quirks import CustomDevice +from zigpy.zcl.clusters.general import ( + Basic, + Identify, + OnOff, + Ota, + PollControl, + PowerConfiguration, +) + +from zhaquirks.const import ( + BUTTON, + CLUSTER_ID, + COMMAND, + COMMAND_OFF, + COMMAND_ON, + COMMAND_TOGGLE, + DEVICE_TYPE, + DOUBLE_PRESS, + ENDPOINT_ID, + ENDPOINTS, + INPUT_CLUSTERS, + LONG_PRESS, + MODELS_INFO, + OUTPUT_CLUSTERS, + PROFILE_ID, + SHORT_PRESS, +) + +SONOFF_CLUSTER_ID = 0xFC57 + + +class SonoffSmartButtonSNZB01P(CustomDevice): + """Sonoff smart button remote - model SNZB-01P""" + + signature = { + # + MODELS_INFO: [ + ("eWeLink", "SNZB-01P"), + ], + ENDPOINTS: { + 1: { + PROFILE_ID: zha.PROFILE_ID, + DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH, + INPUT_CLUSTERS: [ + Basic.cluster_id, + PowerConfiguration.cluster_id, + Identify.cluster_id, + PollControl.cluster_id, + SONOFF_CLUSTER_ID, + ], + OUTPUT_CLUSTERS: [ + Identify.cluster_id, + OnOff.cluster_id, + Ota.cluster_id, + ], + }, + }, + } + + replacement = { + ENDPOINTS: { + 1: { + PROFILE_ID: zha.PROFILE_ID, + DEVICE_TYPE: zha.DeviceType.ON_OFF_SWITCH, + INPUT_CLUSTERS: [ + Basic.cluster_id, + PowerConfiguration.cluster_id, + Identify.cluster_id, + PollControl.cluster_id, + SONOFF_CLUSTER_ID, + ], + OUTPUT_CLUSTERS: [ + Identify.cluster_id, + OnOff.cluster_id, + Ota.cluster_id, + ], + }, + }, + } + + device_automation_triggers = { + (SHORT_PRESS, BUTTON): {COMMAND: COMMAND_TOGGLE, CLUSTER_ID: 6, ENDPOINT_ID: 1}, + (DOUBLE_PRESS, BUTTON): {COMMAND: COMMAND_ON, CLUSTER_ID: 6, ENDPOINT_ID: 1}, + (LONG_PRESS, BUTTON): {COMMAND: COMMAND_OFF, CLUSTER_ID: 6, ENDPOINT_ID: 1}, + }