Elixir 通過Onvif 對IP設備進行控制時,可以使用 ExOnvif 庫。ExOnvif官方文檔
此文章僅提供了ContinuousMove的控制方式及示例。
Elixir Onvif協議控制IP設備的其他命令,可以參考以下鏈接
絕對移動 【AbsoluteMove】
調用指定預置位 【GotoPreset】
停止運動 【Stop】
獲取預置位列表 【GetPresets】
1. ContinuousMove
ExOnvif官方文檔中未給出攝像機連續運動命令,自己按照onvif協議 Onvif協議 擴展的此項功能;
連續移動的命令 ContinuousMove,屬于PTZ服務的一部分,允許客戶端向網絡攝像機或其他視頻監控設備發送指令,以使云臺持續平移(Pan)、傾斜(Tilt)、變焦(Zoom)。 這個操作讓監控人員能夠靈活地追蹤移動的目標或調整視角,而不僅僅是跳轉到預設的位置。
由以上協議可以看出,控制攝像機連續移動,需要參數2個
- ProfileToken:ProfileToken指定執行PTZ操作的配置文件標識符,必須先從設備獲取有效的ProfileToken。
- Velocity:PTZ參數,PanTilt定義了平移和傾斜的速度,x軸通常對應水平方向(Pan),y軸對應垂直方向(Tilt)。正值表示正方向移動,負值反之。Zoom定義了變焦速度,值為0通常意味著不改變當前變焦狀態。
2. 函數實現
程序實現步驟如下
- 初始化Device設備
- 獲取Device設備的ProfileToken
- 控制設備
完整的文件:
defmodule MvOnvif.Action douse GenServer@moduledoc """自定義的Onvif的部分協議獲取當前狀態(exonvif)absolute move調用攝像頭到指定位置,continuous move攝像頭連續移動調用指定預置位停止運動"""import ExOnvif.Utils.XmlBuilderimport SweetXmlalias ExOnvif.Devicealias ExOnvif.Media2import ExOnvif.Utils.ApiClient, only: [ptz_request: 4]# 初始化device設備defp get_device(uri) when not is_nil(uri) do%{host: host, userinfo: userinfo} = URI.parse(uri)[user, pw] = String.split(userinfo, ":")Device.new("http://" <> host, user, pw);enddefp get_device(uri) do:errorend # 獲取profiletoken標識符defp get_main_stream_profile_token(device) doprofiles = Media2.get_profiles(device)case profiles do{:ok, list} -> {:ok, hd(list).reference_token}_ -> "something went wrong"endend@spec mv_continuous_move(ExOnvif.Device.t(), ExOnvif.PTZ.AbsoluteMove.t()) :: {:ok, String.t()} | {:error, any()}def mv_continuous_move(device, ab_m) dobody = encode(ab_m)ptz_request(device, "ContinuousMove", body, fn resp -> :ok end )end# 按照xml格式編碼def encode(absolute_move) doelement("tptz:ContinuousMove",[element("tptz:ProfileToken", absolute_move.profile_token),element("tptz:Velocity", Vector.encode(absolute_move.speed))])end# 攝像頭連續移動def continuous_move_(uri, speed \\ {0.5, 0.5, 0.1}) dowith {:ok, device} <- get_device(uri),{:ok, profile_token} <- get_main_stream_profile_token(device)do{x, y, z} = speedspeed = %ExOnvif.PTZ.Vector{pan_tilt: %ExOnvif.PTZ.Vector.PanTilt{x: x,y: y},zoom: z}abm = ExOnvif.PTZ.AbsoluteMove.new(profile_token, nil, speed)mv_continuous_move(device, abm)endend
end
停止移動 參考連接
3. xml文件示例
連續運動請求的標準xml文件示例
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelopexmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope"xmlns:wsdl="http://www.onvif.org/ver20/ptz/wsdl"xmlns:tt="http://www.onvif.org/ver10/schema"><SOAP-ENV:Header><!-- 安全認證頭 --><Security SOAP-ENV:mustUnderstand="true"xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><UsernameToken><Username>admin</Username><Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest"><!-- 加密密碼(示例值) -->dGhpcyBpcyBub3QgYSByZWFsIHBhc3N3b3JkIEJhc2U2NA==</Password><Nonce>eUYbbbyFbcLbcByKUvbcsA==</Nonce><Created>2025-08-14T10:30:00.000Z</Created></UsernameToken></Security></SOAP-ENV:Header><SOAP-ENV:Body><wsdl:ContinuousMove><!-- 必填參數:配置集Token --><wsdl:ProfileToken>Profile_1</wsdl:ProfileToken><!-- 必填參數:運動速度向量 --><wsdl:Velocity><tt:PanTilt x="0.5" y="0.0" space="http://www.onvif.org/ver10/tptz/PanTiltSpaces/VelocityGenericSpace"/><tt:Zoom x="0.0" space="http://www.onvif.org/ver10/tptz/ZoomSpaces/VelocityGenericSpace"/></wsdl:Velocity><!-- 可選參數:超時時間(單位:秒) --><!-- <wsdl:Timeout>PT30S</wsdl:Timeout> --></wsdl:ContinuousMove></SOAP-ENV:Body>
</SOAP-ENV:Envelope>