gSoap實現ONVIF的設備發現(windows下)

1、要準備的文件: html

1.ONVIF相關的WSDL文件,對於設備發現,只須要用到RemoteDiscovery.wsdl一個便可, ios

2.gSoap的壓縮包,找到/gsoap/bin/win32文件夾中的soapcpp2.exe以及wsdl2h.exe,以及在/gSoap目錄下的typemap.dat文件,將這些文件放到一個文件夾下。 c++

2、對typemap.bat進行修改, shell

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生成相關源文件以後,查看源代碼可發如今代碼上對這些改動的體現。 app


3、根據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 ui

1.使用URL產生onvif.h:wsdl2h.exe -o onvif.h -c -s -t typemap.dat http://www.onvif.org/onvif/ver10/network/wsdl/remotediscovery.wsdl url

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 E:\gsoap\import -I E:\gsoap
因爲客戶端主動發起Probe探針,因此只需產生客戶端C代碼,其中-x表示不產生xml文件,-I表示指定import路徑。特別注意須要指定兩個gsoap的兩個目錄,當中有產生源文件時所需的相關文件,若是不添加目錄,也可在使用下面
soapcpp2.exe -x onvif.h

而後按照提示找到缺乏的文件後添加到目錄下。

5、完成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;
} 

6、結果

啓動onvif的測試工具,點開Discovery,點擊Discovery Device

相關文章
相關標籤/搜索