Onvif协议:IPC客户端开发之获取设备能力
生活随笔
收集整理的這篇文章主要介紹了
Onvif协议:IPC客户端开发之获取设备能力
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
原理簡介
ONVIF協議接口由多個模塊組成,每個模塊分別對應著不同的WSDL文檔,在ONVIF官網中能查看到這些模塊,以及每個模塊中的接口函數,這里列舉幾個模塊:
- DeviceMgmt(設備管理)
- 使用GetDeviceInformation接口獲取設備基本信息
- 使用GetSystemDateAndTime接口和SetSystemDateAndTime接口對設備進行校時
- DeviceIO(設備IO服務)
- Event(事件處理)
- Analytics(視頻分析)
- AnalyticsDevice(分析設備)
- Display(顯示服務)
- Imaging(圖像配置)
- Media(媒體配置)
- PTZ(PTZ控制)
- Receiver(接收端配置)
- RemoteDiscovery(設備發現)
- Recording(錄像控制)
- Replay(重放控制)
- Search(記錄搜索)
除了「RemoteDiscovery」模塊之外,每個模塊都有各自的「服務地址」,客戶端要使用這些模塊接口之前,必須先知道對應模塊的「服務地址」。
怎樣才能獲取這些模塊的「服務地址」呢?分兩步:
-
利用WS-Discovery搜索到IPC,就能得知該設備「DeviceMgmt」模塊的「服務地址」,我們稱之為「設備服務地址」(就是我們搜索設備的時候獲取到的http://10.0.0.47/onvif/device_service)。
-
使用「設備服務地址」調用「DeviceMgmt」模塊的GetCapabilities接口(這個接口不需要鑒權就可以得到),就能獲取到所有模塊的「服務地址」。
實踐
具體請參考
但是main.cpp修改為:
#include <assert.h> #include "soapH.h" #include "wsdd.nsmap" #include "soapStub.h" #include "wsseapi.h" #include "wsaapi.h"#define USERNAME "admin" #define PASSWORD "hik12345"#define SOAP_ASSERT assert #define SOAP_DBGLOG printf #define SOAP_DBGERR printf#define SOAP_TO "urn:schemas-xmlsoap-org:ws:2005:04:discovery" #define SOAP_ACTION "http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe"#define SOAP_MCAST_ADDR "soap.udp://239.255.255.250:3702" // onvif規定的組播地址#define SOAP_ITEM "" // 尋找的設備范圍 #define SOAP_TYPES "dn:NetworkVideoTransmitter" // 尋找的設備類型#define SOAP_SOCK_TIMEOUT (10) // socket超時時間(單秒秒)void soap_perror(struct soap *soap, const char *str) {if (nullptr == str) {SOAP_DBGERR("[soap] error: %d, %s, %s\n", soap->error, *soap_faultcode(soap), *soap_faultstring(soap));} else {SOAP_DBGERR("[soap] %s error: %d, %s, %s\n", str, soap->error, *soap_faultcode(soap), *soap_faultstring(soap));} }void* ONVIF_soap_malloc(struct soap *soap, unsigned int n) {void *p = nullptr;if (n > 0) {p = soap_malloc(soap, n);SOAP_ASSERT(nullptr != p);memset(p, 0x00 ,n);}return p; }struct soap *ONVIF_soap_new(int timeout) {struct soap *soap = nullptr; // soap環境變量SOAP_ASSERT(nullptr != (soap = soap_new()));soap_set_namespaces(soap, namespaces); // 設置soap的namespacessoap->recv_timeout = timeout; // 設置超時(超過指定時間沒有數據就退出)soap->send_timeout = timeout;soap->connect_timeout = timeout;#if defined(__linux__) || defined(__linux) // 參考https://www.genivia.com/dev.html#client-c的修改:soap->socket_flags = MSG_NOSIGNAL; // To prevent connection reset errors #endifsoap_set_mode(soap, SOAP_C_UTFSTRING); // 設置為UTF-8編碼,否則疊加中文OSD會亂碼return soap; }void ONVIF_soap_delete(struct soap *soap) {soap_destroy(soap); // remove deserialized class instances (C++ only)soap_end(soap); // Clean up deserialized data (except class instances) and temporary datasoap_done(soap); // Reset, close communications, and remove callbackssoap_free(soap); // Reset and deallocate the context created with soap_new or soap_copy }/************************************************************************ **函數:ONVIF_init_header **功能:初始化soap描述消息頭 **參數:[in] soap - soap環境變量 **返回:無 **備注:1). 在本函數內部通過ONVIF_soap_malloc分配的內存,將在ONVIF_soap_delete中被釋放 ************************************************************************/ void ONVIF_init_header(struct soap *soap) {struct SOAP_ENV__Header *header = nullptr;SOAP_ASSERT(nullptr != soap);header = (struct SOAP_ENV__Header *)ONVIF_soap_malloc(soap, sizeof(struct SOAP_ENV__Header));soap_default_SOAP_ENV__Header(soap, header);header->wsa__MessageID = (char*)soap_wsa_rand_uuid(soap);header->wsa__To = (char*)ONVIF_soap_malloc(soap, strlen(SOAP_TO) + 1);header->wsa__Action = (char*)ONVIF_soap_malloc(soap, strlen(SOAP_ACTION) + 1);strcpy(header->wsa__To, SOAP_TO);strcpy(header->wsa__Action, SOAP_ACTION);soap->header = header; }/************************************************************************ **函數:ONVIF_init_ProbeType **功能:初始化探測設備的范圍和類型 **參數:[in] soap - soap環境變量[out] probe - 填充要探測的設備范圍和類型 **返回:0表明探測到,非0表明未探測到 **備注:1). 在本函數內部通過ONVIF_soap_malloc分配的內存,將在ONVIF_soap_delete中被釋放 ************************************************************************/ void ONVIF_init_ProbeType(struct soap *soap, struct wsdd__ProbeType *probe) {struct wsdd__ScopesType *scope = nullptr; // 用于描述查找哪類的Web服務SOAP_ASSERT(nullptr != soap);SOAP_ASSERT(nullptr != probe);scope = (struct wsdd__ScopesType *)ONVIF_soap_malloc(soap, sizeof(struct wsdd__ScopesType));soap_default_wsdd__ScopesType(soap, scope); // 設置尋找設備的范圍scope->__item = (char*)ONVIF_soap_malloc(soap, strlen(SOAP_ITEM) + 1);strcpy(scope->__item, SOAP_ITEM);memset(probe, 0x00, sizeof(struct wsdd__ProbeType));soap_default_wsdd__ProbeType(soap, probe);probe->Scopes = scope;probe->Types = (char*)ONVIF_soap_malloc(soap, strlen(SOAP_TYPES) + 1); // 設置尋找設備的類型strcpy(probe->Types, SOAP_TYPES); }void ONVIF_DetectDevice(void (*cb)(char *DeviceXAddr)) {int i;int result = 0;unsigned int count = 0; // 搜索到的設備個數struct soap *soap = nullptr; // soap環境變量struct wsdd__ProbeType req; // 用于發送Probe消息struct __wsdd__ProbeMatches rep; // 用于接收Probe應答struct wsdd__ProbeMatchType *probeMatch;SOAP_ASSERT(nullptr != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT)));ONVIF_init_header(soap); // 設置消息頭描述ONVIF_init_ProbeType(soap, &req); // 設置尋找的設備的范圍和類型result = soap_send___wsdd__Probe(soap, SOAP_MCAST_ADDR, nullptr, &req); // 向組播地址廣播Probe消息while (SOAP_OK == result) // 開始循環接收設備發送過來的消息{memset(&rep, 0x00, sizeof(rep));result = soap_recv___wsdd__ProbeMatches(soap, &rep);if (SOAP_OK == result) {if (soap->error) {soap_perror(soap, "ProbeMatches");} else { // 成功接收到設備的應答消息printf("__sizeProbeMatch:%d\n",rep.wsdd__ProbeMatches->__sizeProbeMatch);if (nullptr != rep.wsdd__ProbeMatches) {count += rep.wsdd__ProbeMatches->__sizeProbeMatch;for(i = 0; i < rep.wsdd__ProbeMatches->__sizeProbeMatch; i++) {probeMatch = rep.wsdd__ProbeMatches->ProbeMatch + i;if (nullptr != cb) {cb(probeMatch->XAddrs); // 使用設備服務地址執行函數回調}}}}} else if (soap->error) {break;}}SOAP_DBGLOG("\ndetect end! It has detected %d devices!\n", count);if (nullptr != soap) {ONVIF_soap_delete(soap);}}#define SOAP_CHECK_ERROR(result, soap, str) \do { \if (SOAP_OK != (result) || SOAP_OK != (soap)->error) { \soap_perror((soap), (str)); \if (SOAP_OK == (result)) { \(result) = (soap)->error; \} \goto EXIT; \} \ } while (0)/************************************************************************ **函數:ONVIF_SetAuthInfo **功能:設置認證信息 **參數:[in] soap - soap環境變量[in] username - 用戶名[in] password - 密碼 **返回:0表明成功,非0表明失敗 **備注: ************************************************************************/ static int ONVIF_SetAuthInfo(struct soap *soap, const char *username, const char *password) {int result = 0;SOAP_ASSERT(nullptr != username);SOAP_ASSERT(nullptr != password);result = soap_wsse_add_UsernameTokenDigest(soap, NULL, username, password);SOAP_CHECK_ERROR(result, soap, "add_UsernameTokenDigest");EXIT:return result; } /************************************************************************ **函數:ONVIF_GetDeviceInformation **功能:獲取設備基本信息 **參數:[in] DeviceXAddr - 設備服務地址 **返回:0表明成功,非0表明失敗 **備注: ************************************************************************/ int ONVIF_GetDeviceInformation(const char *DeviceXAddr) {int result = 0;struct soap *soap = nullptr;_tds__GetDeviceInformation devinfo_req;_tds__GetDeviceInformationResponse devinfo_resp;SOAP_ASSERT(nullptr != DeviceXAddr);SOAP_ASSERT(nullptr != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT)));ONVIF_SetAuthInfo(soap, USERNAME, PASSWORD);result = soap_call___tds__GetDeviceInformation(soap, DeviceXAddr, nullptr, &devinfo_req, devinfo_resp);SOAP_CHECK_ERROR(result, soap, "GetDeviceInformation");std::cout << " Manufacturer:\t" << devinfo_resp.Manufacturer << "\n";std::cout << " Model:\t" << devinfo_resp.Model << "\n";std::cout << " FirmwareVersion:\t" << devinfo_resp.FirmwareVersion << "\n";std::cout << " SerialNumber:\t" << devinfo_resp.SerialNumber << "\n";std::cout << " HardwareId:\t" << devinfo_resp.HardwareId << "\n";EXIT:if (nullptr != soap) {ONVIF_soap_delete(soap);}return result; }/************************************************************************ **函數:ONVIF_GetCapabilities **功能:獲取設備能力信息 **參數:[in] DeviceXAddr - 設備服務地址 **返回:0表明成功,非0表明失敗 **備注:1). 其中最主要的參數之一是媒體服務地址 ************************************************************************/ int ONVIF_GetCapabilities(const char *DeviceXAddr) {int result = 0;struct soap *soap = NULL;_tds__GetCapabilities devinfo_req;_tds__GetCapabilitiesResponse devinfo_resp;SOAP_ASSERT(NULL != DeviceXAddr);SOAP_ASSERT(NULL != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT)));result = soap_call___tds__GetCapabilities(soap, DeviceXAddr, NULL, &devinfo_req, devinfo_resp);SOAP_CHECK_ERROR(result, soap, "GetCapabilities");std::cout << " Device.XAddr: " << devinfo_resp.Capabilities->Device->XAddr << "\n";std::cout << " Analytics.XAddr: " << devinfo_resp.Capabilities->Analytics->XAddr << "\n";std::cout << " Events.XAddr: " << devinfo_resp.Capabilities->Events->XAddr << "\n";std::cout << " Imaging.XAddr: " << devinfo_resp.Capabilities->Imaging->XAddr << "\n";std::cout << " Media.XAddr: " << devinfo_resp.Capabilities->Media->XAddr << "\n";if (devinfo_resp.Capabilities->PTZ != nullptr){std::cout << " PTZ.XAddr: " << devinfo_resp.Capabilities->PTZ->XAddr << "\n";}std::cout << " Extension.DeviceIO.XAddr: " << devinfo_resp.Capabilities->Extension->DeviceIO->XAddr << "\n";EXIT:if (NULL != soap) {ONVIF_soap_delete(soap);}return result; }/************************************************************************ **函數:ONVIF_GetCapabilities **功能:獲取wsdl的地址 **參數:[in] DeviceXAddr - 設備服務地址 **返回:0表明成功,非0表明失敗 **備注:1). 其中最主要的參數之一是媒體服務地址 ************************************************************************/ int ONVIF_GetWsdlUrl(const char *DeviceXAddr) {int result = 0;struct soap *soap = nullptr;_tds__GetWsdlUrl devinfo_req;_tds__GetWsdlUrlResponse devinfo_resp;SOAP_ASSERT(nullptr != DeviceXAddr);SOAP_ASSERT(nullptr != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT)));result = soap_call___tds__GetWsdlUrl(soap, DeviceXAddr, nullptr, &devinfo_req, devinfo_resp);SOAP_CHECK_ERROR(result, soap, "ONVIF_GetWsdlUrl");std::cout << " WsdlUrl:\t" << devinfo_resp.WsdlUrl << "\n";EXIT:if (nullptr != soap) {ONVIF_soap_delete(soap);}return result; }void cb_discovery(char *DeviceXAddr) {ONVIF_GetDeviceInformation(DeviceXAddr);ONVIF_GetCapabilities(DeviceXAddr); }int main(int argc, char **argv) {ONVIF_DetectDevice(cb_discovery);return 0; }其他文章
- Onvif協議:理解什么是Web Services
- Onvif協議:使用gSOAP創建SOAP調用實例
- Onvif協議:門外漢理解ONVIF協議
- Onvif協議:到底什么是ONVIF協議
- Onvif協議:實現Probe命令來進行設備發現(discover)
- Onvif協議:IPC客戶端開發之獲取設備基本信息
- Onvif協議:IPC客戶端開發之鑒權
- Onvif協議:IPC客戶端開發之獲取設備能力
- Onvif協議:IPC客戶端開發之PTZ控制
- Onvif協議:IPC客戶端開發之獲取實時預覽的Url地址
- Onvif協議:IPC客戶端開發之圖像抓拍
- ONVIF Device Test Tool測試工具使用方法
總結
以上是生活随笔為你收集整理的Onvif协议:IPC客户端开发之获取设备能力的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux设置断网自动关机(蓄电池)
- 下一篇: UG通讯类复杂薄壁产品工厂案例,00多张