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
684 stars 636 forks source link

[Device Support Request] Popp Thermostat Radiator Valve 701721 #2728

Open deechte opened 8 months ago

deechte commented 8 months ago

Problem description

This Popp TRV is a great product, hardwire-wise: https://popp.eu/popp-smart-thermostat-701721/ However ZHA only exposes a thermostat card. Much more could be exposed to Home Assistant if I look at what Zigbee2mqtt offers: https://www.zigbee2mqtt.io/devices/701721.html.

This product has identical hardware to the Danfoss Aly TRV.

Solution description

Could what Zigbee2mqtt exposes please be implemented in ZHA as well? I'm especially looking for:

Thank you!

Screenshots/Video

Screenshots/Video [Paste/upload your media here]

Device signature

Device signature ```json [": "NodeDescriptor(logical_type=, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=, mac_capability_flags=, manufacturer_code=4678, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=, *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": "0x0301", "input_clusters": [ "0x0000", "0x0001", "0x0003", "0x000a", "0x0020", "0x0201", "0x0204", "0x0b05" ], "output_clusters": [ "0x0000", "0x0019" ] } }, "manufacturer": "D5X84YU", "model": "eT093WRG", "class": "zigpy.device.Device" } ] ```

Diagnostic information

Diagnostic information ```json [{ "home_assistant": { "installation_type": "Home Assistant OS", "version": "2023.11.1", "dev": false, "hassio": true, "virtualenv": false, "python_version": "3.11.6", "docker": true, "arch": "aarch64", "timezone": "Europe/Amsterdam", "os_name": "Linux", "os_version": "6.1.21-v8", "supervisor": "2023.10.1", "host_os": "Home Assistant OS 11.1", "docker_version": "24.0.6", "chassis": "embedded", "run_as_root": true }, "custom_components": { "bold": { "version": "0.1.4", "requirements": [ "bold_smart_lock==0.3.9" ] }, "tplink_deco": { "version": "3.5.3", "requirements": [ "pycryptodome>=3.12.0" ] }, "tapo": { "version": "2.9.0", "requirements": [ "plugp100==3.10.3" ] }, "hacs": { "version": "1.33.0", "requirements": [ "aiogithubapi>=22.10.1" ] } }, "integration_manifest": { "domain": "zha", "name": "Zigbee Home Automation", "after_dependencies": [ "onboarding", "usb" ], "codeowners": [ "@dmulcahey", "@adminiuga", "@puddly" ], "config_flow": true, "dependencies": [ "file_upload" ], "documentation": "https://urldefense.com/v3/__https://www.home-assistant.io/integrations/zha__;!!Oqvv-oCmSU8!WbBh0eDlETwyBRBcrg7K1sF61m_cMGh0xwGO1Hqo_d1ISuKPSGp1jUQRwJPADjZLW2g_a13z4RJbfc-RUofidw$ ", "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.36.8", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.106", "zigpy-deconz==0.21.1", "zigpy==0.59.0", "zigpy-xbee==0.19.0", "zigpy-zigate==0.11.0", "zigpy-znp==0.11.6", "universal-silabs-flasher==0.0.14", "pyserial-asyncio-fast==0.11" ], "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" ] } ], "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": 49367, "manufacturer": "D5X84YU", "model": "eT093WRG", "name": "D5X84YU eT093WRG", "quirk_applied": false, "quirk_class": "zigpy.device.Device", "quirk_id": null, "manufacturer_code": 4678, "power_source": "Battery or Unknown", "lqi": 120, "rssi": -70, "last_seen": "2023-11-08T10:55:03", "available": true, "device_type": "EndDevice", "signature": { "node_descriptor": "NodeDescriptor(logical_type=, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=, mac_capability_flags=, manufacturer_code=4678, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=, *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": "0x0301", "input_clusters": [ "0x0000", "0x0001", "0x0003", "0x000a", "0x0020", "0x0201", "0x0204", "0x0b05" ], "output_clusters": [ "0x0000", "0x0019" ] } }, "manufacturer": "D5X84YU", "model": "eT093WRG" }, "active_coordinator": false, "entities": [ { "entity_id": "button.trv_studk_popp_d5x84yu_et093wrg_identificeren", "name": "D5X84YU eT093WRG" }, { "entity_id": "climate.trv_studk_popp_d5x84yu_et093wrg_thermostaat", "name": "D5X84YU eT093WRG" }, { "entity_id": "sensor.trv_studk_popp_d5x84yu_et093wrg_batterij", "name": "D5X84YU eT093WRG" }, { "entity_id": "sensor.trv_studk_popp_d5x84yu_et093wrg_actie_air_conditioner", "name": "D5X84YU eT093WRG" } ], "neighbors": [], "routes": [], "endpoint_names": [ { "name": "THERMOSTAT" } ], "user_given_name": "TRV-studk-Popp-D5X84YU eT093WRG", "device_reg_id": "d97ca63df5bec989f38e2dc1c5ca81c7", "area_id": "studeerkamer_1e_vd", "cluster_details": { "1": { "device_type": { "name": "THERMOSTAT", "id": 769 }, "profile_id": 260, "in_clusters": { "0x0000": { "endpoint_attribute": "basic", "attributes": { "0x0004": { "attribute_name": "manufacturer", "value": "D5X84YU" }, "0x0005": { "attribute_name": "model", "value": "eT093WRG" } }, "unsupported_attributes": {} }, "0x0001": { "endpoint_attribute": "power", "attributes": { "0x0021": { "attribute_name": "battery_percentage_remaining", "value": 198 }, "0x0020": { "attribute_name": "battery_voltage", "value": 32 } }, "unsupported_attributes": { "0x0031": { "attribute_name": "battery_size" }, "0x0033": { "attribute_name": "battery_quantity" } } }, "0x0003": { "endpoint_attribute": "identify", "attributes": {}, "unsupported_attributes": {} }, "0x000a": { "endpoint_attribute": "time", "attributes": {}, "unsupported_attributes": {} }, "0x0020": { "endpoint_attribute": "poll_control", "attributes": { "0x0000": { "attribute_name": "checkin_interval", "value": 13200 } }, "unsupported_attributes": {} }, "0x0201": { "endpoint_attribute": "thermostat", "attributes": { "0x0004": { "attribute_name": "abs_max_heat_setpoint_limit", "value": 3500 }, "0x0003": { "attribute_name": "abs_min_heat_setpoint_limit", "value": 500 }, "0x001b": { "attribute_name": "ctrl_sequence_of_oper", "value": 2 }, "0x0000": { "attribute_name": "local_temperature", "value": 1537 }, "0x0016": { "attribute_name": "max_heat_setpoint_limit", "value": 3500 }, "0x0015": { "attribute_name": "min_heat_setpoint_limit", "value": 500 }, "0x0012": { "attribute_name": "occupied_heating_setpoint", "value": 1100 }, "0x0008": { "attribute_name": "pi_heating_demand", "value": 1 }, "0x0030": { "attribute_name": "setpoint_change_source", "value": 2 }, "0x001c": { "attribute_name": "system_mode", "value": 4 } }, "unsupported_attributes": { "0x0002": { "attribute_name": "occupancy" }, "0x0005": { "attribute_name": "abs_min_cool_setpoint_limit" }, "0x0006": { "attribute_name": "abs_max_cool_setpoint_limit" }, "0x0007": { "attribute_name": "pi_cooling_demand" }, "0x0014": { "attribute_name": "unoccupied_heating_setpoint" }, "0x0018": { "attribute_name": "max_cool_setpoint_limit" }, "0x0011": { "attribute_name": "occupied_cooling_setpoint" }, "0x0013": { "attribute_name": "unoccupied_cooling_setpoint" }, "0x0017": { "attribute_name": "min_cool_setpoint_limit" }, "0x001e": { "attribute_name": "running_mode" }, "0x0019": { "attribute_name": "min_setpoint_dead_band" }, "0x0023": { "attribute_name": "temp_setpoint_hold" }, "0x0045": { "attribute_name": "ac_louver_position" }, "0x0029": { "attribute_name": "running_state" }, "0x0035": { "attribute_name": "occupied_setback_min" }, "0x0046": { "attribute_name": "ac_coil_temperature" } } }, "0x0204": { "endpoint_attribute": "thermostat_ui", "attributes": {}, "unsupported_attributes": {} }, "0x0b05": { "endpoint_attribute": "diagnostic", "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": { "0x0000": { "endpoint_attribute": "basic", "attributes": {}, "unsupported_attributes": {} }, "0x0019": { "endpoint_attribute": "ota", "attributes": {}, "unsupported_attributes": {} } } } } } }] ```

