Skip to content

Commit a995cec

Browse files
committed
onvif: Major overhaul of ONVIF support
Makes the ONVIF driver usable end-to-end against real-world cameras (including budget Xiongmai/XM-chipset firmwares that are loose with the spec), and adds WS-Discovery as a first-class entry path so users no longer have to type host/port by hand. Bug fixes --------- - absoluteMove() / relativeMove() declared pan/tilt/zoom as int, truncating the normalized doubles to 0 or 1 and breaking every absolute/relative move. - Drop the Basic auth Authorization header on every SOAP request. The WS-UsernameToken in the envelope already authenticates and some firmwares rejected the duplicate as ambiguous. - Default port changed from 8899 to 80 (more common ONVIF default). - sendRequest() bails out early on an empty URL instead of letting Qt emit `Protocol "" is unknown` once per command when an operation fires before GetCapabilities has populated the per-service XAddrs. - Per-request transfer timeout (10s) so failures surface in seconds instead of waiting the OS TCP timeout (~2 min). - Sanitize unescaped `&` inside SOAP body text before parsing. ONVIF cameras commonly emit `&protocol=` / `&channel=` etc. in stream URIs, which Python's lenient parser tolerates but Qt's QDomDocument rejects, dropping the whole document. Preset save ----------- SetPreset's response carries the camera-assigned PresetToken; the old code ignored it, so memory_recall() never had a valid token to send back. We now remember which slot triggered the SetPreset and apply the new token to that slot when the response arrives. memory_reset() also clears the stale local token after RemovePreset. Clock-skew handling ------------------- connectCamera() now starts with GetSystemDateAndTime (an unauthenticated call per spec), computes the offset between camera and host clocks, and adjusts every WS-Security `Created` timestamp by it. Cameras with bad NTP no longer reject our calls as out-of-window. ensureCapabilitiesRequested() makes GetCapabilities still happen if the time probe errors out, so the device doesn't stay un-initialized. Stale XAddr host rewrites ------------------------- Some firmwares advertise their static/DHCP IP in WS-Discovery XAddrs and in GetCapabilities responses even when reached via a different address (NAT, multi-homed, IP changed since boot, etc.). We now override the host of any XAddr that doesn't match the responder/configured host with the address we know works — both in the WS-Discovery parse and in handleGetCapabilitiesResponse. Connection status + auto-reconnect ---------------------------------- PTZOnvif now calls setConnected() on every success/failure, so the dock's red/green dot reflects reality. After 3 consecutive failures (~15s), the device is marked disconnected and the next status-timer tick restarts the full connect chain from GetSystemDateAndTime — so a camera reboot or a network blip recovers without user intervention. GetStatus polling ----------------- A 5s timer polls GetStatus while connected, keeping cached pan/tilt/ zoom position in sync with the camera. The same timer drives the reconnect retry when disconnected. WS-Discovery + selection dialog ------------------------------- Adding an ONVIF device now pops a dialog that: - Sends a SOAP-over-UDP Probe to 239.255.255.250:3702 from every suitable interface (so multi-homed hosts find cameras on every LAN). - Lists discovered cameras with host/port/manufacturer/model parsed from the response Scopes. - Provides a manual-add row for cameras the multicast probe can't reach (different subnet, multicast-blocked LAN, etc.). - Fetches per-profile RTSP stream URIs via GetCapabilities → GetProfiles → GetStreamUri, with the same clock-skew handling as the runtime driver and a SOAP-fault surface so auth/credential failures produce a readable error. - Supports anonymous probing for cameras that don't require auth (empty password ⇒ skip WS-Security header entirely). - Has a stream selector for which profile's URL to use when auto-creating a Media Source. - Optionally auto-creates an OBS Media Source from the picked stream URI, with the user's credentials embedded as Basic auth so it survives token expiry. Other new features ------------------ - Media profile combo in the device settings; persists across reloads. - Imaging service: continuous focus moves + AutoFocusMode toggle, and WhiteBalance mode (AUTO/MANUAL). Focus is wired through PTZDevice's focus_changed and only fires on cameras that advertise an Imaging XAddr. - Per-device speed multiplier slider (0.1..10.0) for cameras that accept ONVIF velocities above the spec maximum. - SetHomePosition via right-click on the dock's Home button. Gated by a new virtual supportsSetHome() (default false), so VISCA/Pelco/USB devices show no menu and behavior there is unchanged. Signed-off-by: Jonatã Bolzan Loss <jonata@jonata.org>
1 parent 97980d2 commit a995cec

10 files changed

