最先要申明的一点:onvif开发并不需要编译安装gsoap,gsoap只是用来获取onvif源代码的工具!
一、准备"onvif"源码
需要gsoap来帮助我们将.wdsl生成为.h,最后再生成.c文件。因为wdsl互相之间有相关性,离线安装会出现更多的麻烦(修改更多的配置信息),所以整个过程都在联网状态
完成,虽然比较耗时,但是强烈建议。
gsoap项目地址(需要下载)
http://www.cs.fsu.edu/~engelen/soap.html
onvif项目的wdsl地址(不需要下载)
http://www.onvif.org/Documents/Specifications.aspx中的ONVIF WSDL and XML Schemas Specifications
二、生成源文件
1、准备生成环境(2.8.10以上版本应该不需要这个步骤,2.8.17r并不需要修改typemap.dat!)
解压gsoap到任意文件夹,修改gsoap目录下的typemap.dat文件,gsoap官网对onvif编译的说明如下:
How do I use gSOAP for the ONVIF specifications?
Use gSOAP 2.8.10 and up. In the typemap.dat file used by wsdl2h, add:
- # ONVIF recommended prefixes
- tds = "http://www.onvif.org/ver10/device/wsdl"
- tev = "http://www.onvif.org/ver10/events/wsdl"
- tls = "http://www.onvif.org/ver10/display/wsdl"
- tmd = "http://www.onvif.org/ver10/deviceIO/wsdl"
- timg = "http://www.onvif.org/ver20/imaging/wsdl"
- trt = "http://www.onvif.org/ver10/media/wsdl"
- tptz = "http://www.onvif.org/ver20/ptz/wsdl"
- trv = "http://www.onvif.org/ver10/receiver/wsdl"
- trc = "http://www.onvif.org/ver10/recording/wsdl"
- tse = "http://www.onvif.org/ver10/search/wsdl"
- trp = "http://www.onvif.org/ver10/replay/wsdl"
- tan = "http://www.onvif.org/ver20/analytics/wsdl"
- tad = "http://www.onvif.org/ver10/analyticsdevice/wsdl"
- tdn = "http://www.onvif.org/ver10/network/wsdl"
- tt = "http://www.onvif.org/ver10/schema"
- # OASIS recommended prefixes
- wsnt = "http://docs.oasis-open.org/wsn/b-2"
- wsntw = "http://docs.oasis-open.org/wsn/bw-2"
- wsrfbf = "http://docs.oasis-open.org/wsrf/bf-2"
- wsrfr = "http://docs.oasis-open.org/wsrf/r-2"
- wsrfrw = "http://docs.oasis-open.org/wsrf/rw-2"
- wstop = "http://docs.oasis-open.org/wsn/t-1"
- # WS-Discovery 1.0 remapping
- wsdd10__HelloType = | wsdd__HelloType
- wsdd10__ByeType = | wsdd__ByeType
- wsdd10__ProbeType = | wsdd__ProbeType
- wsdd10__ProbeMatchesType = | wsdd__ProbeMatchesType
- wsdd10__ProbeMatchType = | wsdd__ProbeMatchType
- wsdd10__ResolveType = | wsdd__ResolveType
- wsdd10__ResolveMatchesType = | wsdd__ResolveMatchesType
- wsdd10__ResolveMatchType = | wsdd__ResolveMatchType
- # SOAP-ENV mapping
- SOAP_ENV__Envelope = struct SOAP_ENV__Envelope { struct SOAP_ENV__Header *SOAP_ENV__Header; _XML SOAP_ENV__Body; }; | struct SOAP_ENV__Envelope
- SOAP_ENV__Header = | struct SOAP_ENV__Header
- SOAP_ENV__Fault = | struct SOAP_ENV__Fault
- SOAP_ENV__Detail = | struct SOAP_ENV__Detail
- SOAP_ENV__Code = | struct SOAP_ENV__Code
- SOAP_ENV__Subcode = | struct SOAP_ENV__Subcode
- SOAP_ENV__Reason = | struct SOAP_ENV__Reason
对typemap.dat文件添加如上代码段,并复制到编译目录gsoap\bin\win32(win32对应windows,linux386对应linux,macosx对应macosx)。
2、生成.h文件
进入编译目录gsoap\bin\win32,这时目录下会有3个文件wsdl2h.exe、soapcpp2.exe以及typemap.dat。
运行命令行
- wsdl2h -P -x -c -s -t typemap.dat -o onvif.h <wsdl地址> <wsdl地址> ...
其中<wsdl地址>为http://www.onvif.org/Documents/Specifications.aspx中的ONVIF WSDL and XML Schemas Specifications列表下各个wsdl文件网络位置,用空格分隔
<wsdl地址>举例
- http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl
- http://www.onvif.org/onvif/ver10/events/wsdl/event.wsdl
- http://www.onvif.org/onvif/ver10/display.wsdl
- http://www.onvif.org/onvif/ver10/deviceio.wsdl
- http://www.onvif.org/onvif/ver20/imaging/wsdl/imaging.wsdl
- http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl
- http://www.onvif.org/onvif/ver20/ptz/wsdl/ptz.wsdl
- http://www.onvif.org/onvif/ver10/receiver.wsdl
- http://www.onvif.org/onvif/ver10/recording.wsdl
- http://www.onvif.org/onvif/ver10/search.wsdl
- http://www.onvif.org/onvif/ver10/network/wsdl/remotediscovery.wsdl
- http://www.onvif.org/onvif/ver10/replay.wsdl
- http://www.onvif.org/onvif/ver20/analytics/wsdl/analytics.wsdl
- http://www.onvif.org/onvif/ver10/analyticsdevice.wsdl
- http://www.onvif.org/ver10/actionengine.wsdl
- http://www.onvif.org/ver10/pacs/accesscontrol.wsdl
- http://www.onvif.org/ver10/pacs/doorcontrol.wsdl
- http://www.onvif.org/ver10/advancedsecurity/wsdl/advancedsecurity.wsdl
- http://www.onvif.org/onvif/ver10/schema/onvif.xsd
等待完毕,会生成onvif.h文件在编译目录,大小在3~4m左右,失败的话大小为0k。
如果需要身份验证,修改生成的onvif.h,增加
3、生成.c文件
进入编译目录gsoap\bin\win32,运行命令行
- soapcpp2 -c -x -L -I ../../import -I ../../../gsoap/ onvif.h
使用gsoap版本gSOAP 2.8.17r stable (update) (20.7 MB)出现如下错误(这错误太低级了,完全没有宏保护)
wsa5.h(288): **ERROR**: remote method name clash: struct/class 'SOAP_ENV__Fault'
already declared at line 274
回到gsoap\import目录下修改wsa5.h,将重复申明的部分注释如下。
重新运行上面的生成命令,生成成功。在目录下会生成很多文件,有用的文件如下:soapC.c
soapClient.c
soapServer.c(与soapClient.c根据需要选择其一)
onvif.h
soapH.h
soapStub.h
wsdd.nsmap
除此之外,还需要gsoap-2.8\gsoap目录下的两个文件:
stdsoap2.c
stdsoap2.h
这些文件放在自己的代码目录下即可
四、onvif源码的使用
1、注释soapServer.c中SOAP_ENV__Fault部分代码
编译发生以下错误:
soapServer.c:259: undefined reference to `SOAP_ENV__Fault'
这里有两个解决办法,①如下注释soapServer.c中与这函数有关的代码,②自己实现这个函数。
- SOAP_FMAC5 int SOAP_FMAC6 soap_serve_request(struct soap *soap)
- {
- soap_peek_element(soap);
-
-
- if (!soap_match_tag(soap, soap->tag, "wsdd:Hello"))
- return soap_serve___wsdd__Hello(soap);
- if (!soap_match_tag(soap, soap->tag, "wsdd:Bye"))
- return soap_serve___wsdd__Bye(soap);
- if (!soap_match_tag(soap, soap->tag, "wsdd:Probe"))
- return soap_serve___wsdd__Probe(soap);
- if (!soap_match_tag(soap, soap->tag, "wsdd:ProbeMatches"))
- return soap_serve___wsdd__ProbeMatches(soap);
- if (!soap_match_tag(soap, soap->tag, "wsdd:Resolve"))
- return soap_serve___wsdd__Resolve(soap);
- if (!soap_match_tag(soap, soap->tag, "wsdd:ResolveMatches"))
- return soap_serve___wsdd__ResolveMatches(soap);
- return soap->error = SOAP_NO_METHOD;
- }
2、重定义soapH.h中soap_default_xsd_duration、soap_out_xsd__duration、soap_in_xsd__duration申明
编译发生很多类似以下的错误:
soapC.c:197: undefined reference to `soap_in_xsd__duration'
这里有两个解决办法,①如下修改soapH.h头文件,②项目包含gsoap/custom/duration.c文件(实现在此文件中)
-
- #define soap_default_xsd__duration(soap, a) soap_default_unsignedLONG64(soap, (ULONG64 *)a)
-
- #define soap_out_xsd__duration(soap,a,b,c,d) soap_out_unsignedLONG64(soap, a, b, (ULONG64 *)c, d)
-
- #define soap_in_xsd__duration(soap, a, b, c) (LONG64*)soap_in_unsignedLONG64(soap,a,(ULONG64 *)b,c)
3、实现功能函数
这时候编译我们的代码后会发生如下的错误(错误会有很多,做好思想准备,这里只列出一小部分)
- /alex/discovery/soapServer.c:489: undefined reference to `__tds__GetServices'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetServiceCapabilities':
- /alex/discovery/soapServer.c:530: undefined reference to `__tds__GetServiceCapabilities'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetDeviceInformation':
- /alex/discovery/soapServer.c:571: undefined reference to `__tds__GetDeviceInformation'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__SetSystemDateAndTime':
- /alex/discovery/soapServer.c:612: undefined reference to `__tds__SetSystemDateAndTime'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetSystemDateAndTime':
- /alex/discovery/soapServer.c:653: undefined reference to `__tds__GetSystemDateAndTime'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__SetSystemFactoryDefault':
- /alex/discovery/soapServer.c:694: undefined reference to `__tds__SetSystemFactoryDefault'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__UpgradeSystemFirmware':
- /alex/discovery/soapServer.c:735: undefined reference to `__tds__UpgradeSystemFirmware'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__SystemReboot':
- /alex/discovery/soapServer.c:776: undefined reference to `__tds__SystemReboot'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__RestoreSystem':
- /alex/discovery/soapServer.c:817: undefined reference to `__tds__RestoreSystem'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetSystemBackup':
- /alex/discovery/soapServer.c:858: undefined reference to `__tds__GetSystemBackup'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetSystemLog':
- /alex/discovery/soapServer.c:899: undefined reference to `__tds__GetSystemLog'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetSystemSupportInformation':
- /alex/discovery/soapServer.c:940: undefined reference to `__tds__GetSystemSupportInformation'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetScopes':
- /alex/discovery/soapServer.c:981: undefined reference to `__tds__GetScopes'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__SetScopes':
- /alex/discovery/soapServer.c:1022: undefined reference to `__tds__SetScopes'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__AddScopes':
- /alex/discovery/soapServer.c:1063: undefined reference to `__tds__AddScopes'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__RemoveScopes':
- /alex/discovery/soapServer.c:1104: undefined reference to `__tds__RemoveScopes'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetDiscoveryMode':
- /alex/discovery/soapServer.c:1145: undefined reference to `__tds__GetDiscoveryMode'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__SetDiscoveryMode':
- /alex/discovery/soapServer.c:1186: undefined reference to `__tds__SetDiscoveryMode'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetRemoteDiscoveryMode':
- /alex/discovery/soapServer.c:1227: undefined reference to `__tds__GetRemoteDiscoveryMode'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__SetRemoteDiscoveryMode':
- /alex/discovery/soapServer.c:1268: undefined reference to `__tds__SetRemoteDiscoveryMode'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetDPAddresses':
- /alex/discovery/soapServer.c:1309: undefined reference to `__tds__GetDPAddresses'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetEndpointReference':
- /alex/discovery/soapServer.c:1350: undefined reference to `__tds__GetEndpointReference'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetRemoteUser':
- /alex/discovery/soapServer.c:1391: undefined reference to `__tds__GetRemoteUser'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__SetRemoteUser':
- /alex/discovery/soapServer.c:1432: undefined reference to `__tds__SetRemoteUser'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetUsers':
- /alex/discovery/soapServer.c:1473: undefined reference to `__tds__GetUsers'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__CreateUsers':
- /alex/discovery/soapServer.c:1514: undefined reference to `__tds__CreateUsers'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__DeleteUsers':
- /alex/discovery/soapServer.c:1555: undefined reference to `__tds__DeleteUsers'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__SetUser':
- /alex/discovery/soapServer.c:1596: undefined reference to `__tds__SetUser'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetWsdlUrl':
- /alex/discovery/soapServer.c:1637: undefined reference to `__tds__GetWsdlUrl'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetCapabilities':
- /alex/discovery/soapServer.c:1678: undefined reference to `__tds__GetCapabilities'
- /tmp/cc9R4RNL.o: In function `soap_serve___tds__SetDPAddresses':
- /alex/discovery/soapServer.c:1719: undefined reference to `__tds__SetDPAddresses'
这里便是我们会调用的功能函数,需要自己实现,每个函数都需要实现,但是对于我们不需要的功能函数,只做最简单的定义即可
- int __wsdd__ProbeMatches(struct soap* soap, struct wsdd__ProbeMatchesType *wsdd__ProbeMatches)
- {
- fprintf(stderr,"__wsdd__ProbeMatches\n");
- }
- int __wsdd__Resolve(struct soap* soap, struct wsdd__ResolveType *wsdd__Resolve)
- {
- fprintf(stderr,"__wsdd__Resolve\n");
- }
- int __wsdd__ResolveMatches(struct soap* soap, struct wsdd__ResolveMatchesType *wsdd__ResolveMatches)
- {
- fprintf(stderr,"__wsdd__ResolveMatches\n");
- }
- int __tdn__Hello(struct soap* soap, struct wsdd__HelloType tdn__Hello, struct wsdd__ResolveType *tdn__HelloResponse)
- {
- fprintf(stderr,"__ns1__Hello\n");
- }
- int __tdn__Bye(struct soap* soap, struct wsdd__ByeType tdn__Bye, struct wsdd__ResolveType *tdn__ByeResponse)
- {
- fprintf(stderr,"__ns1__Bye\n");
- }
- int __tdn__Probe(struct soap* soap, struct wsdd__ProbeType tdn__Probe, struct wsdd__ProbeMatchesType *tdn__ProbeResponse)
- {
- fprintf(stderr,"__ns2__Probe\n");
- }
三、onvif开发手册
onvif开发手册
四、调试
1、打开onvif调试开关,以便让onvif打印一些可用的调试信息
在Makefile中添加调试宏定义如
2、打开调试宏后,程序运行目录会产生三个文件:
RECV.log:记录了onvif接收到的SOAP数据
SENT.log:记录了onvif发送出去的SOAP数据
TEST.log:记录了onvif的实时的工作状态
0 0