Onvif soap库使用辅助类

便于调用gsoap onvif接口

#pragma once
#include 
#include "soapStub.h"
#include "wsseapi.h"
#include "wsddapi.h"
#include "httpda.h"

extern SOAP_NMAC struct Namespace discoveryNamespaces[];
extern SOAP_NMAC struct Namespace mediaNamespaces[];
namespace ONVIF
{
    using cstrRef = const std::string&;
    template <class T, class U >
    class SoapHelper
    {
    public:
        using _soap_call_ = int(*)(struct soap*, const char*, const char*, T*, U&);
    public:
        SoapHelper(
            cstrRef url,
            cstrRef user,
            cstrRef pwd,
            T& req,
            _soap_call_ call,
            int timeout = 5)
            : _url(url)
            , _user(user)
            , _pwd(pwd)
            , _req(req)
            , _call(call)
        {
            _soap = soap_new1(SOAP_IO_DEFAULT | SOAP_C_UTFSTRING);
            _soap->send_timeout = timeout;
            _soap->recv_timeout = timeout;
            _soap->connect_timeout = timeout;

            soap_wsse_add_UsernameTokenDigest(_soap, NULL, user.c_str(), pwd.c_str());
        }

        SoapHelper(
            struct soap* soap,
            cstrRef url,
            cstrRef user,
            cstrRef pwd,
            T& req,
            _soap_call_ call,
            int timeout = 5)
            : _soap(soap)
            , _url(url)
            , _user(user)
            , _pwd(pwd)
            , _req(req)
            , _call(call)
        {
            _soap->send_timeout = timeout;
            _soap->recv_timeout = timeout;
            _soap->connect_timeout = timeout;

            soap_wsse_add_UsernameTokenDigest(_soap, NULL, user.c_str(), pwd.c_str());
        }

        ~SoapHelper()
        {
            soap_destroy(_soap); // delete managed objects
            soap_end(_soap);     // delete managed data and temporaries 
            soap_free(_soap);    // finalize and delete the context
        }

        U& Rsp()
        {
            return _rsp;
        }

        int Call()
        {
            // make a copy for soap_header;
            auto header = _soap->header;
            // make a copy for wsse security;
            auto wsse = header->wsse__Security;

            auto ret = _call(_soap, _url.c_str(), NULL, &_req, _rsp);
            if (ret != SOAP_OK)
            {
                // retry with digest authorization
                if (_soap->error == 401 || _soap->status == 400)
                {
                    // clear wsse
                    header->wsse__Security = nullptr;
                    // regist http digest plugin
                    soap_register_plugin(_soap, http_da);
                    struct http_da_info info;
                    // set header
                    _soap->header = header;
                    ret = _call(_soap, _url.c_str(), NULL, &_req, _rsp);
                    if (_soap->error == 401) // HTTP authentication is required
                    {
                        http_da_save(_soap, &info, _soap->authrealm, _user.c_str(), _pwd.c_str());
                        // set header
                        _soap->header = header;
                        ret = _call(_soap, _url.c_str(), NULL, &_req, _rsp);// make a call with authentication
                        http_da_release(_soap, &info); // release
                    }
                }
            }
            // restore wsse security, soap will free that
            header->wsse__Security = wsse;
            return ret;
        }

        bool Ok()
        {
            return _soap->error == SOAP_OK ? true : false;
        }

