#设备发现协议
发送如下XML消息。服务端会返回设备信息1
2
3
4
5
6
7
8
9
10
11
12
13<?xml version="1.0" encoding="utf-8"?>
<Envelope xmlns:dn="http://www.onvif.org/ver10/network/wsdl" xmlns="http://www.w3.org/2003/05/soap-envelope">
<Header>
<wsa:MessageID xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">uuid:6d09a111-2662-49de-ba92-b429b35ec189</wsa:MessageID>
<wsa:To xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">urn:schemas-xmlsoap-org:ws:2005:04:discovery</wsa:To>
<wsa:Action xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</wsa:Action>
</Header>
<Body>
<Probe xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/ws/2005/04/discovery">
<Types>dn:NetworkVideoTransmitter</Types><Scopes />
</Probe>
</Body>
</Envelope>
##erlang 脚本
首先需要向239.255.255.250:3702 以UDP协议发送XML消息。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18% udp Client
client(Port,Msg) ->
{ok, Socket} = gen_udp:open(0, [binary]),
io:format("client opened socket=~p~n",[Socket]),
ok = gen_udp:send(Socket, Port, 3702, Msg ),
Value = udp_recieve(Socket,[]),
gen_udp:close(Socket),
Value.
%
udp_recieve(Sock,Value)->
receive
{udp, Sock, _, _, Bin} ->
%io:format("client received:~p~n",[Bin]),
udp_recieve(Sock,[Bin]++Value)
after 500 ->
Value
end.
##XML解析
发送完消息后,接收服务端的消息,然后收到新的XML文件。使用erlang 的xmerl_scan 模块进行解析。解析完在编写脚本来获取需要的信息。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27%% 从[xmlText] 中提取path 和 value
%% Tuple: xmlText ,Res:[]
%% get path and value from xmlText
get_info([],Res) ->
Res;
get_info([Tuple|R],Res)->
case Tuple of
#xmlText{parents = Parents,value = Value}
-> get_info(R,Res++[{Parents,Value}]);
_Else->
Res
end.
%% 从xmlElement 根据节点名提取 子节点[xmlElement]
%%Tuple : xmlElement, Node : String
search(Tuple,Node) when is_tuple(Tuple) ->
case Tuple of
#xmlElement{nsinfo = {_, Node}} ->
#xmlElement{content=Res}=Tuple,
Res;
#xmlElement{content= Children } ->
search(Children,Node,[]);
_Else ->
[]
end.
search([],_Node,Res)-> Res;
search([Tuple|R],Node,Res) ->
search(R,Node,Res ++ search(Tuple,Node)).
反馈消息格式
1 |
|
##完整代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79%%%-------------------------------------------------------------------
%%% @author PC
%%% @copyright (C) 2016, <COMPANY>
%%% @doc
%%%
%%% @end
%%% Created : 30. 五月 2016 11:23
%%%-------------------------------------------------------------------
-module(xmlparser).
-author("PC").
-include_lib("xmerl/include/xmerl.hrl").
-include_lib("xmerl/include/xmerl_xpath.hrl").
-include_lib("xmerl/include/xmerl_xsd.hrl").
-include_lib("eunit/include/eunit.hrl").
-export([main/1,get_info/2,search/2]).
main(_v) ->
{ok, Req } = file:read_file("c:/erl/soap-master/uri.xml"),
Recv=client("239.255.255.250",Req),
Fun=fun F([Xml|R])->
io:format("get xml ~n"),
{Doc,_} = xmerl_scan:string(binary_to_list(Xml)),
get_info(search(Doc,"XAddrs"),[])++F(R);
F([])->[] end,
io:format("~p~n",[Fun(Recv)]).
% Client code
client(Port,Msg) ->
{ok, Socket} = gen_udp:open(0, [binary]),
io:format("client opened socket=~p~n",[Socket]),
ok = gen_udp:send(Socket, Port, 3702, Msg ),
Value = udp_recieve(Socket,[]),
gen_udp:close(Socket),
Value.
udp_recieve(Sock,Value)->
receive
{udp, Sock, _, _, Bin} ->
%io:format("client received:~p~n",[Bin]),
udp_recieve(Sock,[Bin]++Value)
after 500 ->
Value
end.
genera_path(Paths,NS)->% Paths: list() ,NS : namespace
lists:flatmap(fun(Item)-> "/"++NS++":"++Item end,Paths).
%%get ns from xmlnode
get_env(Xml_ns,Url) -> %Xml_ns : xmlElement, Url: atom()
List=element(3,Xml_ns),
lists:filter(fun(Raw) -> case Raw of
{_,Url } -> true;
_Else-> false end end, List).
%% Tuple: xmlText ,Res:[]
%% get path and value from xmlText
get_info([],Res) ->
Res;
get_info([Tuple|R],Res)->
case Tuple of
#xmlText{parents = Parents,value = Value}
-> get_info(R,Res++[{Parents,Value}]);
_Else->
Res
end.
%%Tuple : xmlElement, Node : String
search(Tuple,Node) when is_tuple(Tuple) ->
case Tuple of
#xmlElement{nsinfo = {_, Node}} ->
#xmlElement{content=Res}=Tuple,
Res;
#xmlElement{content= Children } ->
search(Children,Node,[]);
_Else ->
[]
end.
search([],_Node,Res)-> Res;
search([Tuple|R],Node,Res) ->
search(R,Node,Res ++ search(Tuple,Node)).