天天看点

linux下gsoap编译onvif,实现discovery探测设备

1.首先下载gsoap工具。我目前使用的gsoap 2.8

2.解压到某个目录,编译安装

./configure
make 
make install
           

3.新建一个工程目录,cd进去,用wsdl2h生成onvif.h文件

wsdl2h -o onvif.h -s -t ./typemap.dat http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl http://www.onvif.org/onvif/ver10/media/wsdl/media.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/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/ver10/actionengine.wsdl http://www.onvif.org/ver10/pacs/accesscontrol.wsdl http://www.onvif.org/ver10/pacs/doorcontrol.wsdl
           

其中,-c为产生纯c代码,不然为c++代码;-s为不使用STL库;因为习惯用C++了,所有就不加-c了。

注意:http的url之间是空格。

4.在onvif.h中,添加

#import "wsse.h" 
           

打开文件gsoap_2.8/gsoap-2.8/gsoap/import/ wsa5.h

将277行int SOAP_ENV__Fault修改为int SOAP_ENV__Fault_alex

5.在自定义的工程目录中,根据onvif.h产生onvif代码

soapcpp2 -cpp onvif.h -x -I../gsoap-2.8 -I../gsoap-2.8/gsoap -I../gsoap-2.8/gsoap/import/
           

其中-x表示不产生xml文件,-I表示指定import路径。

6.从gsoap源码目录,拷贝一些需要的文件到工程目录,可参考的文件有,可供参考(只需看*.cpp,*.c,*.h文件)

linux下gsoap编译onvif,实现discovery探测设备

7.测试一个简单的discovery例子程序,main.cpp(网上找的)

#include <iostream>
#include "RemoteDiscoveryBinding.nsmap"
#include "soapH.h"

using namespace std;
int main()
{
printf("onvif\n");
    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;
} 
           

8.编译链接

g++ -ggdb -I./ -c -o main.o main.cpp -I./ 
 g++ -ggdb -I./ -c -o duration.o duration.c
 g++ -ggdb -I./ -c -o soapC.o soapC.cpp 
 g++ -ggdb -I./ -c -o soapClient.o soapClient.cpp
 g++ -ggdb -I./ -c -o stdsoap2.o stdsoap2.cpp 
 g++ -ggdb -I./ ./*.o -o main
           

时间关系,就不写makefile了,谁写了makefile可以留言分享一下,感激!

9.执行./main发现断错误了,于是gdb调试了以下,原来是一个数组没有初始化,可能是新版本的问题,也可能是我不懂用把,直接注释掉整个if就OK了

gdb main
r

15671	        soap->labbuf[soap->labidx > 0 ? soap->labidx - 1 : 0] = '\0';
(gdb) bt
#0  0x086d2e97 in soap_QName2s (soap=0x88bf008, s=0x86de812 "")
    at stdsoap2.cpp:15671
#1  0x085417ad in soap_out_wsdd__ProbeType (soap=0x88bf008, 
    tag=0x86f4c4d "wsdd:Probe", id=0, a=0xbffff5b8, type=0x86e9f85 "")
    at soapC.cpp:354751
#2  0x08653ecc in soap_out_PointerTowsdd__ProbeType (soap=0x88bf008, 
    tag=0x86f4c4d "wsdd:Probe", id=0, a=0xbffff54c, type=0x86e9f85 "")
    at soapC.cpp:429797
#3  0x0853d805 in soap_out___wsdd__Probe (soap=0x88bf008, 
    tag=0x86dea18 "-wsdd:Probe", id=-2, a=0xbffff54c, type=0x86de940 "")
    at soapC.cpp:353485
#4  0x0853da6a in soap_put___wsdd__Probe (soap=0x88bf008, a=0xbffff54c, 
    tag=0x86dea18 "-wsdd:Probe", type=0x86de940 "") at soapC.cpp:353541
#5  0x0804b1f3 in soap_send___wsdd__Probe (soap=0x88bf008, 
    soap_endpoint=0x86de814 "soap.udp://239.255.255.250:3702", 
    soap_action=0x86de9dc "http://docs.oasis-open.org/ws-dd/ns/discovery/2009/01/Probe", wsdd__Probe=0xbffff5b8) at soapClient.cpp:208
#6  0x0804a268 in main () at main.cpp:41
(gdb) 
           

找到stdsoap2.cpp的第15671行,把原来的if(...)改成if(0);

10. 执行

./main
           

继续阅读