参见文章《gsoap2.8.11实现onvif_discover详细教程》和文章(重点看),还有文章
1.下载gsoap
2.去onvif相关页面,将对应的wsdl文件下载下来,也可以去页面,查找ONVIF WSDL and XML Schemas Specifications得到,提供一个下载onvif的wsdl下载文件
3.打开所有的wsdl,查找对应的schemaLocation="http://xxx/xxx.xsd",下载对应的xsd文件
4.查找所有wsdl和xsd,查找location="http://xxx/xxx.wsdl",下载对应的wsdl
5.修改所有的wsdl和xsd,将上述schemaLocation和location等号后面的内容中关于路径部分的全去掉,因为对应文件已经下载到本地了,比如schemaLocation=“http://docs.oasis-open.org/wsn/b-2.xsd"改为schemaLocation=“b-2.xsd"
6.修改typemap.dat文件
参见文档的“How do I use gSOAP for the ONVIF specifications?”
# ONVIF recommended prefixes 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
7.修改gsoap目录下的wsa5.h,将如下内容注释掉
// Added //gsoap SOAP_ENV service method-action: Fault http://www.w3.org/2005/08/addressing/soap/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, // SOAP 1.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 );
@echo off set GSoapPath=E:\Source\c++\gsoap-2.8 Set GSoapSPath=%GSoapPath%\gsoap set GSoapBinPath=%GSoapSPath%\bin\win32 set TypeMapFile=%GSoapBinPath%\typemap.dat set OnVifHFile=onvif.h set DestSourcePath=.\ echo "generate %OnVifHFile%" if exist "%OnVifHFile%" del "%OnVifHFile%" %GSoapBinPath%\wsdl2h.exe -sck -t %TypeMapFile% -o %OnVifHFile% analytics.wsdl analyticsdevice.wsdl deviceio.wsdl devicemgmt.wsdl display.wsdl event.wsdl imaging.wsdl media.wsdl ptz.wsdl Receiver.wsdl Recording.wsdl remotediscovery.wsdl Replay.wsdl Search.wsdl if not exist "%OnVifHFile%" goto 2 echo "generate %OnVifHFile% success" :2
当然也可以直接通过访问网上的wsdl完成
%GSoapBinPath%\wsdl2h.exe -sck -t %TypeMapFile% -o %OnVifHFile% http://www.onvif.org/onvif/ver20/ptz/wsdl/ptz.wsdl http://www.onvif.org/onvif/ver20/analytics/wsdl/analytics.wsdl ...
9.修改生成的onvif.h,增加一句#import "wsse.h",用于身份验证
10.运行soapcpp2,生成代码,可以建立如下bat脚本运行
@echo off set GSoapPath=E:\Source\c++\gsoap-2.8 Set GSoapSPath=%GSoapPath%\gsoap set GSoapBinPath=%GSoapSPath%\bin\win32 set OnVifHFile=onvif.h set DestSourcePath=.\ if not exist "%OnVifHFile%" goto 1 echo "generate Onvif source code" %GSoapBinPath%\soapcpp2.exe -2 -L -c -x -d%DestSourcePath% -I%GSoapSPath%\import;%GSoapSPath%\custom;%GSoapSPath% %OnVifHFile% echo "generate Onvif source code end" goto 2 :1 echo "%OnVifHFile% not exist" :2
11.8-10步可以用如下bat脚本完成
@echo off set GSoapPath=E:\Source\c++\gsoap-2.8 Set GSoapSPath=%GSoapPath%\gsoap set GSoapBinPath=%GSoapSPath%\bin\win32 set TypeMapFile=%GSoapBinPath%\typemap.dat set OnVifHFile=onvif.h set OnVifHTempFile=onviftmp.h set DestSourcePath=..\onvifserver set AllWSDLFiles=actionengine.wsdl analytics.wsdl analyticsdevice.wsdl deviceio.wsdl devicemgmt.wsdl display.wsdl event.wsdl imaging.wsdl media.wsdl ptz.wsdl Receiver.wsdl Recording.wsdl remotediscovery.wsdl Replay.wsdl Search.wsdl set WSDLFiles=%AllWSDLFiles% set WSDLCFlag=-s -c -k set WSDLCPPFlag=-s -k set SOAPCFlag=-L -x -S -2 -c set SOAPCPPFlag=-L -x -S -2 if "%1"=="-h" goto help if "%1"=="-l" ( if "%2"=="cpp" ( set MFlag=2 ) else ( set MFlag=1 ) ) echo "delete files" if exist "%OnVifHFile%" del "%OnVifHFile%" del *.nsmap del %DestSourcePath%\*.nsmap del *.h del %DestSourcePath%\*.h del *.c del %DestSourcePath%\*.c del *.cpp del %DestSourcePath%\*.cpp if "%1"=="-d" goto 1 if %MFlag% EQU 1 ( echo "generate c %OnVifHFile%" %GSoapBinPath%\wsdl2h.exe %WSDLCFlag% -t %TypeMapFile% -o %OnVifHTempFile% %WSDLFiles% ) else ( echo "generate c++ %OnVifHFile%" %GSoapBinPath%\wsdl2h.exe %WSDLCPPFlag% -t %TypeMapFile% -o %OnVifHTempFile% %WSDLFiles% ) if not exist "%OnVifHTempFile%" goto 2 echo #import "wsse.h" >> %OnVifHFile% copy %OnVifHFile%+%OnVifHTempFile% if not exist "%OnVifHFile%" goto 2 del %OnVifHTempFile% echo "generate %OnVifHFile% success" if %MFlag% EQU 1 ( echo "soapcpp generate c Onvif source code" %GSoapBinPath%\soapcpp2.exe %SOAPCFlag% -d%DestSourcePath% -I%GSoapSPath%\import;%GSoapSPath%\custom;%GSoapSPath% %OnVifHFile% ) else ( echo "soapcpp generate c++ Onvif source code" %GSoapBinPath%\soapcpp2.exe %SOAPCPPFlag% -d%DestSourcePath% -I%GSoapSPath%\import;%GSoapSPath%\custom;%GSoapSPath% %OnVifHFile% ) if not exist "%DestSourcePath%\wsdd.nsmap" goto 3 del "%OnVifHFile%" echo "generate Onvif source code success" echo "copy stdsoap2 files" copy "%GSoapSPath%\stdsoap2.h" "%DestSourcePath%\stdsoap2.h" if %MFlag% EQU 1 ( copy "%GSoapSPath%\stdsoap2.c" "%DestSourcePath%\stdsoap2.c" ) else ( copy "%GSoapSPath%\stdsoap2.cpp" "%DestSourcePath%\stdsoap2.cpp" ) goto 1 :2 echo "generate %OnVifHFile% fail" goto 1 :3 echo "generate Onvif source code fail" goto 1 :help echo generate onvif source code release 1.0 echo Usage: runwsdl [-h] [-l c level] echo -h display help info echo -l language level, c is c language, cpp is c++ language echo -d clean generated source code goto 1 :1
SOAP_FMAC5 int SOAP_FMAC6 soap_serve_request(struct soap *soap) { soap_peek_element(soap); #if 0 if (!soap_match_tag(soap, soap->tag, "SOAP-ENV:Fault")) return soap_serve_SOAP_ENV__Fault(soap); #endif
#if 0 SOAP_FMAC5 int SOAP_FMAC6 soap_serve_SOAP_ENV__Fault(struct soap *soap) { struct SOAP_ENV__Fault soap_tmp_SOAP_ENV__Fault; soap_default_SOAP_ENV__Fault(soap, &soap_tmp_SOAP_ENV__Fault); soap->encodingStyle = NULL; if (!soap_get_SOAP_ENV__Fault(soap, &soap_tmp_SOAP_ENV__Fault, "SOAP-ENV:Fault", NULL)) return soap->error; if (soap_body_end_in(soap) || soap_envelope_end_in(soap) || soap_end_recv(soap)) return soap->error; soap->error = SOAP_ENV__Fault(soap, soap_tmp_SOAP_ENV__Fault.faultcode, soap_tmp_SOAP_ENV__Fault.faultstring, soap_tmp_SOAP_ENV__Fault.faultactor, soap_tmp_SOAP_ENV__Fault.detail, soap_tmp_SOAP_ENV__Fault.SOAP_ENV__Code, soap_tmp_SOAP_ENV__Fault.SOAP_ENV__Reason, soap_tmp_SOAP_ENV__Fault.SOAP_ENV__Node, soap_tmp_SOAP_ENV__Fault.SOAP_ENV__Role, soap_tmp_SOAP_ENV__Fault.SOAP_ENV__Detail); if (soap->error) return soap->error; return soap_closesock(soap); } #endif
// SOAP_FMAC1 void SOAP_FMAC2 soap_default_xsd__duration(struct soap*, LONG64 *); #define soap_default_xsd__duration(soap, a) soap_default_unsignedLONG64(soap, (ULONG64 *)a) // SOAP_FMAC1 int SOAP_FMAC2 soap_out_xsd__duration(struct soap*, const char*, int, const LONG64 *, const char*); #define soap_out_xsd__duration(soap,a,b,c,d) soap_out_unsignedLONG64(soap, a, b, (ULONG64 *)c, d) // SOAP_FMAC1 LONG64 * SOAP_FMAC2 soap_in_xsd__duration(struct soap*, const char*, LONG64 *, const char*); #define soap_in_xsd__duration(soap, a, b, c) (LONG64*)soap_in_unsignedLONG64(soap,a,(ULONG64 *)b,c)