diff --git a/homeassistant/components/homekit/const.py b/homeassistant/components/homekit/const.py index ead5179b5dc..b32d7f4bad4 100644 --- a/homeassistant/components/homekit/const.py +++ b/homeassistant/components/homekit/const.py @@ -55,6 +55,7 @@ CONF_SUPPORT_AUDIO = "support_audio" CONF_VIDEO_CODEC = "video_codec" CONF_VIDEO_MAP = "video_map" CONF_VIDEO_PACKET_SIZE = "video_packet_size" +CONF_STREAM_COUNT = "stream_count" # #### Config Defaults #### DEFAULT_SUPPORT_AUDIO = False @@ -72,6 +73,7 @@ DEFAULT_SAFE_MODE = False DEFAULT_VIDEO_CODEC = VIDEO_CODEC_LIBX264 DEFAULT_VIDEO_MAP = "0:v:0" DEFAULT_VIDEO_PACKET_SIZE = 1316 +DEFAULT_STREAM_COUNT = 3 # #### Features #### FEATURE_ON_OFF = "on_off" diff --git a/homeassistant/components/homekit/manifest.json b/homeassistant/components/homekit/manifest.json index 916a8cbde76..87ef0dc5ec8 100644 --- a/homeassistant/components/homekit/manifest.json +++ b/homeassistant/components/homekit/manifest.json @@ -3,7 +3,7 @@ "name": "HomeKit", "documentation": "https://www.home-assistant.io/integrations/homekit", "requirements": [ - "HAP-python==2.9.2", + "HAP-python==3.0.0", "fnvhash==0.1.0", "PyQRCode==1.2.1", "base36==0.1.1", diff --git a/homeassistant/components/homekit/type_cameras.py b/homeassistant/components/homekit/type_cameras.py index 9cfacc9866d..629e1019f4a 100644 --- a/homeassistant/components/homekit/type_cameras.py +++ b/homeassistant/components/homekit/type_cameras.py @@ -5,7 +5,6 @@ import logging from haffmpeg.core import HAFFmpeg from pyhap.camera import ( - STREAMING_STATUS, VIDEO_CODEC_PARAM_LEVEL_TYPES, VIDEO_CODEC_PARAM_PROFILE_ID_TYPES, Camera as PyhapCamera, @@ -24,7 +23,6 @@ from homeassistant.util import get_local_ip from .accessories import TYPES, HomeAccessory from .const import ( CHAR_MOTION_DETECTED, - CHAR_STREAMING_STRATUS, CONF_AUDIO_CODEC, CONF_AUDIO_MAP, CONF_AUDIO_PACKET_SIZE, @@ -33,6 +31,7 @@ from .const import ( CONF_MAX_HEIGHT, CONF_MAX_WIDTH, CONF_STREAM_ADDRESS, + CONF_STREAM_COUNT, CONF_STREAM_SOURCE, CONF_SUPPORT_AUDIO, CONF_VIDEO_CODEC, @@ -44,11 +43,11 @@ from .const import ( DEFAULT_MAX_FPS, DEFAULT_MAX_HEIGHT, DEFAULT_MAX_WIDTH, + DEFAULT_STREAM_COUNT, DEFAULT_SUPPORT_AUDIO, DEFAULT_VIDEO_CODEC, DEFAULT_VIDEO_MAP, DEFAULT_VIDEO_PACKET_SIZE, - SERV_CAMERA_RTP_STREAM_MANAGEMENT, SERV_MOTION_SENSOR, ) from .img_util import scale_jpeg_camera_image @@ -121,6 +120,7 @@ CONFIG_DEFAULTS = { CONF_VIDEO_CODEC: DEFAULT_VIDEO_CODEC, CONF_AUDIO_PACKET_SIZE: DEFAULT_AUDIO_PACKET_SIZE, CONF_VIDEO_PACKET_SIZE: DEFAULT_VIDEO_PACKET_SIZE, + CONF_STREAM_COUNT: DEFAULT_STREAM_COUNT, } @@ -131,7 +131,6 @@ class Camera(HomeAccessory, PyhapCamera): def __init__(self, hass, driver, name, entity_id, aid, config): """Initialize a Camera accessory object.""" self._ffmpeg = hass.data[DATA_FFMPEG] - self._cur_session = None for config_key in CONFIG_DEFAULTS: if config_key not in config: config[config_key] = CONFIG_DEFAULTS[config_key] @@ -178,6 +177,7 @@ class Camera(HomeAccessory, PyhapCamera): "audio": audio_options, "address": stream_address, "srtp": True, + "stream_count": config[CONF_STREAM_COUNT], } super().__init__( @@ -313,51 +313,42 @@ class Camera(HomeAccessory, PyhapCamera): if not opened: _LOGGER.error("Failed to open ffmpeg stream") return False - session_info["stream"] = stream + _LOGGER.info( "[%s] Started stream process - PID %d", session_info["id"], stream.process.pid, ) - ffmpeg_watcher = async_track_time_interval( - self.hass, self._async_ffmpeg_watch, FFMPEG_WATCH_INTERVAL + session_info["stream"] = stream + session_info[FFMPEG_PID] = stream.process.pid + + async def watch_session(_): + await self._async_ffmpeg_watch(session_info["id"]) + + session_info[FFMPEG_WATCHER] = async_track_time_interval( + self.hass, watch_session, FFMPEG_WATCH_INTERVAL, ) - self._cur_session = { - FFMPEG_WATCHER: ffmpeg_watcher, - FFMPEG_PID: stream.process.pid, - SESSION_ID: session_info["id"], - } - return await self._async_ffmpeg_watch(0) + return await self._async_ffmpeg_watch(session_info["id"]) - async def _async_ffmpeg_watch(self, _): + async def _async_ffmpeg_watch(self, session_id): """Check to make sure ffmpeg is still running and cleanup if not.""" - ffmpeg_pid = self._cur_session[FFMPEG_PID] - session_id = self._cur_session[SESSION_ID] + ffmpeg_pid = self.sessions[session_id][FFMPEG_PID] if pid_is_alive(ffmpeg_pid): return True _LOGGER.warning("Streaming process ended unexpectedly - PID %d", ffmpeg_pid) - self._async_stop_ffmpeg_watch() - self._async_set_streaming_available(session_id) + self._async_stop_ffmpeg_watch(session_id) + self.set_streaming_available(self.sessions[session_id]["stream_idx"]) return False @callback - def _async_stop_ffmpeg_watch(self): + def _async_stop_ffmpeg_watch(self, session_id): """Cleanup a streaming session after stopping.""" - if not self._cur_session: + if FFMPEG_WATCHER not in self.sessions[session_id]: return - self._cur_session[FFMPEG_WATCHER]() - self._cur_session = None - - @callback - def _async_set_streaming_available(self, session_id): - """Free the session so they can start another.""" - self.streaming_status = STREAMING_STATUS["AVAILABLE"] - self.get_service(SERV_CAMERA_RTP_STREAM_MANAGEMENT).get_characteristic( - CHAR_STREAMING_STRATUS - ).notify() + self.sessions[session_id].pop(FFMPEG_WATCHER)() async def stop_stream(self, session_info): """Stop the stream for the given ``session_id``.""" @@ -367,7 +358,7 @@ class Camera(HomeAccessory, PyhapCamera): _LOGGER.debug("No stream for session ID %s", session_id) return - self._async_stop_ffmpeg_watch() + self._async_stop_ffmpeg_watch(session_id) if not pid_is_alive(stream.process.pid): _LOGGER.info("[%s] Stream already stopped", session_id) diff --git a/homeassistant/components/homekit/util.py b/homeassistant/components/homekit/util.py index c79b97adb87..449d2506d04 100644 --- a/homeassistant/components/homekit/util.py +++ b/homeassistant/components/homekit/util.py @@ -41,6 +41,7 @@ from .const import ( CONF_MAX_HEIGHT, CONF_MAX_WIDTH, CONF_STREAM_ADDRESS, + CONF_STREAM_COUNT, CONF_STREAM_SOURCE, CONF_SUPPORT_AUDIO, CONF_VIDEO_CODEC, @@ -53,6 +54,7 @@ from .const import ( DEFAULT_MAX_FPS, DEFAULT_MAX_HEIGHT, DEFAULT_MAX_WIDTH, + DEFAULT_STREAM_COUNT, DEFAULT_SUPPORT_AUDIO, DEFAULT_VIDEO_CODEC, DEFAULT_VIDEO_MAP, @@ -112,6 +114,9 @@ CAMERA_SCHEMA = BASIC_INFO_SCHEMA.extend( vol.Optional(CONF_MAX_FPS, default=DEFAULT_MAX_FPS): cv.positive_int, vol.Optional(CONF_AUDIO_MAP, default=DEFAULT_AUDIO_MAP): cv.string, vol.Optional(CONF_VIDEO_MAP, default=DEFAULT_VIDEO_MAP): cv.string, + vol.Optional(CONF_STREAM_COUNT, default=DEFAULT_STREAM_COUNT): vol.All( + vol.Coerce(int), vol.Range(min=1, max=10) + ), vol.Optional(CONF_VIDEO_CODEC, default=DEFAULT_VIDEO_CODEC): vol.In( VALID_VIDEO_CODECS ), diff --git a/requirements_all.txt b/requirements_all.txt index 25569ee1a45..e49abe8b6f0 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -18,7 +18,7 @@ Adafruit-SHT31==1.0.2 # Adafruit_BBIO==1.1.1 # homeassistant.components.homekit -HAP-python==2.9.2 +HAP-python==3.0.0 # homeassistant.components.mastodon Mastodon.py==1.5.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 24a14ddfc70..1e235e38aba 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -5,7 +5,7 @@ -r requirements_test.txt # homeassistant.components.homekit -HAP-python==2.9.2 +HAP-python==3.0.0 # homeassistant.components.plugwise Plugwise_Smile==1.1.0