Logs

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

Custom quirk

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

Additional information

Don't know if it's relevant, but I'm using the HA SkyConnect USB stick.

MattWestb commented 8 months ago

I think its the POP version of the updated Aly and need being added here in the Danfoss quirk: https://github.com/zigpy/zha-device-handlers/blob/cbd0f037fbc3c5b696e499bdf13bf935bc8746ff/zhaquirks/danfoss/thermostat.py#L130

deechte commented 8 months ago

Thanks for checking it out Matt!! Who could add that to the quirk?

MattWestb commented 8 months ago

Some must testing doing it with local quirk and if its working making one PR and its being added to next ZHA release.

deechte commented 8 months ago

Thanks. I'd be happy to test a quirk. I'm familiar with using local quirks, but not to making them. I suppose the Danfoss quirk needs changing to work for the Popp?

MattWestb commented 8 months ago

Put the danfoss quirk in your local quirk folder and then adding the new device MODELS_INFO: one one new line after the last one (131) i was showing and save and restart HA and look if its loading the quirk.

Caius-Bonus commented 8 months ago

There is already a PR for this in ZHA and here: https://github.com/home-assistant/core/pull/86907 and https://github.com/zigpy/zha-device-handlers/pull/2150/. It just needs a few other bits into place before it can get merged. In the meantime you can run custom components and custom quirks.

