diff --git a/homeassistant/components/lcn/services.py b/homeassistant/components/lcn/services.py index fd5b29fb1928..ced2ed7023fc 100644 --- a/homeassistant/components/lcn/services.py +++ b/homeassistant/components/lcn/services.py @@ -21,7 +21,8 @@ from homeassistant.core import ( callback, ) from homeassistant.exceptions import ServiceValidationError -from homeassistant.helpers import config_validation as cv, device_registry as dr +from homeassistant.helpers import config_validation as cv +from homeassistant.helpers.service import async_get_device_and_config_entry from .const import ( CONF_KEYS, @@ -69,28 +70,11 @@ class LcnServiceCall: def get_device_connection(self, service: ServiceCall) -> DeviceConnection: """Get address connection object.""" - entries: list[LcnConfigEntry] = self.hass.config_entries.async_loaded_entries( - DOMAIN + entry: LcnConfigEntry + device, entry = async_get_device_and_config_entry( + self.hass, DOMAIN, service.data[CONF_DEVICE_ID] ) - device_id = service.data[CONF_DEVICE_ID] - device_registry = dr.async_get(self.hass) - if not (device := device_registry.async_get(device_id)) or not ( - entry := next( - ( - entry - for entry in entries - if entry.entry_id == device.primary_config_entry - ), - None, - ) - ): - raise ServiceValidationError( - translation_domain=DOMAIN, - translation_key="invalid_device_id", - translation_placeholders={"device_id": device_id}, - ) - - return entry.runtime_data.device_connections[device_id] + return entry.runtime_data.device_connections[device.id] async def async_call_service(self, service: ServiceCall) -> ServiceResponse: """Execute service call.""" diff --git a/homeassistant/components/lcn/strings.json b/homeassistant/components/lcn/strings.json index e02a2bd7e56b..548799b78de5 100644 --- a/homeassistant/components/lcn/strings.json +++ b/homeassistant/components/lcn/strings.json @@ -76,9 +76,6 @@ "cannot_connect": { "message": "Unable to connect to {config_entry_title}." }, - "invalid_device_id": { - "message": "LCN device for given device ID {device_id} has not been configured." - }, "invalid_domain": { "message": "Invalid domain {domain}." }, diff --git a/tests/components/lcn/test_services.py b/tests/components/lcn/test_services.py index 2987fd0064ed..ec29607c2891 100644 --- a/tests/components/lcn/test_services.py +++ b/tests/components/lcn/test_services.py @@ -29,7 +29,7 @@ from homeassistant.const import ( CONF_STATE, CONF_UNIT_OF_MEASUREMENT, ) -from homeassistant.core import HomeAssistant +from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant from homeassistant.exceptions import HomeAssistantError, ServiceValidationError from homeassistant.setup import async_setup_component @@ -505,3 +505,49 @@ async def test_service_pck( ) pck.assert_awaited_with("PIN4") + + +async def test_service_unknown_device_id( + hass: HomeAssistant, + entry: MockConfigEntry, +) -> None: + """Test service call with an unknown device id raises.""" + await async_setup_component(hass, "persistent_notification", {}) + await init_integration(hass, entry) + + with pytest.raises(ServiceValidationError) as exc_info: + await hass.services.async_call( + DOMAIN, + LcnService.PCK, + { + CONF_DEVICE_ID: "unknown_device_id", + CONF_PCK: "PIN4", + }, + blocking=True, + ) + assert exc_info.value.translation_domain == HOMEASSISTANT_DOMAIN + assert exc_info.value.translation_key == "service_device_not_found" + + +async def test_service_unloaded_config_entry( + hass: HomeAssistant, + entry: MockConfigEntry, +) -> None: + """Test service call to a device of an unloaded config entry raises.""" + await async_setup_component(hass, "persistent_notification", {}) + await init_integration(hass, entry) + device_id = get_device(hass, entry, (0, 7, False)).id + assert await hass.config_entries.async_unload(entry.entry_id) + + with pytest.raises(ServiceValidationError) as exc_info: + await hass.services.async_call( + DOMAIN, + LcnService.PCK, + { + CONF_DEVICE_ID: device_id, + CONF_PCK: "PIN4", + }, + blocking=True, + ) + assert exc_info.value.translation_domain == HOMEASSISTANT_DOMAIN + assert exc_info.value.translation_key == "service_config_entry_not_loaded"