前言

做开发有8年时间了,ffmpeg和onvif与我是特别有缘的了(说着玩的,我更认为是因为他们确实强大^_^)。 ffmpeg在毕业设计时就有用到,5年后做windows、linux播放库时又有用到,于是又重新研究!!! onvif是我在毕业第二年的时候,有从0开始写过一个onvif服务端NVT,没想到6年后,项目中的客户端又需要用到它!!!其实本来不想开发它的,但是因为客户端依赖的onvif部分是别人的库,我们需要onvif抓图功能,结果对方没时间做,也不愿意把代码开放给我们,我特郁闷,这个又没什么技术含量,没必要当个宝藏着吧! 于是花了一周时间开发了自己的onvif客户端(这里不是从0开发,而是基于现有的开源onvif客户端开发的)。

onvif客户端开发过程

开发这类东西一般有两条路可选择,要么从0开始编码(当然,也不全是从0开始,可以基于onvif的wsdl来生成一些调用类,这样至少不用自己实现底层通讯及协议封装了,更多的只是为上层接口具体功能做封装,填充结构成员,调用对应的方法等),要么基于现有的开源代码进行改进,完善(开源的代码一般也是通过从wsdl生成的代码为基础而做的封装)。我通常会先尝试后者,没有合适的开源代码可参考时,才会从0开始编码,没必要发明轮子。下面记录下我的开发过程。

首先,用搜索引擎搜索onvif客户端,去github或者gitlab上搜索onvif客户端,从找到的结果中刷选出一些可能合适的,我最开始得出以下可能:

我主要的过滤条件包括:

  1. 我们项目是C++的,我希望是onvif客户端库也是c/c++开发的
  2. 我希望该onvif库的最后维护时间尽可能新,因为onvif有很多版本,不同版本的wsdl生成的最终文件包含的功能有很大不同
  3. 能够在1天内编译通过该开源的代码,因为很多开源的项目不够完善,别人很难很快的将其用起来
  4. 代码写的尽量的标准、规范,换句话说,要写的好看

经过以上几个过滤实施后,我选择了 rapidonvif,它是c++开发的,而且和最新的onvif几乎同步,也是一次就编译通过了,通过简单的代码阅读,觉得代码写的挺漂亮的^_^

进一步了解代码后,发现rapidonvif所提供的开源部分只是包含了onvif客户端的开发框架,很多功能都没有完全实现,但是很容易的进行完善,这得益于它漂亮的代码编写!这里简单的描述下我二次开发的过程,目录结构图如下:

onvif客户端功能的核心部分都是在onvifgen目录里面实现的(当然,很多都没写完,但是很容易补充全),它对应了onvifcpplib工程,生成onvifclient.lib静态库

example\client\onvifclientwin32里面包含了一个onvifclient.lib静态库对应的测试demo

分析出以上两部分之后,就可以得出二次开发的方案了,我采用的修改example\client\onvifclientwin32,将它变成自己onvif客户端对外的导出层,将编译生成exe改成生成dll,然后根据需求完善onvifcpplib。

举例说明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客户端实现是非常适合的。

