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
760 stars 698 forks source link

[Device Support Request] SASWELL SAS980SWT-7-Z01 Smart irrigation, water timer #3287

Open emmanuelg34 opened 3 months ago

emmanuelg34 commented 3 months ago

Problem description

https://www.domadoo.fr/fr/jardin-connecte/5886-saswell-electrovanne-et-programmateur-d-arrosage-connecte-zigbee-mesure-de-consommation.html https://www.saswell.com/smart-irrigation-wifi-water-timer-sas980swt-7-z01_p147.html

Wifi smart sprinkler controller Smart irrigation,Wifi water timer SAS980SWT-7-Z01

same as S0601 - TZE200_81isopgh

"TS0601 by _TZE204_qtnjuoae Zigbee info IEEE: a4:c1:38:23:6c:b8:8c:ca NWK: 0xc713 Device Type: EndDevice LQI: 30 RSSI: Unknown Last seen: 2024-08-02T14:26:52 Power source: Battery or Unknown"

Solution description

Could you please add the device to ZHA ? TS0601 by _TZE204_qtnjuoae

Screenshots/Video

Screenshots/Video ![image](https://github.com/user-attachments/assets/4e574b03-68d0-43bd-a2c0-12cdee80dd7a) ![image](https://github.com/user-attachments/assets/4f24469d-4c2a-4952-8f9c-2f22236c9f2b)

Device signature

{ "node_descriptor": "NodeDescriptor(logical_type=<LogicalType.EndDevice: 2>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress: 128>, manufacturer_code=4417, maximum_buffer_size=66, maximum_incoming_transfer_size=66, server_mask=10752, maximum_outgoing_transfer_size=66, descriptor_capability_field=<DescriptorCapability.NONE: 0>, allocate_address=True, is_alternate_pan_coordinator=False, is_coordinator=False, is_end_device=True, is_full_function_device=False, is_mains_powered=False, is_receiver_on_when_idle=False, is_router=False, *is_security_capable=False)", "endpoints": { "1": { "profile_id": "0x0104", "device_type": "0x0051", "input_clusters": [ "0x0000", "0x0004", "0x0005", "0xef00" ], "output_clusters": [ "0x000a", "0x0019" ] } }, "manufacturer": "_TZE204_qtnjuoae", "model": "TS0601", "class": "zigpy.device.Device" }

Diagnostic information

{ "home_assistant": { "installation_type": "Home Assistant OS", "version": "2024.7.4", "dev": false, "hassio": true, "virtualenv": false, "python_version": "3.12.4", "docker": true, "arch": "x86_64", "timezone": "Europe/Paris", "os_name": "Linux", "os_version": "6.6.33-haos", "supervisor": "2024.08.0", "host_os": "Home Assistant OS 12.4", "docker_version": "26.1.4", "chassis": "embedded", "run_as_root": true }, "custom_components": { "smartlife": { "documentation": "https://www.home-assistant.io/integrations/smartlife", "version": "0.1.0", "requirements": [ "tuya-device-sharing-sdk==0.2.0" ] }, "meross_lan": { "documentation": "https://github.com/krahabb/meross_lan", "version": "5.3.0", "requirements": [] }, "climate_group": { "documentation": "https://github.com/daenny/climate_group", "version": "0.4.2", "requirements": [] }, "localtuya": { "documentation": "https://github.com/rospogrigio/localtuya/", "version": "5.2.1", "requirements": [] }, "versatile_thermostat": { "documentation": "https://github.com/jmcollin78/versatile_thermostat", "version": "6.2.9", "requirements": [] }, "nodered": { "documentation": "https://zachowj.github.io/node-red-contrib-home-assistant-websocket/guide/custom_integration/", "version": "4.0.1", "requirements": [] }, "myEnedis": { "documentation": "https://github.com/saniho/apiEnedis/", "version": "2.3.0", "requirements": [ "packaging>=20.8" ] }, "hacs": { "documentation": "https://hacs.xyz/docs/configuration/start", "version": "1.34.0", "requirements": [ "aiogithubapi>=22.10.1" ] }, "scheduler": { "documentation": "https://github.com/nielsfaber/scheduler-component", "version": "v0.0.0", "requirements": [] }, "gazpar": { "documentation": "https://github.com/ssenart/home-assistant-gazpar", "version": "1.3.5", "requirements": [ "pygazpar==1.2.2" ] } }, "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", "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.39.1", "pyserial==3.5", "zha-quirks==0.0.117", "zigpy-deconz==0.23.2", "zigpy==0.64.1", "zigpy-xbee==0.20.1", "zigpy-zigate==0.12.1", "zigpy-znp==0.12.2", "universal-silabs-flasher==0.0.20", "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": "sonoffplus", "known_devices": [ "sonoff zigbee dongle plus v2" ] }, { "vid": "10C4", "pid": "EA60", "description": "sonoffplus", "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" }, { "type": "_xzg._tcp.local.", "name": "xzg" }, { "type": "_czc._tcp.local.", "name": "czc" } ], "is_built_in": true }, "setup_times": { "null": { "setup": 3.785700027947314e-05 }, "7df7a6c44a97f740cdccda44e88296e0": { "wait_import_platforms": -0.00010848599958990235, "wait_base_component": -0.0009090060011658352, "config_entry_setup": 3.4247984060002636 } }, "data": { "ieee": "REDACTED", "nwk": 39451, "manufacturer": "_TZE204_qtnjuoae", "model": "TS0601", "name": "_TZE204_qtnjuoae TS0601", "quirk_applied": false, "quirk_class": "zigpy.device.Device", "quirk_id": null, "manufacturer_code": 4417, "power_source": "Battery or Unknown", "lqi": 17, "rssi": null, "last_seen": "2024-08-06T14:56:56", "available": true, "device_type": "EndDevice", "signature": { "node_descriptor": "NodeDescriptor(logical_type=<LogicalType.EndDevice: 2>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress: 128>, manufacturer_code=4417, maximum_buffer_size=66, maximum_incoming_transfer_size=66, server_mask=10752, maximum_outgoing_transfer_size=66, descriptor_capability_field=<DescriptorCapability.NONE: 0>, allocate_address=True, is_alternate_pan_coordinator=False, is_coordinator=False, is_end_device=True, is_full_function_device=False, is_mains_powered=False, is_receiver_on_when_idle=False, is_router=False, is_security_capable=False)", "endpoints": { "1": { "profile_id": "0x0104", "device_type": "0x0051", "input_clusters": [ "0x0000", "0x0004", "0x0005", "0xef00" ], "output_clusters": [ "0x000a", "0x0019" ] } }, "manufacturer": "_TZE204_qtnjuoae", "model": "TS0601" }, "active_coordinator": false, "entities": [ { "entity_id": "update.tze204_qtnjuoae_ts0601_firmware", "name": "_TZE204_qtnjuoae TS0601" } ], "neighbors": [], "routes": [], "endpoint_names": [ { "name": "SMART_PLUG" } ], "user_given_name": null, "device_reg_id": "8355b2ce49c0f1e14fd7695d3acc465a", "area_id": "piscine", "cluster_details": { "1": { "device_type": { "name": "SMART_PLUG", "id": 81 }, "profile_id": 260, "in_clusters": { "0x0004": { "endpoint_attribute": "groups", "attributes": {}, "unsupported_attributes": {} }, "0x0005": { "endpoint_attribute": "scenes", "attributes": {}, "unsupported_attributes": {} }, "0xef00": { "endpoint_attribute": null, "attributes": {}, "unsupported_attributes": {} }, "0x0000": { "endpoint_attribute": "basic", "attributes": { "0x0004": { "attribute_name": "manufacturer", "value": "_TZE204_qtnjuoae" }, "0x0005": { "attribute_name": "model", "value": "TS0601" } }, "unsupported_attributes": {} } }, "out_clusters": { "0x0019": { "endpoint_attribute": "ota", "attributes": { "0x0002": { "attribute_name": "current_file_version", "value": 73 } }, "unsupported_attributes": {} }, "0x000a": { "endpoint_attribute": "time", "attributes": {}, "unsupported_attributes": {} } } } } } }

