Elixir通过Onvif协议控制IP摄像机,扩展ExOnvif的获取摄像机云台当前状态函数GetStatus

1. ExOnvif在调用 getStatus 的返回值时,存在的问题

ExOnvif官方文档

在使用 Elixir 的 ExOnvif 库获取云台当前状态时,大华的云台可以正常获取,并解析返回值;海康的云台获取状态正常,但在在解析返回值的时候出错

仔细观察两种设备的返回值,可以发现差异在SOAP的前缀不一致:<s:Envelope> 和 env:Envelope
s 和 env 命名空间前缀不一致,为什么会出现这种不一致呢?

2. 为什么会出现以上问题

Onvif协议的核心是 互操作性,而不是要求完全一致,它定义了必须实现的核心功能,但同时允许大量功能是可选择的。再有不同厂家的开发团队对于Onvif协议的理解也存在细微的差别。

总而言之,Onvif协议提供了“通用语言”, 但是每个厂商都有自己的“口音”和“方言”,所以我们在做集成时,不能要求大家说话完全一致,但是您的代码要能听懂各种口音,并优雅的解析。

3. 更新后状态解析函数

以下内容修改了解析状态返回值的函数,根据厂家不同,调用不同的函数:

  import SweetXml
  alias ExOnvif.PTZ.Status

  # 获取设备当前状态
  @spec get_status(ExOnvif.Device.t(), String.t(), String.t()) :: {:ok, Status.t()} | {:error, any()}
  def get_status(device, profile_token, type) do
    body = element("tptz:GetStatus", element("tptz:ProfileToken", profile_token))
    ptz_request(device, "GetStatus", body, fn resp -> parse_status_response(resp, type) end )
  end

  # 大华的摄像机
  defp parse_status_response(xml_response_body, type) when type == "dahua" do
    xml_response_body
    |> parse(namespace_conformant: true, quiet: true)
    |> xpath(
      ~x"//s:Envelope/s:Body/tptz:GetStatusResponse/tptz:PTZStatus"e
      |> add_namespace("s", "http://www.w3.org/2003/05/soap-envelope")
      |> add_namespace("tt", "http://www.onvif.org/ver10/schema")
      |> add_namespace("tptz", "http://www.onvif.org/ver20/ptz/wsdl")
    )
    |> mvparse()
    |> Status.to_struct()
  end

  # 海康摄像机
  defp parse_status_response(xml_response_body, type) when type == 'hikvision' do
    xml_response_body
    |> parse(namespace_conformant: true, quiet: true)
    |> xpath(
      ~x"//env:Envelope/env:Body/tptz:GetStatusResponse/tptz:PTZStatus"e
      |> add_namespace("s", "http://www.w3.org/2003/05/soap-envelope")
      |> add_namespace("tt", "http://www.onvif.org/ver10/schema")
      |> add_namespace("tptz", "http://www.onvif.org/ver20/ptz/wsdl")
    )
    |> mvparse()
    |> Status.to_struct()
  end

  defp parse_status_response(xml_response_body, type\\nil) do
    xml_response_body
    |> parse(namespace_conformant: true, quiet: true)
    |> xpath(
      ~x"//tptz:GetStatusResponse/tptz:PTZStatus"e
      |> add_namespace("s", "http://www.w3.org/2003/05/soap-envelope")
      |> add_namespace("tt", "http://www.onvif.org/ver10/schema")
      |> add_namespace("tptz", "http://www.onvif.org/ver20/ptz/wsdl")
    )
    |> mvparse()
    |> Status.to_struct()
  end
  
  def mvparse(doc) do
    xmap(
      doc,
      position: ~x"./tt:Position" |> transform_by(&ExOnvif.PTZ.Vector.parse/1),
      utc_time: ~x"./tt:UtcTime/text()"s
    )
  end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值