diff --git a/homeassistant/components/netatmo/camera.py b/homeassistant/components/netatmo/camera.py index 4d6141e2dfb..2666409f28e 100644 --- a/homeassistant/components/netatmo/camera.py +++ b/homeassistant/components/netatmo/camera.py @@ -11,7 +11,7 @@ import voluptuous as vol from homeassistant.components.camera import SUPPORT_STREAM, Camera from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant, callback -from homeassistant.exceptions import PlatformNotReady +from homeassistant.exceptions import HomeAssistantError, PlatformNotReady from homeassistant.helpers import config_validation as cv, entity_platform from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.entity_platform import AddEntitiesCallback @@ -83,10 +83,16 @@ async def async_setup_entry( for camera in all_cameras ] - for person_id, person_data in data_handler.data[ - CAMERA_DATA_CLASS_NAME - ].persons.items(): - hass.data[DOMAIN][DATA_PERSONS][person_id] = person_data.get(ATTR_PSEUDO) + for home in data_class.homes.values(): + if home.get("id") is None: + continue + + hass.data[DOMAIN][DATA_PERSONS][home["id"]] = { + person_id: person_data.get(ATTR_PSEUDO) + for person_id, person_data in data_handler.data[CAMERA_DATA_CLASS_NAME] + .persons[home["id"]] + .items() + } _LOGGER.debug("Adding cameras %s", entities) async_add_entities(entities, True) @@ -309,14 +315,31 @@ class NetatmoCamera(NetatmoBase, Camera): ] = f"{self._vpnurl}/vod/{event['video_id']}/files/{self._quality}/index.m3u8" return events - async def _service_set_persons_home(self, **kwargs: Any) -> None: - """Service to change current home schedule.""" - persons = kwargs.get(ATTR_PERSONS, {}) + def fetch_person_ids(self, persons: list[str | None]) -> list[str]: + """Fetch matching person ids for give list of persons.""" person_ids = [] + person_id_errors = [] + for person in persons: - for pid, data in self._data.persons.items(): + person_id = None + for pid, data in self._data.persons[self._home_id].items(): if data.get("pseudo") == person: person_ids.append(pid) + person_id = pid + break + + if person_id is None: + person_id_errors.append(person) + + if person_id_errors: + raise HomeAssistantError(f"Person(s) not registered {person_id_errors}") + + return person_ids + + async def _service_set_persons_home(self, **kwargs: Any) -> None: + """Service to change current home schedule.""" + persons = kwargs.get(ATTR_PERSONS, []) + person_ids = self.fetch_person_ids(persons) await self._data.async_set_persons_home( person_ids=person_ids, home_id=self._home_id @@ -326,24 +349,17 @@ class NetatmoCamera(NetatmoBase, Camera): async def _service_set_person_away(self, **kwargs: Any) -> None: """Service to mark a person as away or set the home as empty.""" person = kwargs.get(ATTR_PERSON) - person_id = None - if person: - for pid, data in self._data.persons.items(): - if data.get("pseudo") == person: - person_id = pid + person_ids = self.fetch_person_ids([person] if person else []) + person_id = next(iter(person_ids), None) + + await self._data.async_set_persons_away( + person_id=person_id, + home_id=self._home_id, + ) if person_id: - await self._data.async_set_persons_away( - person_id=person_id, - home_id=self._home_id, - ) - _LOGGER.debug("Set %s as away", person) - + _LOGGER.debug("Set %s as away %s", person, person_id) else: - await self._data.async_set_persons_away( - person_id=person_id, - home_id=self._home_id, - ) _LOGGER.debug("Set home as empty") async def _service_set_camera_light(self, **kwargs: Any) -> None: diff --git a/homeassistant/components/netatmo/manifest.json b/homeassistant/components/netatmo/manifest.json index 6c99f3c0786..f51f1a22f48 100644 --- a/homeassistant/components/netatmo/manifest.json +++ b/homeassistant/components/netatmo/manifest.json @@ -3,7 +3,7 @@ "name": "Netatmo", "documentation": "https://www.home-assistant.io/integrations/netatmo", "requirements": [ - "pyatmo==5.2.3" + "pyatmo==6.0.0" ], "after_dependencies": [ "cloud", diff --git a/homeassistant/components/netatmo/webhook.py b/homeassistant/components/netatmo/webhook.py index 4f39d5fe5f5..9761c8298c7 100644 --- a/homeassistant/components/netatmo/webhook.py +++ b/homeassistant/components/netatmo/webhook.py @@ -10,6 +10,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_send from .const import ( ATTR_EVENT_TYPE, ATTR_FACE_URL, + ATTR_HOME_ID, ATTR_IS_KNOWN, ATTR_PERSONS, DATA_DEVICE_IDS, @@ -60,9 +61,9 @@ def async_evaluate_event(hass: HomeAssistant, event_data: dict) -> None: for person in event_data.get(ATTR_PERSONS, {}): person_event_data = dict(event_data) person_event_data[ATTR_ID] = person.get(ATTR_ID) - person_event_data[ATTR_NAME] = hass.data[DOMAIN][DATA_PERSONS].get( - person_event_data[ATTR_ID], DEFAULT_PERSON - ) + person_event_data[ATTR_NAME] = hass.data[DOMAIN][DATA_PERSONS][ + event_data[ATTR_HOME_ID] + ].get(person_event_data[ATTR_ID], DEFAULT_PERSON) person_event_data[ATTR_IS_KNOWN] = person.get(ATTR_IS_KNOWN) person_event_data[ATTR_FACE_URL] = person.get(ATTR_FACE_URL) diff --git a/requirements_all.txt b/requirements_all.txt index 5b16bd0f064..8b14f2dc932 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1355,7 +1355,7 @@ pyarlo==0.2.4 pyatag==0.3.5.3 # homeassistant.components.netatmo -pyatmo==5.2.3 +pyatmo==6.0.0 # homeassistant.components.atome pyatome==0.1.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index f9428de92d3..44ac5935a13 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -791,7 +791,7 @@ pyarlo==0.2.4 pyatag==0.3.5.3 # homeassistant.components.netatmo -pyatmo==5.2.3 +pyatmo==6.0.0 # homeassistant.components.apple_tv pyatv==0.8.2 diff --git a/tests/components/netatmo/test_camera.py b/tests/components/netatmo/test_camera.py index 4825946beab..c8132331bf3 100644 --- a/tests/components/netatmo/test_camera.py +++ b/tests/components/netatmo/test_camera.py @@ -14,6 +14,7 @@ from homeassistant.components.netatmo.const import ( SERVICE_SET_PERSONS_HOME, ) from homeassistant.const import CONF_WEBHOOK_ID +from homeassistant.exceptions import HomeAssistantError from homeassistant.util import dt from .common import fake_post_request, selected_platforms, simulate_webhook @@ -220,6 +221,60 @@ async def test_service_set_person_away(hass, config_entry, netatmo_auth): ) +async def test_service_set_person_away_invalid_person(hass, config_entry, netatmo_auth): + """Test service to set invalid person as away.""" + with selected_platforms(["camera"]): + await hass.config_entries.async_setup(config_entry.entry_id) + + await hass.async_block_till_done() + + await hass.async_block_till_done() + + data = { + "entity_id": "camera.netatmo_hall", + "person": "Batman", + } + + with pytest.raises(HomeAssistantError) as excinfo: + await hass.services.async_call( + "netatmo", + SERVICE_SET_PERSON_AWAY, + service_data=data, + blocking=True, + ) + await hass.async_block_till_done() + + assert excinfo.value.args == ("Person(s) not registered ['Batman']",) + + +async def test_service_set_persons_home_invalid_person( + hass, config_entry, netatmo_auth +): + """Test service to set invalid persons as home.""" + with selected_platforms(["camera"]): + await hass.config_entries.async_setup(config_entry.entry_id) + + await hass.async_block_till_done() + + await hass.async_block_till_done() + + data = { + "entity_id": "camera.netatmo_hall", + "persons": "Batman", + } + + with pytest.raises(HomeAssistantError) as excinfo: + await hass.services.async_call( + "netatmo", + SERVICE_SET_PERSONS_HOME, + service_data=data, + blocking=True, + ) + await hass.async_block_till_done() + + assert excinfo.value.args == ("Person(s) not registered ['Batman']",) + + async def test_service_set_persons_home(hass, config_entry, netatmo_auth): """Test service to set persons as home.""" with selected_platforms(["camera"]):