Skip to content

Commit d3d43b1

Browse files
authored
Add Telink devices with custom ZigbeeTlc firmware quirk (#3719)
1 parent 47872ef commit d3d43b1

File tree

2 files changed

+210
-0
lines changed

2 files changed

+210
-0
lines changed

zhaquirks/custom/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Quirks for diy devices or with custom firmware."""

zhaquirks/custom/telink.py

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
"""Telink TLSR825x based devices with custom firmware.
2+
3+
see https://github.com/pvvx/ZigbeeTLc
4+
"""
5+
6+
from zigpy.quirks.v2 import QuirkBuilder
7+
from zigpy.quirks.v2.homeassistant import PERCENTAGE, UnitOfTemperature, UnitOfTime
8+
import zigpy.types as t
9+
from zigpy.zcl import ClusterType
10+
from zigpy.zcl.clusters.hvac import ScheduleProgrammingVisibility, UserInterface
11+
from zigpy.zcl.foundation import ZCLAttributeDef
12+
13+
from zhaquirks import CustomCluster
14+
15+
16+
class Display(t.enum8):
17+
"""Turn off the display."""
18+
19+
Off = 0x01
20+
On = 0x00
21+
22+
23+
class CustomUserInterfaceCluster(CustomCluster, UserInterface):
24+
"""Custom User Interface Cluster with smiley control."""
25+
26+
class AttributeDefs(UserInterface.AttributeDefs):
27+
"""Attribute Definitions."""
28+
29+
# display. 0 - display is off, 1 - display is on
30+
display = ZCLAttributeDef(
31+
id=0x0106,
32+
type=Display,
33+
access="rw",
34+
is_manufacturer_specific=True,
35+
)
36+
37+
# comfort temperature min: A value in 0.01ºC to set minimum comfort temperature for happy face
38+
comfort_temperature_min = ZCLAttributeDef(
39+
id=0x0102,
40+
type=t.int16s,
41+
access="rw",
42+
is_manufacturer_specific=True,
43+
)
44+
45+
# comfort temperature max: A value in 0.01ºC to set maximum comfort temperature for happy face
46+
comfort_temperature_max = ZCLAttributeDef(
47+
id=0x0103,
48+
type=t.int16s,
49+
access="rw",
50+
is_manufacturer_specific=True,
51+
)
52+
53+
# comfort humidity min: A value in 0.01%RH to set minimum comfort humidity for happy face
54+
comfort_humidity_min = ZCLAttributeDef(
55+
id=0x0104,
56+
type=t.uint16_t,
57+
access="rw",
58+
is_manufacturer_specific=True,
59+
)
60+
61+
# comfort humidity max: A value in 0.01%RH to set maximum comfort humidity for happy face
62+
comfort_humidity_max = ZCLAttributeDef(
63+
id=0x0105,
64+
type=t.uint16_t,
65+
access="rw",
66+
is_manufacturer_specific=True,
67+
)
68+
69+
# A value in 0.01ºC offset to fix up incorrect values from sensor
70+
temperature_offset = ZCLAttributeDef(
71+
id=0x0100,
72+
type=t.int16s,
73+
access="rw",
74+
is_manufacturer_specific=True,
75+
)
76+
77+
# A value in 0.01%RH offset to fix up incorrect values from sensor
78+
humidity_offset = ZCLAttributeDef(
79+
id=0x0101,
80+
type=t.int16s,
81+
access="rw",
82+
is_manufacturer_specific=True,
83+
)
84+
# Measurement interval, step 1 second, range: 3..255 seconds. Default 10 seconds.
85+
measurement_interval = ZCLAttributeDef(
86+
id=0x0107,
87+
type=t.uint8_t,
88+
access="rw",
89+
is_manufacturer_specific=True,
90+
)
91+
92+
93+
(
94+
QuirkBuilder("MiaoMiaoCe", "MHO-C401N-z")
95+
.applies_to("MiaMiaoCe", "MHO-C401N-z") # typo until v. 1.2.2
96+
.applies_to("MiaoMiaoCe", "MHO-C401-z")
97+
.applies_to("MiaoMiaoCe", "MHO-C122-z")
98+
.applies_to("MiaMiaoCe", "MHO-C122-z") # typo until v. 1.2.2
99+
.applies_to("Xiaomi", "LYWSD03MMC-z")
100+
.applies_to("Tuya", "TS0201-z")
101+
.applies_to("Tuya", "TH03Z-z")
102+
.applies_to("Tuya", "ZTH01-z")
103+
.applies_to("Tuya", "ZTH02-z")
104+
.applies_to("Tuya", "LKTMZL02-z")
105+
.applies_to("Tuya", "ZY-ZTH02-z")
106+
.applies_to("Sonoff", "TH03-z")
107+
.applies_to("Qingping", "CGDK2-z")
108+
.removes(CustomUserInterfaceCluster.cluster_id, cluster_type=ClusterType.Client)
109+
.adds(CustomUserInterfaceCluster)
110+
.number(
111+
CustomUserInterfaceCluster.AttributeDefs.temperature_offset.name,
112+
CustomUserInterfaceCluster.cluster_id,
113+
min_value=-327.67,
114+
max_value=327.67,
115+
step=0.01,
116+
unit=UnitOfTemperature.CELSIUS,
117+
translation_key="temperature_offset",
118+
fallback_name="Temperature offset",
119+
multiplier=0.01,
120+
mode="box",
121+
)
122+
.number(
123+
CustomUserInterfaceCluster.AttributeDefs.humidity_offset.name,
124+
CustomUserInterfaceCluster.cluster_id,
125+
min_value=-327.67,
126+
max_value=327.67,
127+
step=0.01,
128+
unit=PERCENTAGE,
129+
translation_key="humidity_offset",
130+
fallback_name="Humidity offset",
131+
multiplier=0.01,
132+
mode="box",
133+
)
134+
.number(
135+
CustomUserInterfaceCluster.AttributeDefs.comfort_temperature_min.name,
136+
CustomUserInterfaceCluster.cluster_id,
137+
min_value=-327.67,
138+
max_value=327.67,
139+
step=0.01,
140+
unit=UnitOfTemperature.CELSIUS,
141+
translation_key="comfort_temperature_min",
142+
fallback_name="Comfort temperature min",
143+
multiplier=0.01,
144+
mode="box",
145+
)
146+
.number(
147+
CustomUserInterfaceCluster.AttributeDefs.comfort_temperature_max.name,
148+
CustomUserInterfaceCluster.cluster_id,
149+
min_value=-327.67,
150+
max_value=327.67,
151+
step=0.01,
152+
unit=UnitOfTemperature.CELSIUS,
153+
translation_key="comfort_temperature_max",
154+
fallback_name="Comfort temperature max",
155+
multiplier=0.01,
156+
mode="box",
157+
)
158+
.number(
159+
CustomUserInterfaceCluster.AttributeDefs.comfort_humidity_min.name,
160+
CustomUserInterfaceCluster.cluster_id,
161+
min_value=0,
162+
max_value=99,
163+
step=1,
164+
unit=PERCENTAGE,
165+
translation_key="comfort_humidity_min",
166+
fallback_name="Comfort humidity min",
167+
multiplier=0.01,
168+
mode="box",
169+
)
170+
.number(
171+
CustomUserInterfaceCluster.AttributeDefs.comfort_humidity_max.name,
172+
CustomUserInterfaceCluster.cluster_id,
173+
min_value=0,
174+
max_value=99,
175+
step=1,
176+
unit=PERCENTAGE,
177+
translation_key="comfort_humidity_max",
178+
fallback_name="Comfort humidity max",
179+
multiplier=0.01,
180+
mode="box",
181+
)
182+
.number(
183+
CustomUserInterfaceCluster.AttributeDefs.measurement_interval.name,
184+
CustomUserInterfaceCluster.cluster_id,
185+
min_value=3,
186+
max_value=255,
187+
unit=UnitOfTime.SECONDS,
188+
translation_key="measurement_interval",
189+
fallback_name="Measurement interval",
190+
mode="box",
191+
)
192+
.switch(
193+
CustomUserInterfaceCluster.AttributeDefs.display.name,
194+
CustomUserInterfaceCluster.cluster_id,
195+
off_value=1,
196+
on_value=0,
197+
translation_key="display_enabled",
198+
fallback_name="Display enabled",
199+
)
200+
.switch(
201+
CustomUserInterfaceCluster.AttributeDefs.schedule_programming_visibility.name,
202+
CustomUserInterfaceCluster.cluster_id,
203+
translation_key="show_smiley",
204+
fallback_name="Show smiley",
205+
off_value=ScheduleProgrammingVisibility.Disabled,
206+
on_value=ScheduleProgrammingVisibility.Enabled,
207+
)
208+
.add_to_registry()
209+
)

0 commit comments

Comments
 (0)