Closed dgaust closed 1 year ago
Caveat that I'm not 100% sure what I'm doing but, cobbling together a quirk an existing temp/humidity sensor, and getting the datapoints from the zigbee-herdsman posts, I have a somewhat working quirk that results in the right data being shown in Home Assistant (I compared the resulting values against what is displayed in zigbee2mqtt and it matches - so at least that's correct).
It does just come in as 'humidity' rather than something else more descriptive, but it works.
"""Tuya Soil Moisture Sensor."""
from typing import Any, Dict
from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
from zigpy.zcl.clusters.general import Basic, Groups, Ota, Scenes, Time
from zigpy.zcl.clusters.measurement import RelativeHumidity, TemperatureMeasurement
from zhaquirks.const import (
DEVICE_TYPE,
ENDPOINTS,
INPUT_CLUSTERS,
MODELS_INFO,
OUTPUT_CLUSTERS,
PROFILE_ID,
SKIP_CONFIGURATION,
)
from zhaquirks.tuya import TuyaLocalCluster, TuyaPowerConfigurationCluster2AAA
from zhaquirks.tuya.mcu import DPToAttributeMapping, TuyaDPType, TuyaMCUCluster
class TuyaTemperatureMeasurement(TemperatureMeasurement, TuyaLocalCluster):
"""Tuya local TemperatureMeasurement cluster."""
class TuyaRelativeHumidity(RelativeHumidity, TuyaLocalCluster):
"""Tuya local RelativeHumidity cluster with a device RH_MULTIPLIER factor."""
def update_attribute(self, attr_name: str, value: Any) -> None:
"""Apply a correction factor to value."""
if attr_name == "measured_value":
value = value * (
self.endpoint.device.RH_MULTIPLIER
if hasattr(self.endpoint.device, "RH_MULTIPLIER")
else 100
)
return super().update_attribute(attr_name, value)
class TemperatureHumidityManufCluster(TuyaMCUCluster):
"""Tuya Manufacturer Cluster with Temperature and Humidity data points."""
dp_to_attribute: Dict[int, DPToAttributeMapping] = {
5: DPToAttributeMapping(
TuyaTemperatureMeasurement.ep_attribute,
"measured_value",
dp_type=TuyaDPType.VALUE,
converter=lambda x: x * 100,
),
3: DPToAttributeMapping(
TuyaRelativeHumidity.ep_attribute,
"measured_value",
dp_type=TuyaDPType.VALUE,
),
15: DPToAttributeMapping(
TuyaPowerConfigurationCluster2AAA.ep_attribute,
"battery_percentage_remaining",
dp_type=TuyaDPType.VALUE,
converter=lambda x: x * 2, # double reported percentage
),
}
data_point_handlers = {
3: "_dp_2_attr_update",
5: "_dp_2_attr_update",
15: "_dp_2_attr_update",
}
class TuyaSoilSensor(CustomDevice):
"""Tuya temp and humidity sensor (variation 03)."""
signature = {
# "profile_id": 260,
# "device_type": "0x0051",
# "in_clusters": ["0x0000","0x0004","0x0005","0xef00"],
# "out_clusters": ["0x000a","0x0019"]
MODELS_INFO: [("_TZE200_myd45weu", "TS0601")],
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
INPUT_CLUSTERS: [
Basic.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
TemperatureHumidityManufCluster.cluster_id,
],
OUTPUT_CLUSTERS: [Ota.cluster_id, Time.cluster_id],
}
},
}
replacement = {
SKIP_CONFIGURATION: True,
ENDPOINTS: {
1: {
DEVICE_TYPE: zha.DeviceType.TEMPERATURE_SENSOR,
INPUT_CLUSTERS: [
Basic.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
TemperatureHumidityManufCluster,
TuyaTemperatureMeasurement,
TuyaRelativeHumidity,
TuyaPowerConfigurationCluster2AAA,
],
OUTPUT_CLUSTERS: [Ota.cluster_id, Time.cluster_id],
}
},
}
Please add support for the Tuya TS0601 Soil Sensor.
Describe the solution you'd like Inclusion of a quirk to support data provided by the sensor.
Device signature
```{ "node_descriptor": "NodeDescriptor(logical_type=Diagnostic information
``` { "home_assistant": { "installation_type": "Home Assistant OS", "version": "2023.1.4", "dev": false, "hassio": true, "virtualenv": false, "python_version": "3.10.7", "docker": true, "arch": "x86_64", "timezone": "Australia/Sydney", "os_name": "Linux", "os_version": "5.15.80", "supervisor": "2022.12.1", "host_os": "Home Assistant OS 9.4", "docker_version": "20.10.19", "chassis": "embedded", "run_as_root": true }, "custom_components": { "alexa_media": { "version": "4.5.0", "requirements": [ "alexapy==1.26.4", "packaging>=20.3", "wrapt>=1.12.1" ] }, "smart_irrigation": { "version": "0.0.78", "requirements": [] }, "auto_backup": { "version": "1.3.0", "requirements": [] }, "better_thermostat": { "version": "1.0.0", "requirements": [] }, "tapo": { "version": "1.3.7", "requirements": [ "plugp100==2.3.0" ] }, "hdhomerun": { "version": "2022.11.1", "requirements": [] }, "whatspie": { "version": "1.0.0", "requirements": [] }, "bureau_of_meteorology": { "version": "1.1.16", "requirements": [ "iso8601" ] }, "xiaomi_cloud_map_extractor": { "version": "v2.2.0", "requirements": [ "pillow", "pybase64", "python-miio", "requests", "pycryptodome" ] }, "dwains_dashboard": { "version": "3.3.0", "requirements": [] }, "hacs": { "version": "1.29.1", "requirements": [ "aiogithubapi>=22.10.1" ] }, "thermal_comfort": { "version": "2.0.1", "requirements": [] }, "dual_smart_thermostat": { "version": "0.5.5", "requirements": [] }, "automate": { "version": "0.9.8", "requirements": [ "aiopulse2==0.7.0" ] }, "samsungtv_smart": { "version": "0.9.4", "requirements": [ "websocket-client!=1.4.0,>=0.58.0", "wakeonlan>=2.0.0", "aiofiles>=0.8.0" ] }, "unifigateway": { "version": "0.3.3", "requirements": [ "pyunifi==2.21" ] }, "sonos_cloud": { "version": "0.3.4", "requirements": [] }, "auto_areas": { "version": "1.0.0", "requirements": [] }, "irrigation_unlimited": { "version": "2022.12.0", "requirements": [ "crontab" ] }, "grocy": { "version": "v4.5.2", "requirements": [ "pygrocy==1.4.1" ] }, "nest_protect": { "version": "0.3.8", "requirements": [] }, "average": { "version": "2.3.0", "requirements": [] }, "ai_thermostat": { "version": "0.9.3", "requirements": [] } }, "integration_manifest": { "domain": "zha", "name": "Zigbee Home Automation", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/zha", "requirements": [ "bellows==0.34.6", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.90", "zigpy-deconz==0.19.2", "zigpy==0.53.0", "zigpy-xbee==0.16.2", "zigpy-zigate==0.10.3", "zigpy-znp==0.9.2" ], "usb": [ { "vid": "10C4", "pid": "EA60", "description": "*2652*", "known_devices": [ "slae.sh cc2652rb stick" ] }, { "vid": "1A86", "pid": "55D4", "description": "*sonoff*plus*", "known_devices": [ "sonoff zigbee dongle plus v2" ] }, { "vid": "10C4", "pid": "EA60", "description": "*sonoff*plus*", "known_devices": [ "sonoff zigbee dongle plus" ] }, { "vid": "10C4", "pid": "EA60", "description": "*tubeszb*", "known_devices": [ "TubesZB Coordinator" ] }, { "vid": "1A86", "pid": "7523", "description": "*tubeszb*", "known_devices": [ "TubesZB Coordinator" ] }, { "vid": "1A86", "pid": "7523", "description": "*zigstar*", "known_devices": [ "ZigStar Coordinators" ] }, { "vid": "1CF1", "pid": "0030", "description": "*conbee*", "known_devices": [ "Conbee II" ] }, { "vid": "10C4", "pid": "8A2A", "description": "*zigbee*", "known_devices": [ "Nortek HUSBZB-1" ] }, { "vid": "0403", "pid": "6015", "description": "*zigate*", "known_devices": [ "ZiGate+" ] }, { "vid": "10C4", "pid": "EA60", "description": "*zigate*", "known_devices": [ "ZiGate" ] }, { "vid": "10C4", "pid": "8B34", "description": "*bv 2010/10*", "known_devices": [ "Bitron Video AV2010/10" ] } ], "codeowners": [ "@dmulcahey", "@adminiuga", "@puddly" ], "zeroconf": [ { "type": "_esphomelib._tcp.local.", "name": "tube*" }, { "type": "_zigate-zigbee-gateway._tcp.local.", "name": "*zigate*" }, { "type": "_zigstar_gw._tcp.local.", "name": "*zigstar*" }, { "type": "_slzb-06._tcp.local.", "name": "slzb-06*" } ], "dependencies": [ "file_upload" ], "after_dependencies": [ "onboarding", "usb", "zeroconf" ], "iot_class": "local_polling", "loggers": [ "aiosqlite", "bellows", "crccheck", "pure_pcapy3", "zhaquirks", "zigpy", "zigpy_deconz", "zigpy_xbee", "zigpy_zigate", "zigpy_znp" ], "is_built_in": true }, "data": { "ieee": "**REDACTED**", "nwk": 31774, "manufacturer": "_TZE200_myd45weu", "model": "TS0601", "name": "_TZE200_myd45weu TS0601", "quirk_applied": false, "quirk_class": "zigpy.device.Device", "manufacturer_code": 4417, "power_source": "Battery or Unknown", "lqi": 124, "rssi": -69, "last_seen": "2023-01-14T15:38:51", "available": true, "device_type": "EndDevice", "signature": { "node_descriptor": "NodeDescriptor(logical_type=Additional logs
``` Paste any additional debug logs here. Don't remove the extra line breaks outside the ``` marks. ```Additional context. A fingerprint currently exists for the device in ZigbeeHerdsman that may assist https://github.com/Koenkk/zigbee-herdsman-converters/blob/master/devices/tuya.js
``` { fingerprint: tuya.fingerprint('TS0601', ['_TZE200_myd45weu']), model: 'TS0601_soil', vendor: 'TuYa', description: 'Soil sensor', fromZigbee: [tuya.fz.datapoints], toZigbee: [tuya.tz.datapoints], configure: tuya.configureMagicPacket, exposes: [e.temperature(), e.soil_moisture(), tuya.exposes.temperatureUnit(), e.battery(), tuya.exposes.batteryState()], meta: { tuyaDatapoints: [ [3, 'soil_moisture', tuya.valueConverter.raw], [5, 'temperature', tuya.valueConverter.raw], [9, 'temperature_unit', tuya.valueConverter.temperatureUnit], [14, 'battery_state', tuya.valueConverter.batteryState], [15, 'battery', tuya.valueConverter.raw], ], }, }, ```