onvif开发之二:discovery
自己调试OK的客户端discovery功能,discovery code
先从remotediscovery.wsdl解析入手吧。可以参考此网页WSDL实例解析 和 一个完整的WSDL文档及各标签详解。
1、命名空间
这个非常重要,直接导致是否可以调用到web server的功能函数。
|
1
|
<wsdl:definitions xmlns:dn="http://www.onvif.org/ver10/network/wsdl" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.onvif.org/ver10/network/wsdl"> |
targetNamespace="http://www.onvif.org/ver10/network/wsdl",采用的命空间。
2、结构体定义
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<wsdl:types> <xs:schema targetNamespace="http://www.onvif.org/ver10/network/wsdl" xmlns:d="http://schemas.xmlsoap.org/ws/2005/04/discovery" elementFormDefault="qualified"> <xs:import namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery" schemaLocation="http://schemas.xmlsoap.org/ws/2005/04/discovery/ws-discovery.xsd"/> <!-- Message Request/Responses elements --> <!--===============================--> <xs:element name="Hello" type="d:HelloType"/> <xs:element name="HelloResponse" type="d:ResolveType"/> <xs:element name="Probe" type="d:ProbeType"/> <xs:element name="ProbeResponse" type="d:ProbeMatchesType"/> <xs:element name="Bye" type="d:ByeType"/> <xs:element name="ByeResponse" type="d:ResolveType"/> <!--===============================--> </xs:schema> </wsdl:types> |
schemaLocation="http://schemas.xmlsoap.org/ws/2005/04/discovery/ws-discovery.xsd"/,进入/ws-discovery.xsd可以看到
|
1
2
3
4
5
6
7
8
|
<xs:complexType name="ProbeType"><xs:sequence><xs:element ref="tns:Types" minOccurs="0"/><xs:element ref="tns:Scopes" minOccurs="0"/><xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/></xs:sequence><xs:anyAttribute namespace="##other" processContents="lax"/></xs:complexType |
code中对应的为,命名由 <xs:element name="Probe" type="d:ProbeType"/> 中的 type="d:ProbeType"而来
|
1
2
3
4
5
6
7
8
9
10
11
12
|
#ifndef SOAP_TYPE_d__ProbeType#define SOAP_TYPE_d__ProbeType (290)/* d:ProbeType */struct d__ProbeType{ char **Types; /* optional element of type xsd:QName */ struct d__ScopesType *Scopes; /* optional element of type d:ScopesType */ int __size; /* sequence of elements <-any> */ char **__any; char *__anyAttribute; /* optional attribute of type xsd:anyType */};#endif |
3、参数
|
1
2
3
4
|
</wsdl:message><wsdl:message name="ProbeRequest"> <wsdl:part name="parameters" element="dn:Probe"/></wsdl:message> |
<wsdl:part name="parameters" element="dn:Probe"/> 表明使用的是 <xs:element name="Probe" type="d:ProbeType"/>,也即为struct d__ProbeType。
4、函数体
|
1
2
3
4
5
6
|
<wsdl:portType name="DiscoveryLookupPort"> <wsdl:operation name="Probe"> <wsdl:input message="dn:ProbeRequest" dn:Action="http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe"/> <wsdl:output message="dn:ProbeResponse" dn:Action="http://schemas.xmlsoap.org/ws/2005/04/discovery/ProbeMatches"/> </wsdl:operation> </wsdl:portType> |
这个 dn:Action="http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe" 望文生义是关于Probe()的,具体不知道什么意义,也没有找到此页面。知道的同学请告知。
客户端:
SOAP_FMAC5 int SOAP_FMAC6 soap_call___d__Probe(struct soap *soap, const char *soap_endpoint, const char *soap_action, struct d__ProbeType *d__Probe, struct d__ProbeMatchesType *d__ProbeMatches)
此soap_call___d__Probe(和soap_serve___d__Probe交互)可以调用用web server的Probe功能。
服务端:
|
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
80
81
82
83
84
85
86
87
|
/*soap_serve --> soap_serve_request --> soap_serve___d__Probe --> sever_probe*/int main(int argc, char **argv){ int m, s; struct soap add_soap; soap_init(&add_soap); soap_set_namespaces(&add_soap, namespaces); if (argc < 2) { printf("usage: %s <server_port> \n", argv[0]); exit(1); } else { m = soap_bind(&add_soap, NULL, atoi(argv[1]), 100); if (m < 0) { soap_print_fault(&add_soap, stderr); exit(-1); } fprintf(stderr, "Socket connection successful: master socket = %d\n", m); for (;;) { s = soap_accept(&add_soap); if (s < 0) { soap_print_fault(&add_soap, stderr); exit(-1); } fprintf(stderr, "Socket connection successful: slave socket = %d\n", s); soap_serve(&add_soap); soap_end(&add_soap); } } return 0;}SOAP_FMAC5 int SOAP_FMAC6 soap_serve(struct soap *soap){#ifndef WITH_FASTCGI unsigned int k = soap->max_keep_alive;#endif do {#ifndef WITH_FASTCGI if (soap->max_keep_alive > 0 && !--k) soap->keep_alive = 0;#endif if (soap_begin_serve(soap)) { if (soap->error >= SOAP_STOP) continue; return soap->error; } if (soap_serve_request(soap) || (soap->fserveloop && soap->fserveloop(soap))) {#ifdef WITH_FASTCGI soap_send_fault(soap);#else return soap_send_fault(soap);#endif }#ifdef WITH_FASTCGI soap_destroy(soap); soap_end(soap); } while (1);#else } while (soap->keep_alive);#endif return SOAP_OK;}SOAP_FMAC5 int SOAP_FMAC6 soap_serve_request(struct soap *soap){ soap_peek_element(soap); if (!soap_match_tag(soap, soap->tag, "SOAP-ENV:Fault")) return soap_serve_SOAP_ENV__Fault(soap); if (!soap_match_tag(soap, soap->tag, "d:Hello")) return soap_serve___d__Hello(soap); if (!soap_match_tag(soap, soap->tag, "d:Bye")) return soap_serve___d__Bye(soap); if (!soap_match_tag(soap, soap->tag, "d:Probe")) return soap_serve___d__Probe(soap);......} soap_serve___d__Probe{ sever_probe();} |
5、绑定
这个就是wsdl和soap的结合了。前面的理解没问题的话,这部分就不用关心了。
调通了discovery,只是一个良好的开端。后续还有一堆事情要解决。待续。
6、其他
最后采用的代码是soap_send___wsdd__Probe/soap_recv___wsdd__ProbeMatches,空间不同而已。换用soap_send___wsdd__Probe的时候,出了一个小BUG:设定的timeout 似乎对soap_recv___wsdd__ProbeMatches无效。经排查对比,发现是gsoap版本的差异。
while (result == SOAP_OK)
{
//gsoap2.8.17 block, gsoap2.8.1.10 timeout enable
result = soap_recv___wsdd__ProbeMatches(psoap, &res);
}

浙公网安备 33010602011771号