相關文章:
ONVIF專題--Onvif標準解讀(2)--Core Spec::Device Discovery(1)
ONVIF專題--Onvif標準解讀(2)--Core Spec::Device Discovery(3)
gSoap實現ONVIF的設備發現
1 依賴
- ONVIF相關的WSDL文件,對於設備發現,只需要用到remoteDiscovery.wsdl[http://www.onvif.org/onvif/ver10/network/wsdl/remotediscovery.wsdl]即可
- gSoap的壓縮包,找到/gsoap/bin/win32文件夾中的soapcpp2.exe以及wsdl2h.exe,以及在/gSoap目錄下的typemap.dat文件,將這些文件放到一個文件夾下。
注:gSoap使用版本。因爲ONVIF的DD是基於WS-Discovery1.0規範做的改動,建議使用2.8.80或2.8.81版本gsoap。另外官網下載gsoap時注意不要下載商業版本。開源GPLv2的版本路徑:https://sourceforge.net/projects/gsoap2/
2 修改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生成相關源文件之後,查看源代碼可發現在代碼上對這些改動的體現。
注:gsoap-2.8.80以上已經加默認入到typemap.dat中
3 產生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的標識
4 根據onvif來產生相關源文件
soapcpp2.exe onvif.h -x -I [your path]\gsoap\import -I [your path]\gsoap
由於客戶端主動發起Probe探針,所以只需產生客戶端C代碼,其中-x表示不產生xml文件,-I表示指定import路徑。特別注意需要指定兩個gsoap的兩個目錄,當中有產生源文件時所需的相關文件,如果不添加目錄,也可在使用下面命令
soapcpp2.exe -x onvif.h
然後按照提示找到缺少的文件後添加到目錄下。
產生文件如下
5 測試代碼
客戶端測試代碼
#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;
}
6 結果
啓動onvif的測試工具,點開Discovery,點擊Discovery Device