Skip to main content

oxvif/
lib.rs

1//! # oxvif
2//!
3//! An async Rust client library for the [ONVIF] IP camera protocol.
4//!
5//! ONVIF (Open Network Video Interface Forum) is the industry standard for
6//! interoperability between IP-based security cameras. This library provides
7//! a complete async client covering device management, media streaming,
8//! PTZ control, imaging, on-screen display, events, recording, search, and
9//! replay — all over SOAP/HTTP(S) with WS-Security and HTTP Digest
10//! authentication.
11//!
12//! ## ONVIF Profile coverage
13//!
14//! | Profile | Description | Coverage | Notes |
15//! |---------|-------------|----------|-------|
16//! | **Profile S** | Video streaming | ~95% | All core operations implemented |
17//! | **Profile T** | Advanced streaming (H.265, focus, OSD, audio) | ~95% | HTTP Digest Auth, Media2 audio/metadata/analytics config, PTZ compat; Analytics rules and DeviceIO not yet implemented |
18//! | **Profile G** | Recording & playback | ~85% | Read/search/replay + full recording/job write management; live-source job binding not yet implemented |
19//!
20//! ## Supported services
21//!
22//! - **Device** — capabilities, scopes, device info, hostname, NTP, reboot,
23//!   user management, network interfaces/protocols/DNS/gateway, relay outputs,
24//!   storage configurations, system log/URIs, factory default, discovery mode,
25//!   auxiliary commands (wiper/IR lamp)
26//! - **Media1 / Media2** — profiles, RTSP/snapshot URIs, video + audio config, OSD,
27//!   metadata config, audio decoder/output config, video source modes,
28//!   unified AddConfiguration/RemoveConfiguration
29//! - **PTZ** — absolute/relative/continuous move, presets, home position, status,
30//!   configurations, nodes, compatible configurations
31//! - **Imaging** — brightness/contrast/exposure settings, focus move/stop/status
32//! - **Events** — pull-point subscriptions, event polling, renew, unsubscribe,
33//!   continuous `event_stream`, synchronization point
34//! - **Recording** — list stored recordings; create/delete recordings, tracks, and recording jobs
35//! - **Search** — find recordings by scope, collect results, end search
36//! - **Replay** — get RTSP playback URI for a stored recording
37//! - **WS-Discovery** — UDP multicast probe to find cameras on the local network
38//!
39//! ## Architecture
40//!
41//! ```text
42//! ┌──────────────────────────────────────────────────────┐
43//! │                  OnvifSession                        │
44//! │     caches service URLs — delegates every call       │
45//! ├──────────────────────────────────────────────────────┤
46//! │                   OnvifClient                        │
47//! │     stateless — you supply service URLs per call     │
48//! ├──────────────────────────────────────────────────────┤
49//! │    soap::SoapEnvelope  │  soap::WsSecurityToken      │  ← SOAP layer
50//! ├──────────────────────────────────────────────────────┤
51//! │                  Transport trait                     │  ← HTTP abstraction
52//! │          (HttpTransport / mock in tests)             │
53//! └──────────────────────────────────────────────────────┘
54//! ```
55//!
56//! ## Quick start
57//!
58//! Two ways to use oxvif — pick whichever suits your workflow.
59//!
60//! ### `OnvifSession` — URL caching handled for you
61//!
62//! [`OnvifSession`] calls `GetCapabilities` once at construction and caches all
63//! service URLs. No URL parameters needed for individual methods.
64//!
65//! ```no_run
66//! use oxvif::{OnvifSession, OnvifError};
67//!
68//! async fn run() -> Result<(), OnvifError> {
69//!     let session = OnvifSession::builder("http://192.168.1.100/onvif/device_service")
70//!         .with_credentials("admin", "password")
71//!         .with_clock_sync()  // syncs WS-Security timestamp with device clock
72//!         .build()
73//!         .await?;
74//!
75//!     let profiles = session.get_profiles().await?;
76//!     let uri = session.get_stream_uri(&profiles[0].token).await?;
77//!     println!("RTSP stream: {}", uri.uri);
78//!
79//!     let status = session.ptz_get_status(&profiles[0].token).await?;
80//!     println!("Pan: {:?}  Tilt: {:?}", status.pan, status.tilt);
81//!     Ok(())
82//! }
83//! ```
84//!
85//! ### `OnvifClient` — direct control, you manage service URLs
86//!
87//! [`OnvifClient`] is stateless and gives direct control over every call.
88//! You fetch and forward service URLs yourself for full routing control.
89//!
90//! ```no_run
91//! use oxvif::{OnvifClient, OnvifError};
92//!
93//! async fn run() -> Result<(), OnvifError> {
94//!     let client = OnvifClient::new("http://192.168.1.100/onvif/device_service")
95//!         .with_credentials("admin", "password");
96//!
97//!     let dt = client.get_system_date_and_time().await?;
98//!     let client = client.with_utc_offset(dt.utc_offset_secs());
99//!
100//!     let caps = client.get_capabilities().await?;
101//!     let media_url = caps.media.url.as_deref().unwrap();
102//!
103//!     let profiles = client.get_profiles(media_url).await?;
104//!     let uri = client.get_stream_uri(media_url, &profiles[0].token).await?;
105//!     println!("RTSP stream: {}", uri.uri);
106//!     Ok(())
107//! }
108//! ```
109//!
110//! ## Testing without a real camera
111//!
112//! Implement [`transport::Transport`] to inject any XML fixture:
113//!
114//! ```no_run
115//! use oxvif::transport::{Transport, TransportError};
116//! use async_trait::async_trait;
117//! use std::sync::Arc;
118//!
119//! struct MockTransport { xml: String }
120//!
121//! #[async_trait]
122//! impl Transport for MockTransport {
123//!     async fn soap_post(&self, _url: &str, _action: &str, _body: String)
124//!         -> Result<String, TransportError>
125//!     {
126//!         Ok(self.xml.clone())
127//!     }
128//! }
129//!
130//! # async fn example() {
131//! let client = oxvif::OnvifClient::new("http://ignored")
132//!     .with_transport(Arc::new(MockTransport { xml: "<s:Envelope/>".into() }));
133//! # }
134//! ```
135//!
136//! [ONVIF]: https://www.onvif.org
137
138pub mod client;
139pub mod discovery;
140pub mod error;
141pub mod session;
142pub mod soap;
143pub mod transport;
144pub mod types;
145
146pub use client::{OnvifClient, notification_listener};
147pub use discovery::{DiscoveredDevice, DiscoveryEvent, probe_unicast};
148pub use error::OnvifError;
149pub use session::{OnvifSession, OnvifSessionBuilder};
150pub use types::{
151    AnalyticsCapabilities, AudioDecoderConfiguration, AudioEncoderConfiguration,
152    AudioEncoderConfigurationOptions, AudioEncoderOptions, AudioEncoding, AudioOutputConfiguration,
153    AudioSource, AudioSourceConfiguration, BoundsRange, Capabilities, DeviceCapabilities,
154    DeviceInfo, DeviceIoCapabilities, DnsInformation, EncoderInstanceInfo, EventProperties,
155    EventsCapabilities, FindRecordingResults, FloatRange, FocusMove, H264Configuration,
156    H264Options, H265Configuration, H265Options, Hostname, ImagingCapabilities, ImagingMoveOptions,
157    ImagingOptions, ImagingSettings, ImagingStatus, IntRange, IoCapabilities, JpegOptions,
158    Media2Capabilities, MediaCapabilities, MediaProfile, MediaProfile2, MetadataConfiguration,
159    MetadataConfigurationOptions, MulticastConfiguration, NetworkCapabilities, NetworkGateway,
160    NetworkInterface, NetworkProtocol, NotificationMessage, NtpInfo, OnvifService, OsdColor,
161    OsdConfiguration, OsdOptions, OsdPosition, OsdTextString, PtzCapabilities, PtzConfiguration,
162    PtzConfigurationOptions, PtzNode, PtzPreset, PtzSpaceRange, PtzSpeed, PtzStatus,
163    PullPointSubscription, PushSubscription, RecordingCapabilities, RecordingConfiguration,
164    RecordingInformation, RecordingItem, RecordingJob, RecordingJobConfiguration,
165    RecordingJobState, RecordingSourceInformation, RecordingTrack, RelayOutput, ReplayCapabilities,
166    Resolution, SearchCapabilities, SecurityCapabilities, SetDateTimeRequest, SnapshotUri,
167    SourceBounds, StorageConfiguration, StreamUri, StreamingCapabilities, SystemCapabilities,
168    SystemDateTime, SystemLog, SystemUris, User, UtcDateTime, VideoEncoderConfiguration,
169    VideoEncoderConfiguration2, VideoEncoderConfigurationOptions,
170    VideoEncoderConfigurationOptions2, VideoEncoderInstances, VideoEncoderOptions2, VideoEncoding,
171    VideoRateControl, VideoRateControl2, VideoSource, VideoSourceConfiguration,
172    VideoSourceConfigurationOptions, VideoSourceMode,
173};