Closed PlusPlus-ua closed 2 years ago
There is a possible quick and dirty quirk for your device:
"""Neo Tuya Temperature, Humidity and Illumination Sensor."""
from zigpy.profiles import zha
from zigpy.profiles.zha import DeviceType
from zigpy.quirks import CustomCluster, CustomDevice
import zigpy.types as t
from zigpy.zcl.clusters.general import Basic, Identify, Ota, PowerConfiguration, Time
from zigpy.zcl.clusters.measurement import (
RelativeHumidity,
TemperatureMeasurement,
)
from zhaquirks.const import (
DEVICE_TYPE,
ENDPOINTS,
INPUT_CLUSTERS,
MODELS_INFO,
OUTPUT_CLUSTERS,
PROFILE_ID,
)
class ValueAlarm(t.enum8):
"""Temperature and Humidity alarm values."""
ALARM_OFF = 0x02
MAX_ALARM_ON = 0x01
MIN_ALARM_ON = 0x00
class NeoTemperatureHumidityAlarmCluster(CustomCluster):
"""Neo Temperature and Humidity Alarm Cluster (0xE002)."""
name = "Neo Temperature and Humidity Alarm Cluster"
cluster_id = 0xE002
attributes = {
# Alarm settings
0xD00A: ("alarm_temperature_max", t.uint16_t, True),
0xD00B: ("alarm_temperature_min", t.uint16_t, True),
0xD00C: ("alarm_humidity_max", t.uint16_t, True),
0xD00E: ("alarm_humidity_min", t.uint16_t, True),
# Alarm information
0xD00F: ("alarm_humidity", ValueAlarm, True),
0xD006: ("temperature_humidity", ValueAlarm, True),
# Unknown
0xD010: ("unknown", t.uint8_t, True),
}
class RelativeHumidityX10(CustomCluster, RelativeHumidity):
"""Handles invalid values for Humidity."""
def _update_attribute(self, attrid, value):
# x10 factor in `measured_value` (attrid=0)
if attrid == 0:
value = value * 10
super()._update_attribute(attrid, value)
class MoesTemperatureHumidtyIlluminanceSensorWithScreen(CustomDevice):
"""Moes Tuya ZigBee Smart Home Temperature And Humidity Sensor With LED screen."""
signature = {
# <SimpleDescriptor endpoint=1, profile=260, device_type="0x0302"
# input_clusters=["0x0000", "0x0001", "0x0003", "0x0402", "0x0405", "0xe002"]
# output_clusters=["0x0003", "0x000a", "0x0019"]>
MODELS_INFO: [("_TZ3000_itnrsufe", "TS0201")],
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: DeviceType.LIGHT_SENSOR,
INPUT_CLUSTERS: [
Basic.cluster_id,
PowerConfiguration.cluster_id,
Identify.cluster_id,
TemperatureMeasurement.cluster_id,
RelativeHumidity.cluster_id,
NeoTemperatureHumidityAlarmCluster.cluster_id,
],
OUTPUT_CLUSTERS: [
Identify.cluster_id,
Time.cluster_id,
Ota.cluster_id,
],
},
},
}
replacement = {
ENDPOINTS: {
1: {
INPUT_CLUSTERS: [
Basic.cluster_id,
PowerConfiguration.cluster_id,
Identify.cluster_id,
TemperatureMeasurement.cluster_id,
RelativeHumidityX10,
NeoTemperatureHumidityAlarmCluster,
],
OUTPUT_CLUSTERS: [
Identify.cluster_id,
Time.cluster_id,
Ota.cluster_id,
],
},
},
}
If you are not familiar, there are some guides about it. Maybe the most popular can be:
You will need to create the ts0201.py
file in your local custom_zha_quirks
folder.
Save & restart.
Then check if device signature changes, that would mean that the device loads the quirk.
@javicalle thanks, it did the trick. I think it has a sense to merge ts0201_neo.py and ts0201_zemismart.py in one file and add there this new class. What do you think?
I think it has a sense to merge ts0201_neo.py and ts0201_zemismart.py in one file and add there this new class.
That's exactly the same thing I was thinking. I second to put all classes in the same ts0201.py
file.
I don't really know if all the attributes from NeoTemperatureHumidityAlarmCluster
are usefull, but since cluster ID is the same I would prefer to have just one cluster definition.
I don't really know if all the attributes from
NeoTemperatureHumidityAlarmCluster
are usefull, but since cluster ID is the same I would prefer to have just one cluster definition.
In Tuya Smart app alarm settings for this device is grayed, but I think it's better to keep it as is.
Sorry @PlusPlus-ua but I may have misunderstood your intention. Would you mind creating the PR with the new version? I can give you support if you have any questions.
Regards.
Yes, I'll prepare PR. Just have spent rest of weekend with my family, so had no time for it.
No problem. The important things first! It was just to confirm it.
Thanks.
Is your feature request related to a problem? Please describe. Device from https://www.aliexpress.com/item/1005004443497564.html reports relative humidity in a wrong way. Instead of reporting value*100 (as it described in ZCL) it reports value*10. As a result ZHA converts it to actual_relative_humidity/10. Right now LED screen on the device showing 42% but HA showing 4.2%
Describe the solution you'd like I think zhaquirk is needed for the device. The zhaquirk should apply multiplication by 10 for relative humidity value.
Device signature
```yaml { "node_descriptor": "NodeDescriptor(logical_type=Diagnostic information
```yaml { "home_assistant": { "installation_type": "Home Assistant OS", "version": "2022.7.6", "dev": false, "hassio": true, "virtualenv": false, "python_version": "3.10.5", "docker": true, "arch": "x86_64", "timezone": "Europe/Kiev", "os_name": "Linux", "os_version": "5.15.55", "supervisor": "2022.07.1", "host_os": "Home Assistant OS 8.4", "docker_version": "20.10.14", "chassis": "embedded", "run_as_root": true }, "custom_components": { "hisense_tv": { "version": "22.05.09", "requirements": [ "wakeonlan==2.0.1" ] }, "xiaomi_cloud_map_extractor": { "version": "v2.2.0", "requirements": [ "pillow", "pybase64", "python-miio", "requests", "pycryptodome" ] }, "hacs": { "version": "1.25.5", "requirements": [ "aiogithubapi>=22.2.4" ] }, "viomi_vacuum_v8": { "version": "0.0.1", "requirements": [ "construct==2.10.59", "python-miio==0.5.4" ] }, "xiaomi_miot": { "version": "0.6.7", "requirements": [ "construct==2.10.56", "python-miio>=0.5.6", "micloud>=0.3" ] } }, "integration_manifest": { "domain": "zha", "name": "Zigbee Home Automation", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/zha", "requirements": [ "bellows==0.31.1", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.77", "zigpy-deconz==0.18.0", "zigpy==0.47.3", "zigpy-xbee==0.15.0", "zigpy-zigate==0.9.0", "zigpy-znp==0.8.1" ], "usb": [ { "vid": "10C4", "pid": "EA60", "description": "*2652*", "known_devices": [ "slae.sh cc2652rb stick" ] }, { "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" ], "zeroconf": [ { "type": "_esphomelib._tcp.local.", "name": "tube*" }, { "type": "_zigate-zigbee-gateway._tcp.local.", "name": "*zigate*" } ], "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": 9904, "manufacturer": "_TZ3000_itnrsufe", "model": "TS0201", "name": "_TZ3000_itnrsufe TS0201", "quirk_applied": false, "quirk_class": "zigpy.device.Device", "manufacturer_code": 4417, "power_source": "Battery or Unknown", "lqi": 134, "rssi": null, "last_seen": "2022-07-29T17:24:12", "available": true, "device_type": "EndDevice", "signature": { "node_descriptor": "NodeDescriptor(logical_type=Additional logs
``` 2022-07-29 16:23:58 DEBUG (MainThread) [zigpy_znp.api] Received command: AF.IncomingMsg.Callback(GroupId=0x0000, ClusterId=1029, SrcAddr=0x26B0, SrcEndpoint=1, DstEndpoint=1, WasBroadcast=