1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//! # onvif-server
//!
//! An ONVIF **Profile S streaming-core** device server library for Rust.
//!
//! Implement the service traits for your camera hardware to expose a device that
//! standard ONVIF clients (VMS, NVR, Home Assistant, Frigate, python-onvif-zeep,
//! ONVIF Device Manager) can discover and stream from. It targets the Profile S
//! streaming core, not every ONVIF operation — see the Operation Coverage matrix
//! in the user guide for the exact support claims.
//!
//! ## ONVIF Profile S coverage
//!
//! | Service | Status |
//! |----------------|---------------|
//! | Device | Supported |
//! | Media | Supported |
//! | PTZ | Supported |
//! | Imaging | Supported |
//! | Events | Supported |
//!
//! ## Quick start
//!
//! An empty `impl DeviceService for MyCamera {}` compiles but faults on the first
//! real request — `GetDeviceInformation` and `GetStreamUri` have no working
//! default. This is the smallest *usable* device (see the `minimal_device`
//! example, and the Operation Coverage matrix in the user guide for what each
//! operation does by default):
//!
//! ```rust,no_run
//! use async_trait::async_trait;
//! use onvif_server::{DeviceInfo, DeviceService, MediaService, OnvifError, OnvifServer};
//!
//! #[derive(Clone)]
//! struct MinimalCamera {
//! media_host: String,
//! }
//!
//! #[async_trait]
//! impl DeviceService for MinimalCamera {
//! async fn get_device_information(&self) -> Result<DeviceInfo, OnvifError> {
//! Ok(DeviceInfo {
//! manufacturer: "Example Corp".into(),
//! model: "Minimal-1".into(),
//! firmware_version: "1.0.0".into(),
//! serial_number: "SN-0001".into(),
//! hardware_id: "minimal-hw-1".into(),
//! })
//! }
//! }
//!
//! #[async_trait]
//! impl MediaService for MinimalCamera {
//! async fn get_stream_uri(&self, _profile: &str) -> Result<String, OnvifError> {
//! Ok(format!("rtsp://{}:8554/stream", self.media_host))
//! }
//! }
//!
//! #[tokio::main]
//! async fn main() {
//! let host = "192.168.1.10";
//! let cam = MinimalCamera { media_host: host.into() };
//! OnvifServer::builder()
//! .port(8080)
//! .advertised_host(host)
//! .device_service(cam.clone())
//! .media_service(cam)
//! .auth("admin", "password")
//! .build()
//! .expect("build failed")
//! .run()
//! .await
//! .expect("server error");
//! }
//! ```
//!
//! ## WS-Security
//!
//! Call `.auth(username, password)` on the builder to enable WS-Security
//! UsernameToken digest authentication. `GetSystemDateAndTime` is automatically
//! exempt from auth (required by ONVIF spec for clock synchronisation before
//! the client has valid credentials).
//!
//! ## WS-Discovery
//!
//! Enable the optional `discovery` feature to have the server respond to
//! WS-Discovery multicast probes on `239.255.255.250:3702`, making the device
//! auto-discoverable on the local network.
//!
//! ```toml
//! [dependencies]
//! onvif-server = { version = "0.1", features = ["discovery"] }
//! ```
pub use *;
pub use OnvifError;
pub use ;
pub use ;
pub use DeviceServiceHandler;
pub use EventServiceHandler;
pub use ImagingServiceHandler;
pub use MediaServiceHandler;
pub use PTZServiceHandler;
pub use WsdlError;
pub use WsdlLoader;
pub use ;
pub use EmbeddedWsdlLoader;
// ─── Discovery helpers ────────────────────────────────────────────────────────
//
// Thin wrappers exposing the WS-Discovery probe-parsing and probe-response
// building functions. These are always available (the underlying logic is pure
// XML); only the UDP listener requires the `discovery` feature.
/// Returns `true` when `msg` is a well-formed WS-Discovery `Probe` message
/// (SOAP body first child = `Probe` in namespace
/// `http://schemas.xmlsoap.org/ws/2005/04/discovery`).
/// Build a WS-Discovery `ProbeMatches` response XML with a stable
/// `device_uuid` embedded in `EndpointReference/Address`.