From bc067fd88851bdb7ddfc0bcae4aa8ec4ac6e6be7 Mon Sep 17 00:00:00 2001 From: Nick Mowen Date: Thu, 12 Jan 2023 13:50:16 -0700 Subject: [PATCH] Add ptz controls ot birdseye --- frigate/config.py | 3 ++- frigate/ptz.py | 12 ++++++------ web/src/routes/Birdseye.jsx | 24 ++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/frigate/config.py b/frigate/config.py index 788f51c18..42324b530 100644 --- a/frigate/config.py +++ b/frigate/config.py @@ -950,7 +950,8 @@ class FrigateConfig(FrigateBaseModel): input.path = input.path.format(**FRIGATE_ENV_VARS) # ONVIF substitution - if camera_config.onvif.password: + if camera_config.onvif.user or camera_config.onvif.password: + camera_config.onvif.user = camera_config.onvif.user.format(**FRIGATE_ENV_VARS) camera_config.onvif.password = camera_config.onvif.password.format(**FRIGATE_ENV_VARS) # Add default filters diff --git a/frigate/ptz.py b/frigate/ptz.py index 3ae2aefe4..67e513b8e 100644 --- a/frigate/ptz.py +++ b/frigate/ptz.py @@ -41,17 +41,14 @@ class OnvifController: cam.onvif.port, cam.onvif.user, cam.onvif.password, - wsdl_dir=site.getsitepackages()[0].replace( - "dist-packages", "site-packages" - ) - + "/wsdl", + wsdl_dir="/home/vscode/.local/lib/python3.4/site-packages/wsdl/", ), "init": False, "active": False, "presets": {}, } - def _init_onvif(self, camera_name: str) -> None: + def _init_onvif(self, camera_name: str) -> bool: onvif: ONVIFCamera = self.cams[camera_name]["onvif"] # create init services @@ -61,6 +58,7 @@ class OnvifController: profile = media.GetProfiles()[0] except ONVIFError as e: logger.error(f"Unable to connect to camera: {camera_name}: {e}") + return False ptz = onvif.create_ptz_service() request = ptz.create_type("GetConfigurationOptions") @@ -89,6 +87,7 @@ class OnvifController: self.cams[camera_name]["features"] = supported_features self.cams[camera_name]["init"] = True + return True def _stop(self, camera_name: str) -> None: onvif: ONVIFCamera = self.cams[camera_name]["onvif"] @@ -177,7 +176,8 @@ class OnvifController: return if not self.cams[camera_name]["init"]: - self._init_onvif(camera_name) + if not self._init_onvif(camera_name): + return if command == OnvifCommandEnum.init: # already init diff --git a/web/src/routes/Birdseye.jsx b/web/src/routes/Birdseye.jsx index 91c97fcb9..97de37494 100644 --- a/web/src/routes/Birdseye.jsx +++ b/web/src/routes/Birdseye.jsx @@ -6,6 +6,8 @@ import Heading from '../components/Heading'; import WebRtcPlayer from '../components/WebRtcPlayer'; import MsePlayer from '../components/MsePlayer'; import useSWR from 'swr'; +import { useMemo } from 'preact/hooks'; +import CameraControlPanel from '../components/CameraControlPanel'; export default function Birdseye() { const { data: config } = useSWR('config'); @@ -16,6 +18,16 @@ export default function Birdseye() { ); const sourceValues = ['mse', 'webrtc', 'jsmpeg']; + const ptzCameras = useMemo(() => { + if (!config) { + return []; + } + + return Object.entries(config.cameras) + .filter(([_, conf]) => conf.onvif?.host) + .map(([_, camera]) => camera.name); + }, [config]); + if (!config || !sourceIsLoaded) { return ; } @@ -80,6 +92,18 @@ export default function Birdseye() { {player} + + {ptzCameras && ( +
+ Control Panel + {ptzCameras.map((camera) => ( +
+ {camera.replaceAll('_', ' ')} + +
+ ))} +
+ )} ); }