1 """Switch platform for Hyperion."""
3 from __future__
import annotations
8 from collections.abc
import AsyncGenerator
9 from contextlib
import asynccontextmanager
11 from typing
import Any
13 from aiohttp
import web
14 from hyperion
import client
15 from hyperion.const
import (
26 async_get_still_stream,
32 async_dispatcher_connect,
33 async_dispatcher_send,
38 get_hyperion_device_id,
39 get_hyperion_unique_id,
40 listen_for_instance_updates,
43 CONF_INSTANCE_CLIENTS,
45 HYPERION_MANUFACTURER_NAME,
51 IMAGE_STREAM_JPG_SENTINEL =
"data:image/jpg;base64,"
56 config_entry: ConfigEntry,
57 async_add_entities: AddEntitiesCallback,
59 """Set up a Hyperion platform from config entry."""
60 entry_data = hass.data[DOMAIN][config_entry.entry_id]
61 server_id = config_entry.unique_id
63 def camera_unique_id(instance_num: int) -> str:
64 """Return the camera unique_id."""
69 def instance_add(instance_num: int, instance_name: str) ->
None:
70 """Add entities for a new Hyperion instance."""
78 entry_data[CONF_INSTANCE_CLIENTS][instance_num],
84 def instance_remove(instance_num: int) ->
None:
85 """Remove entities for an old Hyperion instance."""
89 SIGNAL_ENTITY_REMOVE.format(
90 camera_unique_id(instance_num),
107 """ComponentBinarySwitch switch class."""
109 _attr_has_entity_name =
True
117 hyperion_client: client.HyperionClient,
119 """Initialize the switch."""
123 server_id, instance_num, TYPE_HYPERION_CAMERA
130 self.
_image_image: bytes |
None =
None
136 f
"{KEY_LEDCOLORS}-{KEY_IMAGE_STREAM}-{KEY_UPDATE}": self.
_update_imagestream_update_imagestream
139 identifiers={(DOMAIN, self.
_device_id_device_id)},
140 manufacturer=HYPERION_MANUFACTURER_NAME,
141 model=HYPERION_MODEL_NAME,
143 configuration_url=hyperion_client.remote_url,
148 """Return true if the camera is on."""
153 """Return server availability."""
157 """Update Hyperion components."""
160 img_data = img.get(KEY_RESULT, {}).
get(KEY_IMAGE)
161 if not img_data
or not img_data.startswith(IMAGE_STREAM_JPG_SENTINEL):
166 img_data.removeprefix(IMAGE_STREAM_JPG_SENTINEL)
168 except binascii.Error:
173 """Return a single camera image in a stream."""
179 """Start streaming for a client."""
182 and not await self.
_client_client.async_send_image_stream_start()
192 """Stop streaming for a client."""
196 await self.
_client_client.async_send_image_stream_stop()
202 """Async context manager to start/stop image streaming."""
209 self, width: int |
None =
None, height: int |
None =
None
211 """Return single camera image bytes."""
218 self, request: web.Request
219 ) -> web.StreamResponse |
None:
220 """Serve an HTTP MJPEG stream from the camera."""
226 DEFAULT_CONTENT_TYPE,
232 """Register callbacks when entity added to hass."""
237 functools.partial(self.
async_removeasync_remove, force_remove=
True),
244 """Cleanup prior to hass removal."""
249 TYPE_HYPERION_CAMERA: HyperionCamera,
None async_write_ha_state(self)
None async_added_to_hass(self)
bytes|None _async_wait_for_camera_image(self)
AsyncGenerator _image_streaming(self)
bytes|None async_camera_image(self, int|None width=None, int|None height=None)
web.StreamResponse|None handle_async_mjpeg_stream(self, web.Request request)
bool _start_image_streaming_for_client(self)
None _update_imagestream(self, dict[str, Any]|None img=None)
None __init__(self, str server_id, int instance_num, str instance_name, client.HyperionClient hyperion_client)
None async_will_remove_from_hass(self)
None _stop_image_streaming_for_client(self)
None async_write_ha_state(self)
None async_on_remove(self, CALLBACK_TYPE func)
None async_remove(self, *bool force_remove=False)
web.StreamResponse async_get_still_stream(web.Request request, Callable[[], Awaitable[bytes|None]] image_cb, str content_type, float interval)
web.Response get(self, web.Request request, str config_key)
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
str get_hyperion_device_id(str server_id, int instance)
str get_hyperion_unique_id(str server_id, int instance, str name)
None listen_for_instance_updates(HomeAssistant hass, ConfigEntry config_entry, Callable add_func, Callable remove_func)
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)
None async_dispatcher_send(HomeAssistant hass, str signal, *Any args)