diff --git a/custom_components/goecharger_api2/number.py b/custom_components/goecharger_api2/number.py index 211981e..a6507ba 100644 --- a/custom_components/goecharger_api2/number.py +++ b/custom_components/goecharger_api2/number.py @@ -10,6 +10,7 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.const import Platform, ATTR_ENTITY_ID from homeassistant.core import HomeAssistant +from homeassistant.exceptions import ServiceValidationError from homeassistant.helpers.entity_platform import AddEntitiesCallback from custom_components.goecharger_api2.pygoecharger_ha import INTG_TYPE @@ -152,10 +153,12 @@ async def async_set_native_value(self, value) -> None: result = await self.coordinator.async_write_key(self.data_key, final_object_to_write, self, require_ack=validate_write_success) # must we verify that the setting of the value was successful? - if validate_write_success and result: + if validate_write_success: self.tag.tag_func_validate_output(result, value) - except ValueError: + except ValueError as exc: + if validate_write_success: + raise ServiceValidationError(str(exc)) from exc return "unavailable" def check_amp_min_max(self, value): diff --git a/tests/integration/test_platform_values.py b/tests/integration/test_platform_values.py index 2ab2e64..ab567b5 100644 --- a/tests/integration/test_platform_values.py +++ b/tests/integration/test_platform_values.py @@ -196,6 +196,44 @@ async def test_number_set_value_swallows_write_errors(hass): assert await number.async_set_native_value(10) == "unavailable" +@pytest.mark.parametrize("reply", [{}, {"err": "rejected"}, {"tcl": True}, {"tcl": 8}, None]) +async def test_confirmed_number_rejects_missing_or_invalid_acknowledgement(hass, reply): + from unittest.mock import AsyncMock + from homeassistant.exceptions import ServiceValidationError + from custom_components.goecharger_api2.pygoecharger_ha.keys import Tag + + number, coordinator = _number(hass, {"tcl": 9, "var": 22, "ama": 32, "mca": 6}, key="tcl", tag=Tag.TCL) + coordinator.async_write_key = AsyncMock(return_value=reply) + with pytest.raises(ServiceValidationError): + await number.async_set_native_value(9) + coordinator.async_write_key.assert_awaited_once_with("tcl", 9, number, require_ack=True) + + +async def test_confirmed_number_propagates_write_failure(hass): + from unittest.mock import AsyncMock + from homeassistant.exceptions import ServiceValidationError + from custom_components.goecharger_api2.pygoecharger_ha.keys import Tag + + number, coordinator = _number(hass, {"tcl": 9, "var": 22, "ama": 32, "mca": 6}, key="tcl", tag=Tag.TCL) + coordinator.async_write_key = AsyncMock(side_effect=ValueError("disconnected")) + with pytest.raises(ServiceValidationError, match="disconnected"): + await number.async_set_native_value(9) + + +async def test_confirmed_number_renews_identical_limit_without_changing_user_settings(hass): + from unittest.mock import AsyncMock + from custom_components.goecharger_api2.pygoecharger_ha.keys import Tag + + data = {"tcl": 9, "var": 22, "ama": 32, "mca": 6, "amp": 12} + number, coordinator = _number(hass, data, key="tcl", tag=Tag.TCL) + coordinator.async_write_key = AsyncMock(return_value={"tcl": 9}) + for _ in range(2): + await number.async_set_native_value(9) + assert coordinator.async_write_key.await_count == 2 + assert all(call.kwargs == {"require_ack": True} for call in coordinator.async_write_key.await_args_list) + assert data["amp"] == 12 and data["ama"] == 32 + + # ----------------------------------------------------------------------------- number: limits of amp def _amp(value):