Split Netatmo camera persons by home (#55598)

* Split persons by home
* Bump pyatmo to 6.0.0
* Check is person exists
* Extract method for fetching person ids
This commit is contained in:
Tobias Sauerwein 2021-09-22 14:32:30 +02:00 committed by GitHub
parent aab4b5ec06
commit 26d310fc8a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 102 additions and 30 deletions

View file

@ -11,7 +11,7 @@ import voluptuous as vol
from homeassistant.components.camera import SUPPORT_STREAM, Camera from homeassistant.components.camera import SUPPORT_STREAM, Camera
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback 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 import config_validation as cv, entity_platform
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
@ -83,10 +83,16 @@ async def async_setup_entry(
for camera in all_cameras for camera in all_cameras
] ]
for person_id, person_data in data_handler.data[ for home in data_class.homes.values():
CAMERA_DATA_CLASS_NAME if home.get("id") is None:
].persons.items(): continue
hass.data[DOMAIN][DATA_PERSONS][person_id] = person_data.get(ATTR_PSEUDO)
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) _LOGGER.debug("Adding cameras %s", entities)
async_add_entities(entities, True) 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" ] = f"{self._vpnurl}/vod/{event['video_id']}/files/{self._quality}/index.m3u8"
return events return events
async def _service_set_persons_home(self, **kwargs: Any) -> None: def fetch_person_ids(self, persons: list[str | None]) -> list[str]:
"""Service to change current home schedule.""" """Fetch matching person ids for give list of persons."""
persons = kwargs.get(ATTR_PERSONS, {})
person_ids = [] person_ids = []
person_id_errors = []
for person in persons: 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: if data.get("pseudo") == person:
person_ids.append(pid) 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( await self._data.async_set_persons_home(
person_ids=person_ids, home_id=self._home_id 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: async def _service_set_person_away(self, **kwargs: Any) -> None:
"""Service to mark a person as away or set the home as empty.""" """Service to mark a person as away or set the home as empty."""
person = kwargs.get(ATTR_PERSON) person = kwargs.get(ATTR_PERSON)
person_id = None person_ids = self.fetch_person_ids([person] if person else [])
if person: person_id = next(iter(person_ids), None)
for pid, data in self._data.persons.items():
if data.get("pseudo") == person: await self._data.async_set_persons_away(
person_id = pid person_id=person_id,
home_id=self._home_id,
)
if person_id: if person_id:
await self._data.async_set_persons_away( _LOGGER.debug("Set %s as away %s", person, person_id)
person_id=person_id,
home_id=self._home_id,
)
_LOGGER.debug("Set %s as away", person)
else: else:
await self._data.async_set_persons_away(
person_id=person_id,
home_id=self._home_id,
)
_LOGGER.debug("Set home as empty") _LOGGER.debug("Set home as empty")
async def _service_set_camera_light(self, **kwargs: Any) -> None: async def _service_set_camera_light(self, **kwargs: Any) -> None:

View file

@ -3,7 +3,7 @@
"name": "Netatmo", "name": "Netatmo",
"documentation": "https://www.home-assistant.io/integrations/netatmo", "documentation": "https://www.home-assistant.io/integrations/netatmo",
"requirements": [ "requirements": [
"pyatmo==5.2.3" "pyatmo==6.0.0"
], ],
"after_dependencies": [ "after_dependencies": [
"cloud", "cloud",

View file

@ -10,6 +10,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_send
from .const import ( from .const import (
ATTR_EVENT_TYPE, ATTR_EVENT_TYPE,
ATTR_FACE_URL, ATTR_FACE_URL,
ATTR_HOME_ID,
ATTR_IS_KNOWN, ATTR_IS_KNOWN,
ATTR_PERSONS, ATTR_PERSONS,
DATA_DEVICE_IDS, 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, {}): for person in event_data.get(ATTR_PERSONS, {}):
person_event_data = dict(event_data) person_event_data = dict(event_data)
person_event_data[ATTR_ID] = person.get(ATTR_ID) person_event_data[ATTR_ID] = person.get(ATTR_ID)
person_event_data[ATTR_NAME] = hass.data[DOMAIN][DATA_PERSONS].get( person_event_data[ATTR_NAME] = hass.data[DOMAIN][DATA_PERSONS][
person_event_data[ATTR_ID], DEFAULT_PERSON 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_IS_KNOWN] = person.get(ATTR_IS_KNOWN)
person_event_data[ATTR_FACE_URL] = person.get(ATTR_FACE_URL) person_event_data[ATTR_FACE_URL] = person.get(ATTR_FACE_URL)

View file

@ -1355,7 +1355,7 @@ pyarlo==0.2.4
pyatag==0.3.5.3 pyatag==0.3.5.3
# homeassistant.components.netatmo # homeassistant.components.netatmo
pyatmo==5.2.3 pyatmo==6.0.0
# homeassistant.components.atome # homeassistant.components.atome
pyatome==0.1.1 pyatome==0.1.1

View file

@ -791,7 +791,7 @@ pyarlo==0.2.4
pyatag==0.3.5.3 pyatag==0.3.5.3
# homeassistant.components.netatmo # homeassistant.components.netatmo
pyatmo==5.2.3 pyatmo==6.0.0
# homeassistant.components.apple_tv # homeassistant.components.apple_tv
pyatv==0.8.2 pyatv==0.8.2

View file

@ -14,6 +14,7 @@ from homeassistant.components.netatmo.const import (
SERVICE_SET_PERSONS_HOME, SERVICE_SET_PERSONS_HOME,
) )
from homeassistant.const import CONF_WEBHOOK_ID from homeassistant.const import CONF_WEBHOOK_ID
from homeassistant.exceptions import HomeAssistantError
from homeassistant.util import dt from homeassistant.util import dt
from .common import fake_post_request, selected_platforms, simulate_webhook 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): async def test_service_set_persons_home(hass, config_entry, netatmo_auth):
"""Test service to set persons as home.""" """Test service to set persons as home."""
with selected_platforms(["camera"]): with selected_platforms(["camera"]):