From b2fac92c981221eb0098b50a0915c0f7c58db2eb Mon Sep 17 00:00:00 2001 From: TheJulianJES Date: Wed, 26 Mar 2025 09:33:21 +0100 Subject: [PATCH 1/4] Bump ZHA to 0.0.54 --- homeassistant/components/zha/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/zha/manifest.json b/homeassistant/components/zha/manifest.json index 6ed8b253e75363..4daa2f2aa40813 100644 --- a/homeassistant/components/zha/manifest.json +++ b/homeassistant/components/zha/manifest.json @@ -21,7 +21,7 @@ "zha", "universal_silabs_flasher" ], - "requirements": ["zha==0.0.53"], + "requirements": ["zha==0.0.54"], "usb": [ { "vid": "10C4", diff --git a/requirements_all.txt b/requirements_all.txt index 267281885adef5..50aeacae6aaf65 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -3152,7 +3152,7 @@ zeroconf==0.146.0 zeversolar==0.3.2 # homeassistant.components.zha -zha==0.0.53 +zha==0.0.54 # homeassistant.components.zhong_hong zhong-hong-hvac==1.0.13 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 45c5353d6f07b4..8957e12bd2f70e 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -2542,7 +2542,7 @@ zeroconf==0.146.0 zeversolar==0.3.2 # homeassistant.components.zha -zha==0.0.53 +zha==0.0.54 # homeassistant.components.zwave_js zwave-js-server-python==0.62.0 From 59c65696495397ffe5e655fb7945ed06a749077d Mon Sep 17 00:00:00 2001 From: TheJulianJES Date: Wed, 26 Mar 2025 09:33:52 +0100 Subject: [PATCH 2/4] Add strings for v2 quirk entities --- homeassistant/components/zha/strings.json | 33 +++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/homeassistant/components/zha/strings.json b/homeassistant/components/zha/strings.json index 23bb9ae051e542..a35dd50df54c8b 100644 --- a/homeassistant/components/zha/strings.json +++ b/homeassistant/components/zha/strings.json @@ -610,6 +610,12 @@ }, "flow_switch": { "name": "Flow switch" + }, + "water_leak": { + "name": "Water leak" + }, + "water_supply": { + "name": "Water supply" } }, "button": { @@ -1101,6 +1107,27 @@ }, "shutdown_timer": { "name": "Shutdown timer" + }, + "calibration_vertical_run_time_up": { + "name": "Calibration vertical run time up" + }, + "calibration_vertical_run_time_down": { + "name": "Calibration vertical run time down" + }, + "calibration_rotation_run_time_up": { + "name": "Calibration rotation run time up" + }, + "calibration_rotation_run_time_down": { + "name": "Calibration rotation run time down" + }, + "impulse_mode_duration": { + "name": "Impulse mode duration" + }, + "water_duration": { + "name": "Water duration" + }, + "water_interval": { + "name": "Water interval" } }, "select": { @@ -1319,6 +1346,9 @@ }, "hysteresis_mode": { "name": "Hysteresis mode" + }, + "speed": { + "name": "Speed" } }, "sensor": { @@ -1666,6 +1696,9 @@ }, "last_watering_duration": { "name": "Last watering duration" + }, + "device_status": { + "name": "Device status" } }, "switch": { From 1a65293ad688dbc7fcbf709d805106ac0b570192 Mon Sep 17 00:00:00 2001 From: TheJulianJES Date: Wed, 26 Mar 2025 09:34:22 +0100 Subject: [PATCH 3/4] Adjust cover tests for new ZHA behavior --- tests/components/zha/test_cover.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/tests/components/zha/test_cover.py b/tests/components/zha/test_cover.py index e5d588aa1bf5c6..2afe208f443c0d 100644 --- a/tests/components/zha/test_cover.py +++ b/tests/components/zha/test_cover.py @@ -117,10 +117,16 @@ async def test_cover(hass: HomeAssistant, setup_zha, zigpy_device_mock) -> None: assert state.attributes[ATTR_CURRENT_POSITION] == 100 assert state.attributes[ATTR_CURRENT_TILT_POSITION] == 58 - # test that the state has changed from unavailable to off + # test that the state has changed from unavailable to open (lift closed, tilt open) await send_attributes_report( hass, cluster, {WCAttrs.current_position_lift_percentage.id: 100} ) + assert hass.states.get(entity_id).state == CoverState.OPEN + + # now also close the tilt + await send_attributes_report( + hass, cluster, {WCAttrs.current_position_tilt_percentage.id: 100} + ) assert hass.states.get(entity_id).state == CoverState.CLOSED # test to see if it opens @@ -154,11 +160,11 @@ async def test_cover(hass: HomeAssistant, setup_zha, zigpy_device_mock) -> None: assert hass.states.get(entity_id).state == CoverState.CLOSING + # close lift only, tilt still open await send_attributes_report( hass, cluster, {WCAttrs.current_position_lift_percentage.id: 100} ) - - assert hass.states.get(entity_id).state == CoverState.CLOSED + assert hass.states.get(entity_id).state == CoverState.OPEN with patch("zigpy.zcl.Cluster.request", return_value=[0x1, zcl_f.Status.SUCCESS]): await hass.services.async_call( @@ -179,6 +185,7 @@ async def test_cover(hass: HomeAssistant, setup_zha, zigpy_device_mock) -> None: assert hass.states.get(entity_id).state == CoverState.CLOSING + # now also close tilt await send_attributes_report( hass, cluster, {WCAttrs.current_position_tilt_percentage.id: 100} ) @@ -281,13 +288,13 @@ async def test_cover(hass: HomeAssistant, setup_zha, zigpy_device_mock) -> None: assert hass.states.get(entity_id).state == CoverState.CLOSING await send_attributes_report( - hass, cluster, {WCAttrs.current_position_lift_percentage.id: 35} + hass, cluster, {WCAttrs.current_position_tilt_percentage.id: 35} ) assert hass.states.get(entity_id).state == CoverState.CLOSING await send_attributes_report( - hass, cluster, {WCAttrs.current_position_lift_percentage.id: 53} + hass, cluster, {WCAttrs.current_position_tilt_percentage.id: 53} ) assert hass.states.get(entity_id).state == CoverState.OPEN @@ -351,8 +358,8 @@ async def test_cover_failures( entity_id = find_entity_id(Platform.COVER, zha_device_proxy, hass) assert entity_id is not None - # test that the state has changed from unavailable to closed - await send_attributes_report(hass, cluster, {0: 0, 8: 100, 1: 1}) + # test that the state has changed from unavailable to closed (lift and tilt closed) + await send_attributes_report(hass, cluster, {0: 0, 8: 100, 9: 100, 1: 1}) assert hass.states.get(entity_id).state == CoverState.CLOSED # test to see if it opens From c13631f273d15fbf2c439f7b316f4452fac3e91d Mon Sep 17 00:00:00 2001 From: TheJulianJES Date: Wed, 26 Mar 2025 09:45:17 +0100 Subject: [PATCH 4/4] Improve cover tests further --- tests/components/zha/test_cover.py | 48 +++++++++++++++--------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/tests/components/zha/test_cover.py b/tests/components/zha/test_cover.py index 2afe208f443c0d..4bc4d6c97cf227 100644 --- a/tests/components/zha/test_cover.py +++ b/tests/components/zha/test_cover.py @@ -81,7 +81,7 @@ async def test_cover(hass: HomeAssistant, setup_zha, zigpy_device_mock) -> None: cluster = zigpy_device.endpoints[1].window_covering cluster.PLUGGED_ATTR_READS = { WCAttrs.current_position_lift_percentage.name: 0, - WCAttrs.current_position_tilt_percentage.name: 42, + WCAttrs.current_position_tilt_percentage.name: 100, WCAttrs.window_covering_type.name: WCT.Tilt_blind_tilt_and_lift, WCAttrs.config_status.name: WCCS(~WCCS.Open_up_commands_reversed), } @@ -115,39 +115,33 @@ async def test_cover(hass: HomeAssistant, setup_zha, zigpy_device_mock) -> None: assert state assert state.state == CoverState.OPEN assert state.attributes[ATTR_CURRENT_POSITION] == 100 - assert state.attributes[ATTR_CURRENT_TILT_POSITION] == 58 + assert state.attributes[ATTR_CURRENT_TILT_POSITION] == 0 - # test that the state has changed from unavailable to open (lift closed, tilt open) + # test that the state has changed from open to closed await send_attributes_report( hass, cluster, {WCAttrs.current_position_lift_percentage.id: 100} ) - assert hass.states.get(entity_id).state == CoverState.OPEN - - # now also close the tilt - await send_attributes_report( - hass, cluster, {WCAttrs.current_position_tilt_percentage.id: 100} - ) assert hass.states.get(entity_id).state == CoverState.CLOSED - # test to see if it opens + # test that it opens await send_attributes_report( hass, cluster, {WCAttrs.current_position_lift_percentage.id: 0} ) assert hass.states.get(entity_id).state == CoverState.OPEN - # test that the state remains after tilting to 100% + # test that the state remains after tilting to 0% (open) await send_attributes_report( - hass, cluster, {WCAttrs.current_position_tilt_percentage.id: 100} + hass, cluster, {WCAttrs.current_position_tilt_percentage.id: 0} ) assert hass.states.get(entity_id).state == CoverState.OPEN - # test to see the state remains after tilting to 0% + # test that the state remains after tilting to 100% (closed) await send_attributes_report( - hass, cluster, {WCAttrs.current_position_tilt_percentage.id: 0} + hass, cluster, {WCAttrs.current_position_tilt_percentage.id: 100} ) assert hass.states.get(entity_id).state == CoverState.OPEN - # close from UI + # close lift from UI with patch("zigpy.zcl.Cluster.request", return_value=[0x1, zcl_f.Status.SUCCESS]): await hass.services.async_call( COVER_DOMAIN, SERVICE_CLOSE_COVER, {"entity_id": entity_id}, blocking=True @@ -160,12 +154,17 @@ async def test_cover(hass: HomeAssistant, setup_zha, zigpy_device_mock) -> None: assert hass.states.get(entity_id).state == CoverState.CLOSING - # close lift only, tilt still open await send_attributes_report( hass, cluster, {WCAttrs.current_position_lift_percentage.id: 100} ) - assert hass.states.get(entity_id).state == CoverState.OPEN + assert hass.states.get(entity_id).state == CoverState.CLOSED + + # close tilt from UI, needs re-opening first + await send_attributes_report( + hass, cluster, {WCAttrs.current_position_tilt_percentage.id: 0} + ) + assert hass.states.get(entity_id).state == CoverState.OPEN with patch("zigpy.zcl.Cluster.request", return_value=[0x1, zcl_f.Status.SUCCESS]): await hass.services.async_call( COVER_DOMAIN, @@ -185,14 +184,13 @@ async def test_cover(hass: HomeAssistant, setup_zha, zigpy_device_mock) -> None: assert hass.states.get(entity_id).state == CoverState.CLOSING - # now also close tilt await send_attributes_report( hass, cluster, {WCAttrs.current_position_tilt_percentage.id: 100} ) assert hass.states.get(entity_id).state == CoverState.CLOSED - # open from UI + # open lift from UI with patch("zigpy.zcl.Cluster.request", return_value=[0x0, zcl_f.Status.SUCCESS]): await hass.services.async_call( COVER_DOMAIN, SERVICE_OPEN_COVER, {"entity_id": entity_id}, blocking=True @@ -211,6 +209,7 @@ async def test_cover(hass: HomeAssistant, setup_zha, zigpy_device_mock) -> None: assert hass.states.get(entity_id).state == CoverState.OPEN + # open tilt from UI with patch("zigpy.zcl.Cluster.request", return_value=[0x0, zcl_f.Status.SUCCESS]): await hass.services.async_call( COVER_DOMAIN, @@ -236,7 +235,7 @@ async def test_cover(hass: HomeAssistant, setup_zha, zigpy_device_mock) -> None: assert hass.states.get(entity_id).state == CoverState.OPEN - # set position UI + # set lift position from UI with patch("zigpy.zcl.Cluster.request", return_value=[0x5, zcl_f.Status.SUCCESS]): await hass.services.async_call( COVER_DOMAIN, @@ -268,6 +267,7 @@ async def test_cover(hass: HomeAssistant, setup_zha, zigpy_device_mock) -> None: assert hass.states.get(entity_id).state == CoverState.OPEN + # set tilt position from UI with patch("zigpy.zcl.Cluster.request", return_value=[0x5, zcl_f.Status.SUCCESS]): await hass.services.async_call( COVER_DOMAIN, @@ -345,7 +345,7 @@ async def test_cover_failures( # load up cover domain cluster = zigpy_device.endpoints[1].window_covering cluster.PLUGGED_ATTR_READS = { - WCAttrs.current_position_tilt_percentage.name: 42, + WCAttrs.current_position_tilt_percentage.name: 100, WCAttrs.window_covering_type.name: WCT.Tilt_blind_tilt_and_lift, } update_attribute_cache(cluster) @@ -358,11 +358,11 @@ async def test_cover_failures( entity_id = find_entity_id(Platform.COVER, zha_device_proxy, hass) assert entity_id is not None - # test that the state has changed from unavailable to closed (lift and tilt closed) - await send_attributes_report(hass, cluster, {0: 0, 8: 100, 9: 100, 1: 1}) + # test that the state has changed from unavailable to closed + await send_attributes_report(hass, cluster, {0: 0, 8: 100, 1: 1}) assert hass.states.get(entity_id).state == CoverState.CLOSED - # test to see if it opens + # test that it opens await send_attributes_report(hass, cluster, {0: 1, 8: 0, 1: 100}) assert hass.states.get(entity_id).state == CoverState.OPEN