前言

^_^

onvif客戶端開發過程

開發這類東西通常有兩條路可選擇,要麼從0開始編碼(固然,也不全是從0開始,能夠基於onvif的wsdl來生成一些調用類,這樣至少不用本身實現底層通信及協議封裝了,更多的只是爲上層接口具體功能作封裝,填充結構成員,調用對應的方法等),要麼基於現有的開源代碼進行改進,完善(開源的代碼通常也是經過從wsdl生成的代碼爲基礎而作的封裝)。我一般會先嚐試後者,沒有合適的開源代碼可參考時,纔會從0開始編碼,不必發明輪子。下面記錄下個人開發過程。c++

首先,用搜索引擎搜索onvif客戶端,去github或者gitlab上搜索onvif客戶端,從找到的結果中刷選出一些可能合適的,我最開始得出如下可能:git

我主要的過濾條件包括:github

  1. 咱們項目是C++的,我但願是onvif客戶端庫也是c/c++開發的
  2. 我但願該onvif庫的最後維護時間儘量新,由於onvif有不少版本,不一樣版本的wsdl生成的最終文件包含的功能有很大不一樣
  3. 可以在1天內編譯經過該開源的代碼,由於不少開源的項目不夠完善,別人很難很快的將其用起來
  4. 代碼寫的儘可能的標準、規範,換句話說,要寫的好看
^_^

進一步瞭解代碼後,發現rapidonvif所提供的開源部分只是包含了onvif客戶端的開發框架,不少功能都沒有徹底實現,可是很容易的進行完善,這得益於它漂亮的代碼編寫!這裏簡單的描述下我二次開發的過程,目錄結構圖以下: api

onvif客戶端功能的核心部分都是在onvifgen目錄裏面實現的(固然,不少都沒寫完,可是很容易補充全),它對應了onvifcpplib工程,生成onvifclient.lib靜態庫 example\client\onvifclientwin32裏面包含了一個onvifclient.lib靜態庫對應的測試demo框架

分析出以上兩部分以後,就能夠得出二次開發的方案了,我採用的修改example\client\onvifclientwin32,將它變成本身onvif客戶端對外的導出層,將編譯生成exe改爲生成dll,而後根據需求完善onvifcpplib。gitlab

舉例說明1:onvif搜索實現

搜索的實現是經過OnvifClientSearch類來完成的,該類已定義,可是功能須要本身補充,對應的頭文件onvifclientsearch.hpp,它內部是經過wsddProxy代理來實現搜索的,該代理封裝了soap,代理部分的大部分功能這個開源庫已經實現了,也就是說學會怎麼使用該類便可。測試

舉例說明2:onvif ptz實現

ptz的實現是經過OnvifClientPTZ類來完成的,該類已定義,可是功能須要本身補充,對應的頭文件onvifclientptz.hpp,它內部是經過PTZBindingProxy代理來實現ptz控制的,該代理封裝了soap,代理部分的大部分功能這個開源庫已經實現了,也就是說學會怎麼使用該類便可。所以,好消息是onvif ptz協議部分基本已經實現,咱們要作的就是根據PTZBindingProxy類實現一些ptz方法,而後補充到OnvifClientPTZ類中。搜索引擎

舉例說明3:onvif 抓圖實現

抓圖的實現是經過OnvifClientMedia類來完成的,該類已定義,可是功能須要本身補充,對應的頭文件onvifclientmedia.hpp,它內部是經過MediaBindingProxy代理來實現ptz控制的,該代理封裝了soap,代理部分的大部分功能這個開源庫已經實現了,也就是說學會怎麼使用該類便可。咱們主要須要經過onvif協議獲取抓圖uri,而後經過http去這個uri取抓圖的數據便可。參考實現以下:

inline int OnvifClientMedia::GetSnapshotUri(_trt__GetSnapshotUriResponse &SnapshotUriResponse,string profileToken)
{
	string strUrl;
	string strUser;
	string strPass;
	if (m_Device.GetUserPasswd(strUser, strPass) == false 
		|| m_Device.GetMediaUrl(strUrl) == false)
	{
		return SOAP_ERR;
	}

	mediaProxy.soap_endpoint =  strUrl.c_str();
	soap_wsse_add_Security(&mediaProxy);
	soap_wsse_add_UsernameTokenDigest(&mediaProxy, "Id", strUser.c_str() , strPass.c_str());

	_trt__GetSnapshotUri SnapshotUriReq;
	SnapshotUriReq.ProfileToken = profileToken;
	return mediaProxy.GetSnapshotUri(&SnapshotUriReq, &SnapshotUriResponse);
}

總結

個人onvif客戶端的實現沒有從0開始,而是採用基於rapidonvif二次開發實現的,該開源的代碼寫的很是漂亮,且onvif的功能也實現的很是全,同時,要擴展本身的功能的操做也是那固定的幾步,所以我認爲用它做爲本身onvif客戶端實現是很是適合的。