zigpy / zha-device-handlers

ZHA device handlers bridge the functionality gap created when manufacturers deviate from the ZCL specification, handling deviations and exceptions by parsing custom messages to and from Zigbee devices.
Apache License 2.0
758 stars 696 forks source link

[Device Support Request] RETRY: SASWELL SAS980SWT-7-Z01 (_TZE200_akjefhj5, TS0601) Smart Irrigation Valve #3491

Open nicktrigger opened 1 week ago

nicktrigger commented 1 week ago

Problem description

I have been searching for a custom quirk to support this valve. I found this request, now closed. The custom quirk there does not support anything other than simple on/off operation.

https://github.com/zigpy/zha-device-handlers/issues/1668

I added my product to tuya valve in the latest release as a custom quirk but unfortunately it gives the exact same functionality.

Currently this valve works perfectly with local tuya, but i want to get rid of my tuya zigbee hub and go native zha for all my devices.

Solution description

I would like further support for this valve including timers, status updates and battery. If love is someone could give me guidance on how to build up a custom quirk to add more support.

Screenshots/Video

Screenshots/Video [Paste/up ![Screenshot_20241108_071546_Edge](https://github.com/user-attachments/assets/12bb1b54-0b58-4fe3-9a83-93f678882d47) ![Screenshot_20241108_071537_Edge](https://github.com/user-attachments/assets/42655c2c-7acb-4f68-bdd4-de1e9a70f9e2) ![Screenshot_20241108_071530_Edge](https://github.com/user-attachments/assets/ad654c08-3d91-4eb6-b491-af6543778f6f) ![Screenshot_20241108_071453_Edge](https://github.com/user-attachments/assets/63f25f0c-6b8b-41b0-a2c8-f7c0be1741f8) ![Screenshot_20241108_071442_Edge](https://github.com/user-attachments/assets/aaa15b74-195f-41a9-8475-2249f933df90) load your media here]

Device signature

Device signature ```json [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 ⌄ ⌄ ⌄ ⌄ ⌄ ⌄ { "node_descriptor": { "logical_type": 2, "complex_descriptor_available": 0, "user_descriptor_available": 0, "reserved": 0, "aps_flags": 0, "frequency_band": 8, "mac_capability_flags": 128, "manufacturer_code": 4098, "maximum_buffer_size": 82, "maximum_incoming_transfer_size": 82, "server_mask": 11264, "maximum_outgoing_transfer_size": 82, "descriptor_capability_field": 0 }, "endpoints": { "1": { "profile_id": "0x0104", "device_type": "0x0051", "input_clusters": [ "0x0000", "0x0001", "0x0004", "0x0005", "0x0006", "0x0702", "0xef00" ], "output_clusters": [ "0x000a", "0x0019" ] } }, "manufacturer": "_TZE200_akjefhj5", "model": "TS0601", "class": "ts0601_TZE200_akjefhj5_valve.TuyaValve" } ] ```

Diagnostic information

Diagnostic information ```json [zha-01J9XY83W61D8PMQM9FG20JYW5-_TZE200_akjefhj5 TS0601-acf53a2be849a1a19f5c194772a61da4 (1).json](https://github.com/user-attachments/files/17670698/zha-01J9XY83W61D8PMQM9FG20JYW5-_TZE200_akjefhj5.TS0601-acf53a2be849a1a19f5c194772a61da4.1.json) ```

Logs

No response

Custom quirk

Custom quirk ```python class TuyaValve(CustomDevice): """Tuya valve device.""" signature = { MODELS_INFO: [("_TZE200_akjefhj5", "TS0601")], ```

Additional information

No response

prairiesnpr commented 1 week ago

Do you have the data points? That's the first step, either from the tuya developer console or a zigbee2mqtt converter.

nicktrigger commented 1 week ago

I think that the diagnostics for Local Tuya should be useful for the DP IDs. I verified from Tuya Developer that these are correct.

{ "home_assistant": { "installation_type": "Home Assistant OS", "version": "2024.11.0", "dev": false, "hassio": true, "virtualenv": false, "python_version": "3.12.4", "docker": true, "arch": "x86_64", "timezone": "Asia/Makassar", "os_name": "Linux", "os_version": "6.6.54-haos", "supervisor": "2024.11.2", "host_os": "Home Assistant OS 13.2", "docker_version": "27.2.0", "chassis": "embedded", "run_as_root": true }, "custom_components": { "hacs": { "documentation": "https://hacs.xyz/docs/configuration/start", "version": "2.0.1", "requirements": [ "aiogithubapi>=22.10.1" ] }, "localtuya": { "documentation": "https://github.com/xZetsubou/hass-localtuya/", "version": "2024.9.0", "requirements": [] } }, "integration_manifest": { "domain": "localtuya", "name": "Local Tuya", "codeowners": [], "config_flow": true, "dependencies": [], "documentation": "https://github.com/xZetsubou/hass-localtuya/", "integration_type": "hub", "iot_class": "local_push", "issue_tracker": "https://github.com/xZetsubou/hass-localtuya/issues", "requirements": [], "version": "2024.9.0", "is_built_in": false, "overwrites_built_in": false }, "setup_times": { "null": { "setup": 0.0008731919806450605 }, "d3d7c7bd6a0d6eae5b514de424d066c4": { "wait_import_platforms": -0.7227834760560654, "wait_base_component": -0.0014464319683611393, "config_entry_setup": 0.7861054820241407 } }, "data": { "device_config": { "device_id": "eb4e6234a74b8fbb65dthm", "dps_strings": [ "1 ( code: switch , value: False )", "3 ( code: percent_state , value: 0, cloud pull )", "4 ( code: fault , value: 0, cloud pull )", "5 ( code: water_once , value: 0 )", "7 ( code: battery_percentage , value: 50 )", "8 ( code: battery_state , value: low, cloud pull )", "9 ( code: time_use , value: 0, cloud pull )", "10 ( code: weather_delay , value: cancel, cloud pull )", "11 ( code: countdown , value: 600 )", "12 ( code: work_state , value: idle )", "13 ( code: smart_weather , value: sunny, cloud pull )", "14 ( code: switch_weather , value: False, cloud pull )", "15 ( code: use_time_one , value: 0 )", "16 ( code: cycle_timing , value: AA== )", "17 ( code: timer , value: AA== )" ], "enable_debug": false, "entities": [ { "entity_category": "None", "friendly_name": "", "icon": "mdi:valve", "id": "1", "is_passive_entity": false, "platform": "switch", "restore_on_reconnect": false }, { "device_class": "problem", "entity_category": "diagnostic", "friendly_name": "Fault", "icon": "", "id": "4", "platform": "binary_sensor", "state_on": "1" }, { "device_class": "battery", "entity_category": "diagnostic", "friendly_name": "Battery", "icon": "", "id": "7", "platform": "sensor", "scaling": 1.0, "state_class": "measurement", "unit_of_measurement": "%" }, { "entity_category": "diagnostic", "friendly_name": "Battery Level", "icon": "mdi:battery", "id": "8", "platform": "sensor" }, { "entity_category": "diagnostic", "friendly_name": "Usage Time", "icon": "mdi:chart-arc", "id": "9", "platform": "sensor", "scaling": 1.0, "unit_of_measurement": "s" }, { "entity_category": "config", "friendly_name": "Switch Timer", "icon": "mdi:timer", "id": "11", "is_passive_entity": false, "max_value": 86400.0, "min_value": 0.0, "platform": "number", "restore_on_reconnect": false, "scaling": 1.0, "step_size": 1.0, "unit_of_measurement": "s" }, { "entity_category": "diagnostic", "friendly_name": "State", "icon": "mdi:state-machine", "id": "12", "platform": "sensor" }, { "entity_category": "config", "friendly_name": "Smart Weather Mode", "icon": "mdi:cog", "id": "13", "is_passive_entity": false, "platform": "select", "restore_on_reconnect": false, "select_options": { "clear": "clear", "cloud": "cloud", "cloudy": "Cloudy", "fog": "fog", "rainy": "Rainy", "snow": "snow", "sunny": "sunny" } }, { "entity_category": "config", "friendly_name": "Smart Weather", "icon": "mdi:auto-mode", "id": "14", "is_passive_entity": false, "platform": "switch", "restore_on_reconnect": false }, { "entity_category": "diagnostic", "friendly_name": "Single Usage Time", "icon": "mdi:chart-arc", "id": "15", "platform": "sensor", "scaling": 1.0, "unit_of_measurement": "s" } ], "friendly_name": "Irrigation Top Garden", "gateway_id": "****", "host": "192.168.50.100", "local_key": "**'", "model": "Flora", "node_id": "*", "protocol_version": "3.3" }, "device_cloud_info": { "active_time": 1730506468, "biz_type": 18, "category": "sfkzq", "create_time": 1715259144, "icon": "smart/icon/ay1537509218624daaHb/3d856d5bcc4d51a3ed733da21b8a884e.jpg", "id": "eb4e6234a74b8fbb65dthm", "ip": "", "lat": "", "local_key": "**'", "lon": "", "model": "Flora", "name": "top garden smart watering", "node_id": "*", "online": false, "owner_id": "**", "product_id": "akjefhj5", "product_name": "Smart Irrigator", "status": [ { "code": "switch", "value": false }, { "code": "percent_state", "value": 0 }, { "code": "water_once", "value": 0 }, { "code": "battery_percentage", "value": 50 }, { "code": "battery_state", "value": "low" }, { "code": "time_use", "value": 0 }, { "code": "weather_delay", "value": "cancel" }, { "code": "countdown", "value": 0 }, { "code": "work_state", "value": "idle" }, { "code": "smart_weather", "value": "sunny" }, { "code": "use_time_one", "value": 0 } ], "sub": true, "time_zone": "+08:00", "uid": "az1...8nF", "update_time": 1730727593, "uuid": "842712fffe7af5e1", "dps_data": { "1": { "code": "switch", "custom_name": "", "dp_id": 1, "time": 1730715900566, "type": "Boolean", "value": false, "values": "{\"type\": \"bool\"}", "id": 1, "accessMode": "rw" }, "3": { "code": "percent_state", "custom_name": "", "dp_id": 3, "time": 1730506468371, "type": "value", "value": 0, "id": 3, "accessMode": "ro", "values": "{\"type\": \"value\", \"max\": 100, \"min\": 0, \"scale\": 0, \"step\": 1, \"unit\": \"%\"}" }, "4": { "code": "fault", "custom_name": "", "dp_id": 4, "time": 1730506468371, "type": "bitmap", "value": 0, "id": 4, "accessMode": "ro", "values": "{\"type\": \"bitmap\", \"label\": [\"low_battery\", \"fault\", \"lack_water\", \"sensor_fault\", \"motor_fault\", \"low_temp\"], \"maxlen\": 6}" }, "5": { "code": "water_once", "custom_name": "", "dp_id": 5, "time": 1730543102347, "type": "value", "value": 0, "id": 5, "accessMode": "ro", "values": "{\"type\": \"value\", \"max\": 1000, \"min\": 0, \"scale\": 1, \"step\": 1, \"unit\": \"L\"}" }, "7": { "code": "battery_percentage", "custom_name": "", "dp_id": 7, "time": 1730727331354, "type": "value", "value": 50, "id": 7, "accessMode": "ro", "values": "{\"type\": \"value\", \"max\": 100, \"min\": 0, \"scale\": 0, \"step\": 1, \"unit\": \"%\"}" }, "8": { "code": "battery_state", "custom_name": "", "dp_id": 8, "time": 1730506468371, "type": "enum", "value": "low", "id": 8, "accessMode": "ro", "values": "{\"type\": \"enum\", \"range\": [\"low\", \"middle\", \"high\"]}" }, "9": { "code": "time_use", "custom_name": "", "dp_id": 9, "time": 1730506468371, "type": "value", "value": 0, "id": 9, "accessMode": "ro", "values": "{\"type\": \"value\", \"max\": 2592000, \"min\": 0, \"scale\": 0, \"step\": 1, \"unit\": \"s\"}" }, "10": { "code": "weather_delay", "custom_name": "", "dp_id": 10, "time": 1730506468371, "type": "Enum", "value": "cancel", "values": "{\"type\": \"enum\", \"range\": [\"cancel\", \"24h\", \"48h\", \"72h\"]}", "id": 10, "accessMode": "rw" }, "11": { "code": "countdown", "custom_name": "", "dp_id": 11, "time": 1730506468371, "type": "Integer", "value": 0, "values": "{\"type\": \"value\", \"max\": 86400, \"min\": 0, \"scale\": 0, \"step\": 1, \"unit\": \"s\"}", "id": 11, "accessMode": "rw" }, "12": { "code": "work_state", "custom_name": "", "dp_id": 12, "time": 1730506468975, "type": "enum", "value": "idle", "id": 12, "accessMode": "ro", "values": "{\"type\": \"enum\", \"range\": [\"auto\", \"manual\", \"idle\"]}" }, "13": { "code": "smart_weather", "custom_name": "", "dp_id": 13, "time": 1730506468371, "type": "Enum", "value": "sunny", "values": "{\"type\": \"enum\", \"range\": [\"sunny\", \"clear\", \"cloud\", \"cloudy\", \"rainy\", \"snow\", \"fog\"]}", "id": 13, "accessMode": "rw" }, "14": { "code": "switch_weather", "custom_name": "", "dp_id": 14, "time": 1730506468371, "type": "bool", "value": false, "id": 14, "accessMode": "rw", "values": "{\"type\": \"bool\"}" }, "15": { "code": "use_time_one", "custom_name": "", "dp_id": 15, "time": 1730715901150, "type": "value", "value": 0, "id": 15, "accessMode": "ro", "values": "{\"type\": \"value\", \"max\": 86400, \"min\": 0, \"scale\": 0, \"step\": 1, \"unit\": \"s\"}" }, "16": { "code": "cycle_timing", "custom_name": "", "dp_id": 16, "time": 1730506469089, "type": "raw", "value": "AA==", "id": 16, "accessMode": "rw", "values": "{\"type\": \"raw\", \"maxlen\": 128}" }, "17": { "code": "timer", "custom_name": "", "dp_id": 17, "time": 1730506469411, "type": "raw", "value": "AA==", "id": 17, "accessMode": "rw", "values": "{\"type\": \"raw\", \"maxlen\": 128}" } } } } }

prairiesnpr commented 1 week ago

Let's start simple, see if this works.

from zhaquirks.tuya import TuyaPowerConfigurationCluster4AA
from zhaquirks.tuya.builder import TuyaQuirkBuilder

(
    TuyaQuirkBuilder("_TZE200_akjefhj5", "TS0601") 
    .tuya_onoff(dp_id=1)
    .tuya_battery(dp_id=7, power_cfg=TuyaPowerConfigurationCluster4AA)
    .skip_configuration()
    .add_to_registry()
)
nicktrigger commented 1 week ago

Thank you, I replaced the whole quirk with this code only, and the switch works fine, while the battery showed as 50%, which is what tuya reports too. However, I had another, older quirk still there which I deleted and now battery shows as unknown again. I tried reloading the other quirk too but no change to battery reporting after this. Still showing as unknown. I wonder if it's because this device has 2 batteries, not 4? I see the code refers to 4aa.

nicktrigger commented 1 week ago

I deleted the old quirk again, rebooted home assistant and now I have battery too!

prairiesnpr commented 1 week ago

Nice, OK what other DPs do you want to add?

You can see here https://github.com/prairiesnpr/zha-device-handlers/blob/Tuya-Quirk-Builder-Docs/tuya.md for examples if you want to try adding some yourself.

Feel free to swap the 4aa for 2aa, I assumed it would as 4 since most of the other valves were.

prairiesnpr commented 1 week ago

I would remove your nabu casa link in the screenshots also, but I'm paranoid.

nicktrigger commented 1 week ago

Very cool! Thanks so much

Ideally I'd like to have access to these dpids

"4 ( code: fault , value: 0, cloud pull )", "5 ( code: water_once , value: 0 )", "8 ( code: battery_state , value: low, cloud pull )", "9 ( code: time_use , value: 0, cloud pull )", "11 ( code: countdown , value: 600 )", "12 ( code: work_state , value: idle )", "15 ( code: use_time_one , value: 0 )", "17 ( code: timer , value: AA== )"

If you don't have time, I'll have a play with the instructions on the link you sent!

And thanks for the advice re nabu casa, I have removed the screenshots.

nicktrigger commented 1 week ago

It would be great to get the setting to determine what volume to water or report the volume but I'm not convinced this device ever had that even with Tuya.

nicktrigger commented 1 week ago

Nice, OK what other DPs do you want to add?

You can see here https://github.com/prairiesnpr/zha-device-handlers/blob/Tuya-Quirk-Builder-Docs/tuya.md for examples if you want to try adding some yourself.

Feel free to swap the 4aa for 2aa, I assumed it would as 4 since most of the other valves were.

Regarding the 2aa batteries. If I change to 2aa, it fails to load the quirk, I assume as this is not in the quirk currently? Is there a way to add this to the custom quirk ans base it off 1.2volts for rechargeable batteries?

prairiesnpr commented 1 week ago

Regarding the 2aa batteries. If I change to 2aa, it fails to load the quirk, I assume as this is not in the quirk currently? Is there a way to add this to the custom quirk ans base it off 1.2volts for rechargeable batteries?

Updating the scaling wouldn't be that simple, Tuya is reporting as a percentage, so we would have to apply a convertor to that percentage to get to the desired value, possible, but no idea what the conversion would be and it's probably not going to be very accurate anyways. These battery reports are seldom accurate using stock batteries.

I'm assuming you are importing this as a custom quirk as detailed in the ZHA documentation. Where we have a single file per custom quirk. So, you need to import the 2AA config. Which looks like so.

from zhaquirks.tuya import TuyaPowerConfigurationCluster2AA
from zhaquirks.tuya.builder import TuyaQuirkBuilder

(
    TuyaQuirkBuilder("_TZE200_akjefhj5", "TS0601") 
    .tuya_onoff(dp_id=1)
    .tuya_battery(dp_id=7, power_cfg=TuyaPowerConfigurationCluster2AA)
    .skip_configuration()
    .add_to_registry()
)
prairiesnpr commented 1 week ago

You can try this, DP 9 and 15 seem the same, I might be missing something and 17 would need more details. It's rw, but I don't know what it actually does and how to translate the value.

from zhaquirks.tuya import TuyaPowerConfigurationCluster2AA
from zhaquirks.tuya.builder import TuyaQuirkBuilder
from zigpy.quirks.v2 import EntityPlatform, EntityType
from zigpy.quirks.v2.homeassistant import UnitOfTime
from zigpy.quirks.v2.homeassistant.sensor import SensorDeviceClass, SensorStateClass
import zigpy.types as t

class IrrigationStatus(t.enum8):
    """Irrigation Status Enum."""

    Auto = 0x00
    Manual = 0x01
    Idle = 0x02

(
    TuyaQuirkBuilder("_TZE200_akjefhj5", "TS0601")
    .tuya_onoff(dp_id=1)
    .tuya_binary_sensor(dp_id=4,
                        attribute_name="is_faulted", 
                        translation_key="device_fault",
                        fallback_name="Fault"
    )
    .tuya_metering(dp_id=5)
    .tuya_battery(dp_id=7, power_cfg=TuyaPowerConfigurationCluster2AA)
    .tuya_sensor(
        dp_id=9,
        attribute_name="valve_duration",
        type=t.uint32_t,
        state_class=SensorStateClass.MEASUREMENT,
        device_class=SensorDeviceClass.DURATION,
        unit=UnitOfTime.SECONDS,
        entity_type=EntityType.STANDARD,
        translation_key="irriation_duration",
        fallback_name="Irrigation duration",
    )
    .tuya_number(
        dp_id=11,
        attribute_name="valve_countdown",
        type=t.uint16_t,
        device_class=SensorDeviceClass.DURATION,
        unit=UnitOfTime.SECONDS,
        min_value=0,
        max_value=86400,
        step=1,
        translation_key="valve_countdown",
        fallback_name="Irrigation time",
    )
    .tuya_enum(
        dp_id=12,
        attribute_name="valve_state",
        enum_class=IrrigationStatus,
        entity_platform=EntityPlatform.SENSOR,
        entity_type=EntityType.STANDARD,
        translation_key="valve_state",
        fallback_name="Work State",
    )
    .tuya_sensor(
        dp_id=15,
        attribute_name="valve_use_time",
        type=t.uint32_t,
        state_class=SensorStateClass.MEASUREMENT,
        device_class=SensorDeviceClass.DURATION,
        unit=UnitOfTime.SECONDS,
        entity_type=EntityType.STANDARD,
        translation_key="valve_use_time",
        fallback_name="Valve use time on",
    )
    .skip_configuration()
    .add_to_registry()
)
nicktrigger commented 1 week ago

This is mostly working! I changed back to 4aa for the power settings as zha fails to load completely when 2aa is in the quirk. I will post the error message below.

For dp4 it currently shows as fault "off". Is this the default state? Then it gives these values if there is a fault? ["low_battery", "fault", "lack_water", "sensor_fault", "motor_fault", "low_temp"]

The valve time doesn't seem to do anything. I'd expect that you set a time and then when activating the switch it runs for this amount of time. Is this possible?

Duration shows twice, the 2nd entry being accurate.

The instantaneous demand section doesn't seem to show anything, expect for an error saying its not being provided by the zha integration any more.

If its possible to remove the extra duration entry and the instantaneous demand, and fix the valve time section (and the 2aa power issue) I think this is done!

Screenshot_20241109_200244_Home Assistant

2aa power error from the logs:

Logger: homeassistant.config_entries Source: config_entries.py:635 First occurred: 20:12:28 (1 occurrences) Last logged: 20:12:28

Error setting up entry for zha Traceback (most recent call last): File "/usr/src/homeassistant/homeassistant/config_entries.py", line 635, in async_setup_with_context result = await component.async_setup_entry(hass, self) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/components/zha/init.py", line 132, in async_setup_entry async with radio_mgr.connect_zigpy_app() as app: File "/usr/local/lib/python3.12/contextlib.py", line 210, in aenter return await anext(self.gen) ^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/components/zha/radio_manager.py", line 182, in connect_zigpy_app app = await self.radio_type.controller.new( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/zigpy/application.py", line 254, in new await app._load_db() File "/usr/local/lib/python3.12/site-packages/zigpy/application.py", line 110, in _load_db await self._dblistener.load() File "/usr/local/lib/python3.12/site-packages/zigpy/appdb.py", line 684, in load device = zigpy.quirks.get_device(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/zigpy/quirks/init.py", line 43, in get_device return _DEVICE_REGISTRY.get_device(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/zigpy/quirks/registry.py", line 130, in get_device return quirk_entry.create_device(device) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/zigpy/quirks/v2/init.py", line 429, in create_device return CustomDeviceV2(device.application, device.ieee, device.nwk, device, self) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/zigpy/quirks/v2/init.py", line 90, in init add_meta(self) File "/usr/local/lib/python3.12/site-packages/zigpy/quirks/v2/init.py", line 173, in call cluster = self.cluster(endpoint, is_server=True) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/zhaquirks/tuya/init.py", line 895, in init__ self.endpoint.device.battery_bus.add_listener(self) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ AttributeError: 'CustomDeviceV2' object has no attribute 'battery_bus'

prairiesnpr commented 1 week ago

Looks like there is a difference in the power configuration clusters, 2AA and 3AA don't match the others, hence the error. We would need to look into why that is. It's not a huge deal, it only sets the UI to tell you the correct battery size and quantity.

Just delete instantaneous demand, it's left over from the old quirk.

Delete the demand sensor that's not working, common for Tuya to have a ton of extra DPs that don't actually do anything.

Fault is interesting, you show it as a binary sensor above, but it's actually a bitmap. If you want all the values, you will need to extract the correct bit corresponding to the fault, then add a binary sensor for each possible fault. That would require adding multiple entries for a single DP though, which isn't currently supported.

On valve time, that's the behavior I would expect, is that how it responds in local Tuya? If so, then it will just take some more digging. You unfortunately are getting to the point, you will either need to compare to a zigbee2mqtt convertor or sniff the traffic between local Tuya to determine what local Tuya sends, to which DP and compare it to what the quirk sends.

nicktrigger commented 4 days ago

I can't delete the entries, but have hidden them anyway for the unnecessary DPs

For fault, its not the end of the world, maybe 1 day!

For Valve time, I suspect this is related to the difference between the 2 different watering states, manual & automatic. Automatic takes the time setting, manual does not. When I have a moment I will add back to Local Tuya & see what it is sending to start the watering for pre-determined time periods vs. manual watering.