Logs

Logs ```python [Paste the logs here] ```

Custom quirk

Custom quirk ```python [Paste your custom quirk here] ```

Additional information

No response

nicktrigger commented 1 month ago

Seconded. I guess this is basically the same as the similar valves with slightly different ids.

So hopefully just a case of adding to ZHA with the product name.

I'm not technically minded enough to get my head around these custom quirks.

nicktrigger commented 1 week ago

I hope @prairiesnpr may be can assist here too, I have 2 of these devices but could not even get the switch to work using any custom quirk (I tried with all the entries from the current Tuya Valve Quirk to see if 1 would get me that far).

Below I have the relevant DP details (I hope) from Local Tuya.

{ "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": "eb88692f1a3ca81d6fn2nq", "dps_strings": [ "1 ( code: switch , value: False, cloud pull )", "3 ( code: percent_state , value: 0, cloud pull )", "4 ( code: fault , value: 0, cloud pull )", "5 ( code: water_once , value: 831, cloud pull )", "6 ( code: water_total , value: 83, cloud pull )", "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: 60, cloud pull )", "12 ( code: work_state , value: idle, cloud pull )", "13 ( code: smart_weather , value: sunny, cloud pull )", "14 ( code: switch_weather , value: False, cloud pull )", "15 ( code: use_time_one , value: 540, cloud pull )", "16 ( code: cycle_timing , value: AA==, cloud pull )", "17 ( code: timer , value: AA==, cloud pull )" ], "enable_debug": false, "entities": [ { "entity_category": "None", "friendly_name": "", "icon": "mdi:valve", "id": "1", "platform": "switch" }, { "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, "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, "unit_of_measurement": "s" }, { "entity_category": "config", "friendly_name": "Switch Timer", "icon": "mdi:timer", "id": "11", "max_value": 86400, "min_value": 0, "platform": "number", "scaling": 1.0, "step_size": 1, "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", "platform": "select", "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", "platform": "switch" }, { "entity_category": "diagnostic", "friendly_name": "Single Usage Time", "icon": "mdi:chart-arc", "id": "15", "platform": "sensor", "scaling": 1, "unit_of_measurement": "s" } ], "friendly_name": "bedroom garden watering", "gateway_id": "****", "host": "192.168.50.100", "local_key": "****'", "model": "SAS980SWT-7-ZTU(EU)", "node_id": "**", "product_key": null, "protocol_version": "3.3" }, "device_cloud_info": { "active_time": 1728574984, "biz_type": 18, "category": "sfkzq", "create_time": 1728134509, "icon": "smart/icon/ay1537509218624daaHb/3641f0d0b300fc0e4b1a3914c219b413.jpg", "id": "*", "ip": "", "lat": "", "local_key": "~]q...d#'", "lon": "", "model": "", "name": "bedroom garden watering", "node_id": "***", "online": true, "owner_id": "****", "product_id": "qtnjuoae", "product_name": "SAS980SWT-7-ZTU(EU)", "status": [ { "code": "switch", "value": false }, { "code": "percent_state", "value": 0 }, { "code": "water_once", "value": 0 }, { "code": "water_total", "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": 300 }, { "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": 1730919765, "uuid": "a4c1382da68d88f1", "dps_data": { "1": { "code": "switch", "custom_name": "", "dp_id": 1, "time": 1731016801911, "type": "Boolean", "value": false, "values": "{\"type\": \"bool\"}", "id": 1, "accessMode": "rw" }, "3": { "code": "percent_state", "custom_name": "", "dp_id": 3, "time": 1728574984129, "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": 1728574985944, "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": 1731016802711, "type": "value", "value": 0, "id": 5, "accessMode": "ro", "values": "{\"type\": \"value\", \"max\": 1000, \"min\": 0, \"scale\": 1, \"step\": 1, \"unit\": \"L\"}" }, "6": { "code": "water_total", "custom_name": "", "dp_id": 6, "time": 1731016802591, "type": "value", "value": 0, "id": 6, "accessMode": "ro", "values": "{\"type\": \"value\", \"max\": 9999, \"min\": 0, \"scale\": 0, \"step\": 1, \"unit\": \"L\"}" }, "7": { "code": "battery_percentage", "custom_name": "", "dp_id": 7, "time": 1731024300859, "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": 1728574984129, "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": 1728574984129, "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": 1728574984129, "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": 1728901201551, "type": "Integer", "value": 300, "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": 1728901202210, "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": 1728574984129, "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": 1728574984129, "type": "bool", "value": false, "id": 14, "accessMode": "rw", "values": "{\"type\": \"bool\"}" }, "15": { "code": "use_time_one", "custom_name": "", "dp_id": 15, "time": 1731016802469, "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": 1728574986292, "type": "raw", "value": "AA==", "id": 16, "accessMode": "rw", "values": "{\"type\": \"raw\", \"maxlen\": 128}" }, "17": { "code": "timer", "custom_name": "", "dp_id": 17, "time": 1728574986554, "type": "raw", "value": "AA==", "id": 17, "accessMode": "rw", "values": "{\"type\": \"raw\", \"maxlen\": 128}" } } } } }

prairiesnpr commented 1 week ago

Same on this one, see if this gives control, then we can add in the other DPs.

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

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

Awesome this also works! I really appreciate the help with this.

The other dpids that would be useful would be:

"1 ( code: switch , value: False, cloud pull )", "4 ( code: fault , value: 0, cloud pull )", "5 ( code: water_once , value: 831, cloud pull )", "6 ( code: water_total , value: 83, cloud pull )", "8 ( code: battery_state , value: low, cloud pull )", "9 ( code: time_use , value: 0, cloud pull )", "11 ( code: countdown , value: 60, cloud pull )", "12 ( code: work_state , value: idle, cloud pull )", "15 ( code: use_time_one , value: 540, cloud pull )", "17 ( code: timer , value: AA==, cloud pull )"

nicktrigger commented 1 week ago

I used the same code as your helpful response in the other valve thread and its working great with the 4aa power setting, but not 2aa.

This one reports summation delivered but its always 86L, which is definitely not correct. And irrigation time also seems to have no affect on the watering time.

Screenshot_20241109_201812_Home Assistant