    protected:
        cstrRef _url;
        cstrRef _user;
        cstrRef _pwd;
        T& _req;
        U _rsp;
        _soap_call_ _call;
    private:
        struct soap* _soap;
    };
    // 由用户传入时间,若出错,返回int
#define soapcalli_t(addr, usr, pwd, req, x, t)  \
        using ReqType = x;\
        using RspType = x##Response;\
        auto  callFunc = soap_call__##x;\
        SoapHelper<ReqType, RspType>\
            rsp(addr, usr, pwd, req, callFunc, t);\
        auto ret = rsp.Call();\
        if (ret != SOAP_OK)\
        {\
            LOG_ERROR(*context_onvif->pLogger, "<%s>: soap_call__%s failed. soap code: %?d, addr: %s",\
                string(__FUNCTION__), std::string(#x), ret, addr);\
            return SoapCodeToJxCode(ret);\
        }
    // 默认5秒超时,若出错,返回int
#define soapcalli(addr, usr, pwd, req, x)  soapcalli_t(addr, usr, pwd, req, x, 5)

    // 由用户传入时间,若出错,返回void
#define soapcallv_t(addr, usr, pwd, req, x, t)  \
        using ReqType = x;\
        using RspType = x##Response;\
        auto  callFunc = soap_call__##x;\
        SoapHelper<ReqType, RspType>\
            rsp(addr, usr, pwd, req, callFunc, t);\
        auto ret = rsp.Call();\
        if (ret != SOAP_OK)\
        {\
            LOG_ERROR(*context_onvif->pLogger, "<%s>: soap_call__%s failed. soap code: %?d, addr: %s",\
                string(__FUNCTION__), std::string(#x), ret, addr);\
            return;\
        }
    // 默认5秒超时,若出错,返回void
#define soapcallv(addr, usr, pwd, req, x)  soapcallv_t(addr, usr, pwd, req, x, 5)

    // 由用户传入时间,无论是否出错,均不返回
#define soapcalln_t(addr, usr, pwd, req, x, t)  \
        using ReqType = x;\
        using RspType = x##Response;\
        auto  callFunc = soap_call__##x;\
        SoapHelper<ReqType, RspType>\
            rsp(addr, usr, pwd, req, callFunc, t);\
        auto ret = rsp.Call();\
        if (ret != SOAP_OK)\
        {\
            LOG_WARNING(*context_onvif->pLogger, "<%s>: soap_call__%s failed. soap code: %?d, addr: %s",\
                string(__FUNCTION__), std::string(#x), ret, addr);\
        }
    // 默认5秒超时,无论是否出错,均不返回
#define soapcalln(addr, usr, pwd, req, x)  soapcalln_t(addr, usr, pwd, req, x, 5)

    // 由用户传入soap、时间,若出错,返回int
#define soapcalli_s_t(soap, addr, usr, pwd, req, x, t)  \
        using ReqType = x;\
        using RspType = x##Response;\
        auto  callFunc = soap_call__##x;\
        SoapHelper<ReqType, RspType>\
            rsp(soap, addr, usr, pwd, req, callFunc, t);\
        auto ret = rsp.Call();\
        if (ret != SOAP_OK)\
        {\
            LOG_ERROR(*context_onvif->pLogger, "<%s>: soap_call__%s failed. soap code: %?d, addr: %s",\
                string(__FUNCTION__), std::string(#x), ret, addr);\
            return SoapCodeToJxCode(ret);\
        }
    // 由用户传入soap,默认5s超时,若出错,返回int
#define soapcalli_s(soap, addr, usr, pwd, req, x)  soapcalli_s_t(soap, addr, usr, pwd, req, x, 5)

    // 由用户传入传入soap、时间,若出错,返回void
#define soapcallv_s_t(soap, addr, usr, pwd, req, x, t)  \
        using ReqType = x;\
        using RspType = x##Response;\
        auto  callFunc = soap_call__##x;\
        SoapHelper<ReqType, RspType>\
            rsp(soap, addr, usr, pwd, req, callFunc, t);\
        auto ret = rsp.Call();\
        if (ret != SOAP_OK)\
        {\
            LOG_ERROR(*context_onvif->pLogger, "<%s>: soap_call__%s failed. soap code: %?d, addr: %s",\
                string(__FUNCTION__), std::string(#x), ret, addr);\
            return;\
        }
    // 由用户传入传入soap、默认5s超时,若出错,返回void
#define soapcallv_s(soap, addr, usr, pwd, req, x)  soapcallv_s_t(soap, addr, usr, pwd, req, x, 5)

    // 由用户传入传入soap、时间,无论是否出错,均不返回
#define soapcalln_s_t(soap, addr, usr, pwd, req, x, t)  \
        using ReqType = x;\
        using RspType = x##Response;\
        auto  callFunc = soap_call__##x;\
        SoapHelper<ReqType, RspType>\
            rsp(soap, addr, usr, pwd, req, callFunc, t);\
        auto ret = rsp.Call();\
        if (ret != SOAP_OK)\
        {\
            LOG_WARNING(*context_onvif->pLogger, "<%s>: soap_call__%s failed. soap code: %?d, addr: %s",\
                string(__FUNCTION__), std::string(#x), ret, addr);\
        }
    // 由用户传入传入soap、默认5s超时,无论是否出错,均不返回
#define soapcalln_s(soap, addr, usr, pwd, req, x)  soapcalln_s_t(soap, addr, usr, pwd, req, x, 5)

    // 若指针为空,返回void
#define CHECK_POINTER_V(p) \
        if (p == nullptr) \
        { \
            LOG_ERROR(*context_onvif->pLogger, "<%s>: null pointer: %s", string(__FUNCTION__), std::string(#p)); \
            return; \
        }

    // 若指针为空,返回int
#define CHECK_POINTER_I(p) \
        if (p == nullptr) \
        { \
            LOG_ERROR(*context_onvif->pLogger, "<%s>: null pointer: %s", string(__FUNCTION__), std::string(#p)); \
            return EC_NULL_POINTERER; \
        }

    //若指针为空,跳出当前迭代
#define CHECK_POINTER_C(p) \
        if (p == nullptr) \
        { \
            LOG_WARNING(*context_onvif->pLogger, "<%s>: null pointer: %s", string(__FUNCTION__), std::string(#p)); \
            continue; \
        }

#define SOAP_FREE_FOR_NEW(soap)\
        soap_destroy(soap); \
        soap_end(soap); \
        soap_free(soap);
}

调用举例

// 调用举例
int main(int argc, char* argv[])
{
    // 1

    _trt__GetProfiles req;
    soapcalli(_devAddrs[t_media], _strUserName, _strPassword, req, _trt__GetProfiles);
    
    // 2
    struct soap* soap = soap_new();
    _tr2__GetProfiles req;
    req.soap_default(soap);
    req.Token = (std::string*)&profileToken;
    req.Type.push_back(soap_tr2__ConfigurationEnumeration2s(soap, tr2__ConfigurationEnumeration__VideoEncoder));
    req.Type.push_back(soap_tr2__ConfigurationEnumeration2s(soap, tr2__ConfigurationEnumeration__AudioEncoder));
    soapcalli_s(soap, _devAddrs[t_media2], _strUserName, _strPassword, req, _tr2__GetProfiles);
    // 3    
    _tds__GetDeviceInformation req;
    soapcalli(_strDevAddr, _strUserName, _strPassword, req, _tds__GetDeviceInformation);
    // save device info
    _deviceInfo.strManufacturer = rsp.Rsp().Manufacturer;
    _deviceInfo.strModel = rsp.Rsp().Model;
    _deviceInfo.strFireware = rsp.Rsp().FirmwareVersion;
}

你可能感兴趣的:(Onvif,linux,c++,c++,onvif)