mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-07-02 10:01:15 +03:00
turn on switch by default if pan and/or tilt capability is available
This commit is contained in:
parent
470abbab9d
commit
3aadc88a29
@ -591,6 +591,32 @@ async def _connect_onvif_camera(
|
|||||||
raise first_error
|
raise first_error
|
||||||
|
|
||||||
|
|
||||||
|
def _supports_continuous_pan_tilt(nodes) -> bool:
|
||||||
|
"""Whether any PTZ node advertises continuous pan/tilt velocity.
|
||||||
|
|
||||||
|
The web UI's directional controls issue ContinuousMove with a PanTilt
|
||||||
|
velocity, so continuous pan/tilt is what makes those controls usable. This
|
||||||
|
is intentionally narrower than ptz_supported, which is true for any device
|
||||||
|
exposing the ONVIF PTZ service - including zoom/focus-only varifocal lenses.
|
||||||
|
"""
|
||||||
|
for node in nodes or []:
|
||||||
|
spaces = getattr(node, "SupportedPTZSpaces", None) or (
|
||||||
|
node.get("SupportedPTZSpaces") if isinstance(node, dict) else None
|
||||||
|
)
|
||||||
|
if spaces is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
continuous = getattr(spaces, "ContinuousPanTiltVelocitySpace", None) or (
|
||||||
|
spaces.get("ContinuousPanTiltVelocitySpace")
|
||||||
|
if isinstance(spaces, dict)
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
if continuous:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
@router.get(
|
@router.get(
|
||||||
"/onvif/probe",
|
"/onvif/probe",
|
||||||
dependencies=[Depends(require_role(["admin"]))],
|
dependencies=[Depends(require_role(["admin"]))],
|
||||||
@ -748,6 +774,7 @@ async def onvif_probe(
|
|||||||
|
|
||||||
# Check PTZ support and capabilities
|
# Check PTZ support and capabilities
|
||||||
ptz_supported = False
|
ptz_supported = False
|
||||||
|
pan_tilt_supported = False
|
||||||
presets_count = 0
|
presets_count = 0
|
||||||
autotrack_supported = False
|
autotrack_supported = False
|
||||||
|
|
||||||
@ -781,6 +808,15 @@ async def onvif_probe(
|
|||||||
logger.debug(f"Failed to get presets: {e}")
|
logger.debug(f"Failed to get presets: {e}")
|
||||||
presets_count = 0
|
presets_count = 0
|
||||||
|
|
||||||
|
# Check for real (continuous) pan/tilt, which the UI controls need
|
||||||
|
if ptz_supported:
|
||||||
|
try:
|
||||||
|
nodes = await ptz_service.GetNodes()
|
||||||
|
pan_tilt_supported = _supports_continuous_pan_tilt(nodes)
|
||||||
|
logger.debug(f"Continuous pan/tilt supported: {pan_tilt_supported}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.debug(f"Failed to read PTZ nodes for pan/tilt support: {e}")
|
||||||
|
|
||||||
# Check for autotracking support - requires both FOV relative movement and MoveStatus
|
# Check for autotracking support - requires both FOV relative movement and MoveStatus
|
||||||
if ptz_supported and first_profile_token and ptz_config_token:
|
if ptz_supported and first_profile_token and ptz_config_token:
|
||||||
# First check for FOV relative movement support
|
# First check for FOV relative movement support
|
||||||
@ -900,6 +936,7 @@ async def onvif_probe(
|
|||||||
"firmware_version": device_info["firmware_version"],
|
"firmware_version": device_info["firmware_version"],
|
||||||
"profiles_count": profiles_count,
|
"profiles_count": profiles_count,
|
||||||
"ptz_supported": ptz_supported,
|
"ptz_supported": ptz_supported,
|
||||||
|
"pan_tilt_supported": pan_tilt_supported,
|
||||||
"presets_count": presets_count,
|
"presets_count": presets_count,
|
||||||
"autotrack_supported": autotrack_supported,
|
"autotrack_supported": autotrack_supported,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -78,7 +78,7 @@ export default function Step3StreamConfig({
|
|||||||
|
|
||||||
const onvif = wizardData.onvif;
|
const onvif = wizardData.onvif;
|
||||||
const ptzSupported = wizardData.probeResult?.ptz_supported === true;
|
const ptzSupported = wizardData.probeResult?.ptz_supported === true;
|
||||||
const hasPresets = (wizardData.probeResult?.presets_count ?? 0) > 0;
|
const panTiltSupported = wizardData.probeResult?.pan_tilt_supported === true;
|
||||||
const onvifInvalid = !!onvif?.enabled && (!onvif.host?.trim() || !onvif.port);
|
const onvifInvalid = !!onvif?.enabled && (!onvif.host?.trim() || !onvif.port);
|
||||||
|
|
||||||
// Seed the PTZ pane once from the successful ONVIF probe
|
// Seed the PTZ pane once from the successful ONVIF probe
|
||||||
@ -87,7 +87,7 @@ export default function Step3StreamConfig({
|
|||||||
if (ptzSupported && wizardData.onvif === undefined) {
|
if (ptzSupported && wizardData.onvif === undefined) {
|
||||||
onUpdate({
|
onUpdate({
|
||||||
onvif: {
|
onvif: {
|
||||||
enabled: hasPresets,
|
enabled: panTiltSupported,
|
||||||
host: wizardData.host ?? "",
|
host: wizardData.host ?? "",
|
||||||
port: wizardData.onvifPort ?? 8000,
|
port: wizardData.onvifPort ?? 8000,
|
||||||
user: wizardData.username ?? "",
|
user: wizardData.username ?? "",
|
||||||
@ -97,7 +97,7 @@ export default function Step3StreamConfig({
|
|||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
ptzSupported,
|
ptzSupported,
|
||||||
hasPresets,
|
panTiltSupported,
|
||||||
wizardData.onvif,
|
wizardData.onvif,
|
||||||
wizardData.host,
|
wizardData.host,
|
||||||
wizardData.onvifPort,
|
wizardData.onvifPort,
|
||||||
|
|||||||
@ -212,6 +212,7 @@ export type OnvifProbeResponse = {
|
|||||||
firmware_version?: string;
|
firmware_version?: string;
|
||||||
profiles_count?: number;
|
profiles_count?: number;
|
||||||
ptz_supported?: boolean;
|
ptz_supported?: boolean;
|
||||||
|
pan_tilt_supported?: boolean;
|
||||||
presets_count?: number;
|
presets_count?: number;
|
||||||
autotrack_supported?: boolean;
|
autotrack_supported?: boolean;
|
||||||
move_status_supported?: boolean;
|
move_status_supported?: boolean;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user