From 19951d9403da55381d0002f924aaa254e77a6c37 Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Tue, 8 Jul 2025 06:07:41 +0200 Subject: [PATCH] Handle when heat pump rejects same value writes in nibe_heatpump (#148366) --- .../components/nibe_heatpump/button.py | 1 + .../components/nibe_heatpump/coordinator.py | 15 +++--- .../components/nibe_heatpump/strings.json | 3 -- .../nibe_heatpump/snapshots/test_number.ambr | 18 +++++++ tests/components/nibe_heatpump/test_number.py | 47 +++++++++++++++++-- 5 files changed, 67 insertions(+), 17 deletions(-) diff --git a/homeassistant/components/nibe_heatpump/button.py b/homeassistant/components/nibe_heatpump/button.py index 849912af656..8b6c8abf359 100644 --- a/homeassistant/components/nibe_heatpump/button.py +++ b/homeassistant/components/nibe_heatpump/button.py @@ -52,6 +52,7 @@ class NibeAlarmResetButton(CoordinatorEntity[CoilCoordinator], ButtonEntity): async def async_press(self) -> None: """Execute the command.""" + await self.coordinator.async_write_coil(self._reset_coil, 0) await self.coordinator.async_write_coil(self._reset_coil, 1) await self.coordinator.async_read_coil(self._alarm_coil) diff --git a/homeassistant/components/nibe_heatpump/coordinator.py b/homeassistant/components/nibe_heatpump/coordinator.py index 71f87698792..05e652d7f42 100644 --- a/homeassistant/components/nibe_heatpump/coordinator.py +++ b/homeassistant/components/nibe_heatpump/coordinator.py @@ -143,15 +143,12 @@ class CoilCoordinator(ContextCoordinator[dict[int, CoilData], int]): data = CoilData(coil, value) try: await self.connection.write_coil(data) - except WriteDeniedException as e: - raise HomeAssistantError( - translation_domain=DOMAIN, - translation_key="write_denied", - translation_placeholders={ - "address": str(coil.address), - "value": str(value), - }, - ) from e + except WriteDeniedException: + LOGGER.debug( + "Denied write on address %d with value %s. This is likely already the value the pump has internally", + coil.address, + value, + ) except WriteTimeoutException as e: raise HomeAssistantError( translation_domain=DOMAIN, diff --git a/homeassistant/components/nibe_heatpump/strings.json b/homeassistant/components/nibe_heatpump/strings.json index 3312bc2287f..1b339526586 100644 --- a/homeassistant/components/nibe_heatpump/strings.json +++ b/homeassistant/components/nibe_heatpump/strings.json @@ -47,9 +47,6 @@ } }, "exceptions": { - "write_denied": { - "message": "Writing of coil {address} with value `{value}` was denied" - }, "write_timeout": { "message": "Timeout while writing coil {address}" }, diff --git a/tests/components/nibe_heatpump/snapshots/test_number.ambr b/tests/components/nibe_heatpump/snapshots/test_number.ambr index 343d5569a2d..9c0dbaa83ca 100644 --- a/tests/components/nibe_heatpump/snapshots/test_number.ambr +++ b/tests/components/nibe_heatpump/snapshots/test_number.ambr @@ -1,4 +1,22 @@ # serializer version: 1 +# name: test_set_value_same + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'F1155 Room sensor setpoint S1', + 'max': 30.0, + 'min': 5.0, + 'mode': , + 'step': 0.1, + 'unit_of_measurement': '°C', + }), + 'context': , + 'entity_id': 'number.room_sensor_setpoint_s1_47398', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '25.0', + }) +# --- # name: test_update[Model.F1155-47011-number.heat_offset_s1_47011--10] StateSnapshot({ 'attributes': ReadOnlyDict({ diff --git a/tests/components/nibe_heatpump/test_number.py b/tests/components/nibe_heatpump/test_number.py index eeb9587f425..b789515e764 100644 --- a/tests/components/nibe_heatpump/test_number.py +++ b/tests/components/nibe_heatpump/test_number.py @@ -115,11 +115,6 @@ async def test_set_value( @pytest.mark.parametrize( ("exception", "translation_key", "translation_placeholders"), [ - ( - WriteDeniedException("denied"), - "write_denied", - {"address": "47398", "value": "25.0"}, - ), ( WriteTimeoutException("timeout writing"), "write_timeout", @@ -171,3 +166,45 @@ async def test_set_value_fail( assert exc_info.value.translation_domain == "nibe_heatpump" assert exc_info.value.translation_key == translation_key assert exc_info.value.translation_placeholders == translation_placeholders + + +@pytest.mark.usefixtures("entity_registry_enabled_by_default") +async def test_set_value_same( + hass: HomeAssistant, + mock_connection: AsyncMock, + coils: dict[int, Any], + snapshot: SnapshotAssertion, +) -> None: + """Test setting a value, which the pump will reject.""" + + value = 25 + model = Model.F1155 + address = 47398 + entity_id = "number.room_sensor_setpoint_s1_47398" + coils[address] = 0 + + await async_add_model(hass, model) + + await hass.async_block_till_done() + assert hass.states.get(entity_id) + + mock_connection.write_coil.side_effect = WriteDeniedException() + + # Write value + await hass.services.async_call( + PLATFORM_DOMAIN, + SERVICE_SET_VALUE, + {ATTR_ENTITY_ID: entity_id, ATTR_VALUE: value}, + blocking=True, + ) + + # Verify attempt was done + args = mock_connection.write_coil.call_args + assert args + coil = args.args[0] + assert isinstance(coil, CoilData) + assert coil.coil.address == address + assert coil.value == value + + # State should have been set + assert hass.states.get(entity_id) == snapshot