1. ExOnvif在调用 getStatus 的返回值时,存在的问题
在使用 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

5280

被折叠的 条评论
为什么被折叠?



