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:
parent
aab4b5ec06
commit
26d310fc8a
6 changed files with 102 additions and 30 deletions
|
@ -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:
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"]):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue