基于ONVIF协议的(IPC)客户端程序开发-5:使用gSOAP生成ONVIF框架代码
2018-02-05 17:50
896 查看
原文链接:点击打开链接
1. 前言
前一篇文章介绍了什么是ONVIF,也梳理了ONVIF开发流程,本文接着介绍些如何使用gSOAP工具生成ONVIF协议框架代码。本文生成的ONVIF协议框架代码,后续文章都会用到,我这里会考虑生成「大而全」的代码以支撑后续的文章。主要体现在:
一次性把所有可能会用到的WSDL文档都纳入编译,以便得到一份尽可能齐全的ONVIF接口代码。我这样做是为了省事,但我希望你在心底里能明白一件事情:ONVIF有好多个模块,每个模块分别对应着不同的WSDL文档,如果你只是想实现其中某个模块的功能,其实只要拿那个模块对应的WSDL文档来编译即可(可以忽略其他WSDL)。比如你只是想实现「设备发现」功能,只要拿remotediscovery.wsdl来编译即可。
为了让代码同时兼容Windows和Linux两个平台(未考虑其他平台),在我后续专栏中的示例代码都会做一些兼容性的处理。如果你是用Windows来开发,那得用Microsoft Visual Studio SP1(或更高版本),后续会涉及到SOAP协议数据「中文字符乱码」的问题,Microsoft Visual Studio SP1以下的版本不好处理。
把我所遇到的问题尽可能的提前进行说明,至于没其他问题,只能大家自己搞定了,也欢迎大家来一起交流(留言/邮箱)
要用gsoap生成onvif源码,必须用到wsdl2h和soapcpp2两个工具(执行文件)。在gsoap\bin目录下,win32和macosx平台已经有现成的了(官方帮我们编译好了的),linux下的要自己编译咯,可参考INSTALL.txt文件进行编译安装(不同gSOAP版本的编译安装方法会略有不同,以你gSOAP版本中的INSTALL.txt为准)。
通过实验证实,wsdl2h和soapcpp2两个工具,不管是Windows版的,还是Linux版的,它们从WSDL转成的框架代码,是一样样的,没有区别。
既然有现成的Windows版wsdl2h.exe,那就直接拿来用咯。结果让人沮丧,在从ONVIF的WSDL转为头文件时出错,错误信息如下:
从提示信息也能看出大概意思,就是wsdl2h不支持SSL/TLS,无法下载HTTPS文件。我2016年9月份也有用gSOAP生成ONVIF代码,为啥没碰到这个问题,而现在(2017年4月25日)却碰到了?
早期,ONVIF的WSDL文档URL地址是HTTP开头的(不会出现这个问题),2017年3月底ONVIF官网进行了一次改版,改版之后WSDL的URL地址变成HTTPS的了,即使你访问早期的HTTP地址,如:
http://www.onvif.org/onvif/ver10/network/wsdl/remotediscovery.wsdl
最终也会被跳转到HTTPS地址:
https://www.onvif.org/onvif/ver10/network/wsdl/remotediscovery.wsdl
gSOAP官方提供的、已编译好的wsdl2h默认是禁用SSL/TLS的,所以不支持HTTPS下载WSDL文件。至少我的版本gsoap_2.8.45是如此,未来的版本会如何只能靠大家自己尝试。根据出错的提示信息,有两种解决办法:
重新编译gSOAP源码,生成带SSL/TLS的wsdl2h工具。
自己手动下载WSDL文档后,再用本地WSDL文档执行wsdl2h命令。
网上很多教程有提到使用第2种方法,这对其他的WSDL文档可能合适,但对ONVIF的WSDL不合适,ONVIF的WSDL文档会依赖其他WSDL和xsd文档,依赖关系隐藏在每个WSDL文档中,一般人很难厘清这里面复杂的依赖关系,容易出错,也整不清楚xsd文件该从哪里下载。
所以这里推荐用第1种方法,如何编译gSOAP源码,以便得到开启SSL/TLS的wsdl2h,不同版本的gSOAP方法不同,具体要参考对应gSOAP版本中的INSTALL.txt文件说明。
下面介绍下如何在linux平台下重新编译gSOAP源码,以便得到开启SSL/TLS的wsdl2h,从而让wsdl2h支持HTTPS。
http://blog.csdn.net/u011425939/article/details/79258335
gSOAP官网上有一篇文章「How do I use gSOAP with the ONVIF specifications」,专门介绍如何使用gSOAP生成ONVIF框架代码,链接如下:
地址:https://www.genivia.com/resources.html
找到「How do I use gSOAP with the ONVIF specifications」章节。
操作步骤如下:
(1). 参考gSOAP官网说明修改gsoap\typemap.dat
参考「How do I use gSOAP with the ONVIF specifications」(https://www.genivia.com/resources.html)说明,看是否需要修改typemap.dat。我用的gSOAP工具版本是gsoap_2.8.45,typemap.dat文件刚好符合要求,不用改。
(2). 使用wsdl2h工具,根据WSDL产生头文件
a、在线生成onvif.h
编写脚本文件https_wsdl_to_onvif_h_build.sh
编写脚本local_wsdl_to_onvif_h_build.sh
修改每个wsdl文件的schemaLocation或location
例如:
schemaLocation="../ver10/schema/onvif.xsd"/ schemaLocation="./onvif.xsd"/ //修改成本地onvif.xsd的路径location="../ver10/device/wsdl/devicemgmt.wsdl"/> location="../build/local/wsdl/devicemgmt.wsdl" //修改成本
地devicemgmt.wsdl的路径
wsdl2h相关命令参数
-c 产生c语言的代码,否则产生C++
-s 不使用STL代码
-t 指定typemap.dat文件
-o 指定生成的头文件名
具体用wsdl2h.exe -help查看帮助
(3). 因「鉴权(认证)」需要,修改onvif.h头文件
有些ONVIF接口调用时需要携带认证信息,要使用soap_wsse_add_UsernameTokenDigest函数进行授权,所以要在onvif.h头文件开头加入
编写脚本onvif_build.sh
-2
采用SOAP1.2
-x
不产生xml文件(不推荐使用此命令,因为xml文档很有用)
-I
为引入路径(注意:I为i的大写)
-C
只产生客户端代码(注意:C是大写)
具体通过soapcpp2.exe -help查看帮助。
根据不同的gSOAP版本,这个过程你可能会遇到这样的错误:
(5). 拷贝其他还有会用的源码
$ cp
stdsoap2.c
stdsoap2.h
wsaapi.c
wsaapi.h
duration.c
duration.h
wsseapi.h
wsseapi.c
smdevp.h
smdevp.c
mecevp.h
mecevp.c
threads.c
threads.h
dom.c
dom.h
soapC.c会调用到soap_in_xsd__duration函数,需要duration.c和duration.h文件。
后续示例代码会调用到soap_wsa_rand_uuid函数(用于生成UUID),需要wsaapi.c和wsaapi.h文件。
(6). 关联自己的命名空间,修改stdsoap2.c文件
在samples\onvif\stdsoap2.h中有命名空间「namespaces变量」的定义声明,如下所示:
(7). 大功告成
至此,我开发IPC客户端程序要用到的ONVIF框架代码已经生成。我专栏里的上层实例代码就是基于这份ONVIF框架代码而开发的。
1. 前言
前一篇文章介绍了什么是ONVIF,也梳理了ONVIF开发流程,本文接着介绍些如何使用gSOAP工具生成ONVIF协议框架代码。本文生成的ONVIF协议框架代码,后续文章都会用到,我这里会考虑生成「大而全」的代码以支撑后续的文章。主要体现在:
一次性把所有可能会用到的WSDL文档都纳入编译,以便得到一份尽可能齐全的ONVIF接口代码。我这样做是为了省事,但我希望你在心底里能明白一件事情:ONVIF有好多个模块,每个模块分别对应着不同的WSDL文档,如果你只是想实现其中某个模块的功能,其实只要拿那个模块对应的WSDL文档来编译即可(可以忽略其他WSDL)。比如你只是想实现「设备发现」功能,只要拿remotediscovery.wsdl来编译即可。
为了让代码同时兼容Windows和Linux两个平台(未考虑其他平台),在我后续专栏中的示例代码都会做一些兼容性的处理。如果你是用Windows来开发,那得用Microsoft Visual Studio SP1(或更高版本),后续会涉及到SOAP协议数据「中文字符乱码」的问题,Microsoft Visual Studio SP1以下的版本不好处理。
把我所遇到的问题尽可能的提前进行说明,至于没其他问题,只能大家自己搞定了,也欢迎大家来一起交流(留言/邮箱)
2. wsdl2h和soapcpp2简介
要用gsoap生成onvif源码,必须用到wsdl2h和soapcpp2两个工具(执行文件)。在gsoap\bin目录下,win32和macosx平台已经有现成的了(官方帮我们编译好了的),linux下的要自己编译咯,可参考INSTALL.txt文件进行编译安装(不同gSOAP版本的编译安装方法会略有不同,以你gSOAP版本中的INSTALL.txt为准)。通过实验证实,wsdl2h和soapcpp2两个工具,不管是Windows版的,还是Linux版的,它们从WSDL转成的框架代码,是一样样的,没有区别。
3. wsdl2h不支持HTTPS
既然有现成的Windows版wsdl2h.exe,那就直接拿来用咯。结果让人沮丧,在从ONVIF的WSDL转为头文件时出错,错误信息如下:wsdl2h.exe -P -x -o onvif.h -c -s -t typemap.dat https://www.onvif.org/ver10/network/wsdl/remotediscovery.wsdl https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl https://www.onvif.org/ver10/media/wsdl/media.wsdl Saving onvif.h ** The gSOAP WSDL/WADL/XSD processor for C and C++, wsdl2h release 2.8.45 ** Copyright (C) 2000-2017 Robert van Engelen, Genivia Inc. ** All Rights Reserved. This product is provided "as is", without any warranty. ** The wsdl2h tool and its generated software are released under the GPL. ** ---------------------------------------------------------------------------- ** A commercial use license is available from Genivia Inc., contact@genivia.com ** ---------------------------------------------------------------------------- Reading type definitions from type map "typemap.dat" Cannot connect to https site: SSL/TLS support not enabled, please rebuild wsdl2h with SSL/TLS enabled using 'make secure' or download the WSDL/WADL and XSD files and rerun wsdl2h on these files directly by specifying the file names on the command line.
从提示信息也能看出大概意思,就是wsdl2h不支持SSL/TLS,无法下载HTTPS文件。我2016年9月份也有用gSOAP生成ONVIF代码,为啥没碰到这个问题,而现在(2017年4月25日)却碰到了?
早期,ONVIF的WSDL文档URL地址是HTTP开头的(不会出现这个问题),2017年3月底ONVIF官网进行了一次改版,改版之后WSDL的URL地址变成HTTPS的了,即使你访问早期的HTTP地址,如:
http://www.onvif.org/onvif/ver10/network/wsdl/remotediscovery.wsdl
最终也会被跳转到HTTPS地址:
https://www.onvif.org/onvif/ver10/network/wsdl/remotediscovery.wsdl
gSOAP官方提供的、已编译好的wsdl2h默认是禁用SSL/TLS的,所以不支持HTTPS下载WSDL文件。至少我的版本gsoap_2.8.45是如此,未来的版本会如何只能靠大家自己尝试。根据出错的提示信息,有两种解决办法:
重新编译gSOAP源码,生成带SSL/TLS的wsdl2h工具。
自己手动下载WSDL文档后,再用本地WSDL文档执行wsdl2h命令。
网上很多教程有提到使用第2种方法,这对其他的WSDL文档可能合适,但对ONVIF的WSDL不合适,ONVIF的WSDL文档会依赖其他WSDL和xsd文档,依赖关系隐藏在每个WSDL文档中,一般人很难厘清这里面复杂的依赖关系,容易出错,也整不清楚xsd文件该从哪里下载。
所以这里推荐用第1种方法,如何编译gSOAP源码,以便得到开启SSL/TLS的wsdl2h,不同版本的gSOAP方法不同,具体要参考对应gSOAP版本中的INSTALL.txt文件说明。
4. 编译gSOAP源码让wsdl2h支持HTTPS
下面介绍下如何在linux平台下重新编译gSOAP源码,以便得到开启SSL/TLS的wsdl2h,从而让wsdl2h支持HTTPS。
4.1 编译gSOAP源
http://blog.csdn.net/u011425939/article/details/79258335
5. 使用gSOAP生成ONVIF框架代码
gSOAP官网上有一篇文章「How do I use gSOAP with the ONVIF specifications」,专门介绍如何使用gSOAP生成ONVIF框架代码,链接如下:地址:https://www.genivia.com/resources.html
找到「How do I use gSOAP with the ONVIF specifications」章节。
操作步骤如下:
(1). 参考gSOAP官网说明修改gsoap\typemap.dat
参考「How do I use gSOAP with the ONVIF specifications」(https://www.genivia.com/resources.html)说明,看是否需要修改typemap.dat。我用的gSOAP工具版本是gsoap_2.8.45,typemap.dat文件刚好符合要求,不用改。
(2). 使用wsdl2h工具,根据WSDL产生头文件
a、在线生成onvif.h
编写脚本文件https_wsdl_to_onvif_h_build.sh
#!/bin/sh ./wsdl2h -P -x -c -s -t ./typemap.dat -o ../build/local/onvif.h \ ../build/local/wsdl/remotediscovery.wsdl \ ../build/local/wsdl/devicemgmt.wsdl \ ../build/local/wsdl/accesscontrol.wsdl \ ../build/local/wsdl/accessrules.wsdl \ ../build/local/wsdl/actionengine.wsdl \ ../build/local/wsdl/advancedsecurity.wsdl \ ../build/local/wsdl/analytics.wsdl \ ../build/local/wsdl/credential.wsdl \ ../build/local/wsdl/deviceio.wsdl \ ../build/local/wsdl/display.wsdl \ ../build/local/wsdl/doorcontrol.wsdl \ ../build/local/wsdl/imaging.wsdl \ ../build/local/wsdl/media.wsdl \ ../build/local/wsdl/media2.wsdl \ ../build/local/wsdl/provisioning.wsdl \ ../build/local/wsdl/ptz.wsdl \ ../build/local/wsdl/receiver.wsdl \ ../build/local/wsdl/recording.wsdl \ ../build/local/wsdl/search.wsdl \ ../build/local/wsdl/replay.wsdl \ ../build/local/wsdl/schedule.wsdl \ ../build/local/wsdl/thermal.wsdl \ ../build/local/wsdl/analyticsdevice.wsdl \ ../build/local/wsdl/event.wsdl \b、离线生成onvif.h文件
编写脚本local_wsdl_to_onvif_h_build.sh
./wsdl2h -P -x -c -s -t ./typemap.dat -o ../build/local/onvif.h \ ../build/local/wsdl/remotediscovery.wsdl \ ../build/local/wsdl/devicemgmt.wsdl \ ../build/local/wsdl/accesscontrol.wsdl \ ../build/local/wsdl/accessrules.wsdl \ ../build/local/wsdl/actionengine.wsdl \ ../build/local/wsdl/advancedsecurity.wsdl \ ../build/local/wsdl/analytics.wsdl \ ../build/local/wsdl/credential.wsdl \ ../build/local/wsdl/deviceio.wsdl \ ../build/local/wsdl/display.wsdl \ ../build/local/wsdl/doorcontrol.wsdl \ ../build/local/wsdl/imaging.wsdl \ ../build/local/wsdl/media.wsdl \ ../build/local/wsdl/media2.wsdl \ ../build/local/wsdl/provisioning.wsdl \ ../build/local/wsdl/ptz.wsdl \ ../build/local/wsdl/receiver.wsdl \ ../build/local/wsdl/recording.wsdl \ ../build/local/wsdl/search.wsdl \ ../build/local/wsdl/replay.wsdl \ ../build/local/wsdl/schedule.wsdl \ ../build/local/wsdl/thermal.wsdl \ ../build/local/wsdl/analyticsdevice.wsdl \ ../build/local/wsdl/event.wsdl \
修改每个wsdl文件的schemaLocation或location
例如:
schemaLocation="../ver10/schema/onvif.xsd"/ schemaLocation="./onvif.xsd"/ //修改成本地onvif.xsd的路径location="../ver10/device/wsdl/devicemgmt.wsdl"/> location="../build/local/wsdl/devicemgmt.wsdl" //修改成本
地devicemgmt.wsdl的路径
wsdl2h相关命令参数
-c 产生c语言的代码,否则产生C++
-s 不使用STL代码
-t 指定typemap.dat文件
-o 指定生成的头文件名
具体用wsdl2h.exe -help查看帮助
(3). 因「鉴权(认证)」需要,修改onvif.h头文件
有些ONVIF接口调用时需要携带认证信息,要使用soap_wsse_add_UsernameTokenDigest函数进行授权,所以要在onvif.h头文件开头加入
#import "wsse.h"如果onvif.h不加入,使用soap_wsse_add_UsernameTokenDigest函数会导致编译出错(错误信息如下):
wsse2api.c(183): error C2039: “wsse__Security”: 不是“SOAP_ENV__Header”的成员(4). 使用soapcpp2工具,根据头文件产生框架代码
编写脚本onvif_build.sh
./soapcpp2 -C -s -2 -d ../build/local/c -x -I./import/ -I ./custom ../build/local/onvif.hsoapcpp2相关命令参数
-2
采用SOAP1.2
-x
不产生xml文件(不推荐使用此命令,因为xml文档很有用)
-I
为引入路径(注意:I为i的大写)
-C
只产生客户端代码(注意:C是大写)
具体通过soapcpp2.exe -help查看帮助。
根据不同的gSOAP版本,这个过程你可能会遇到这样的错误:
wsa5.h(288): **ERROR**: service operation name clash: struct/class 'SOAP_ENV__Fault' already declared at wsa.h:273之所有会出现这个错误,是因为onvif.h头文件中同时:
#import "wsdd10.h" // wsdd10.h中又#import "wsa.h" #import "wsa5.h" // wsa.h和wsa5.h两个文件重复定义了int SOAP_ENV__Fault解决方法:修改import\wsa5.h文件,将int SOAP_ENV__Fault 注释.
/* int SOAP_ENV__Fault ( _QName faultcode,// SOAP 1.1 char *faultstring, //SOAP 1.1 char *faultactor, //SOAP 1.1 struct SOAP_ENV__Detail *detail,// SOAP 1.1 struct SOAP_ENV__Code *SOAP_ENV__Code,// SOAP1.2 struct SOAP_ENV__Reason *SOAP_ENV__Reason, // SOAP 1.2 char *SOAP_ENV__Node,// SOAP 1.2 char *SOAP_ENV__Role,// SOAP 1.2 struct SOAP_ENV__Detail *SOAP_ENV__Detail,// SOAP 1.2 void); */再执行脚本onvif_build.sh编译成功
Using tse schema namespace: http://www.onvif.org/ver10/search/wsdl Saving ../build/https/c/SearchBinding.nsmap namespace mapping table Saving ../build/https/c/soapClient.c client call stub functions Saving ../build/https/c/soapClientLib.c client stubs with serializers (use only for libs) Saving ../build/https/c/soapC.c serialization functions Compilation successful (2 warnings)
(5). 拷贝其他还有会用的源码
$ cp
stdsoap2.c
stdsoap2.h
wsaapi.c
wsaapi.h
duration.c
duration.h
wsseapi.h
wsseapi.c
smdevp.h
smdevp.c
mecevp.h
mecevp.c
threads.c
threads.h
dom.c
dom.h
soapC.c会调用到soap_in_xsd__duration函数,需要duration.c和duration.h文件。
后续示例代码会调用到soap_wsa_rand_uuid函数(用于生成UUID),需要wsaapi.c和wsaapi.h文件。
(6). 关联自己的命名空间,修改stdsoap2.c文件
在samples\onvif\stdsoap2.h中有命名空间「namespaces变量」的定义声明,如下所示:
extern SOAP_NMAC struct Namespace namespaces[];但「namespaces变量」的定义实现,是在samples\onvif\wsdd.nsmap文件中,为了后续应用程序要顺利编译,修改samples\onvif\stdsoap2.c文件,在开头加入:
#include "wsdd.nsmap"当然,你可以在其他源码中(更上层的应用程序源码)include,我这里是选择在stdsoap2.c中include
(7). 大功告成
至此,我开发IPC客户端程序要用到的ONVIF框架代码已经生成。我专栏里的上层实例代码就是基于这份ONVIF框架代码而开发的。
$ ls -l onvif/ 总用量 9796 -rwxrwxrwx 1 root root 2254 4月 27 17:02 DeviceBinding.nsmap -rwxrwxrwx 1 root root 6725 4月 29 14:30 duration.c -rwxrwxrwx 1 root root 4051 4月 29 14:30 duration.h -rwxrwxrwx 1 root root 2254 4月 27 17:02 MediaBinding.nsmap -rwxrwxrwx 1 root root 3031182 4月 27 16:57 onvif.h -rwxrwxrwx 1 root root 2254 4月 27 17:02 RemoteDiscoveryBinding.nsmap -rwxrwxrwx 1 root root 9277873 4月 27 17:02 soapC.c -rwxrwxrwx 1 root root 406017 4月 27 17:02 soapClient.c -rwxrwxrwx 1 root root 5158122 4月 27 17:02 soapH.h -rwxrwxrwx 1 root root 1344868 4月 27 17:02 soapStub.h -rwxrwxrwx 1 root root 593718 4月 29 14:30 stdsoap2.c -rwxrwxrwx 1 root root 151026 4月 29 14:30 stdsoap2.h -rwxrwxrwx 1 root root 64006 4月 29 14:29 wsaapi.c -rwxrwxrwx 1 root root 7153 4月 29 14:29 wsaapi.h -rwxrwxrwx 1 root root 2254 4月 27 17:02 wsdd.nsmap其中onvif.h文件其实已经没用了,可以删掉,不需要参与后续IPC客户端程序的编译。这里有好多个命名空间的.nsmap文件,文件内容都一模一样,拿wsdd.nsmap一个来用即可,其他也没卵用。
相关文章推荐
- 基于ONVIF协议的(IPC)客户端程序开发-3:使用gSOAP生成Web Services框架代码
- ONVIF协议网络摄像机(IPC)客户端程序开发(4):使用gSOAP生成Web Services框架代码
- ONVIF协议网络摄像机(IPC)客户端程序开发(6):使用gSOAP生成ONVIF框架代码
- ONVIF协议网络摄像机(IPC)客户端程序开发(6):使用gSOAP生成ONVIF框架代码
- 基于ONVIF协议的(IPC)客户端程序开发-6:Gsoap-2.8编译
- ONVIF协议网络摄像机(IPC)客户端程序开发(2):第一次使用IPC摄像头
- 基于ONVIF协议的(IPC)客户端程序开发-14 修改分辨率
- 基于ONVIF协议的(IPC)客户端程序开发-1:测试工具(ONVIF Device Test Tool)
- 基于ONVIF协议的(IPC)客户端程序开发-2:Web Services
- 基于ONVIF协议的(IPC)客户端程序开发-8:获取设备基本信息
- 基于ONVIF协议的(IPC)客户端程序开发-15 遮挡报警
- 基于ONVIF协议的(IPC)客户端程序开发-10 设备校时
- 基于ONVIF协议的(IPC)客户端程序开发-12 读取音视频流
- 基于ONVIF协议的(IPC)客户端程序开发-4:onvif协议有soap和rtsp协议组成
- 基于ONVIF协议的(IPC)客户端程序开发-11 设备能力
- 基于ONVIF协议的(IPC)客户端程序开发-9 鉴权(认证)
- 基于ONVIF协议的(IPC)客户端程序开发-7:设备搜索
- ONVIF协议网络摄像机(IPC)客户端程序开发(2):第一次使用IPC摄像头
- 基于ONVIF协议的(IPC)客户端程序开发-13 图像抓拍
- onvif协议开发:gsoap代码框架生成命令