onvif客户端的更多相关文章

  1. ONVIF客户端搜索设备获取rtsp地址开发笔记(精华篇)

    原文  http://blog.csdn.net/gubenpeiyuan/article/details/25618177   概要: 目前ONVIF协议家族设备已占据数字监控行业半壁江山以上,亲, ...

  2. 【视频开发】ONVIF客户端搜索设备获取rtsp地址开发笔记(精华篇)

    转载地址:http://blog.csdn.net/gubenpeiyuan/article/details/25618177 概要:           目前ONVIF协议家族设备已占据数字监控行业 ...

  3. ONVIF客户端中预置位设置代码实现过程

    simpleOnvif的功能:提供支持Windows.Linux.arm.Android.iOS等各种平台的SDK库,方便集成,二次开发 之前跟大家分享了我们安徽思蔷信息科技的simpleOnvif的 ...

  4. Linux下onvif客户端获取ipc摄像头 GetServices:获取媒体地址(有的h265摄像头必须要这个接口)

    GetServices:获取媒体地址(有些h265的摄像头必须用到这个接口,得到获取能力时没获取到的另一个媒体地址) 鉴权:但是在使用这个接口之前是需要鉴权的.ONVIF协议规定,部分接口需要鉴权,部 ...

  5. Linux下onvif客户端关于ipc摄像头的搜索

    设备搜索:要访问一个IPC摄像头,或者说要调用IPC摄像头提供的WEB服务接口,就要先知道其IP地址,这就是设备发现的过程,或者叫设备搜索的过程.IPC摄像头用的是239.255.255.250(端口 ...

  6. Linux下onvif客户端获取h265 IPC摄像头的RTSP地址

    1. 设备搜索,去获取webserver 的地址 ,目的是在获取能力提供服务地址,demo:https://www.cnblogs.com/croxd/p/10683429.html 2. GetCa ...

  7. Linux下onvif客户端获取ipc摄像头 GetStreamUri:rtsp地址(h264、h265)

    GetStreamUri:rtsp地址 鉴权:但是在使用这个接口之前是需要鉴权的.ONVIF协议规定,部分接口需要鉴权,部分接口不需要鉴权,在调用需要鉴权的接口时不使用鉴权,会导致接口调用失败.实现鉴 ...

  8. Linux下onvif客户端获取ipc摄像头 获取能力:GetCapabilities

    GetCapabilities:获取能力,主要目的获取设备能力信息(获取媒体服务地址) 鉴权:但是在调用获取设备能力之前是需要鉴权的.ONVIF协议规定,部分接口需要鉴权,部分接口不需要鉴权,在调用需 ...

  9. Linux下onvif客户端获取ipc摄像头 GetProfiles:获取h265媒体信息文件

    GetProfiles:获取媒体信息文件 鉴权:但是在使用这个接口之前是需要鉴权的.ONVIF协议规定,部分接口需要鉴权,部分接口不需要鉴权,在调用需要鉴权的接口时不使用鉴权,会导致接口调用失败.实现 ...

随机推荐

  1. 【插件】LinqToExcel常用对象

    1.ExcelQueryFactory对象(1)获取工作表名集合IEnumerable<string> GetWorksheetNames() //获取工作薄中的工作表名foreach ( ...

  2. 【loj6342】跳一跳 期望dp

    题目描述 一个人从 $1$ 开始向 $n$ 跳,在 $i$ 时会等概率跳到 $i,i+1,...,n$ 之一.求从 $1$ 跳到 $n$ 的期望步数. $n\le 10^7$ . 题解 期望dp傻逼题 ...

  3. 【交换机在江湖】第十三章 VLAN划分篇

    江湖各位大侠重温了VLAN的基础知识,是否想过4094个VLAN可以怎样划分,哪种方式又是好用简单的?细心的小编特地整理了一番,给各位大侠把玩把玩. VLAN划分的方式: Ø 基于接口划分VLAN:  ...

  4. mysql索引长度的一些限制

    一.myisam存储引擎 1. 数据库版本:阿里云RDS MySQL5.1 mysql> select @@version;+-------------------------------+| ...

  5. 【CodeChef-SPCLN】Cleaning the Space

    https://odzkskevi.qnssl.com/7dfb262544887eff6fb35bfb444759d6?v=1502084197 做法是类似于最大割之类的东西,把每个碎片按照按钮拆点 ...

  6. BZOJ1069 [SCOI2007]最大土地面积 【凸包 + 旋转卡壳】

    题目链接 BZOJ1069 题解 首先四个点一定在凸包上 我们枚举对角线,剩下两个点分别是两侧最远的点 可以三分,复杂度\(O(n^2logn)\) 可以借鉴旋转卡壳的思想,那两个点随着对角线的一定单 ...

  7. BZOJ4197 [Noi2015]寿司晚宴 【状压dp】

    题目链接 BZOJ4197 题解 两个人选的数都互质,意味着两个人选择了没有交集的质因子集合 容易想到将两个人所选的质因子集合作为状态\(dp\) \(n\)以内质数很多,但容易发现\(\sqrt{n ...

  8. Codeforces 744C. Hongcow Buys a Deck of Cards(状压DP)

    这题的难点在于状态的设计 首先显然是个状压,需要一维表示卡的状态,另一维如果设计成天数,难以知道当前的钱数,没法确定是否能够购买新的卡,如果设计成钱数,会发现状态数过多,空间与时间都无法承受.但是可以 ...

  9. 【bzoj4596】黑暗前的幻想乡

    Portal -->bzoj4596 Solution 这题的话..因为\(N\)比较小啊所以我们可以大力容斥(尽管实际算下来复杂度有点爆炸不过实测是能过的qwq) 枚举包含了哪些颜色的边,每次 ...

  10. Oracle10g数据泵impdp参数详解--摘自网络

    Oracle10g数据泵impdp参数详解 2011-6-30 12:29:05 导入命令Impdp •      ATTACH 连接到现有作业, 例如 ATTACH [=作业名]. •      C ...