Lines changed: 1702 additions & 26 deletions

CMakeLists.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,14 @@ endif()
125125
option(ENABLE_ONVIF "Enable ONVIF camera support" ON)
126126
if(ENABLE_ONVIF)
127127
add_compile_definitions(ENABLE_ONVIF)
128-
target_sources(${CMAKE_PROJECT_NAME} PRIVATE src/ptz-onvif.cpp src/ptz-onvif.hpp)
128+
target_sources(
129+
${CMAKE_PROJECT_NAME}
130+
PRIVATE
131+
src/ptz-onvif.cpp
132+
src/ptz-onvif.hpp
133+
src/onvif-discovery.cpp
134+
src/onvif-discovery.hpp
135+
)
129136
endif()
130137

131138
option(ENABLE_SERIALPORT "Enable UART connected camera support" OFF)

data/locale/en-GB.ini

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ PTZ.Action.Preset.MoveUp.Tooltip="Move Preset Up"
3939
PTZ.Action.Preset.MoveDown.Tooltip="Move Preset Down"
4040
PTZ.Action.Preset.Remove.Tooltip="Remove selected preset"
4141
PTZ.Action.WhiteBalance.OnePushTrigger="Trigger One-Push White Balance"
42+
PTZ.Action.SetHome="Save current position as Home"
4243
PTZ.Dock.Name="PTZ Controls"
4344
PTZ.Dock.Lock.Name="Movement Locked"
4445
PTZ.Dock.Lock.Description="Camera locked to prevent movement while live. Click to unlock"
@@ -75,6 +76,31 @@ PTZ.Pelco.UsePelcoD="Use Pelco-D"
7576
PTZ.UVC.Name="USB Camera (UVC)"
7677
PTZ.ONVIF.Name="ONVIF (experimental)"
7778
PTZ.ONVIF.Warning="Warning: ONVIF support is experimental"
79+
PTZ.ONVIF.SpeedBoost="Speed Boost (multiplies normalized ONVIF velocity; spec max is 1.0)"
80+
PTZ.ONVIF.MediaProfile="Media Profile"
81+
PTZ.ONVIF.NoProfilesYet="(not loaded yet — apply and reopen)"
82+
PTZ.ONVIF.WbDefault="(leave camera default)"
83+
PTZ.ONVIF.Discovery.Title="Discover ONVIF Cameras"
84+
PTZ.ONVIF.Discovery.Rescan="Rescan"
85+
PTZ.ONVIF.Discovery.Searching="Searching the network for ONVIF cameras..."
86+
PTZ.ONVIF.Discovery.Found="Found %1 camera(s). Select one to add."
87+
PTZ.ONVIF.Discovery.NoResponse="No ONVIF cameras responded. Check that your camera is powered on and on the same network."
88+
PTZ.ONVIF.Discovery.UseCamera="Use Selected Camera"
89+
PTZ.ONVIF.Discovery.SelectHint="Select a camera from the list to see its details."
90+
PTZ.ONVIF.Discovery.Col.Host="Host"
91+
PTZ.ONVIF.Discovery.Col.Port="Port"
92+
PTZ.ONVIF.Discovery.Col.Manufacturer="Manufacturer"
93+
PTZ.ONVIF.Discovery.Col.Model="Model"
94+
PTZ.ONVIF.Discovery.CredentialsHint="Enter the camera username and password to fetch RTSP stream URLs (optional)."
95+
PTZ.ONVIF.Discovery.NeedCreds="Enter username and password to fetch stream URLs."
96+
PTZ.ONVIF.Discovery.FetchingStreams="Fetching stream URLs..."
97+
PTZ.ONVIF.Discovery.Streams="Streams"
98+
PTZ.ONVIF.Discovery.StreamError="Could not fetch streams: %1"
99+
PTZ.ONVIF.Discovery.AuthFailed="Authentication failed. Check the username and password."
100+
PTZ.ONVIF.Discovery.ManualPrompt="Don't see your camera? Add manually:"
101+
PTZ.ONVIF.Discovery.ManualAdd="Add"
102+
PTZ.ONVIF.Discovery.ManualLabel="(manual)"
103+
PTZ.ONVIF.Discovery.CreateMediaSource="Also create an OBS Media Source for this camera's stream"
78104
PTZ.Visca.TCP.Name="VISCA TCP"
79105
PTZ.Visca.TCP.HostPortName="VISCA/TCP %1:%2"
80106
PTZ.Visca.TCP.Description="VISCA TCP Connection"

0 commit comments

Comments
 (0)