使用gSOAP生成ONVIF框架协议(离线方式)
时间:2023-06-05 03:07:00
使用gSOAP生成ONVIF框架协议(离线方式)
- 1. 简单介绍
- 2. 写作目的
- 3. 主要内容
-
- 3.1 从在线生成到离线生成
- 3.2 离线生成步骤
- 4. 已完成的资源
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不用担心后生成。
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放进去。
然后我们用windows的终端启动cmd.exe,确保刚刚创建的当前路径onvifCode目录下:
6、然后输入
wsdl2h -P -x -c -s -t ./typemap.dat -o onvif.h http://127.0.0.1:80/ver10/nework/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