前言

做开发有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. JMeter脚本增强之参数化

    JMeter测试脚本录制或者编写,在Web应用和App上的操作方式可能有一点点区别(其实也差不多,哈哈),但是当脚本录制好了之后,对测试脚本的强化,包括参数化.关联.文本检查.集合点设置,甚至再往后的 ...

  2. mysql 、慢查询、到底如何玩

    在项目开发中,那些开发大佬经常会写出一些SQL语句,一条糟糕的SQL语句可能让你测试的整个程序都非常慢,超过10秒的话,我觉得一般用户就会选择关闭网页,如何优化SQL语句将那些运行时间 比较长的SQL ...

  3. 第153天:关于HTML标签嵌套的问题详解

    HTML标签 1.块级元素 div.h1~h6.address.blockquote.center.dir.dl.dt.dd.fieldset.form.hr.isindex.menu.noframe ...

  4. hdu6415 Rikka with Nash Equilibrium (DP)

    题目链接 Problem Description Nash Equilibrium is an important concept in game theory. Rikka and Yuta are ...

  5. HDU 6035 Colorful Tree(dfs)

    题意:一棵有n个点的树,树上每个点都有颜色c[i],定义每条路径的值为这条路径上经过的不同颜色数量和.求所有路径的值的和. 可以把问题转化为对每种颜色有多少条不同的路径至少经过这种颜色的点,然后加和. ...

  6. ES2015中let的暂时性死区(TDZ)

    Tomporal Dead Zone (TDZ)是ES2015中对作用域新的专用定义.是对于某些遇到在区块作用域绑定早于声明语句时的情况.Tomporal Dead Zone (TDZ)可以理解为时间 ...

  7. 【BZOJ4443】小凸玩矩阵(二分答案,二分图匹配)

    [BZOJ4443]小凸玩矩阵(二分答案,二分图匹配) 题面 BZOJ Description 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两 ...

  8. 51NOD 1709:复杂度分析——题解

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1709 (我什么时候看到二进制贡献才能条件反射想到按位处理贡献呢……) 参 ...

  9. Thuwc2018 游记

    上一次没有滚粗的比赛已经是9个月前了QAQ.但我现在回过头去看那篇“zjoi游记”,却发现自己并不能从中得到收获.希望这次写下的东西,可以帮助我更好地准备即将到来的省选(雾) day 0 火车上浪10 ...

  10. WlanGetAvailableNetworkList

    原文msdn链接地址:https://docs.microsoft.com/zh-cn/windows/desktop/api/wlanapi/nf-wlanapi-wlangetavailablen ...