-
Notifications
You must be signed in to change notification settings - Fork 762
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for QUAD-ZIG-SW from smarthjemmet.dk (#3400)
Co-authored-by: TheJulianJES <TheJulianJES@users.noreply.github.com>
- Loading branch information
1 parent
df7e32f
commit 78687d2
Showing
3 changed files
with
145 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
"""Tests for SmartHjemmet quirks.""" | ||
|
||
from unittest import mock | ||
|
||
import pytest | ||
from zigpy.zcl.clusters.general import MultistateInput | ||
|
||
import zhaquirks | ||
|
||
zhaquirks.setup() | ||
|
||
|
||
@pytest.mark.parametrize("endpoint", (2, 3, 4, 5)) | ||
def test_quadzigsw(zigpy_device_from_v2_quirk, endpoint): | ||
"""Test the SmartHjemmet QUAD-ZIG-SW.""" | ||
device = zigpy_device_from_v2_quirk( | ||
"smarthjemmet.dk", "QUAD-ZIG-SW", endpoint_ids=[1, 2, 3, 4, 5] | ||
) | ||
|
||
cluster = device.endpoints[endpoint].multistate_input | ||
listener = mock.MagicMock() | ||
cluster.add_listener(listener) | ||
|
||
multistate_value = MultistateInput.AttributeDefs.present_value.id | ||
multistate_text = MultistateInput.AttributeDefs.state_text.id | ||
|
||
# test that attribute writes are passed through with no events | ||
cluster.update_attribute(MultistateInput.AttributeDefs.state_text.id, "test") | ||
assert listener.zha_send_event.call_count == 0 | ||
assert listener.attribute_updated.call_count == 1 | ||
assert listener.attribute_updated.call_args[0][0] == multistate_text | ||
assert listener.attribute_updated.call_args[0][1] == "test" | ||
|
||
# test that the cluster does not send events for unknown values | ||
cluster.update_attribute(multistate_value, 5) | ||
assert listener.zha_send_event.call_count == 0 | ||
|
||
# test that the cluster sends the correct events | ||
cluster.update_attribute(multistate_value, 0) | ||
assert listener.zha_send_event.call_count == 1 | ||
listener.zha_send_event.assert_called_with("release", {"value": 0}) | ||
|
||
cluster.update_attribute(multistate_value, 1) | ||
assert listener.zha_send_event.call_count == 2 | ||
listener.zha_send_event.assert_called_with("single", {"value": 1}) | ||
|
||
cluster.update_attribute(multistate_value, 2) | ||
assert listener.zha_send_event.call_count == 3 | ||
listener.zha_send_event.assert_called_with("double", {"value": 2}) | ||
|
||
cluster.update_attribute(multistate_value, 3) | ||
assert listener.zha_send_event.call_count == 4 | ||
listener.zha_send_event.assert_called_with("triple", {"value": 3}) | ||
|
||
cluster.update_attribute(multistate_value, 4) | ||
assert listener.zha_send_event.call_count == 5 | ||
listener.zha_send_event.assert_called_with("hold", {"value": 4}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
"""smarthjemmet.dk devices.""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
"""Device handler for smarthjemmet.dk QUAD-ZIG-SW.""" | ||
|
||
from zigpy.quirks import CustomCluster | ||
from zigpy.quirks.v2 import QuirkBuilder | ||
from zigpy.zcl import ClusterType | ||
from zigpy.zcl.clusters.general import MultistateInput | ||
|
||
from zhaquirks import PowerConfigurationCluster | ||
from zhaquirks.const import ( | ||
COMMAND, | ||
COMMAND_DOUBLE, | ||
COMMAND_HOLD, | ||
COMMAND_RELEASE, | ||
COMMAND_SINGLE, | ||
COMMAND_TRIPLE, | ||
DOUBLE_PRESS, | ||
ENDPOINT_ID, | ||
LONG_PRESS, | ||
LONG_RELEASE, | ||
SHORT_PRESS, | ||
TRIPLE_PRESS, | ||
VALUE, | ||
ZHA_SEND_EVENT, | ||
) | ||
|
||
SMARTHJEMMET = "smarthjemmet.dk" | ||
|
||
ACTION_TYPE = { | ||
0: COMMAND_RELEASE, | ||
1: COMMAND_SINGLE, | ||
2: COMMAND_DOUBLE, | ||
3: COMMAND_TRIPLE, | ||
4: COMMAND_HOLD, | ||
} | ||
|
||
|
||
class CR2032PowerConfigurationCluster(PowerConfigurationCluster): | ||
"""CR2032 Power Configuration Cluster.""" | ||
|
||
MIN_VOLTS = 2.2 | ||
MAX_VOLTS = 3.0 | ||
|
||
|
||
class CustomMultistateInputCluster(CustomCluster, MultistateInput): | ||
"""Multistate input cluster.""" | ||
|
||
def _update_attribute(self, attrid, value): | ||
super()._update_attribute(attrid, value) | ||
if ( | ||
attrid == MultistateInput.AttributeDefs.present_value.id | ||
and (action := ACTION_TYPE.get(value)) is not None | ||
): | ||
event_args = {VALUE: value} | ||
self.listener_event(ZHA_SEND_EVENT, action, event_args) | ||
|
||
|
||
( | ||
QuirkBuilder(SMARTHJEMMET, "QUAD-ZIG-SW") | ||
.applies_to(SMARTHJEMMET, "MULTI-ZIG-SW") | ||
.skip_configuration() | ||
.replaces(CR2032PowerConfigurationCluster) | ||
.removes(MultistateInput.cluster_id, cluster_type=ClusterType.Client, endpoint_id=2) | ||
.removes(MultistateInput.cluster_id, cluster_type=ClusterType.Client, endpoint_id=3) | ||
.removes(MultistateInput.cluster_id, cluster_type=ClusterType.Client, endpoint_id=4) | ||
.removes(MultistateInput.cluster_id, cluster_type=ClusterType.Client, endpoint_id=5) | ||
.adds(CustomMultistateInputCluster, endpoint_id=2) | ||
.adds(CustomMultistateInputCluster, endpoint_id=3) | ||
.adds(CustomMultistateInputCluster, endpoint_id=4) | ||
.adds(CustomMultistateInputCluster, endpoint_id=5) | ||
.device_automation_triggers( | ||
{ | ||
(press_type, f"button_{i}"): { | ||
COMMAND: command, | ||
ENDPOINT_ID: i + 1, | ||
} | ||
for i in range(1, 5) | ||
for press_type, command in { | ||
(SHORT_PRESS, COMMAND_SINGLE), | ||
(DOUBLE_PRESS, COMMAND_DOUBLE), | ||
(TRIPLE_PRESS, COMMAND_TRIPLE), | ||
(LONG_PRESS, COMMAND_HOLD), | ||
(LONG_RELEASE, COMMAND_RELEASE), | ||
} | ||
} | ||
) | ||
.add_to_registry() | ||
) |