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

Add Linxura smart controller button quirk #3392

Merged
merged 87 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
5174804
first time to commit linxura integration
simon3panda Sep 23, 2024
4d2c6cd
Add new quirks that support Linxura smart controller.
simon3panda Sep 30, 2024
6057d72
Apply pre-commit auto fixes
pre-commit-ci[bot] Sep 30, 2024
b7b1dc1
Update test_linxura.py
simon3panda Sep 30, 2024
f318362
Merge branch 'dev' of https://github.com/simon3panda/zha-device-handl…
simon3panda Sep 30, 2024
7d477de
Apply pre-commit auto fixes
pre-commit-ci[bot] Sep 30, 2024
9e19d0f
fix pre-commit issue
simon3panda Sep 30, 2024
a6d7be0
Merge branch 'dev' of https://github.com/simon3panda/zha-device-handl…
simon3panda Sep 30, 2024
2409dcc
fix pre-commit issue
simon3panda Sep 30, 2024
3ffa306
Apply pre-commit auto fixes
pre-commit-ci[bot] Sep 30, 2024
aa7b1d5
fix pre-commit ruff-format issue
simon3panda Sep 30, 2024
745d997
Merge branch 'dev' of https://github.com/simon3panda/zha-device-handl…
simon3panda Sep 30, 2024
d5f1346
codecov test issue
simon3panda Sep 30, 2024
d687b3f
Apply pre-commit auto fixes
pre-commit-ci[bot] Sep 30, 2024
60a0ef6
fix pre-commit issue
simon3panda Sep 30, 2024
58a4850
Merge branch 'dev' of https://github.com/simon3panda/zha-device-handl…
simon3panda Sep 30, 2024
5ab15e4
update for solving codecov cover issue
simon3panda Oct 6, 2024
ef07035
solve check issue
simon3panda Oct 6, 2024
f494957
Apply pre-commit auto fixes
pre-commit-ci[bot] Oct 6, 2024
8f19301
Update __init__.py
simon3panda Oct 6, 2024
632ffb3
Merge branch 'dev' of https://github.com/simon3panda/zha-device-handl…
simon3panda Oct 6, 2024
33f8183
Update __init__.py
simon3panda Oct 6, 2024
8b7893d
Apply pre-commit auto fixes
pre-commit-ci[bot] Oct 6, 2024
34b03b5
Update __init__.py
simon3panda Oct 6, 2024
0fbfc86
Apply pre-commit auto fixes
pre-commit-ci[bot] Oct 6, 2024
64712a5
Update __init__.py
simon3panda Oct 6, 2024
b7ce98b
Apply pre-commit auto fixes
pre-commit-ci[bot] Oct 6, 2024
e5c6bf3
update __init__.py
simon3panda Oct 6, 2024
08de105
Update __init__.py
simon3panda Oct 6, 2024
b29670e
Apply pre-commit auto fixes
pre-commit-ci[bot] Oct 6, 2024
85ad4c0
Update __init__.py
simon3panda Oct 6, 2024
a83b4c5
Update __init__.py
simon3panda Oct 6, 2024
6761de0
Apply pre-commit auto fixes
pre-commit-ci[bot] Oct 6, 2024
494cf83
Update __init__.py
simon3panda Oct 6, 2024
5dfd683
update for codecov cover
simon3panda Oct 6, 2024
0cc62dd
Apply pre-commit auto fixes
pre-commit-ci[bot] Oct 6, 2024
e178a8c
Update test_linxura.py
simon3panda Oct 6, 2024
9a83e44
Merge branch 'dev' of https://github.com/simon3panda/zha-device-handl…
simon3panda Oct 6, 2024
8e0bd34
Apply pre-commit auto fixes
pre-commit-ci[bot] Oct 6, 2024
9488899
Update __init__.py
simon3panda Oct 6, 2024
b8407dd
Merge branch 'dev' of https://github.com/simon3panda/zha-device-handl…
simon3panda Oct 6, 2024
680a0ad
Update test_linxura.py
simon3panda Oct 6, 2024
4fedb7c
solve codecov issue
simon3panda Oct 8, 2024
44066f2
Update test_linxura.py
simon3panda Oct 8, 2024
28dc389
Apply pre-commit auto fixes
pre-commit-ci[bot] Oct 8, 2024
abed165
Update test_linxura.py
simon3panda Oct 8, 2024
4613b9f
Merge branch 'dev' of https://github.com/simon3panda/zha-device-handl…
simon3panda Oct 8, 2024
4680fd9
Update __init__.py
simon3panda Oct 8, 2024
f7ca32f
Update __init__.py
simon3panda Oct 8, 2024
60c7bd0
Update __init__.py
simon3panda Oct 8, 2024
427a261
Update __init__.py
simon3panda Oct 8, 2024
df1b192
Update __init__.py
simon3panda Oct 8, 2024
72ca717
Update test_linxura.py
simon3panda Oct 8, 2024
0a51caf
Update test_linxura.py
simon3panda Oct 8, 2024
f490a56
Update __init__.py
simon3panda Oct 8, 2024
767cf75
Update __init__.py
simon3panda Oct 8, 2024
0db43ce
Remove the commented out code
simon3panda Oct 9, 2024
d6b4ecb
Update test_linxura.py
simon3panda Oct 9, 2024
e12e9df
Apply pre-commit auto fixes
pre-commit-ci[bot] Oct 9, 2024
30f5119
Modify 4 endpoint to 1 endpoint.
simon3panda Nov 22, 2024
63021ec
Apply pre-commit auto fixes
pre-commit-ci[bot] Nov 22, 2024
e8e81cb
Update __init__.py
simon3panda Nov 22, 2024
75ce231
Merge branch 'dev' of https://github.com/simon3panda/zha-device-handl…
simon3panda Nov 22, 2024
8d10072
Create test_linxura.py
simon3panda Nov 22, 2024
74b34ac
Update test_linxura.py
simon3panda Nov 22, 2024
19dfe03
Delete test_linxura.py
simon3panda Nov 22, 2024
09a24cd
Create test_linxura.py
simon3panda Nov 22, 2024
29c7fab
Update test_linxura.py
simon3panda Nov 22, 2024
6589ed3
Update __init__.py
simon3panda Nov 25, 2024
3f19563
Apply pre-commit auto fixes
pre-commit-ci[bot] Nov 25, 2024
29cd79f
Update zhaquirks/linxura/__init__.py
simon3panda Nov 25, 2024
e91f2cc
modify based on suggestion
simon3panda Nov 25, 2024
ed4db82
Apply pre-commit auto fixes
pre-commit-ci[bot] Nov 25, 2024
a057796
Update __init__.py
simon3panda Nov 25, 2024
3301f4f
Update __init__.py
simon3panda Nov 25, 2024
b39cffc
Update test_linxura.py
simon3panda Nov 25, 2024
055f228
Update test_linxura.py
simon3panda Nov 25, 2024
6a94895
Apply pre-commit auto fixes
pre-commit-ci[bot] Nov 25, 2024
b81c52d
Clean up tests
TheJulianJES Nov 25, 2024
5a5121b
Simplify comparisons
TheJulianJES Nov 25, 2024
b3cefc2
Use `elif`
TheJulianJES Nov 25, 2024
94e3e2a
Move up `0 < value < 24` check
TheJulianJES Nov 25, 2024
2b189df
Discard invalid values
TheJulianJES Nov 25, 2024
f833451
Clean up tests more
TheJulianJES Nov 26, 2024
0675fca
Remove `COMMAND_ID`
TheJulianJES Nov 26, 2024
dafc3b5
Improve comment on discarding values
TheJulianJES Nov 26, 2024
9294274
Move IAS cluster and constants to button quirk
TheJulianJES Nov 26, 2024
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
116 changes: 116 additions & 0 deletions tests/test_linxura.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
"""Tests for Linxura quirks."""

