Skip to content

Commit

Permalink
Add service to 'favorite' an event (#296)
Browse files Browse the repository at this point in the history
* Add service description

* Add client to camera and call service

* Adjust naming

* Add test and cleanup

* Trying to get tests passing

* Trying to get tests passing

* Update the service to accept boolean

* Use new service

* Fix tests.

* Minor fixes.

* Adjust logic

* Remove fixture

* Remove fixture

Co-authored-by: Dermot Duffy <dermot.duffy@gmail.com>
  • Loading branch information
NickM-27 and dermotduffy authored Jul 2, 2022
1 parent e41ac50 commit 4517529
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 3 deletions.
26 changes: 25 additions & 1 deletion custom_components/frigate/camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@
import aiohttp
import async_timeout
from jinja2 import Template
import voluptuous as vol
from yarl import URL

from custom_components.frigate.api import FrigateApiClient
from homeassistant.components.camera import Camera, CameraEntityFeature
from homeassistant.components.mqtt import async_publish
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_URL
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import entity_platform
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
Expand All @@ -28,10 +31,14 @@
get_frigate_entity_unique_id,
)
from .const import (
ATTR_CLIENT,
ATTR_CONFIG,
ATTR_EVENT_ID,
ATTR_FAVORITE,
CONF_RTMP_URL_TEMPLATE,
DOMAIN,
NAME,
SERVICE_FAVORITE_EVENT,
STATE_DETECTED,
STATE_IDLE,
)
Expand All @@ -45,10 +52,13 @@ async def async_setup_entry(
"""Camera entry setup."""

frigate_config = hass.data[DOMAIN][entry.entry_id][ATTR_CONFIG]
frigate_client = hass.data[DOMAIN][entry.entry_id][ATTR_CLIENT]

async_add_entities(
[
FrigateCamera(entry, cam_name, frigate_config, camera_config)
FrigateCamera(
entry, cam_name, frigate_client, frigate_config, camera_config
)
for cam_name, camera_config in frigate_config["cameras"].items()
]
+ [
Expand All @@ -57,6 +67,14 @@ async def async_setup_entry(
]
)

# setup services
platform = entity_platform.async_get_current_platform()
platform.async_register_entity_service(
SERVICE_FAVORITE_EVENT,
{vol.Required(ATTR_EVENT_ID): str, vol.Required(ATTR_FAVORITE): bool},
SERVICE_FAVORITE_EVENT,
)


class FrigateCamera(FrigateMQTTEntity, Camera): # type: ignore[misc]
"""Representation a Frigate camera."""
Expand All @@ -65,10 +83,12 @@ def __init__(
self,
config_entry: ConfigEntry,
cam_name: str,
frigate_client: FrigateApiClient,
frigate_config: dict[str, Any],
camera_config: dict[str, Any],
) -> None:
"""Initialize a Frigate camera."""
self._client = frigate_client
self._frigate_config = frigate_config
self._camera_config = camera_config
self._cam_name = cam_name
Expand Down Expand Up @@ -214,6 +234,10 @@ async def async_disable_motion_detection(self) -> None:
False,
)

async def favorite_event(self, event_id: str, favorite: bool) -> None:
"""Favorite an event."""
await self._client.async_retain(event_id, favorite)


class FrigateMqttSnapshots(FrigateMQTTEntity, Camera): # type: ignore[misc]
"""Frigate best camera class."""
Expand Down
7 changes: 6 additions & 1 deletion custom_components/frigate/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@

# Attributes
ATTR_CLIENT = "client"
ATTR_CLIENT_ID = "client_id"
ATTR_CONFIG = "config"
ATTR_COORDINATOR = "coordinator"
ATTR_EVENT_ID = "event_id"
ATTR_FAVORITE = "favorite"
ATTR_MQTT = "mqtt"
ATTR_CLIENT_ID = "client_id"

# Configuration and options
CONF_CAMERA_STATIC_IMAGE_HEIGHT = "camera_image_height"
Expand Down Expand Up @@ -69,3 +71,6 @@
STATUS_ERROR = "error"
STATUS_RUNNING = "running"
STATUS_STARTING = "starting"

# Frigate Services
SERVICE_FAVORITE_EVENT = "favorite_event"
20 changes: 20 additions & 0 deletions custom_components/frigate/services.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
favorite_event:
name: Favorite Event
description: Favorites or unfavorites an event indefinitely.
target:
fields:
event_id:
name: Event ID
description: ID of the event to retain.
required: true
advanced: false
example: "1656510950.19548-ihtjj7"
default: ""
favorite:
name: Favorite
description: If the event should be favorited / unfavorited.
required: true
advanced: false
example: true
default: true
45 changes: 44 additions & 1 deletion tests/test_camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,14 @@
import pytest
from pytest_homeassistant_custom_component.common import async_fire_mqtt_message

from custom_components.frigate.const import CONF_RTMP_URL_TEMPLATE, DOMAIN, NAME
from custom_components.frigate.const import (
ATTR_EVENT_ID,
ATTR_FAVORITE,
CONF_RTMP_URL_TEMPLATE,
DOMAIN,
NAME,
SERVICE_FAVORITE_EVENT,
)
from homeassistant.components.camera import (
DOMAIN as CAMERA_DOMAIN,
SERVICE_DISABLE_MOTION,
Expand Down Expand Up @@ -302,3 +309,39 @@ async def test_cameras_setup_correctly_in_registry(
TEST_CAMERA_FRONT_DOOR_PERSON_ENTITY_ID,
},
)


async def test_retain_service_call(
hass: HomeAssistant,
) -> None:
"""Test retain service call."""
post_success = {"success": True, "message": "Post success"}

client = create_mock_frigate_client()
client.async_retain = AsyncMock(return_value=post_success)
await setup_mock_frigate_config_entry(hass, client=client)

event_id = "1656282822.206673-bovnfg"
await hass.services.async_call(
DOMAIN,
SERVICE_FAVORITE_EVENT,
{
ATTR_ENTITY_ID: TEST_CAMERA_FRONT_DOOR_ENTITY_ID,
ATTR_EVENT_ID: event_id,
ATTR_FAVORITE: True,
},
blocking=True,
)
client.async_retain.assert_called_with(event_id, True)

await hass.services.async_call(
DOMAIN,
SERVICE_FAVORITE_EVENT,
{
ATTR_ENTITY_ID: TEST_CAMERA_FRONT_DOOR_ENTITY_ID,
ATTR_EVENT_ID: event_id,
ATTR_FAVORITE: False,
},
blocking=True,
)
client.async_retain.assert_called_with(event_id, False)

0 comments on commit 4517529

Please sign in to comment.