使用gSOAP生成ONVIF框架协议(离线方式)

1. 简单介绍

简单介绍一下:ONVIF标准是一种使用SOAP的方式实现与Web Services交互的协议,通俗的讲就是这个协议需要我们采用XML这种格式与类服务器进行基于BS架构的通信,而这种XML格式就是由XML Schema来约定的,这种约定接口的文件就叫WSDL(Web Services Description Language,网络服务描述语言)。

想要理解gSOAP和ONVIF协议建议仔细看一看该博客:ONVIF协议网络摄像机(IPC)客户端程序开发点这里,这个大神确实讲得足够详细了。

2. 写作目的

首先我不得不吐槽一下国内技术文档的大环境(我不是吐槽全部,还是有非常多的人在为我们铺路),许多博客都在互相转发,从仅有的几个博客出发,内容也都差不多。关于采用gSOAP生成onvif协议C++的方式,我与许振坪大神的内容不一样,在此我也要推荐另一个博客点这里,我也是在陈源荣博客基础上实现了离线生成的方式,但是他略有些粗糙不太详细,我仅把这两位大神的方式结合一下发表出来,希望能帮到大家。

3. 主要内容

3.1 从在线生成转为离线生成

我之前一直想用在线生成onvif的方式,但是gSOAP不支持SSL啊,于是需要重新编译支持SSL的gSOAP工具,其中就需要OpenSSL的几个链接库,结果发现OpenSSL官网上编译好的有几个库没给我们,于是还需要编译OpenSSL,我搞了几天受不了了,决定尝试一下离线生成的方式。

所谓离线方式,就是我们自己手动下载onvif官网上的wsdl文件,然后自己重新创建没有加密的连接,供gSOAP使用。

3.2 离线生成方式步骤

1、我们下载gSOAP工具,gSOAP官方网址:http://www.cs.fsu.edu/~engelen/soap.html。我下载的是gsoap_2.8.114,一个压缩包。

2、我们粗略下载wsdl文件,肯定是下载不全的,不过不用怕我们后面生成的时候会有提示,稍微有点多,但也不是非常多。进入网页后右键点击保存即可。

http://www.onvif.org/onvif/ver10/network/wsdl/remotediscovery.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/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/replay.wsdl
http://www.onvif.org/onvif/ver20/analytics/wsdl/analytics.wsdl
http://www.onvif.org/onvif/ver10/analyticsdevice.wsdl
http://www.onvif.org/onvif/ver10/schema/onvif.xsd
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/ver10/accessrules/wsdl/accessrules.wsdl
http://www.onvif.org/ver10/credential/wsdl/credential.wsdl
http://www.onvif.org/ver10/schedule/wsdl/schedule.wsdl
http://www.onvif.org/ver10/pacs/types.xsd

3、重点来了: 我们把下载的文件放到对应的文件夹下面,比如:
http://www.onvif.org/onvif/ver10/network/wsdl/remotediscovery.wsdl
我们创建一个onvif文件夹(我创建的叫),里面再创建一个ver10文件夹,然后里面再创建…确保remotediscovery.wsdl的路径是一样的,像下面这样。
在这里插入图片描述

4、最终我们弄到了一个文件夹下,然后我们重新创建一个文件夹叫onvifCode,接着把gSOAP的文件复制进去。

gsoap_2.8.45\gsoap-2.8\gsoap\bin\win32\soapcpp2.exe
gsoap_2.8.45\gsoap-2.8\gsoap\bin\win32\wsdl2h.exe
gsoap_2.8.45\gsoap-2.8\gsoap\stdsoap2.c
gsoap_2.8.45\gsoap-2.8\gsoap\stdsoap2.h
gsoap_2.8.45\gsoap-2.8\gsoap\typemap.dat
gsoap_2.8.45\gsoap-2.8\gsoap\import
gsoap_2.8.45\gsoap-2.8\gsoap\custom\

onvif.h是后生成的不要担心
onvif.h是后生成的不要担心。

4、这时候我们需要搭建反向代理web服务器,这样我们能够通过http访问我们的wsdl文件,我这里采用Nginx (engine x),想了解百度就挺全了。
Nginx官网:http://nginx.org/en/download.html
下载后找到nginx-1.20.0\nginx-1.20.0\conf\nginx.conf,可以进行相关配置,我这里就没动:访问的时候http://217.0.0.1:80 就是root路径,就是html路径(能看到根目录下有个html文件夹),我们把刚才创建的ver10、ver20放进去。
在这里插入图片描述
在这里插入图片描述

5、接着我们用windows的终端启动cmd.exe,确保当前路径在刚才创建的onvifCode目录下:
在这里插入图片描述
6、然后输入

