基于 gsoap 生成 onvif 服务端框架代码
文章概要
由于项目要求实现 onvif 功能,从对白对接,一开始很多都不懂,后面琢磨琢磨慢慢对它有所了解了。上网查询很多人说一大堆原理,什么是 soap , http,xml, wsdl, WS-Discovery 等等,对于小白来说突然很多新概念直接很头疼。所以还是先建议有一个完整的 demo, 最好自己动手搭建一份框架代码,跑通代码然后慢慢对接功能点,就慢慢了解 onvif 了。
这篇文章主要讲解 gsoap 生成 onvif 框架代码的过程,以及实现设备发现,出图等功能!其实 gsoap 就是一个工具,用它生成 onvif 的框架代码,里面已经把 xml ,wsdl ,WS-Discovery 集合到里面了,我们就管接口怎么调用即可。想深入了解,后面逐渐熟悉慢慢摸索清楚!
soap 相关的接口调用参考: https://www.genivia.com/doc/guide/html/index.html
1、gsoap 的下载编译
gsoap 下载:https://sourceforge.net/projects/gsoap2/ gsoap下载
下载源码之后新建一个 build.sh 脚本执行编译即可:
#!/bin/bash
set -e
case "$1" in
"")
if [ ! -e $PWD/Makefile ]; then
./configure --prefix=$PWD/install
fi
make -j8
make install
;;
clean)
rm -rf $PWD/install # must rm _install first
make clean
;;
distclean)
make clean
rm -rf $PWD/install # must rm _install first
rm -rf $PWD/Makefile
;;
esac
生成如下内容,就代表成功了,bin 目录下有我们需要的 wsdl2h、soapcpp2 工具!
或者你的环境和我的环境有一样地方,编译 gsoap 提示缺什么安装就好了!
2、生成 onvif.h
生成 onvif.h 文件,需要依赖 gsoap-2.8/gsoap/typemap.dat , wsdl2h 这个两个文件,还有依赖 wsdl 文件 wsdl下载链接
wsdl 的相关文件,根据你们的项目需求,下载对应的 wsdl 文件即可:
注意: 不同 gsoap 版本,typemap.dat 可能需要修改一下,我的是 2.8 版本的就需要修改 typemap.dat 文件末尾添加如下内容:
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
最好新建一个目录 onvif_code, 把 wsdl 、typemap.dat、wsdl2h、soapcpp2 都放到一起
生成 onvif.h ,一般有两种方式:一种直接下载下来 wsdl 文件(之间有互相依赖的情况,需要下载对应的文件,同时修改l依赖文件为本地路径),另一种直接用链接方式(不用考虑互相依赖,网络因素有可能生成失败,多试几次就好)。我建议是用下载本地的方式生成 onvif.h , 因为后面我们需要对相应的 wsdl 做裁剪的
//下载 wsdl 到本地的方式
./wsdl2h -o onvif.h -c -s -t ./typemap.dat ./wsdl/remotediscovery.wsdl ./wsdl/media.wsdl ./wsdl/media2.wsdl ./wsdl/devicemgmt.wsdl ./wsdl/deviceio.wsdl ./wsdl/analytics.wsdl ./wsdl/event.wsdl ./wsdl/imaging.wsdl
// 链接的方式
./wsdl2h -o onvif.h -c -s -t .\typemap.dat \
http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl \
http://www.onvif.org/onvif/ver10/event/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/onvif/ver10/schema/onvif.xsd \
http://www.onvif.org/ver10/actionengine.wsdl
其中,-c 为产生纯 c 代码,不然为 c++ 代码;-s 为不使用 STL 库, -t 指定 typemap.dat 文件、后面指定需要的 wsdl 文件
注意: 有些伙伴可能有疑问了,wsdl 的相关链接哪里找的?点这里 wsdl链接
还有一点就是, 选择本地生成 onvif.h 方式的伙伴,需要修改 wsdl 里面指定依赖文件的路径:
上面操作都顺利的话,onvif_code 目录下会生成 onvif.h 文件,后面生成框架代码需要 onvif.h 文件
在使用命令通过 onvif.h 生成代码之前,得先确认下是否需要做安全验证, 也就是所谓的鉴权,如果不需要的话,那就可以直接使用命令了,如果需要做鉴权的话,则需要修改 onvif.h , 在 onvif.h 中需要加上
import “wsse.h” // 安全验证
3、生成 onvif 框架代码
生成命令:
./soapcpp2 -2 -c onvif.h -x -I ./gsoap-2.8/gsoap/import/ -I ./gsoap-2.8/gsoap/
参数的说明:
-2 //采用SOAP1.2,和 SOAP1.0 版本不同,会导致搜索工具搜索不到
-x //不产生xml文件(可用可不用,xml有一定帮助,但是太多)
-I //为引入路径
-C //只产生客户端代码(注意:C是大写,不推荐有次命令)
其中 /gsoap-2.8/gsoap/import 和 gsoap-2.8/gsoap/ , 引用刚才第一步编译生成 gsoap 的源代码即可
执行命令生成的源文件有:其中有好几个 nsmap 文件,只要 wsdd.nsmap 文件即可
到此你想编译通过?是不太可能,还有依赖一部分文件,往下看需要 copy 哪些文件…
4、整合 onvif 服务端框架代码
在第三步生成的源代码的基础上,同时需要 copy gsoap 里面的如下文件到 onvif_code 目录下:
./gsoap-2.8/gsoap/stdsoap2.c
./gsoap-2.8/gsoap/stdsoap2.h
./gsoap-2.8/gsoap/custom/duration.c
./gsoap-2.8/gsoap/custom/duration.h
./gsoap-2.8/gsoap/plugin/wsddapi.c
./gsoap-2.8/gsoap/plugin/wsddapi.h
大概就这些功能,可能有些人还需要调用 http 相关的内容,可以加上相关的文件在,/gsoap-2.8/gsoap/plugin/ 目录下!!!
此时,框架的代码基本生成!到了这一步写一个 Makefile 编译一下你会发现提示很多接口没有实现定义?? what ???
没错,这个接口都是需要自己实现的,而且还是一大推函数接口, 如下截图只是一小部分,后面还有很多…
当时写实现这些接口都写麻了…
比如我要做 onvif 服务端的,我就对接 soapServer.c 里面所有需要定义没实现的接口,灵动的伙伴们可能到这里开始发现实现接口,参数那些,以及相关结构我怎么知道?
技巧: 你编译提示缺少 XXXXX 函数没实现,你搜索一下会惊讶的发现其实在 soapStub.h 有定义的,所以直接 copy 过来实现就好了!
如下的接口最好重新新建一个文件 onvif_server_interface.c 里面实现
福利福利: github 上的 demo 参考链接:https://github.com/As772309423/onvif-server-discover,里面有实现 onvif_server_interface.c 全部接口
5、错误说明
把对接 soapServer.c 的接口都实现完了,有些伙伴可能编译通过了,有些可能不行。不通的环境下可能有不一样的错误,我当时在 Ubuntu 下 gcc 下是能编译通过。
最后我换到了 mips 工具链发现,编译出错了、提示了 duration 缺少什么定义,或者类型不对,报错 LONG64 错误等
在 typemap.dat 文件添加如下内容,从新生成代码代码编译即可!
xsd__duration = #import "custom/duration.h" | xsd__duration
如果前面说的都能顺利通过,那些 onvif 代码框架已经生成了,这只是第一步,后面还需要接着实现 main 函数,以及 soapServer 里面的相关函数接口,还有 wsdl 的裁剪等等!
__wsdd__Probe
__tds__GetDeviceInformation
__tds__GetCapabilities
__tds__GetServices
__trt__GetProfiles
__trt__GetStreamUr
__tds__SetSystemDateAndTime
__trt__GetVideoSources
timg:GetOptions
__tds__GetNetworkInterfaces
__trt__GetOSDs
以上的实现下一篇文章详细说明。
参考链接:
https://www.onvif.org/onvif/ver20/util/operationIndex.html
https://onvif.github.io/specs/doc/index.html
https://github.com/As772309423/onvif-server-discover
https://www.genivia.com/doc/guide/html/index.html