ONVIF IP camera control for Elixir, backed by the Rust oxvif client.
Find cameras with discover/1, open a session with connect/2, then use
the service modules:
ExOxvif.Device- identity, clock, servicesExOxvif.Media- profiles, RTSP stream and snapshot URIsExOxvif.PTZ- pan, tilt, zoom, presets, homeExOxvif.Imaging- focusExOxvif.Events- pull-point event subscriptions
For example:
{:ok, [camera | _]} = ExOxvif.discover()
{:ok, session} = ExOxvif.connect(hd(camera.xaddrs), username: "admin", password: "secret")
{:ok, [profile | _]} = ExOxvif.Media.profiles(session)
:ok = ExOxvif.PTZ.absolute_move(session, profile.token, pan: 0.25, tilt: -0.1, zoom: 0.5)How calls run
Each call is a NIF that returns at once. The request itself runs on a small Tokio runtime inside the native library, which sends the result back to the calling process. Camera network I/O never occupies a BEAM scheduler, and a slow camera only delays the process that asked.
Every call accepts a :timeout option in milliseconds (default 15000).
oxvif bounds each HTTP exchange at 10 seconds, so the timeout is a
backstop. If it fires, the call returns {:error, %ExOxvif.Error{kind: :timeout}}, and a reply that arrives later may land in the caller's
mailbox as {:ex_oxvif_reply, id, result}. Processes that make calls
with short timeouts (a GenServer, say) should ignore that message in
handle_info/2.
All results are {:ok, value}, :ok, or {:error, %ExOxvif.Error{}}.
Summary
Functions
Connect to a device's ONVIF device service URL, usually
http://<host>/onvif/device_service.
Probe the local network for ONVIF devices with WS-Discovery multicast.
Types
@type call_opts() :: [{:timeout, timeout()}]
Functions
@spec connect(String.t(), keyword()) :: {:ok, ExOxvif.Session.t()} | {:error, ExOxvif.Error.t()}
Connect to a device's ONVIF device service URL, usually
http://<host>/onvif/device_service.
Fetches the device's capabilities and caches its service URLs.
Options:
:username,:password- credentials for WS-SecurityUsernameTokenand HTTP Digest. Give both or neither.:clock_sync- read the device clock first and offset WS-Security timestamps to match it (defaulttrue). Cameras with a drifted clock otherwise reject authenticated requests.:timeout- call timeout in milliseconds
@spec discover(keyword()) :: {:ok, [ExOxvif.DiscoveredDevice.t()]} | {:error, ExOxvif.Error.t()}
Probe the local network for ONVIF devices with WS-Discovery multicast.
Options:
:probe_timeout- how long to listen for answers, in milliseconds (default 3000):timeout- overall call timeout (defaultprobe_timeout + 5000)