gsoap2.8生成onvif C++11客户端开发框架的问题及解决

xingyun86 2021-1-13 1549

1.下载gsoap_2.8.109.zip

2.解压gsoap_2.8.109.zip

3.进入gsoap2.8/gsoap/bin/win64目录

a.拷贝gsoap/wsdl/目录下的typemap.dat文件到当前目录

b.创建脚本auto_code_h_c++11.bat

@ECHO OFF
CD /D "%~dp0"
mkdir output
wsdl2h.exe -o output\onvif.h -c++11 -s -t .\typemap.dat http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.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/ver10/media/wsdl/media.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/onvif/ver10/schema/onvif.xsd  http://www.onvif.org/ver10/actionengine.wsdl  
@ECHO &PAUSE

c.创建脚本auto_code_cpp_c++11.bat

@ECHO OFF
CD /D "%~dp0"
mkdir output
soapcpp2.exe -2 -c++11 -j -x output\onvif.h -I%CD%/../../../../gsoap-2.8/gsoap;%CD%/../../../../gsoap-2.8/gsoap/import; -d output
@ECHO &PAUSE

d.创建脚本auto_code_client_c++11.bat

@ECHO OFF
CD /D "%~dp0"
mkdir output
soapcpp2 -a -x -L -pwsdd -d output -I%CD%/../../../../gsoap-2.8/gsoap/import; %CD%/../../../../gsoap-2.8/gsoap/import/wsdd5.h
@ECHO &PAUSE

4.运行脚本auto_code_h_c++11.bat

在output目录生成onvif.h文件

在onvif.h中添加#import "wsse.h"(鉴权使用)

5.运行脚本auto_code_cpp_c++11.bat

在output目录生成许多文件:


6.运行脚本auto_code_client_c++11.bat

在output目录生成许多文件:


7.使用方法:

新建gsoap-lib目录,三个子目录plugin、custom、stub

拷贝6步骤output目录下所有文件到stub目录。

拷贝

dom.cpp  

stdsoap2.h stdsoap2.cpp

到gsoap-lib目录。

拷贝

chrono_duration.cpp  chrono_time_point.cpp duration.c struct_timeval.c

chrono_duration.h    chrono_time_point.h duration.h struct_timeval.h

到gsoap-lib目录(将后缀.c全部修改为.cpp)。

拷贝

mecevp.c  smdevp.c  threads.c  wsaapi.c  wsseapi.c wsse2api.c

mecevp.h    smdevp.h    threads.h    wsaapi.h    wsseapi.h  wsse2api.c

到gsoap-lib目录(将后缀.c全部修改为.cpp)。

8.编译

编译时添加标志:

-DWITH_NONAMESPACES 

-DWITH_OPENSSL

-DWITH_DOM

9.头文件引入

#include <stdsoap2.h>

#include <wsaapi.h>

#include <wsddStub.h>

#include <wsseapi.h>

#include <wsdd.nsmap>//注意:如果编译提示命名空间多处定义,可以注释此行再次编译

#include <soapStub.h>

#include <httpda.h>

#include <soapPTZBindingProxy.h>

#include <soapDeviceBindingProxy.h>

#include <soapMediaBindingProxy.h>


FAQ常见问题及解决

问题1及解决:

wsa5.h(288): **ERROR**: service operation name clash: struct/class 'SOAP_ENV__Fault' already declared at wsa.h:273

则修改wsa5.h中的SOAP_ENV__Fault 为 SOAP_ENV__Fault_WSA5即可。

问题2及解决:

error LNK2001: unresolved external symbol namespaces

则引入头文件#include <wsdd.nsmap>(根据你实际的项目nsmap文件修改即可)

问题3及解决:

返回400/401,Bad Request/Unauthorized

鉴权方式问题,请参阅另一篇文章《onvif 鉴权最佳实践

问题4及解决:

设备发现加入时总会提示namespaces已经重复定义

解决方法:如果出现问题2错误,则自行定义.

