ONVIF 设备发现 VC++实现

    设备发现的过程:客户端发送报文到239.255.255.250的3702端口(ONVIF协议规定),服务器收到报文后再向客户端返回一个报文,客户端收到这个报文然后解析出Xaddrs,这就完成了一次设备发现。请看下面代码:

// 正在表达式
    std::string ippattren = ("\\d+\.\\d+\.\\d+\.\\d+(\:\\d+|\.{5})");
    std::string brand = ("\/name\/(\.\*)\\s");
    std::string model = ("\/hardware\/(\.\*)\\s");

    std::string stType = ("\/type\/(\.\*)\\s");
    // 忽略大小写
    std::regex_constants::syntax_option_type fl = std::regex_constants::icase;
    // 编译正在表达式
    std::regex regExpress(ippattren, fl);
    std::regex regBrand(brand,fl);
    std::regex regModel(model,fl);

    std::regex regType(stType,fl);

    std::smatch ms;

    char *pBuffer;

    //UUID 好最后是变化的否则 onvif 组播服务可能只回复一次
    std::string guid_string = "uuid:68749E8A-2EDD-49C0-ABF8-45E0733911BF";

    wsddProxy discovery;

    //获取guid(windows下叫guid,linux下叫uuid),格式为urn:uuid:8-4-4-4-12,由系统随机产生
    static char buf[64] = {0};
    GUID guid;
    if (S_OK == ::CoCreateGuid(&guid)) 
    {
        //如果guid生成成功,则将其转为字符串,保存在buf中
        _snprintf_s(buf, sizeof(buf)
            , "uuid:%08X-%04X-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X"
            , guid.Data1
            , guid.Data2
            , guid.Data3
            , guid.Data4[0], guid.Data4[1]
        , guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5]
        , guid.Data4[6], guid.Data4[7]
        );
        guid_string = buf;
    }

    //超过5秒没有数据就退出
    discovery.recv_timeout = 5;
    
    char* wsa_To = "urn:schemas-xmlsoap-org:ws:2005:04:discovery";
    char* wsa_Action = "http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe";

    SOAP_ENV__Header header;
    soap_default_SOAP_ENV__Header(&discovery,&header);
    header.wsa__MessageID = (char *)guid_string.c_str();
    header.wsa__To = wsa_To;
    header.wsa__Action = wsa_Action;
    discovery.header = &header;

    //这个就是传递过去的组播的ip地址和对应的端口发送广播信息
    //设置所需寻找设备的类型和范围,二者至少设定一个,否则可能收到非ONVIF设备,出现异常
    discovery.soap_endpoint = "soap.udp://239.255.255.250:3702";
    struct wsdd__ProbeType wsdd__Probe;
    //设置所需设备的类型,tdn为命名空间前缀,为wsdd.nsmap文件中
    //{"tdn","http://www.onvif.org/ver10/network/wsdl"}的tdn,
    //如果不是tdn,而是其它,如ns1,这里也要随之改为ns1
    soap_default_wsdd__ProbeType(&discovery, &wsdd__Probe);

    wsdd__Probe.Types = "tdn:NetworkVideoTransmitter";
    int result = 0, count = 0;
    //通过组播发送Probe探针,发送成功返回0,否则返回-1
    result = discovery.send_Probe(/*discovery.soap_endpoint, NULL, */&wsdd__Probe);
    if(-1 == result)
    {
        AfxMessageBox(_T("Probe发送失败!"));
        return;
    }
    else
    {    
        struct __wsdd__ProbeMatches wsdd__Probe;        
        while(1)
        {    
            //接收ProbeMatches,成功返回0,否则返回-1     
            result = discovery.recv_ProbeMatches(wsdd__Probe);        
            if(-1 == result){
                //AfxMessageBox(_T("Probe接收失败!"));
                return;
            }
            else
            {
                string stText,strTemp;
                IPCDevice ipcinfo;
                // 获取IP
                pBuffer = wsdd__Probe.wsdd__ProbeMatches->ProbeMatch->XAddrs;
                stText = pBuffer;
                if (std::regex_search(stText,ms,regExpress))
                {
                    strTemp = *ms.begin();
                    int n = strTemp.find(':');
                    if (n != -1)
                    {
                        ipcinfo.strIP = strTemp.substr(0,n);
                        ipcinfo.strPort = strTemp.substr(n + 1,strTemp.length());

                        n = ipcinfo.strPort.find('/');
                        if (n != -1)
                        {
                            ipcinfo.strPort = ipcinfo.strPort.substr(0,n);
                        }
                    }

                }

                // 获取厂商及型号
                if (wsdd__Probe.wsdd__ProbeMatches->ProbeMatch->Scopes == NULL)
                {
                    continue;
                }
                pBuffer = wsdd__Probe.wsdd__ProbeMatches->ProbeMatch->Scopes->__item;
                stText = pBuffer;
                if (std::regex_search(stText,ms,regBrand))
                {
                    strTemp = *ms.begin();
                    ipcinfo.strBrand = strTemp.substr(6,strTemp.find(" ") - 5);
                }
                if (std::regex_search(stText,ms,regModel))
                {
                    strTemp = *ms.begin();
                    ipcinfo.strModel = strTemp.substr(10,strTemp.find(" ") - 9);
                }
                if (std::regex_search(stText,ms,regType))
                {
                    strTemp = *ms.begin();
                    ipcinfo.strModel = strTemp.substr(10,strTemp.find(" ") - 9);
                }
            }
        }
        //清除变量
        discovery.destroy();
    }

工程下载地址:https://download.csdn.net/download/xijundian04083099/11953198

你可能感兴趣的:(ONVIF,学习)