from unittest import mock

import pytest
from zigpy.zcl.clusters.security import IasZone

import zhaquirks
import zhaquirks.linxura

zhaquirks.setup()


async def test_button_ias(zigpy_device_from_quirk):
"""Test Linxura button remotes."""

device = zigpy_device_from_quirk(zhaquirks.linxura.button.LinxuraButton)
ias_zone_status_attr_id = IasZone.AttributeDefs.zone_status.id
cluster = device.endpoints[1].ias_zone
listener = mock.MagicMock()
cluster.add_listener(listener)

for i in range(0, 24):
# button press
cluster.update_attribute(ias_zone_status_attr_id, i)

# update_attribute on the IasZone cluster is always called
assert listener.attribute_updated.call_args[0][0] == ias_zone_status_attr_id
assert listener.attribute_updated.call_args[0][1] == i

# we get 20 events, 4 are discarded as invalid (0, 6, 12, 18)
assert listener.attribute_updated.call_count == 24
assert listener.zha_send_event.call_count == 20


@pytest.mark.parametrize(
"message, button, press_type",
[
(
b"\x18\n\n\x02\x00\x19\x01\x00\xfe\xff0\x01",
"button_1",
"remote_button_short_press",
),
(
b"\x18\n\n\x02\x00\x19\x03\x00\xfe\xff0\x01",
"button_1",
"remote_button_double_press",
),
(
b"\x18\n\n\x02\x00\x19\x05\x00\xfe\xff0\x01",
"button_1",
"remote_button_long_press",
),
(
b"\x18\n\n\x02\x00\x19\x07\x00\xfe\xff0\x01",
"button_2",
"remote_button_short_press",
),
(
b"\x18\n\n\x02\x00\x19\x09\x00\xfe\xff0\x01",
"button_2",
"remote_button_double_press",
),
(
b"\x18\n\n\x02\x00\x19\x0b\x00\xfe\xff0\x01",
"button_2",
"remote_button_long_press",
),
(
b"\x18\n\n\x02\x00\x19\x0d\x00\xfe\xff0\x01",
"button_3",
"remote_button_short_press",
),
(
b"\x18\n\n\x02\x00\x19\x0f\x00\xfe\xff0\x01",
"button_3",
"remote_button_double_press",
),
(
b"\x18\n\n\x02\x00\x19\x11\x00\xfe\xff0\x01",
"button_3",
"remote_button_long_press",
),
(
b"\x18\n\n\x02\x00\x19\x13\x00\xfe\xff0\x01",
"button_4",
"remote_button_short_press",
),
(
b"\x18\n\n\x02\x00\x19\x15\x00\xfe\xff0\x01",
"button_4",
"remote_button_double_press",
),
(
b"\x18\n\n\x02\x00\x19\x17\x00\xfe\xff0\x01",
"button_4",
"remote_button_long_press",
),
],
)
async def test_button_triggers(zigpy_device_from_quirk, message, button, press_type):
"""Test ZHA_SEND_EVENT case."""
device = zigpy_device_from_quirk(zhaquirks.linxura.button.LinxuraButton)
cluster = device.endpoints[1].ias_zone
listener = mock.MagicMock()
cluster.add_listener(listener)

