11 releases

0.2.1 Sep 9, 2023
0.2.0 Sep 8, 2023
0.1.39 Sep 5, 2023

#1555 in Network programming

Download history 16/week @ 2024-09-22

69 downloads per month

MIT license

38KB
701 lines

ONVIF Rust LIB

ONVIF is a industry protocol used widely by many IP cameras. If a camera is ONVIF compliant, you can discover it's IP address and query it for various capabilities and specifications.

This Rust lib provides, at the moment, a very barebones implementation of some of the protocol. More is planned.

This is a very bare bones implementation of the ONVIF protocol. The following messages are implemented:

  • Discovery
  • Capabilities
  • DeviceInfo
  • Profiles
  • GetStreamURI
  • and a couple more now... (see below for complete list)

Implementation of those messages are bare basics and don't store or parse the entire SOAP response in many cases. This whole lib is really in support of an RTSP/RTP/H264 streaming client I wrote at https://github.com/gsuyemoto/rtsp-rtp-rs, which will become a Rust crate soon.

The example discovers an IP camera (only tested on a single Topodome) and then uses OpenCV to stream via RTP and detect faces via Haar cascades.

In order to run the example, you will need Clang and OpenCV. On Debian Linux:

sudo apt-get install libclang-dev libopencv-dev

Getting Started

When creating a new Client object, the Client will first look to see if there is a file in the base directory to provide information about cameras and IP addresses. If the file is not present, then the Client will broadcast a predefined message on the network and compliant cameras should reply with their IP address. With the IP address in hand, you can then continue to query the devices for more information.

use anyhow::Result;
use onvif_cam_rs::builder::camera::CameraBuilder;
use onvif_cam_rs::client::{self, Messages};
use onvif_cam_rs::device::camera::Camera;

#[tokio::main]
async fn main() -> Result<()> {
    // Find all IP Devices on local network using ONVIF
    
    let mut devices = client::discover().await?;
    let mut cameras: Vec<Camera> = Vec::new();
    
    // Enumerate all Camera devices found
    for device in devices {
        let mut camera = Camera::new(device);
        camera.build_all().await?;
        cameras.push(camera);
    }
    
    // Get the RTSP streaming URL for the first camera
    match &cameras[0].stream.uri {
        Some(url) => println!("Stream uri: {url}"),
        None => panic!("Ooops"),
    }

    Ok(())
}

A super simple Camera device object creation can go like this:

use anyhow::Result;
use onvif_cam_rs::builder::camera::CameraBuilder;
use onvif_cam_rs::device::camera::Camera;

#[tokio::main]
async fn main() -> Result<()> {
    let mut camera = Camera::from("http://192.168.1.100:8080/onvif/device_service");
    camera.build_all().await?;

    Ok(())
}

Which might work out better when testing as some cameras and devices might time out with too many discovery messages.

Messages Implemented:

  • Discovery
  • Capabilities
  • DeviceInfo
  • Profiles
  • GetStreamURI
  • GetServices

Messages Started (Basic Response and no Parsing of Reply):

  • GetServiceCapabilities
  • GetDNS
  • GetDot11Status
  • GetGeoLocation
  • CreatePullPointSubscriptionRequest

Dependencies

~8–19MB
~264K SLoC