mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-06 11:15:21 +03:00
ensure camera supports ONVIF MoveStatus
This commit is contained in:
parent
1ff1de3f84
commit
c4fa050659
@ -208,6 +208,17 @@ class PtzAutoTracker:
|
||||
|
||||
return
|
||||
|
||||
movestatus_supported = self.onvif.get_service_capabilities(camera_name)
|
||||
|
||||
if movestatus_supported is None or movestatus_supported.lower() != "true":
|
||||
cam.onvif.autotracking.enabled = False
|
||||
self.ptz_metrics[camera_name]["ptz_autotracker_enabled"].value = False
|
||||
logger.warning(
|
||||
f"Disabling autotracking for {camera_name}: ONVIF MoveStatus not supported"
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
self.onvif.get_camera_status(camera_name)
|
||||
|
||||
# movement thread per camera
|
||||
|
||||
@ -9,6 +9,7 @@ from onvif import ONVIFCamera, ONVIFError
|
||||
|
||||
from frigate.config import FrigateConfig, ZoomingModeEnum
|
||||
from frigate.types import PTZMetricsTypes
|
||||
from frigate.util.builtin import find_by_key
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -83,10 +84,9 @@ class OnvifController:
|
||||
logger.debug(f"Onvif config for {camera_name}: {ptz_config}")
|
||||
|
||||
service_capabilities_request = ptz.create_type("GetServiceCapabilities")
|
||||
service_capabilities = ptz.GetServiceCapabilities(service_capabilities_request)
|
||||
logger.debug(
|
||||
f"Onvif service capabilities for {camera_name}: {service_capabilities}"
|
||||
)
|
||||
self.cams[camera_name][
|
||||
"service_capabilities_request"
|
||||
] = service_capabilities_request
|
||||
|
||||
fov_space_id = next(
|
||||
(
|
||||
@ -453,7 +453,30 @@ class OnvifController:
|
||||
"presets": list(self.cams[camera_name]["presets"].keys()),
|
||||
}
|
||||
|
||||
def get_camera_status(self, camera_name: str) -> dict[str, any]:
|
||||
def get_service_capabilities(self, camera_name: str) -> None:
|
||||
if camera_name not in self.cams.keys():
|
||||
logger.error(f"Onvif is not setup for {camera_name}")
|
||||
return {}
|
||||
|
||||
if not self.cams[camera_name]["init"]:
|
||||
self._init_onvif(camera_name)
|
||||
|
||||
onvif: ONVIFCamera = self.cams[camera_name]["onvif"]
|
||||
service_capabilities_request = self.cams[camera_name][
|
||||
"service_capabilities_request"
|
||||
]
|
||||
service_capabilities = onvif.get_service("ptz").GetServiceCapabilities(
|
||||
service_capabilities_request
|
||||
)
|
||||
|
||||
logger.debug(
|
||||
f"Onvif service capabilities for {camera_name}: {service_capabilities}"
|
||||
)
|
||||
|
||||
# MoveStatus is required for autotracking - should return "true" if supported
|
||||
return find_by_key(vars(service_capabilities), "MoveStatus")
|
||||
|
||||
def get_camera_status(self, camera_name: str) -> None:
|
||||
if camera_name not in self.cams.keys():
|
||||
logger.error(f"Onvif is not setup for {camera_name}")
|
||||
return {}
|
||||
@ -465,17 +488,28 @@ class OnvifController:
|
||||
status_request = self.cams[camera_name]["status_request"]
|
||||
status = onvif.get_service("ptz").GetStatus(status_request)
|
||||
|
||||
# zooming is optional
|
||||
# there doesn't seem to be an onvif standard with this optional parameter
|
||||
# some cameras can report MoveStatus with or without PanTilt or Zoom attributes
|
||||
pan_tilt_status = getattr(status.MoveStatus, "PanTilt", None)
|
||||
zoom_status = getattr(status.MoveStatus, "Zoom", None)
|
||||
|
||||
# if it's not an attribute, see if MoveStatus even exists in the status result
|
||||
if pan_tilt_status is None:
|
||||
logger.error(
|
||||
f"Camera {camera_name} does not support the ONVIF GetStatus method. Autotracking will not function correctly and must be disabled in your config."
|
||||
)
|
||||
return
|
||||
pan_tilt_status = getattr(status, "MoveStatus", None)
|
||||
|
||||
if pan_tilt_status == "IDLE" and (zoom_status is None or zoom_status == "IDLE"):
|
||||
# we're unsupported
|
||||
if pan_tilt_status is None or pan_tilt_status.lower() not in [
|
||||
"idle",
|
||||
"moving",
|
||||
]:
|
||||
logger.error(
|
||||
f"Camera {camera_name} does not support the ONVIF GetStatus method. Autotracking will not function correctly and must be disabled in your config."
|
||||
)
|
||||
return
|
||||
|
||||
if pan_tilt_status.lower() == "idle" and (
|
||||
zoom_status is None or zoom_status.lower() == "idle"
|
||||
):
|
||||
self.cams[camera_name]["active"] = False
|
||||
if not self.ptz_metrics[camera_name]["ptz_stopped"].is_set():
|
||||
self.ptz_metrics[camera_name]["ptz_stopped"].set()
|
||||
@ -517,15 +551,3 @@ class OnvifController:
|
||||
logger.debug(
|
||||
f'Camera zoom level: {self.ptz_metrics[camera_name]["ptz_zoom_level"].value}'
|
||||
)
|
||||
|
||||
return {
|
||||
"pan": status.Position.PanTilt.x,
|
||||
"tilt": status.Position.PanTilt.y,
|
||||
"zoom": status.Position.Zoom.x
|
||||
if self.config.cameras[camera_name].onvif.autotracking.zooming
|
||||
else 0,
|
||||
"pantilt_moving": status.MoveStatus.PanTilt,
|
||||
"zoom_moving": status.MoveStatus.Zoom
|
||||
if self.config.cameras[camera_name].onvif.autotracking.zooming
|
||||
else "IDLE",
|
||||
}
|
||||
|
||||
@ -249,3 +249,15 @@ def update_yaml(data, key_path, new_value):
|
||||
temp[last_key] = new_value
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def find_by_key(dictionary, target_key):
|
||||
if target_key in dictionary:
|
||||
return dictionary[target_key]
|
||||
else:
|
||||
for value in dictionary.values():
|
||||
if isinstance(value, dict):
|
||||
result = find_by_key(value, target_key)
|
||||
if result is not None:
|
||||
return result
|
||||
return None
|
||||
|
||||
Loading…
Reference in New Issue
Block a user