Onvif之裝置發現
阿新 • • 發佈:2019-02-20
研究Onvif終於告一個段落了,有些東西整理出來,供參考分享。
怎麼利用gsoap生成onvif客戶端程式碼,網上有很多介紹這裡就不再說明了。 下面直接上程式碼:
int CONVIFClientDlg::ONVIF_Discovery(char *devType) { struct soap *soap = NULL; //soap環境變數 struct SOAP_ENV__Header header; //SOAP的頭 struct wsdd__ScopesType sScope; //Probe裡面的範圍 struct wsdd__ProbeType req; //客戶端傳送的Probe struct __wsdd__ProbeMatches resp; //服務端回的Probematchs char strUUID[50]; char was_To[] = "urn:schemas-xmlsoap-org:ws:2005:04:discovery"; char was_Action[] = "http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe"; char cDev[] = "tds:Device"; char cNVT[] = "tdn:NetworkVideoTransmitter"; int result = 0; int count = 0; int iTimes = 0; soap = soap_new(); if(NULL == soap ) { printf("[%s][%d]new soap failed!\n", __FUNCTION__,__LINE__); return 0; } soap_set_namespaces(soap, namespaces); // soap_init(soap); soap_init1(soap, SOAP_IO_UDP|SOAP_IO_FLUSH); // soap_init2(soap, SOAP_IO_UDP|SOAP_IO_FLUSH|SOAP_IO_KEEPALIVE, SOAP_IO_UDP|SOAP_IO_FLUSH|SOAP_IO_KEEPALIVE); // if(!soap_valid_socket(soap_bind(soap, NULL, 3702, 10))) // { // return NULL; // } soap->recv_timeout = 3; soap->send_timeout = 3; // soap->connect_timeout = 5; soap_default_SOAP_ENV__Header(soap, &header); soap_default_wsdd__ScopesType(soap, &sScope); soap_default_wsdd__ProbeType(soap, &req); //給頭賦值 //獲取guid(windows下叫guid,linux下叫uuid),格式為urn:uuid:8-4-4-4-12,由系統隨機產生 memset(strUUID, 0, 50); NewUUID(strUUID); header.wsa__MessageID = strUUID; //(char *)soap_wsa_rand_uuid(soap); header.wsa__To = was_To; //"urn:schemas-xmlsoap-org:ws:2005:04:discovery"; header.wsa__Action = was_Action; //"http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe"; soap->header = &header; //設定所需尋找裝置的型別和範圍,二者至少設定一個,否則可能收到非ONVIF裝置,出現異常; sScope.__item = ""; //設定所需裝置的sScope, onvif://www.onvif.org req.Scopes = &sScope; if(devType == NULL) { req.Types = cNVT; } else { //tdn:NetworkVideoTransmitter, 設定所需裝置的型別,tdn為名稱空間字首, //為wsdd.nsmap檔案中{"tdn","http://www.onvif.org/ver10/network/wsdl"}的tdn, //如過不是tdn,而是其它,如ns1這裡也要隨之改為ns1 req.Types = devType; //tdn:NetworkVideoTransmitter } //以下用於UDP繫結IP傳送訊息 int iSelect = m_cbHostIP.GetCurSel(); if(iSelect != -1 && iSelect < m_iIpNum) { soap->ip = inet_addr(m_IpAddr[iSelect].ip); } #if 0 while(iTimes < MAX_SENDMSG_TIMES) //需要傳送多次訊息 { printf("傳送Probe!\n"); result = soap_send___wsdd__Probe(soap,"soap.udp://239.255.255.250:3702", NULL, &req); if(result != SOAP_OK) { printf("Probe傳送失敗!\n"); } iTimes++; printf("已傳送Probe次數:%d\n", iTimes); req.Types = Dev; //重新生成UUID NewUUID(strUUID); ::Sleep(100); } do{ result = soap_recv___wsdd__ProbeMatches(soap,&resp); //接收ProbeMatches,成功返回0,否則-1 if (result != SOAP_OK) { printf("Probe接收失敗!\n"); break; } else { count++; CString strIP; strIP.Format(_T("%d.%d.%d.%d"), ((soap->ip)>>24)&0xFF, ((soap->ip)>>16)&0xFF, ((soap->ip)>>8)&0xFF,(soap->ip)&0xFF); _tprintf(_T("\n%s\n"), strIP); if(resp.wsdd__ProbeMatches != NULL) { cout<<"===============發現裝置"<<count<<"================"<<endl; cout<<"Type:"<<resp.wsdd__ProbeMatches->ProbeMatch->Types<<endl; cout<<"Service Address:"<<resp.wsdd__ProbeMatches->ProbeMatch->XAddrs<<endl; cout<<"UUID:"<<resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.Address<<endl; cout<<"MetadataVersion:"<<resp.wsdd__ProbeMatches->ProbeMatch->MetadataVersion<<endl; cout<<"Scopes:"<<resp.wsdd__ProbeMatches->ProbeMatch->Scopes->__item<<endl; cout<<"========================================="<<endl; //可能有多個服務地址 CString strServiceAddr(resp.wsdd__ProbeMatches->ProbeMatch->XAddrs); CString strUUID(resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.Address); int index = m_stDeviceList.InsertItem(0, _T("OnvifDevice")); m_stDeviceList.SetItemText(index, 0, strIP); m_stDeviceList.SetItemText(index, 1, strServiceAddr); m_stDeviceList.SetItemText(index, 2, strUUID); } } }while(1); #else //通過組播發送Probe探針,傳送成功返回0,否則-1 BOOL bFind = FALSE; while(iTimes < MAX_SENDMSG_TIMES) //需要傳送多次訊息 { if(m_bExit) { break; } printf("傳送Probe!\n"); result = soap_send___wsdd__Probe(soap,"soap.udp://239.255.255.250:3702", NULL, &req); if(result != SOAP_OK) { printf("Probe傳送失敗!\n"); } else { count = 0; do{ result = soap_recv___wsdd__ProbeMatches(soap,&resp); //接收ProbeMatches,成功返回0,否則-1 if (result != SOAP_OK) { printf("Probe接收失敗!\n"); break; } else { count++; CString strIP; strIP.Format(_T("%d.%d.%d.%d"), ((soap->ip)>>24)&0xFF, ((soap->ip)>>16)&0xFF, ((soap->ip)>>8)&0xFF,(soap->ip)&0xFF); _tprintf(_T("\n%s\n"), strIP); if(resp.wsdd__ProbeMatches != NULL) { cout<<"===============發現裝置"<<count<<"================"<<endl; cout<<"Type:"<<resp.wsdd__ProbeMatches->ProbeMatch->Types<<endl; cout<<"Service Address:"<<resp.wsdd__ProbeMatches->ProbeMatch->XAddrs<<endl; if(resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.Address != NULL) { cout<<"UUID:"<<resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.Address<<endl; } cout<<"MetadataVersion:"<<resp.wsdd__ProbeMatches->ProbeMatch->MetadataVersion<<endl; cout<<"Scopes:"<<resp.wsdd__ProbeMatches->ProbeMatch->Scopes->__item<<endl; cout<<"========================================="<<endl; //可能有多個服務地址 CString strServiceAddr(resp.wsdd__ProbeMatches->ProbeMatch->XAddrs); CString strUUID(_T("")); if(resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.Address != NULL) { strUUID = resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.Address; } CString strMetadataVersion; strMetadataVersion.Format("%d", resp.wsdd__ProbeMatches->ProbeMatch->MetadataVersion); int index = m_stDeviceList.InsertItem(0, _T("OnvifDevice")); m_stDeviceList.SetItemText(index, 0, strIP); m_stDeviceList.SetItemText(index, 1, strUUID); m_stDeviceList.SetItemText(index, 2, strServiceAddr); m_stDeviceList.SetItemText(index, 7, strMetadataVersion); } bFind = TRUE; } }while(1); } iTimes++; printf("已傳送Probe次數:%d\n", iTimes); ::Sleep(1); if(bFind) { break; } memset(strUUID, 0, 50); NewUUID(strUUID); header.wsa__MessageID = strUUID; //(char *)soap_wsa_rand_uuid(soap); header.wsa__To = was_To; //"urn:schemas-xmlsoap-org:ws:2005:04:discovery"; header.wsa__Action = was_Action; //"http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe"; soap->header = &header; } #endif printf("\n總共發現裝置數:%d\n\n", count); //清除變數 soap_destroy(soap); //removedeserialized class instances (C++ only) soap_end(soap); //clean up and remove deserialized data // soap_done(soap); soap_free(soap); ::Sleep(1000); return count; }