Open dekar91 opened 3 months ago
Your quirk already support battery state under DP4. Device just doesn't send it. Take out battery, wait few seconds, put it inside. Then probably it will send it. That's battery operated device and it sends as low data as it can.
Thanks for the response @jacekk015! This is weird, because when the device is connected to "Smart Life" it updates the battery status. If your have some debugging guide or docs, so I could check, could you please share it with me?
If your have some debugging guide or docs, so I could check, could you please share it with me?
You cant find in the logs data that haven't been sent. If device sends something from DP4 you can be more than sure that quirk will forward this to HA.
SmartLife just caches last read. Same as HA do, it will just show you last read from the cache/database. You could always try to hack SmartLife <-> Device communication, but I'm pretty sure it's not too wise to often ask battery device about battery status, because that drains battery even more. All battery driven devices are known to be lazy Zigbee devices.
duplicated with https://github.com/zigpy/zha-device-handlers/issues/2304
Problem description
The Quirk from https://github.com/zigpy/zha-device-handlers/issues/1944 works partually for me, apart from the battery and firmware fields. I would like to have it fixed.
Solution description
Battery level should be displayed. Zigbee firmware should also be exposed, if possible.
Screenshots/Video
Screenshots/Video
![image](https://github.com/zigpy/zha-device-handlers/assets/13837421/242027c2-3587-4e27-97e4-85e951a9c2f1)Device signature
Device signature
```json { "node_descriptor": "NodeDescriptor(logical_type=Diagnostic information
Diagnostic information
```json { "home_assistant": { "installation_type": "Home Assistant OS", "version": "2024.3.1", "dev": false, "hassio": true, "virtualenv": false, "python_version": "3.12.2", "docker": true, "arch": "aarch64", "timezone": "Europe/Berlin", "os_name": "Linux", "os_version": "6.1.73-haos-raspi", "supervisor": "2024.03.0", "host_os": "Home Assistant OS 12.1", "docker_version": "24.0.7", "chassis": "embedded", "run_as_root": true }, "custom_components": { "hacs": { "version": "1.34.0", "requirements": [ "aiogithubapi>=22.10.1" ] }, "watchman": { "version": "0.5.1", "requirements": [ "prettytable==3.0.0" ] }, "dwains_dashboard": { "version": "3.6.0", "requirements": [] }, "localtuya": { "version": "5.2.1", "requirements": [] }, "o365": { "version": "v4.7.0", "requirements": [ "O365==2.0.34", "BeautifulSoup4>=4.10.0" ] }, "sonoff": { "version": "3.6.0", "requirements": [ "pycryptodome>=3.6.6" ] }, "tuya_ble": { "version": "0.1.8", "requirements": [ "tuya-iot-py-sdk==0.6.6", "pycountry==22.3.5" ] } }, "integration_manifest": { "domain": "zha", "name": "Zigbee Home Automation", "after_dependencies": [ "onboarding", "usb" ], "codeowners": [ "@dmulcahey", "@adminiuga", "@puddly", "@TheJulianJES" ], "config_flow": true, "dependencies": [ "file_upload" ], "documentation": "https://www.home-assistant.io/integrations/zha", "import_executor": true, "iot_class": "local_polling", "loggers": [ "aiosqlite", "bellows", "crccheck", "pure_pcapy3", "zhaquirks", "zigpy", "zigpy_deconz", "zigpy_xbee", "zigpy_zigate", "zigpy_znp", "universal_silabs_flasher" ], "requirements": [ "bellows==0.38.1", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.112", "zigpy-deconz==0.23.1", "zigpy==0.63.4", "zigpy-xbee==0.20.1", "zigpy-zigate==0.12.0", "zigpy-znp==0.12.1", "universal-silabs-flasher==0.0.18", "pyserial-asyncio-fast==0.11" ], "usb": [ { "vid": "10C4", "pid": "EA60", "description": "*2652*", "known_devices": [ "slae.sh cc2652rb stick" ] }, { "vid": "10C4", "pid": "EA60", "description": "*slzb-07*", "known_devices": [ "smlight slzb-07" ] }, { "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": "0403", "pid": "6015", "description": "*conbee*", "known_devices": [ "Conbee III" ] }, { "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" ] } ], "zeroconf": [ { "type": "_esphomelib._tcp.local.", "name": "tube*" }, { "type": "_zigate-zigbee-gateway._tcp.local.", "name": "*zigate*" }, { "type": "_zigstar_gw._tcp.local.", "name": "*zigstar*" }, { "type": "_uzg-01._tcp.local.", "name": "uzg-01*" }, { "type": "_slzb-06._tcp.local.", "name": "slzb-06*" } ], "is_built_in": true }, "data": { "ieee": "**REDACTED**", "nwk": 50604, "manufacturer": "_TZE200_cirvgep4", "model": "TS0601", "name": "_TZE200_cirvgep4 TS0601", "quirk_applied": true, "quirk_class": "ts0601_temperature.TuyaNousE6TempHumiditySensor", "quirk_id": null, "manufacturer_code": 4417, "power_source": "Battery or Unknown", "lqi": 248, "rssi": -38, "last_seen": "2024-03-15T11:03:04", "available": true, "device_type": "EndDevice", "signature": { "node_descriptor": "NodeDescriptor(logical_type=Logs
Logs
```python [Paste the logs here] ```Custom quirk
Custom quirk
```python """Tuya temp and humidity sensor with screen.""" from typing import Dict ################## clean this up import zigpy.types as t from zigpy.zcl import foundation from zhaquirks.tuya import TuyaTimePayload, TuyaCommand import datetime from typing import Tuple, Optional, Union ################## from zigpy.profiles import zha from zigpy.quirks import CustomDevice from zigpy.zcl.clusters.general import Basic, Groups, Ota, Scenes, Time, AnalogOutput 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 # old from zhaquirks.tuya.mcu import DPToAttributeMapping, TuyaDPType, TuyaMCUCluster from zhaquirks.tuya.mcu import DPToAttributeMapping, TuyaMCUCluster TUYA_SET_TIME = 0x24 # NOTES: # The data comes in as a string on cluster, if there is nothing set up you may see these lines in the logs: # Unknown message (b'19830100a40102000400000118') on cluster 61184: unknown endpoint or cluster id: 'No cluster ID 0xef00 on (a4:c1:38:d0:18:8b:64:aa, 1)' # 28.0 degrees # Unknown message (b'19840100a5020200040000022c') on cluster 61184: unknown endpoint or cluster id: 'No cluster ID 0xef00 on (a4:c1:38:d0:18:8b:64:aa, 1)' # 55.6% humid # Unknown message (b'19850100a60402000400000064') on cluster 61184: unknown endpoint or cluster id: 'No cluster ID 0xef00 on (a4:c1:38:d0:18:8b:64:aa, 1)' # 100% battery class TemperatureUnitConvert(t.enum8): """Tuya Temp unit convert enum.""" Celsius = 0x00 Fahrenheit = 0x01 class TuyaTemperatureMeasurement(TemperatureMeasurement, TuyaLocalCluster): """Tuya local TemperatureMeasurement cluster.""" attributes = TemperatureMeasurement.attributes.copy() attributes.update( { 0x8001: ("temp_unit_convert", t.enum8), 0x8002: ("alarm_max_temperature", t.Single), 0x8003: ("alarm_min_temperature", t.Single), 0x8004: ("temperature_sensitivity", t.Single), } ) class TuyaRelativeHumidity(RelativeHumidity, TuyaLocalCluster): """Tuya local RelativeHumidity cluster.""" class TemperatureHumidityManufCluster(TuyaMCUCluster): """Tuya Manufacturer Cluster with Temperature and Humidity data points.""" dp_to_attribute: Dict[int, DPToAttributeMapping] = { 1: DPToAttributeMapping( TuyaTemperatureMeasurement.ep_attribute, "measured_value", # dp_type=TuyaDPType.VALUE, converter=lambda x: x * 10, # decidegree to centidegree ), 2: DPToAttributeMapping( TuyaRelativeHumidity.ep_attribute, "measured_value", # dp_type=TuyaDPType.VALUE, converter=lambda x: x * 100, # 0.01 to 1.0 ), 4: DPToAttributeMapping( TuyaPowerConfigurationCluster2AAA.ep_attribute, "battery_percentage_remaining", # dp_type=TuyaDPType.VALUE, converter=lambda x: x * 2, # reported percentage is doubled ), 9: DPToAttributeMapping( TuyaTemperatureMeasurement.ep_attribute, "temp_unit_convert", # dp_type=TuyaDPType.ENUM, converter=lambda x: TemperatureUnitConvert(x) ), 10: DPToAttributeMapping( TuyaTemperatureMeasurement.ep_attribute, "alarm_max_temperature", # dp_type=TuyaDPType.VALUE, converter=lambda x: x / 10 ), 11: DPToAttributeMapping( TuyaTemperatureMeasurement.ep_attribute, "alarm_min_temperature", # dp_type=TuyaDPType.VALUE, converter=lambda x: x / 10 ), 19: DPToAttributeMapping( TuyaTemperatureMeasurement.ep_attribute, "temperature_sensitivity", # dp_type=TuyaDPType.VALUE, converter=lambda x: x / 10 ) } set_time_offset = 1970 set_time_local_offset = 1970 data_point_handlers = { 1: "_dp_2_attr_update", 2: "_dp_2_attr_update", 4: "_dp_2_attr_update", 9: "_dp_2_attr_update", 10: "_dp_2_attr_update", 11: "_dp_2_attr_update", 19: "_dp_2_attr_update", } def handle_set_time_request(self, sequence_number: t.uint16_t) -> foundation.Status: payload = TuyaTimePayload() utc_now = datetime.datetime.utcnow() now = datetime.datetime.now() offset_time = datetime.datetime(self.set_time_offset, 1, 1) offset_time_local = datetime.datetime(self.set_time_local_offset, 1, 1) utc_timestamp = int((utc_now - offset_time).total_seconds()) local_timestamp = int((now - offset_time).total_seconds()) payload.extend(utc_timestamp.to_bytes(4, "big", signed=False)) payload.extend(local_timestamp.to_bytes(4, "big", signed=False)) self.create_catching_task( self.command(TUYA_SET_TIME, payload, manufacturer=foundation.ZCLHeader.NO_MANUFACTURER_ID, expect_reply=False) ) return foundation.Status.SUCCESS class TuyaNousE6TempHumiditySensor(CustomDevice): """Custom device representing tuya temp and humidity sensor with a screen (NOUS E6).""" signature = { #Additional information
No response