wsdl2h -P -x -c -s -t ./typemap.dat -o onvif.h http://127.0.0.1:80/ver10/network/wsdl/remotediscovery.wsdl http://127.0.0.1:80/ver10/device/wsdl/devicemgmt.wsdl http://127.0.0.1:80/ver10/events/wsdl/event.wsdl http://127.0.0.1:80/ver10/display.wsdl http://127.0.0.1:80/ver10/deviceio.wsdl  http://127.0.0.1:80/ver20/imaging/wsdl/imaging.wsdl http://127.0.0.1:80/ver10/media/wsdl/media.wsdl  http://127.0.0.1:80/ver20/media/wsdl/media.wsdl  http://127.0.0.1:80/ver20/ptz/wsdl/ptz.wsdl  http://127.0.0.1:80/ver10/receiver.wsdl http://127.0.0.1:80/ver10/recording.wsdl http://127.0.0.1:80/ver10/search.wsdl  http://127.0.0.1:80/ver10/replay.wsdl  http://127.0.0.1:80/ver20/analytics/wsdl/analytics.wsdl   http://127.0.0.1:80/ver10/analyticsdevice.wsdl http://127.0.0.1:80/ver10/schema/onvif.xsd http://127.0.0.1:80/ver10/actionengine.wsdl http://127.0.0.1:80/ver10/pacs/accesscontrol.wsdl   http://127.0.0.1:80/ver10/pacs/doorcontrol.wsdl   http://127.0.0.1:80/ver10/advancedsecurity/wsdl/advancedsecurity.wsdl   http://127.0.0.1:80/ver10/accessrules/wsdl/accessrules.wsdl   http://127.0.0.1:80/ver10/credential/wsdl/credential.wsdl   http://127.0.0.1:80/ver10/schedule/wsdl/schedule.wsdl  http://127.0.0.1:80/ver10/pacs/types.xsd

会出现报错,缺少文件,这时候我们下载对应文件补充到对应目录下,我们再重新生成onvif.h,这里记住每次重新生成的时候要把原来的onvif.h删掉。
7、我们按照这个博客https://blog.csdn.net/benkaoya/article/details/72466827的第三步开始。
因「鉴权(认证)」需要,修改onvif.h头文件,有些ONVIF接口调用时需要携带认证信息,要使用soap_wsse_add_UsernameTokenDigest函数进行授权,所以要在onvif.h头文件开头加入

#import "wsse.h"

如果onvif.h不加入#import “wsse.h”,使用soap_wsse_add_UsernameTokenDigest函数会导致编译出错(错误信息如下):

wsse2api.c(183): error C2039: “wsse__Security”: 不是“SOAP_ENV__Header”的成员

使用soapcpp2工具,根据头文件产生框架代码

$ soapcpp2 -2 -C -L -c -x -Iimport -Icustom -d onvif/ onvif.h

$ soapcpp2 -2 -C -L -c -x -Iimport -Icustom -d onvif/ onvif.h

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_alex,再次使用soapcpp2工具编译就成功了,命令执行过程如下:

$ soapcpp2 -2 -C -L -c -x -Iimport -Icustom -d onvif/ onvif.h

**  The gSOAP code generator for C and C++, soapcpp2 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 soapcpp2 tool and its generated software are released under the GPL.
**  ----------------------------------------------------------------------------
**  A commercial use license is available from Genivia Inc., contact@genivia.com
**  ----------------------------------------------------------------------------


soap12.h(54): *WARNING*: option -1 or -2 overrides SOAP-ENV namespace


soap12.h(55): *WARNING*: option -1 or -2 overrides SOAP-ENC namespace

Using project directory path: onvif/
Saving onvif/soapStub.h annotated copy of the source interface file
Saving onvif/soapH.h serialization functions to #include in projects
Using wsdd service name: wsdd
Using wsdd service style: document
Using wsdd service encoding: literal
Using wsdd schema import namespace: http://schemas.xmlsoap.org/ws/2005/04/discovery
Saving onvif/wsdd.nsmap namespace mapping table
Using tdn service name: RemoteDiscoveryBinding
Using tdn service style: document
Using tdn service encoding: literal
Using tdn schema namespace: http://www.onvif.org/ver10/network/wsdl
Saving onvif/RemoteDiscoveryBinding.nsmap namespace mapping table
Using tds service name: DeviceBinding
Using tds service style: document
Using tds service encoding: literal
Using tds schema namespace: http://www.onvif.org/ver10/device/wsdl
Saving onvif/DeviceBinding.nsmap namespace mapping table
Using trt service name: MediaBinding
Using trt service style: document
Using trt service encoding: literal
Using trt schema namespace: http://www.onvif.org/ver10/media/wsdl
Saving onvif/MediaBinding.nsmap namespace mapping table
Saving onvif/soapClient.c client call stub functions
Saving onvif/soapC.c serialization functions

Compilation successful (2 warnings)

拷贝其他还有会用的源码 就是把对应的文件拷贝到生成目录里面去

$ cp stdsoap2.c stdsoap2.h plugin/wsaapi.c plugin/wsaapi.h custom/duration.c custom/duration.h  onvif/

soapC.c会调用到soap_in_xsd__duration函数,需要duration.c和duration.h文件。

后续示例代码会调用到soap_wsa_rand_uuid函数(用于生成UUID),需要wsaapi.c和wsaapi.h文件。

关联自己的命名空间,修改stdsoap2.c文件
在onvif\stdsoap2.h中有命名空间「namespaces变量」的定义声明,如下所示:

extern SOAP_NMAC struct Namespace namespaces[];

但「namespaces变量」的定义实现,是在onvif\wsdd.nsmap文件中,为了后续应用程序要顺利编译,修改onvif\stdsoap2.c文件,在开头加入:

#include "wsdd.nsmap"

当然,你可以在其他源码中(更上层的应用程序源码)include,我这里是选择在stdsoap2.c中include

在这里插入图片描述

4. 已完成的资源

我自己也弄完了一版,大家可以走个捷径下载用用,一方面节省了大家的精力,反正也都会生成了,另一方面也没有必要非要在这个地方浪费时间,我也会根据大家需求不定时为大家更新资源。现成协议下载
https://download.csdn.net/download/zmxzmx110/19023799

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值