一、要准备的文件:
1.ONVIF相关的WSDL文件,对于设备发现,只需要用到RemoteDiscovery.wsdl一个即可,
2.gSoap的压缩包,找到/gsoap/bin/win32文件夹中的soapcpp2.exe以及wsdl2h.exe,以及在/gSoap目录下的typemap.dat文件,将这些文件放到一个文件夹下。
二、对typemap.bat进行修改,
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的相关前缀,在通过soapcpp2.exe生成相关源文件之后,查看源代码可发现在代码上对这些改动的体现。
三、根据RemoteDiscovery.wsdl的到onvif.h文件
ONVIF官方文档,主要包含了函数的描述,SOAP Action,函数输入、输出接口等
Wsdl的资料在Onvif官方Wsdl文档中的ONVIF WSDL and XML Schemas Specifications一节,虽然可以全部下载为wsdl文件,但是wsdl文件中存在相互依赖的关系,并且是带有存储的依赖,所以一般最好直接使用url来产生头文件,不要下载下来。
官方2.0文档: http://www.onvif.org/onvif/ver20/util/operationIndex.html 官方wsdl文档: http://www.onvif.org/Documents/Specifications.aspx
1.使用URL产生onvif.h:wsdl2h.exe -o onvif.h -c -s -t typemap.dat http://www.onvif.org/onvif/ver10/network/wsdl/remotediscovery.wsdl
2.使用本地文件产生onvif.h:wsdl2h.exe -o onvif.h -s -t typemap.dat remotediscovery.wsdl
其中-c为产生纯c代码,不然为c++代码;-s为不使用STL库,-t为typemap.dat的标识
四、根据onvif来产生相关源文件
soapcpp2.exe onvif.h -x -I E:\gsoap\import -I E:\gsoap由于客户端主动发起Probe探针,所以只需产生客户端C代码,其中-x表示不产生xml文件,-I表示指定import路径。特别注意需要指定两个gsoap的两个目录,当中有产生源文件时所需的相关文件,如果不添加目录,也可在使用下面
soapcpp2.exe -x onvif.h
然后按照提示找到缺少的文件后添加到目录下。
五、完成main函数
#include <iostream> #include "wsdd.nsmap" #include "soapH.h" using namespace std; int main() { struct soap *soap; struct wsdd__ProbeType req; struct __wsdd__ProbeMatches resp; struct wsdd__ScopesType sScope; struct SOAP_ENV__Header header; int count = 0; int result = 0; char guid_string[100]; soap = soap_new(); if(soap==NULL) { return -1; } soap_set_namespaces(soap, namespaces); soap->recv_timeout = 5; //超过5秒钟没有数据就退出 soap_default_SOAP_ENV__Header(soap, &header); header.wsa__MessageID = guid_string; header.wsa__To= "urn:schemas-xmlsoap-org:ws:2005:04:discovery"; header.wsa__Action= "http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe"; soap->header = &header; soap_default_wsdd__ScopesType(soap, &sScope); sScope.__item = ""; soap_default_wsdd__ProbeType(soap, &req); req.Scopes = &sScope; req.Types = ""; result = soap_send___wsdd__Probe(soap, "soap.udp://239.255.255.250:3702", NULL, &req); do{ result = soap_recv___wsdd__ProbeMatches(soap, &resp); if (soap->error) { cout<<"soap error:"<<soap->error<<soap_faultcode(soap)<<"---"<<soap_faultstring(soap)<<endl; result = soap->error; break; } else { cout<<"========================================="<<endl; cout<<"Match size:"<<resp.wsdd__ProbeMatches->__sizeProbeMatch<<endl; cout<<"xsd-unsignedInt:"<<resp.wsdd__ProbeMatches->ProbeMatch->MetadataVersion<<endl; cout<<"scopes item:"<<resp.wsdd__ProbeMatches->ProbeMatch->Scopes->__item<<endl; //cout<<"scopes matchby:"<<resp.wsdd__ProbeMatches->ProbeMatch->Scopes->MatchBy<<endl; cout<<"QName:"<<resp.wsdd__ProbeMatches->ProbeMatch->Types<<endl; cout<<"xsd:string:"<<resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.Address<<endl; cout<<"xsd:QName:"<<resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.PortType<<endl; cout<<"wsa:ServiceNameType:"<<resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.ServiceName<<endl; cout<<"sequence of elements:"<<resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.__size<<endl; cout<<"xsd:anyType:"<<resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.__anyAttribute<<endl; cout<<"endpoint any:"<<resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.__any<<endl; cout<<"wsdd:UriListType:"<<resp.wsdd__ProbeMatches->ProbeMatch->XAddrs<<endl; } }while(1); soap_destroy(soap); // remove deserialized class instances (C++ only) soap_end(soap); // clean up and remove deserialized data soap_done(soap); return result; }
六、结果
启动onvif的测试工具,点开Discovery,点击Discovery Device