onvif_server/lib.rs
1//! # onvif-server
2//!
3//! A spec-compliant ONVIF Profile S device server library for Rust.
4//!
5//! Implement the service traits for your camera hardware and get a fully functional
6//! ONVIF-compatible device accessible by any standard ONVIF client (VMS, NVR,
7//! Home Assistant, Frigate, python-onvif-zeep, ONVIF Device Manager, etc.).
8//!
9//! ## ONVIF Profile S coverage
10//!
11//! | Service | Status |
12//! |----------------|---------------|
13//! | Device | Supported |
14//! | Media | Supported |
15//! | PTZ | Supported |
16//! | Imaging | Supported |
17//! | Events | Supported |
18//!
19//! ## Quick start
20//!
21//! ```rust,no_run
22//! use onvif_server::{OnvifServer, DeviceService};
23//!
24//! struct MyCamera;
25//!
26//! #[async_trait::async_trait]
27//! impl DeviceService for MyCamera {
28//! // Override methods as needed; defaults return NotImplemented.
29//! }
30//!
31//! #[tokio::main]
32//! async fn main() {
33//! OnvifServer::builder()
34//! .port(8080)
35//! .advertised_host("192.168.1.10")
36//! .device_service(MyCamera)
37//! .auth("admin", "password")
38//! .build()
39//! .expect("build failed")
40//! .run()
41//! .await
42//! .expect("server error");
43//! }
44//! ```
45//!
46//! ## WS-Security
47//!
48//! Call `.auth(username, password)` on the builder to enable WS-Security
49//! UsernameToken digest authentication. `GetSystemDateAndTime` is automatically
50//! exempt from auth (required by ONVIF spec for clock synchronisation before
51//! the client has valid credentials).
52//!
53//! ## WS-Discovery
54//!
55//! Enable the optional `discovery` feature to have the server respond to
56//! WS-Discovery multicast probes on `239.255.255.250:3702`, making the device
57//! auto-discoverable on the local network.
58//!
59//! ```toml
60//! [dependencies]
61//! onvif-server = { version = "0.1", features = ["discovery"] }
62//! ```
63
64mod constants;
65pub mod discovery;
66mod error;
67pub mod generated;
68mod server;
69pub mod service;
70pub mod traits;
71mod wsdl_loader;
72
73pub use constants::*;
74pub use error::OnvifError;
75pub use generated::{
76 DeviceInfo, HostnameInformation, ImagingSettings, MediaProfile, NetworkInterface, PTZPreset,
77 PTZStatusResult, Scope, ScopeDefinition, VideoEncoderConfiguration, VideoSource,
78 VideoSourceConfiguration,
79};
80pub use server::{BuildError, OnvifServer, OnvifServerBuilder, RunError};
81pub use service::device::DeviceServiceHandler;
82pub use service::events::EventServiceHandler;
83pub use service::imaging::ImagingServiceHandler;
84pub use service::media::MediaServiceHandler;
85pub use service::ptz::PTZServiceHandler;
86pub use soap_server::WsdlError;
87pub use soap_server::WsdlLoader;
88pub use traits::{DeviceService, EventService, ImagingService, MediaService, PTZService};
89pub use wsdl_loader::EmbeddedWsdlLoader;
90
91// ─── Discovery helpers ────────────────────────────────────────────────────────
92//
93// Thin wrappers exposing the WS-Discovery probe-parsing and probe-response
94// building functions. These are always available (the underlying logic is pure
95// XML); only the UDP listener requires the `discovery` feature.
96
97/// Returns `true` when `msg` is a well-formed WS-Discovery `Probe` message
98/// (SOAP body first child = `Probe` in namespace
99/// `http://schemas.xmlsoap.org/ws/2005/04/discovery`).
100pub fn discovery_is_probe(msg: &[u8]) -> bool {
101 discovery::is_probe_message(msg)
102}
103
104/// Build a WS-Discovery `ProbeMatches` response XML with a stable
105/// `device_uuid` embedded in `EndpointReference/Address`.
106pub fn discovery_build_probe_match(
107 relates_to: &str,
108 xaddr: &str,
109 device_uuid: uuid::Uuid,
110) -> String {
111 discovery::build_probe_match(relates_to, xaddr, device_uuid)
112}