Skip to content

Commit 979551d

Browse files
Split Tuya IAS function into contact & smoke (#3608)
Co-authored-by: TheJulianJES <[email protected]>
1 parent 5f1a7f2 commit 979551d

File tree

3 files changed

+82
-39
lines changed

3 files changed

+82
-39
lines changed

tests/test_tuya_builder.py

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
from tests.common import ClusterListener, wait_for_zigpy_tasks
1414
import zhaquirks
1515
from zhaquirks.tuya.builder import (
16+
TuyaIasContact,
17+
TuyaIasFire,
1618
TuyaPowerConfigurationCluster2AAA,
1719
TuyaQuirkBuilder,
1820
TuyaRelativeHumidity,
@@ -46,6 +48,41 @@ def real_device(MockAppController):
4648
return device
4749

4850

51+
@pytest.mark.parametrize(
52+
"method_name,attr_name,exp_class",
53+
[
54+
("tuya_battery", "power", TuyaPowerConfigurationCluster2AAA),
55+
("tuya_metering", "smartenergy_metering", TuyaValveWaterConsumed),
56+
("tuya_onoff", "on_off", TuyaOnOffNM),
57+
("tuya_soil_moisture", "soil_moisture", TuyaSoilMoisture),
58+
("tuya_temperature", "temperature", TuyaTemperatureMeasurement),
59+
("tuya_humidity", "humidity", TuyaRelativeHumidity),
60+
("tuya_smoke", "ias_zone", TuyaIasFire),
61+
("tuya_contact", "ias_zone", TuyaIasContact),
62+
],
63+
)
64+
async def test_convenience_methods(device_mock, method_name, attr_name, exp_class):
65+
"""Test TuyaQuirkBuilder convenience methods."""
66+
67+
registry = DeviceRegistry()
68+
69+
entry = TuyaQuirkBuilder(
70+
device_mock.manufacturer, device_mock.model, registry=registry
71+
)
72+
entry = getattr(entry, method_name)(dp_id=1)
73+
entry.skip_configuration().add_to_registry()
74+
75+
quirked = registry.get_device(device_mock)
76+
assert isinstance(quirked, CustomDeviceV2)
77+
assert quirked in registry
78+
79+
ep = quirked.endpoints[1]
80+
81+
ep_attr = getattr(ep, attr_name)
82+
assert ep_attr is not None
83+
assert isinstance(ep_attr, exp_class)
84+
85+
4986
async def test_tuya_quirkbuilder(device_mock):
5087
"""Test adding a v2 Tuya Quirk to the registry and getting back a quirked device."""
5188

@@ -60,10 +97,7 @@ class TestEnum(t.enum8):
6097
entry = (
6198
TuyaQuirkBuilder(device_mock.manufacturer, device_mock.model, registry=registry)
6299
.tuya_battery(dp_id=1)
63-
.tuya_metering(dp_id=2)
64100
.tuya_onoff(dp_id=3)
65-
.tuya_soil_moisture(dp_id=4)
66-
.tuya_temperature(dp_id=5)
67101
.tuya_switch(
68102
dp_id=6,
69103
attribute_name="test_onoff",
@@ -97,7 +131,7 @@ class TestEnum(t.enum8):
97131
translation_key="test_enum",
98132
fallback_name="Test enum",
99133
)
100-
.tuya_humidity(dp_id=11)
134+
.skip_configuration()
101135
.add_to_registry()
102136
)
103137

@@ -126,24 +160,6 @@ class TestEnum(t.enum8):
126160
assert tuya_cluster.attributes_by_name["test_sensor"].id == 0xEF09
127161
assert tuya_cluster.attributes_by_name["test_enum"].id == 0xEF0A
128162

129-
assert ep.power is not None
130-
assert isinstance(ep.power, TuyaPowerConfigurationCluster2AAA)
131-
132-
assert ep.smartenergy_metering is not None
133-
assert isinstance(ep.smartenergy_metering, TuyaValveWaterConsumed)
134-
135-
assert ep.on_off is not None
136-
assert isinstance(ep.on_off, TuyaOnOffNM)
137-
138-
assert ep.soil_moisture is not None
139-
assert isinstance(ep.soil_moisture, TuyaSoilMoisture)
140-
141-
assert ep.temperature is not None
142-
assert isinstance(ep.temperature, TuyaTemperatureMeasurement)
143-
144-
assert ep.humidity is not None
145-
assert isinstance(ep.humidity, TuyaRelativeHumidity)
146-
147163
with mock.patch.object(
148164
tuya_cluster.endpoint, "request", return_value=foundation.Status.SUCCESS
149165
) as m1:

zhaquirks/tuya/builder/__init__.py

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,16 @@
3030
from zhaquirks.tuya.mcu import DPToAttributeMapping, TuyaMCUCluster, TuyaOnOffNM
3131

3232

33-
class TuyaIASFire(IasZone, TuyaLocalCluster):
34-
"""Tuya local IAS cluster."""
33+
class TuyaIasContact(IasZone, TuyaLocalCluster):
34+
"""Tuya local IAS contact cluster."""
35+
36+
_CONSTANT_ATTRIBUTES = {
37+
IasZone.AttributeDefs.zone_type.id: IasZone.ZoneType.Contact_Switch
38+
}
39+
40+
41+
class TuyaIasFire(IasZone, TuyaLocalCluster):
42+
"""Tuya local IAS smoke/fire cluster."""
3543

3644
_CONSTANT_ATTRIBUTES = {
3745
IasZone.AttributeDefs.zone_type.id: IasZone.ZoneType.Fire_Sensor
@@ -99,35 +107,54 @@ def tuya_battery(
99107
self.adds(power_cfg)
100108
return self
101109

102-
def tuya_metering(
103-
self,
104-
dp_id: int,
105-
metering_cfg: TuyaLocalCluster = TuyaValveWaterConsumed,
106-
) -> QuirkBuilder:
107-
"""Add a Tuya Metering Configuration."""
108-
self.tuya_dp(
109-
dp_id,
110-
metering_cfg.ep_attribute,
111-
"current_summ_delivered",
110+
def tuya_contact(self, dp_id: int):
111+
"""Add a Tuya IAS contact sensor."""
112+
self.tuya_ias(
113+
dp_id=dp_id,
114+
ias_cfg=TuyaIasContact,
115+
converter=lambda x: IasZone.ZoneStatus.Alarm_1 if x != 0 else 0,
116+
)
117+
return self
118+
119+
def tuya_smoke(self, dp_id: int):
120+
"""Add a Tuya IAS smoke/fire sensor."""
121+
self.tuya_ias(
122+
dp_id=dp_id,
123+
ias_cfg=TuyaIasFire,
124+
converter=lambda x: IasZone.ZoneStatus.Alarm_1 if x == 0 else 0,
112125
)
113-
self.adds(metering_cfg)
114126
return self
115127

116128
def tuya_ias(
117129
self,
118130
dp_id: int,
119-
ias_cfg: TuyaLocalCluster = TuyaIASFire,
131+
ias_cfg: TuyaLocalCluster,
132+
converter: Optional[Callable[[Any], Any]] = None,
120133
) -> QuirkBuilder:
121134
"""Add a Tuya IAS Configuration."""
122135
self.tuya_dp(
123136
dp_id,
124137
ias_cfg.ep_attribute,
125138
IasZone.AttributeDefs.zone_status.name,
126-
converter=lambda x: IasZone.ZoneStatus.Alarm_1 if x == 0 else 0,
139+
converter=converter,
127140
)
128141
self.adds(ias_cfg)
129142
return self
130143

144+
def tuya_metering(
145+
self,
146+
dp_id: int,
147+
metering_cfg: TuyaLocalCluster = TuyaValveWaterConsumed,
148+
) -> QuirkBuilder:
149+
"""Add a Tuya Metering Configuration."""
150+
self.tuya_dp(
151+
dp_id,
152+
metering_cfg.ep_attribute,
153+
"current_summ_delivered",
154+
)
155+
self.adds(metering_cfg)
156+
return self
157+
131158
def tuya_onoff(
132159
self,
133160
dp_id: int,

zhaquirks/tuya/tuya_smoke.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@
1212
.applies_to("_TZE204_vawy74yh", "TS0601")
1313
.applies_to("_TZE284_0zaf1cr8", "TS0601")
1414
.applies_to("_TZ3210_up3pngle", "TS0205")
15-
.tuya_ias(dp_id=1)
15+
.tuya_smoke(dp_id=1)
1616
.skip_configuration()
1717
.add_to_registry()
1818
)
1919

2020
(
2121
TuyaQuirkBuilder("_TZE204_ntcy3xu1", "TS0601")
22-
.tuya_ias(dp_id=1)
22+
.tuya_smoke(dp_id=1)
2323
.tuya_dp(
2424
dp_id=14,
2525
ep_attribute=TuyaPowerConfigurationCluster2AAA.ep_attribute,

0 commit comments

Comments
 (0)