device.handle_message(260, cluster.cluster_id, 1, 1, message)
assert listener.zha_send_event.call_count == 1
assert listener.zha_send_event.call_args == mock.call(
f"{button}_{press_type}",
{
"button": button,
"press_type": press_type,
},
)
3 changes: 3 additions & 0 deletions zhaquirks/linxura/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""Linxura devices."""

LINXURA = "Linxura"
109 changes: 109 additions & 0 deletions zhaquirks/linxura/button.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
"""Linxura button device."""

from zigpy.profiles import zha
from zigpy.quirks import CustomCluster, CustomDevice
from zigpy.zcl.clusters.general import Basic
from zigpy.zcl.clusters.security import IasZone

from zhaquirks.const import (
BUTTON,
BUTTON_1,
BUTTON_2,
BUTTON_3,
BUTTON_4,
CLUSTER_ID,
COMMAND,
DEVICE_TYPE,
DOUBLE_PRESS,
ENDPOINTS,
INPUT_CLUSTERS,
LONG_PRESS,
MODELS_INFO,
OUTPUT_CLUSTERS,
PRESS_TYPE,
PROFILE_ID,
SHORT_PRESS,
ZHA_SEND_EVENT,
)
from zhaquirks.linxura import LINXURA

PRESS_TYPES = {
1: SHORT_PRESS,
2: DOUBLE_PRESS,
3: LONG_PRESS,
}


class LinxuraIASCluster(CustomCluster, IasZone):
"""IAS cluster used for Linxura button."""

def _update_attribute(self, attrid, value):
super()._update_attribute(attrid, value)
if attrid == self.AttributeDefs.zone_status.id and 0 < value < 24:
if 0 < value < 6:
button = BUTTON_1
press_type = PRESS_TYPES[value // 2 + 1]
elif 6 < value < 12:
button = BUTTON_2
press_type = PRESS_TYPES[value // 2 - 3 + 1]
elif 12 < value < 18:
button = BUTTON_3
press_type = PRESS_TYPES[value // 2 - 6 + 1]
elif 18 < value < 24:
button = BUTTON_4
press_type = PRESS_TYPES[value // 2 - 9 + 1]
else:
# discard invalid values: 0, 6, 12, 18
return

action = f"{button}_{press_type}"
event_args = {
BUTTON: button,
PRESS_TYPE: press_type,
}
self.listener_event(ZHA_SEND_EVENT, action, event_args)


class LinxuraButton(CustomDevice):
"""Linxura button device."""

signature = {
# <SimpleDescriptor endpoint=1 profile=260 device_type=1026
# device_version=0
# input_clusters=[0, 3, 1280]=>input_clusters=[0, 1280]
# output_clusters=[3]>=>output_clusters=[]
MODELS_INFO: [(LINXURA, "Smart Controller")],
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.IAS_ZONE,
INPUT_CLUSTERS: [
Basic.cluster_id,
IasZone.cluster_id,
],
OUTPUT_CLUSTERS: [],
},
},
}

replacement = {
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
INPUT_CLUSTERS: [
Basic.cluster_id,
LinxuraIASCluster,
],
OUTPUT_CLUSTERS: [],
},
}
}

device_automation_triggers = {
TheJulianJES marked this conversation as resolved.
Show resolved Hide resolved
(press_type, button): {
COMMAND: f"{button}_{press_type}",
CLUSTER_ID: IasZone.cluster_id,
}
for press_type in (SHORT_PRESS, DOUBLE_PRESS, LONG_PRESS)
for button in (BUTTON_1, BUTTON_2, BUTTON_3, BUTTON_4)
}