//#include <wsdd.nsmap> 注释此行
int OnvifMgr::DeviceDiscovery()
{
    //切记,变量名不可为namespaces.
    SOAP_NMAC struct Namespace discovery_namespaces[] = {
            { "SOAP-ENV", "http://www.w3.org/2003/05/soap-envelope", "http://schemas.xmlsoap.org/soap/envelope/", NULL },
            { "SOAP-ENC", "http://www.w3.org/2003/05/soap-encoding", "http://schemas.xmlsoap.org/soap/encoding/", NULL },
            { "xsi", "http://www.w3.org/2001/XMLSchema-instance", "http://www.w3.org/*/XMLSchema-instance", NULL },
            { "xsd", "http://www.w3.org/2001/XMLSchema", "http://www.w3.org/*/XMLSchema", NULL },
            { "wsa", "http://schemas.xmlsoap.org/ws/2004/08/addressing", "http://www.w3.org/2005/08/addressing", NULL },
            { "wsdd", "http://schemas.xmlsoap.org/ws/2005/04/discovery", NULL, NULL },
            { "chan", "http://schemas.microsoft.com/ws/2005/02/duplex", NULL, NULL },
            { "c14n", "http://www.w3.org/2001/10/xml-exc-c14n#", NULL, NULL },
            { "ds", "http://www.w3.org/2000/09/xmldsig#", NULL, NULL },
            { "saml1", "urn:oasis:names:tc:SAML:1.0:assertion", NULL, NULL },
            { "saml2", "urn:oasis:names:tc:SAML:2.0:assertion", NULL, NULL },
            { "wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", NULL, NULL },
            { "xenc", "http://www.w3.org/2001/04/xmlenc#", NULL, NULL },
            { "wsc", "http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512", "http://schemas.xmlsoap.org/ws/2005/02/sc", NULL },
            { "wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd", NULL },
            { "wsdd10", "http://tempuri.org/wsdd10.xsd", NULL, NULL },
            { "wsa5", "http://www.w3.org/2005/08/addressing", "http://schemas.xmlsoap.org/ws/2004/08/addressing", NULL },
            { "ns1", "http://www.onvif.org/ver20/analytics/humanface", NULL, NULL },
            { "ns2", "http://www.onvif.org/ver20/analytics/humanbody", NULL, NULL },
            { "xmime", "http://tempuri.org/xmime.xsd", NULL, NULL },
            { "xop", "http://www.w3.org/2004/08/xop/include", NULL, NULL },
            { "tt", "http://www.onvif.org/ver10/schema", NULL, NULL },
            { "wsrfbf", "http://docs.oasis-open.org/wsrf/bf-2", NULL, NULL },
            { "wstop", "http://docs.oasis-open.org/wsn/t-1", NULL, NULL },
            { "wsrfr", "http://docs.oasis-open.org/wsrf/r-2", NULL, NULL },
            { "ns3", "http://www.onvif.org/ver10/actionengine/wsdl", NULL, NULL },
            { "tad", "http://www.onvif.org/ver10/analyticsdevice/wsdl", NULL, NULL },
            { "tan", "http://www.onvif.org/ver20/analytics/wsdl", NULL, NULL },
            { "tdn", "http://www.onvif.org/ver10/network/wsdl", NULL, NULL },
            { "tds", "http://www.onvif.org/ver10/device/wsdl", NULL, NULL },
            { "tev", "http://www.onvif.org/ver10/events/wsdl", NULL, NULL },
            { "wsnt", "http://docs.oasis-open.org/wsn/b-2", NULL, NULL },
            { "timg", "http://www.onvif.org/ver20/imaging/wsdl", NULL, NULL },
            { "tls", "http://www.onvif.org/ver10/display/wsdl", NULL, NULL },
            { "tmd", "http://www.onvif.org/ver10/deviceIO/wsdl", NULL, NULL },
            { "tptz", "http://www.onvif.org/ver20/ptz/wsdl", NULL, NULL },
            { "trc", "http://www.onvif.org/ver10/recording/wsdl", NULL, NULL },
            { "trp", "http://www.onvif.org/ver10/replay/wsdl", NULL, NULL },
            { "trt", "http://www.onvif.org/ver10/media/wsdl", NULL, NULL },
            { "trv", "http://www.onvif.org/ver10/receiver/wsdl", NULL, NULL },
            { "tse", "http://www.onvif.org/ver10/search/wsdl", NULL, NULL },
            { NULL, NULL, NULL, NULL}
    };
    // 宏值定义
    const char* MULTICAST_ADDRESS = "soap.udp://239.255.255.250:3702"; // 组播IP:239.255.255.250,Onvif服务端监听的端口为3702
    int result = 0;
    wsdd__ProbeType req;
    struct __wsdd__ProbeMatches resp;
    wsdd__ScopesType sScope;
    struct SOAP_ENV__Header header;
    std::unordered_map<std::string, Camera> camMap = {};
    struct soap* soap;
    soap = soap_new();
    if (NULL == soap)
    {
        DEBUGPRINT("sopa new error\r\n");
        return -1;
    }
    soap->recv_timeout = 10;
    soap_set_namespaces(soap, discovery_namespaces);
    soap_default_SOAP_ENV__Header(soap, &header);
    header.wsa__MessageID = (char*)soap_wsa_rand_uuid(soap);
    header.wsa__To = (char*)"urn:schemas-xmlsoap-org:ws:2005:04:discovery";
    header.wsa__Action = (char*)"http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe";
    soap->header = &header;
    soap_default_wsdd__ScopesType(soap, &sScope);
    sScope.__item = (char*)"";
    soap_default_wsdd__ProbeType(soap, &req);
    req.Scopes = &sScope;
    req.Types = (char*)"dn:NetworkVideoTransmitter";
    int i = 0;
    result = soap_send___wsdd__Probe(soap, MULTICAST_ADDRESS, NULL, &req);
    while (result == SOAP_OK)
    {
        result = soap_recv___wsdd__ProbeMatches(soap, &resp);
        if (result == SOAP_OK)
        {
            if (soap->error)
            {
                DEBUGPRINT("soap error 1: %d, %s, %s\n", soap->error, *soap_faultcode(soap), *soap_faultstring(soap));
                result = soap->error;
            }
            else
            {
                try
                {
                    DEBUGPRINT("*********************************************\r\n");
                    if (soap->header->wsa__MessageID)
                    {
                        DEBUGPRINT("MessageID   : %s\r\n", soap->header->wsa__MessageID);
                    }
                    if (soap->header->wsa__RelatesTo && soap->header->wsa__RelatesTo->__item)
                    {
                        DEBUGPRINT("RelatesTo   : %s\r\n", soap->header->wsa__RelatesTo->__item);
                    }
                    if (soap->header->wsa__To)
                    {
                        DEBUGPRINT("To          : %s\r\n", soap->header->wsa__To);
                    }
                    if (soap->header->wsa__Action)
                    {
                        DEBUGPRINT("Action      : %s\r\n", soap->header->wsa__Action);
                    }
                    for (i = 0; i < resp.wsdd__ProbeMatches->__sizeProbeMatch; i++)
                    {
                        try
                        {
                            if (resp.wsdd__ProbeMatches != nullptr)
                            {
                                DEBUGPRINT("__sizeProbeMatch        : %d\r\n", resp.wsdd__ProbeMatches->__sizeProbeMatch);
                                DEBUGPRINT("wsa__EndpointReference       : %p\r\n", &resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference);
                                DEBUGPRINT("Target EP Address       : %s\r\n", resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.Address);
                                DEBUGPRINT("Target Type             : %s\r\n", resp.wsdd__ProbeMatches->ProbeMatch->Types);
                                DEBUGPRINT("Target Service Address  : %s\r\n", resp.wsdd__ProbeMatches->ProbeMatch->XAddrs);
                                DEBUGPRINT("Target Metadata Version : %d\r\n", resp.wsdd__ProbeMatches->ProbeMatch->MetadataVersion);
                                if (resp.wsdd__ProbeMatches->ProbeMatch->Scopes != nullptr)
                                {
                                    DEBUGPRINT("Target Scopes Address   : %s\r\n", resp.wsdd__ProbeMatches->ProbeMatch->Scopes->__item);
                                }
                                Camera cam = {};
                                if (resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.Address != nullptr
                                    && *resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.Address)
                                {
                                    cam.uuid = resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.Address;
                                    if (resp.wsdd__ProbeMatches->ProbeMatch->Types
                                        && *resp.wsdd__ProbeMatches->ProbeMatch->Types
                                        && std::string(resp.wsdd__ProbeMatches->ProbeMatch->Types).find(' ') != std::string::npos)
                                    {
                                        cam.url = std::string(resp.wsdd__ProbeMatches->ProbeMatch->Types).substr(0, std::string(resp.wsdd__ProbeMatches->ProbeMatch->Types).find(' '));
                                    }
                                    camMap.emplace(std::unordered_map<std::string, Camera>::value_type(cam.uuid, cam));
                                }
                            }
                        }
                        catch (const std::exception& e)
                        {
                            DEBUGPRINT("%s\n", e.what());
                        }
                    }
                }
                catch (const std::exception& e)
                {
                    DEBUGPRINT("%s\n", e.what());
                }
            }
        }
        else if (soap->error)
        {
            DEBUGPRINT("[%d] soap error 2: %d, %s, %s\n", __LINE__, soap->error, *soap_faultcode(soap), *soap_faultstring(soap));
            result = soap->error;
        }
    }
    soap_destroy(soap);
    soap_end(soap);
    soap_free(soap);
    DEBUGPRINT("[%d] discover finish !\n", __LINE__);
    if (!camMap.empty())
    {
        std::lock_guard<std::mutex> lock(m_camLocker);
        for (auto it : camMap)
        {
            m_camMap.emplace(it);
        }
    }
    return 0;
}


上传的附件:
×
打赏作者
最新回复 (0)
只看楼主
全部楼主
返回