Caius-Bonus commented 8 months ago

And OTA updates are already possible using https://www.danfoss.com/nl-nl/products/dhs/smart-heating/smart-heating/danfoss-ally/danfoss-ally-support/#tab-software and the information here: https://www.home-assistant.io/integrations/zha under OTA firmware updates . Haven't confirmed this yet personally, but it should work. Note that the new devices (G prepended serial) have no firmware files available yet.

Caius-Bonus commented 8 months ago

Also duplicate: https://github.com/zigpy/zha-device-handlers/issues/1726

deechte commented 8 months ago

Put the danfoss quirk in your local quirk folder and then adding the new device MODELS_INFO: one one new line after the last one (131) i was showing and save and restart HA and look if its loading the quirk.

@MattWestb Ok, so I've done that. Added a line (D5X84YU, "eT093WRG"), which is the model number of my Popp 701721. Removed the device from ZHA and factory reset the Popp itself, rebooted HA and repaired the Popp. I can now clearly see it is using the quirk in the Popp's device zigbee info. Unfortunately, no new entities or sensors have appeared. It's exactly the same as before without the quirk.

deechte commented 8 months ago

Haven't confirmed this yet personally, but it should work.

@Caius-Bonus It appears to me you have this device as well, right? But do you have the Popp 701721 or the Danfoss Aly? Cause the custom quirk isn't working, like I wrote one post higher.

MattWestb commented 8 months ago

Try restarting HA its some times happening ll handles is not being loaded then the device is being added but the device is OK.

deechte commented 8 months ago

Try restarting HA its some times happening ll handles is not being loaded then the device is being added but the device is OK.

Like I wrote, I did that already in the process :-( . In fact, I did it multiple times already since installing the custom quirk.

Caius-Bonus commented 8 months ago

The updated quirk will work for D5X84YU eT093WRG. Adding that line to the old quirk will not change anything. If you want to have entities in Home Assistant, you need to use the code from both my PRs. If you only use the custom quirk, it will not do anything in home assistant.

deechte commented 8 months ago

OK, thanks, but that's beyond my level of knowledge. How do I do that?

Caius-Bonus commented 8 months ago

If it is, I would advice waiting for my PRs to be merged. It would require you to redo this every large release and it requires editing specific files in specific ways that might break things if not done with knowledge of the intention. I hope to get it merged before the December release, but I can't promise anything. It works, but it requires other PRs to be in place first.

deechte commented 8 months ago

If it is, I would advice waiting for my PRs to be merged. It would require you to redo this every large release and it requires editing specific files in specific ways that might break things if not done with knowledge of the intention. I hope to get it merged before the December release, but I can't promise anything. It works, but it requires other PRs to be in place first.

You're right, that'll be over my head. Fingers crossed your changes come live soon BTW, you have the Popp or the Danfoss trv?

AllardKatan commented 7 months ago

If it is, I would advice waiting for my PRs to be merged. It would require you to redo this every large release and it requires editing specific files in specific ways that might break things if not done with knowledge of the intention. I hope to get it merged before the December release, but I can't promise anything. It works, but it requires other PRs to be in place first.

It looks like your PR's are almost ready? Great work, thanks a lot. It comes at a good time for me, I am getting a completely new heating system (boiler, heat pump, valves, only the radiators stay the same) next week and I was thinking about getting POPP Zigbee TRV's for all my 10 radiators. I have one of them already (but no matching radiator valve to connect it to), and it connects just fine, but I can only read temperature and write setpoint through ZHA now.

If you need anyone to run tests, just let me know. I haven't used custom quirks and stuff like that before but I'm tech-savvy enough to find out how that works. I run my HA in a Virtualbox, so I can simply clone it and run that one for tests without the danger of messing everything up.

Caius-Bonus commented 6 months ago

@deechte I am doing my testing with Popp TRVs. @AllardKatan If you can figure it out yourself, I would say: go for it. It is fully functional and stable on my setup and more testing is better before merging. However mind that it would require certain hacks in python to get it working and I don't have the time to assist in this.

AllardKatan commented 6 months ago

I'll see how far I get. I have all 10 valves installed now and connected to ZHA, they are all Popp but one of them is the older (O) type, the rest is the newer (G). So that should be a decent testing ground. For my understanding, would I need to set up a full dev environment in VScode or would a clone of my VM with a couple of files replaced with the ones from your PRs be enough? I think I can make time for the latter but I think the former is more of an investment than I can currently afford. I was already considering diving in to Ha core development but it's going to take me quite some time to get familiar with it so that will not be soon.

github-actions[bot] commented 2 weeks ago

There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates. Please make sure to update to the latest version and check if that solves the issue. Let us know if that works for you by adding a comment 👍 This issue has now been marked as stale and will be closed if no further activity occurs. Thank you for your contributions.

deechte commented 2 weeks ago

@github bot. This issue isn't solved.