-
Notifications
You must be signed in to change notification settings - Fork 828
Add Tuya v2 quirk builder #3417
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
Changes from 7 commits
851d54f
8555f3e
ded6e7a
88068fc
4e7fb61
91a4012
6b32bff
f1906b0
c9cc9b2
b83c29f
c6d5f30
241a50f
ac35ab9
a698b9d
63725d9
316d3f6
6458e02
9e8fade
3c7e5fc
bc790aa
2123900
56266db
ac9ccc7
24d3e4c
a90674a
6803bc0
fac92fe
c3d1c93
7f27503
eff64ba
868d0a8
3ff810f
d47d2f4
c043b1f
576b8e6
8c28fef
89cd451
87ba6f1
ea9d912
f1323ac
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,9 +5,13 @@ | |
import datetime | ||
from typing import Any, Optional, Union | ||
|
||
from zigpy.quirks import _DEVICE_REGISTRY | ||
from zigpy.quirks.registry import DeviceRegistry | ||
from zigpy.quirks.v2 import QuirkBuilder, QuirksV2RegistryEntry | ||
import zigpy.types as t | ||
from zigpy.zcl import foundation | ||
from zigpy.zcl.clusters.general import LevelControl, OnOff | ||
from zigpy.zcl.clusters.measurement import SoilMoisture, TemperatureMeasurement | ||
|
||
from zhaquirks import Bus, DoublingPowerConfigurationCluster | ||
|
||
|
@@ -19,12 +23,14 @@ | |
TUYA_SET_TIME, | ||
EnchantedDevice, # noqa: F401 | ||
NoManufacturerCluster, | ||
PowerConfiguration, | ||
PowerOnState, | ||
TuyaCommand, | ||
TuyaDatapointData, | ||
TuyaEnchantableCluster, | ||
TuyaLocalCluster, | ||
TuyaNewManufCluster, | ||
TuyaPowerConfigurationCluster2AAA, | ||
TuyaTimePayload, | ||
) | ||
|
||
|
@@ -724,3 +730,143 @@ class TuyaLevelControlManufCluster(TuyaMCUCluster): | |
17: "_dp_2_attr_update", | ||
18: "_dp_2_attr_update", | ||
} | ||
|
||
|
||
class TuyaTemperatureMeasurement(TemperatureMeasurement, TuyaLocalCluster): | ||
"""Tuya local TemperatureMeasurement cluster.""" | ||
|
||
|
||
class TuyaSoilMoisture(SoilMoisture, TuyaLocalCluster): | ||
"""Tuya local SoilMoisture cluster with a device RH_MULTIPLIER factor if required.""" | ||
|
||
|
||
class TuyaQuirkBuilder(QuirkBuilder): | ||
"""Tuya QuirkBuilder.""" | ||
|
||
def __init__( | ||
self, manufacturer: str, model: str, registry: DeviceRegistry = _DEVICE_REGISTRY | ||
) -> None: | ||
"""Init the TuyaQuirkBuilder.""" | ||
self.tuya_data_point_handlers: dict[int, str] = {} | ||
self.tuya_dp_to_attribute: dict[int, DPToAttributeMapping] = {} | ||
super().__init__(manufacturer, model, registry) | ||
|
||
def battery( | ||
self, | ||
dp_id: int = 15, | ||
power_cfg: PowerConfiguration = TuyaPowerConfigurationCluster2AAA, | ||
converter: Optional[ | ||
Callable[ | ||
[ | ||
Any, | ||
], | ||
Any, | ||
] | ||
] = lambda x: x * 2, | ||
) -> QuirkBuilder: | ||
"""Add a Tuya Battery Power Configuration.""" | ||
self.tuya_dp( | ||
dp_id, | ||
power_cfg.ep_attribute, | ||
"battery_percentage_remaining", | ||
converter=converter, | ||
) | ||
self.adds(power_cfg) | ||
return self | ||
|
||
def soil_moisture( | ||
self, | ||
dp_id: int = 3, | ||
soil_cfg: TuyaLocalCluster = TuyaSoilMoisture, | ||
converter: Optional[ | ||
Callable[ | ||
[ | ||
Any, | ||
], | ||
Any, | ||
] | ||
] = lambda x: x * 100, | ||
) -> QuirkBuilder: | ||
"""Add a Tuya Soil Moisture Configuration.""" | ||
self.tuya_dp( | ||
dp_id, | ||
soil_cfg.ep_attribute, | ||
"measured_value", | ||
converter=converter, | ||
) | ||
self.adds(soil_cfg) | ||
return self | ||
|
||
def temperature( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not set on this yet, but would it make sense to append a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm leaning towards adding the tuya prefix. I'm working on adding support for adding attributes, switches, and enums now, and if we add the prefix, then you can still call the original methods if needed. I think it adds clarity and keeps functionality that we may need in the future if we run into something that doesn't fit the normal approach. |
||
self, | ||
dp_id: int = 5, | ||
temp_cfg: TuyaLocalCluster = TuyaTemperatureMeasurement, | ||
converter: Optional[ | ||
Callable[ | ||
[ | ||
Any, | ||
], | ||
Any, | ||
] | ||
] = lambda x: x * 100, | ||
) -> QuirkBuilder: | ||
"""Add a Tuya Soil Moisture Configuration.""" | ||
self.tuya_dp( | ||
dp_id, | ||
temp_cfg.ep_attribute, | ||
"measured_value", | ||
converter=converter, | ||
) | ||
self.adds(temp_cfg) | ||
return self | ||
|
||
def tuya_dp( | ||
self, | ||
dp_id: int, | ||
ep_attribute: str, | ||
attribute_name: Union[str, tuple], | ||
converter: Optional[ | ||
Callable[ | ||
[ | ||
Any, | ||
], | ||
Any, | ||
] | ||
] = None, | ||
dp_converter: Optional[ | ||
Callable[ | ||
[ | ||
Any, | ||
], | ||
Any, | ||
] | ||
] = None, | ||
TheJulianJES marked this conversation as resolved.
Show resolved
Hide resolved
|
||
endpoint_id: Optional[int] = None, | ||
dp_handler: str = "_dp_2_attr_update", | ||
) -> QuirkBuilder: | ||
"""Add Tuya DP Converter.""" | ||
self.tuya_dp_to_attribute.update( | ||
{ | ||
dp_id: DPToAttributeMapping( | ||
ep_attribute, | ||
attribute_name, | ||
converter=converter, | ||
dp_converter=dp_converter, | ||
endpoint_id=endpoint_id, | ||
) | ||
} | ||
) | ||
self.tuya_data_point_handlers.update({dp_id: dp_handler}) | ||
return self | ||
|
||
def add_to_registry(self) -> QuirksV2RegistryEntry: | ||
"""Build the quirks v2 registry entry.""" | ||
|
||
class TuyaReplacementCluster(TuyaMCUCluster): | ||
"""Replacement Tuya Cluster.""" | ||
|
||
data_point_handlers: dict[int, str] = self.tuya_data_point_handlers | ||
dp_to_attribute: dict[int, DPToAttributeMapping] = self.tuya_dp_to_attribute | ||
|
||
self.replaces(TuyaReplacementCluster) | ||
return super().add_to_registry() |
Uh oh!
There was an error while loading. Please reload this page.