Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Forward Philips Hue contact sensor changes to OnOff cluster #3541

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions tests/test_philips.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
from unittest import mock

import pytest
from zigpy.zcl.clusters.general import OnOff
from zigpy.zcl.foundation import ZCLHeader

from tests.common import ClusterListener
import zhaquirks
from zhaquirks.const import (
BUTTON_1,
Expand Down Expand Up @@ -738,3 +740,31 @@ def test_rdm002_triggers():
actual_triggers = PhilipsRDM002.device_automation_triggers

assert actual_triggers == expected_triggers


def test_contact_sensor(zigpy_device_from_v2_quirk):
"""Test that the Hue contact attribute is forwarded to the OnOff cluster."""
quirk = zigpy_device_from_v2_quirk(
"Signify Netherlands B.V.", "SOC001", endpoint_ids=[1, 2]
)
# Add output OnOff cluster to the endpoint. The device has this,
# but the quirk doesn't modify that cluster, so we need to add it manually.
quirk.endpoints[2].add_output_cluster(OnOff.cluster_id)

hue_cluster = quirk.endpoints[2].philips_contact_cluster
on_off_cluster = quirk.endpoints[2].out_clusters[OnOff.cluster_id]
on_off_listener = ClusterListener(on_off_cluster)

# update the contact attribute and check that it is forwarded to the OnOff cluster
hue_cluster.update_attribute(hue_cluster.AttributeDefs.contact.id, 0)
assert on_off_listener.attribute_updates[0] == (0, 0)

hue_cluster.update_attribute(hue_cluster.AttributeDefs.contact.id, 1)
assert on_off_listener.attribute_updates[1] == (0, 1)

# check we didn't exceed the number of expected updates
assert len(on_off_listener.attribute_updates) == 2

# update again with the same value and except no new update
hue_cluster.update_attribute(hue_cluster.AttributeDefs.contact.id, 1)
assert len(on_off_listener.attribute_updates) == 2
17 changes: 17 additions & 0 deletions zhaquirks/philips/soc001.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from zigpy import types
from zigpy.quirks import CustomCluster
from zigpy.quirks.v2 import BinarySensorDeviceClass, EntityType, QuirkBuilder
from zigpy.zcl.clusters.general import OnOff
from zigpy.zcl.foundation import BaseAttributeDefs, ZCLAttributeDef


Expand Down Expand Up @@ -37,6 +38,22 @@ class AttributeDefs(BaseAttributeDefs):
is_manufacturer_specific=True,
)

# catch when contact attribute is updated and forward to OnOff cluster
def _update_attribute(self, attrid, value):
super()._update_attribute(attrid, value)

on_off_cluster = self.endpoint.out_clusters[OnOff.cluster_id]
if (
attrid == self.AttributeDefs.contact.id
and on_off_cluster.get(OnOff.AttributeDefs.on_off.id) != value
):
# This seems to happen after the real OnOff attribute change,
# so we can avoid a duplicate event by checking the current value.
# We'll only update the OnOff cluster if the value is different then,
# this is likely only the case when an update was missed, and we later
# get an attribute report for the custom contact attribute.
on_off_cluster.update_attribute(OnOff.AttributeDefs.on_off.id, value)


(
# <SimpleDescriptor endpoint=2 profile=260 device_type=1026
Expand Down