一、前言
上一篇介绍了onvif协议,介绍了onvif概念以及相关概念的解释,如Web Service、WSDL、SOAP等,这篇将利用gSOAP源码来生成onvif代码框架。
二、安装
1)安装所需依赖
apt install bison
apt install flex
apt install libssl-dev
apt install automake
2)下载gSOAP源码
下载网址:https://sourceforge.net/projects/gsoap2/files/
3)编译安装
1.创建一个目录/work/onvif,将刚刚下载的gSOAP源码放到onvif目录下解压
mkdir /work/onvif
cd /work/onvif/
unzip gsoap_2.8.134.zip
2.创建gsoap安装目录gsoap-install
mkdir /work/onvif/gsoap-install
3. 进入源码目录
cd /work/onvif/gsoap-2.8
4.配置
./configure --prefix /work/onvif/gsoap-install
5.编译并安装
make
make install
在/work/onvif/gsoap-install下包含四个文件夹:
bin包含两个可执行程序soapcpp2 wsdl2h
- wsdl2h:根据WSDL文件生成头文件
- soapcpp2:根据wsdl2h生成的头文件(或者自己写的头文件)生成SOAP Web Services代码框架(RPC + HTTP + XML)
share在后面生成ONVIF服务端/客户端代码框架的时候会用到
6.添加内容
当框架完成搭建后编译时,有的小伙伴可能编译通过了,有些可能不行。
若发生编译出错,提示了 duration 缺少什么定义,或者类型不对,报错 LONG64 错误等
在/work/onvif/ gsoap-2.8/gsoap/typemap.dat 文件添加如下内容,从新生成代码代码编译即可
若编译未出错可跳过此步
三、利用gSOAP生成onvif代码框架
1)创建目录
1.创建/work/onvif/onvif-code目录,用来生成onvif服务端客户端代码
mkdir /work/onvif/onvif-code
cd /work/onvif/onvif-code
2.把安装目录的bin和share里面的gsoap文件夹拷贝到/work/onvif/onvif-code下面
cp -r /work/onvif/gsoap-install/bin .
cp -r /work/onvif/gsoap-install/share/gsoap .
3.还需要把源码里面gsoap(/work/onvif/gsoap-2.8/gsoap/)里面的dom.c dom.cpp stdsoap2.c stdsoap2.cpp stdsoap2.h拷贝到/work/onvif/onvif-code/gsoap下面
cp /work/onvif/gsoap-2.8/gsoap/dom.c ./gsoap/
cp /work/onvif/gsoap-2.8/gsoap/dom.cpp ./gsoap/
cp /work/onvif/gsoap-2.8/gsoap/stdsoap2.c ./gsoap/
cp /work/onvif/gsoap-2.8/gsoap/stdsoap2.cpp ./gsoap/
cp /work/onvif/gsoap-2.8/gsoap/stdsoap2.h ./gsoap/
2)生成头文件
1.在/work/onvif/onvif-code目录下创建一个脚本onvif_head.sh,用来生成头文件
#!/bin/bash
mkdir onvif_head
cd onvif_head
../bin/wsdl2h -o onvif.h -s -c -d -x -t ../gsoap/WS/typemap.dat \
http://www.onvif.org/onvif/ver10/network/wsdl/remotediscovery.wsdl \
https://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl \
http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl \
http://www.onvif.org/onvif/ver20/ptz/wsdl/ptz.wsdl
wsdl2h可以根据在线文档生成头文件,不需要我们把WSDL文档下载下来
视频监控,一般需要的模块有:
- remotediscovery.wsdl-设备发现模块;
- devicemgmt.wsdl-设备管理模块;
- media.wsdl-媒体模块;
- ptz.wsdl-ptz控制模块
wsdl2h参数说明:
指令 | 说明 |
---|---|
-o | 生成头文件名字 |
-s | 不生成STL代码 |
-c | 生成C代码 |
-c++ | 生成C++代码(默认) |
-x | 不生成XML文件 |
-t | 指定typemap.dat位置 |
-C | 仅生成客户端代码 |
-S | 仅生成服务端代码 |
2.执行onvif_head.sh脚本,会在onvif_head文件夹下生成头文件onvif.h
3.添加鉴权
onvif是需要鉴权的,需要修改一下头文件onvif.h,增加一行代码#import "wsse.h"
3)生成onvif代码框架
在/work/onvif/onvif-code目录下创建gen_code.sh脚本,根据头文件 onvif.h生成代码框架
#!/bin/bash
DIR=soap
mkdir $DIR
cd $DIR
../bin/soapcpp2 -2 -x -c ../onvif_head/onvif.h -L -I ../gsoap/import -I ../gsoap/
soapcpp2参数说明:
指令 | 说明 |
---|---|
-1 | 生成soap1.1版本代码 |
-2 | 生成soap1.2版本代码 |
-x | 不生成XML文件 |
-C | 仅生成客户端代码 |
-S | 仅生成服务端代码 |
-c | 生成C语言代码 |
-c++ | 生成C++代码 |
-L | 不生成soapClientLib/soapServerLib |
-l | 指定路径 |
执行gen_code.sh脚本,会报错,如下
wsa5.h(290): **ERROR**: service operation name clash: struct/class 'SOAP_ENV__Fault' already declared at wsa.h:278
报错原因:因为onvif.h头文件中 wsa.h和wsa5.h两个文件重复定义了int SOAP_ENV__Fault
解决办法:修改/work/onvif/onvif-code下面的gsoap/import/wsa5.h,把SOAP_ENV__Fault注释掉即可
重新执行gen_code.sh脚本,在soap目录下生成了onvif的代码框架
其中:
nsmap中定义了onvif xml中的命名空间,DeviceBinding.nsmap MediaBinding.nsmap PTZBinding.nsmap RemoteDiscoveryBinding.nsmap wsdd.nsmap里面的内容完全一样
soapC.c:指定数据结构的序列化和反序列化
soapClient.c:客户端代码
soapH.h:主头文件,所有客户机和服务器源代码都要包括它
soapServer.c:服务器端代码
soapStub.h:从输入头文件(onvif.h)生成的经过修改且带命名空间前缀的头文件
4)生成结果
至此,我们生成了onvif的SOAP Web Services框架
bin:来源于gsoap安装目录
gsoap:来源于gsoap安装目录中的share目录
onvif_head.sh:生成头文件的脚本
onvif_head:存放头文件的目录
gen_code.sh:生成ONVIF Web Services框架的脚本
soap:生成的ONVIF框架代码,包含客户端和服务端代码,也可只生成客户端或者只生成服务端代码,修改onvif_head.sh和gen_code.sh脚本即可(添加-C或-S参数)
四、客户端开发
1)创建client目录
在onvif目录下创建一个client目录,来保存onvif客户端代码
cd /work/onvif
mkdir client
cd client
2)拷贝相关文件
把gSOAP生成的客户端框架拷贝到client下,之前在安装的时候加了鉴权,在wsse.h中指出了鉴权依赖的文件,这里也需要拷贝过来,除此之外,还要拷贝其他一些文件过来
# /work/onvif/onvif-code为onvif框架生成路径
cp /work/onvif/onvif-code/soap/soapC.c .
cp /work/onvif/onvif-code/soap/soapH.h .
cp /work/onvif/onvif-code/soap/soapStub.h .
cp /work/onvif/onvif-code/soap/soapClient.c .
cp /work/onvif/onvif-code/soap/wsdd.nsmap .
cp /work/onvif/onvif-code/gsoap/plugin/wsseapi.h .
cp /work/onvif/onvif-code/gsoap/plugin/wsseapi.c .
cp /work/onvif/onvif-code/gsoap/plugin/mecevp.h .
cp /work/onvif/onvif-code/gsoap/plugin/mecevp.c .
cp /work/onvif/onvif-code/gsoap/plugin/smdevp.h .
cp /work/onvif/onvif-code/gsoap/plugin/smdevp.c .
cp /work/onvif/onvif-code/gsoap/custom/struct_timeval.h .
cp /work/onvif/onvif-code/gsoap/custom/struct_timeval.c .
cp /work/onvif/onvif-code/gsoap/custom/duration.h .
cp /work/onvif/onvif-code/gsoap/custom/duration.c .
cp /work/onvif/onvif-code/gsoap/plugin/wsaapi.h .
cp /work/onvif/onvif-code/gsoap/plugin/wsaapi.c .
cp /work/onvif/onvif-code/gsoap/plugin/threads.h .
cp /work/onvif/onvif-code/gsoap/plugin/threads.c .
cp /work/onvif/onvif-code/gsoap/import/dom.h .
cp /work/onvif/onvif-code/gsoap/dom.c .
# /work/onvif/gsoap-2.8为gsoap源码路径
cp /work/onvif/gsoap-2.8/gsoap/stdsoap2.c .
cp /work/onvif/gsoap-2.8/gsoap/stdsoap2.h .