Skip to content

Commit

Permalink
Add support for QUAD-ZIG-SW from smarthjemmet.dk (#3400)
Browse files Browse the repository at this point in the history
Co-authored-by: TheJulianJES <TheJulianJES@users.noreply.github.com>
  • Loading branch information
mortenmoulder and TheJulianJES authored Feb 6, 2025
1 parent df7e32f commit 78687d2
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 0 deletions.
57 changes: 57 additions & 0 deletions tests/test_smarthjemmet.py
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})
1 change: 1 addition & 0 deletions zhaquirks/smarthjemmet/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""smarthjemmet.dk devices."""
87 changes: 87 additions & 0 deletions zhaquirks/smarthjemmet/quadzigsw.py
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()
)

0 comments on commit 78687d2

Please sign in to comment.