Qt编写视频监控系统77-Onvif组件支持非正常时间的设备

news/2024/5/13 10:17:18

一、前言

在经历了大量的现场设备测试,至少几十种厂家、几百种设备,遇见过奇奇怪怪的问题,一个个想方设法解决,发现有个问题是在下发鉴权的时候,需要带上设备的时间,而不是发送端的时间,如果带的不是设备上的时间很可能鉴权失败。这个问题亲测十几种市面上各种视频监控系统客户端,均未实现,通过抓包分析,客户端软件带的鉴权信息中是本地的时间,而不是设备的时间,导致根本无法通过onvif协议来加载该设备,这种体验非常的不友好,因为很可能设备出厂时间是1970年或者2000年等,而且设备上未必带有电池,断电后时间一长,时间很可能又恢复了,而设置日期时间指令也需要带上鉴权信息,但是好在获取日期时间指令是不需要鉴权信息的,于是通过这个为突破口,首次需要鉴权信息的指令前,主动获取下设备的日期时间,然后和本地的时间比较,取出一个秒数差值(设备上的时间和本地时间相差多少秒),如果设备是2000年那这个差值就是一个很大的负数值,在准备鉴权信息的时候,取本地时间加上这个差值即可,这样相当于下发的时间就是设备上的时间。如果设备上的时间更新过,则需要重新获取时间即可。

Onvif组件功能设计:

  • 搜索设备,获取设备的信息比如厂家、型号等。
  • 可指定网卡搜索,可能有多个网卡多个网段地址。
  • 可手动指定单个设备地址搜索,用于组播搜索不通但是网络通的情况。
  • 可以选择累加的方式统计搜索到的设备,在跨网段大量设备的情况下尤其需要。
  • 获取设备的多个配置文件信息profile。
  • 获取对应配置文件的视频流地址rtsp,以及分辨率等参数。
  • 云台控制,上下左右移动,焦距放大缩小,相对和绝对移动。
  • 获取预置位信息,增删改查,触发预置位。
  • 订阅事件,接收设备的各种消息尤其是报警事件比如IO口的报警。
  • 抓图,获取设备当前的图片。
  • 获取和设备网络配置信息比如IP地址等。
  • 获取和设置NTP时间同步以及设置设备时间。
  • 获取和设置视频参数和图片参数(亮度、色彩、饱和度)。
  • 重启设备。
  • 增加、删除、修改、查询OSD信息。

二、效果图

在这里插入图片描述

三、体验地址

  1. 国内站点:https://gitee.com/feiyangqingyun
  2. 国际站点:https://github.com/feiyangqingyun
  3. 个人作品:https://blog.csdn.net/feiyangqingyun/article/details/97565652
  4. 体验地址:https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g 提取码:01jf 文件名:bin_video_system。

四、相关代码

QString OnvifOther::getDateTime()
{QString result = writeData("GetSystemDateAndTime", "tt:Year|tt:Month|tt:Day|tt:Hour|tt:Minute|tt:Second|tt:TZ", "获取设备时间", true, true);QStringList list = result.split(OnvifResultSplit);if (list.count() != 7) {return result;}QString year = getResult(list.at(0));QString month = getResult(list.at(1));QString day = getResult(list.at(2));QString hour = getResult(list.at(3));QString min = getResult(list.at(4));QString sec = getResult(list.at(5));//计算时区并赋值QString timezone = list.at(6);timezone = timezone.mid(6, timezone.length() - 6);device->timezone = timezone;//将日期根据时区进行运算QString str = QString("%1-%2-%3 %4:%5:%6").arg(year).arg(month).arg(day).arg(hour).arg(min).arg(sec);QDateTime dt = QDateTime::fromString(str, "yyyy-M-d h:m:s");if (!device->timezone.contains("GMT-08")) {dt = dt.addSecs(8 * 60 * 60);}//2023-05-22 新增时间差值计算(有些设备需要用设备的时间去鉴权)device->timeOffset = QDateTime::currentDateTime().secsTo(dt);//不足两位补零list = dt.toString("yyyy-M-d-h-m-s").split("-");result = QString("%1-%2-%3 %4:%5:%6 %7").arg(list.at(0)).arg(list.at(1), 2, '0').arg(list.at(2), 2, '0').arg(list.at(3), 2, '0').arg(list.at(4), 2, '0').arg(list.at(5), 2, '0').arg(timezone);return result;
}bool OnvifOther::setDateTime(const QDateTime &datetime, bool ntp)
{QStringList temp = datetime.toString("yyyy-M-d-h-m-s").split("-");QString wsdl = "http://www.onvif.org/ver10/device/wsdl";QString schema = "http://www.onvif.org/ver10/schema";QStringList list;list << QString("    <SetSystemDateAndTime xmlns=\"%1\">").arg(wsdl);list << QString("      <DateTimeType>%1</DateTimeType>").arg(ntp ? "NTP" : "Manual");list << QString("      <DaylightSavings>%1</DaylightSavings>").arg("false");list << QString("      <TimeZone>");list << QString("        <TZ xmlns=\"%1\">%2</TZ>").arg(schema).arg(ntp ? device->timezone : "CST-8");list << QString("      </TimeZone>");if (!ntp) {list << QString("      <UTCDateTime>");list << QString("        <Date xmlns=\"%1\">").arg(schema);list << QString("          <Year>%1</Year>").arg(temp.at(0));list << QString("          <Month>%1</Month>").arg(temp.at(1));list << QString("          <Day>%1</Day>").arg(temp.at(2));list << QString("        </Date>");list << QString("        <Time xmlns=\"%1\">").arg(schema);list << QString("          <Hour>%1</Hour>").arg(temp.at(3));list << QString("          <Minute>%1</Minute>").arg(temp.at(4));list << QString("          <Second>%1</Second>").arg(temp.at(5));list << QString("        </Time>");list << QString("      </UTCDateTime>");}list << QString("    </SetSystemDateAndTime>");QString result = writeData(list.join("\r\n"), "SetSystemDateAndTimeResponse", "设置设备时间", false);return result.contains("SetSystemDateAndTimeResponse");
}QString OnvifXml::getUserToken(const QString &userName, const QString &userPwd, qint64 timeOffset)
{//要转成UTC格式的时间 "2019-08-10T03:31:37S"  "2020-10-11T09:24:44.988Z"//有些设备需要按照设备上的时间来鉴权(否则会失败)QDateTime DateTime = QDateTime::currentDateTime().addSecs(timeOffset).toUTC();QByteArray Created = DateTime.toString("yyyy-MM-ddThh:mm:ss.zzzZ").toLatin1();//指定字符串进行密码加密 LKqI6G/AikKCQrN0zqZFlg==QByteArray Nonce = Created.toBase64();QByteArray Nonce2 = QByteArray::fromBase64(Nonce);QByteArray Password = Nonce2 + Created + userPwd.toLatin1();Password = QCryptographicHash::hash(Password, QCryptographicHash::Sha1).toBase64();//固定字符串QString Enter = "\r\n        ";QString Type = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest";QString EncodingType = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary";QString xmlns = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";QStringList list;if (wsseToken) {list << QString("%1<wsse:Username>%2</wsse:Username>").arg(Enter).arg(userName);list << QString("%1<wsse:Password Type=\"%2\">%3</wsse:Password>").arg(Enter).arg(Type).arg(QString(Password));list << QString("%1<wsse:Nonce>%2</wsse:Nonce>").arg(Enter).arg(QString(Nonce));list << QString("%1<wsu:Created>%2</wsu:Created>").arg(Enter).arg(QString(Created));} else {list << QString("%1<Username>%2</Username>").arg(Enter).arg(userName);list << QString("%1<Password Type=\"%2\">%3</Password>").arg(Enter).arg(Type).arg(QString(Password));list << QString("%1<Nonce EncodingType=\"%2\">%3</Nonce>").arg(Enter).arg(EncodingType).arg(QString(Nonce));list << QString("%1<Created xmlns=\"%2\">%3</Created>").arg(Enter).arg(xmlns).arg(QString(Created));}list << QString("%1").arg("\r\n      ");return list.join("");
}

五、功能特点

5.1 软件模块

  1. 视频监控模块,各种停靠小窗体子模块,包括设备列表、图文警情、窗口信息、云台控制、预置位、巡航设置、设备控制、悬浮地图、网页浏览等。
  2. 视频回放模块,包括本地回放、远程回放、设备播放、图片回放、视频上传等。
  3. 电子地图模块,包括图片地图、在线地图、离线地图、路径规划等。
  4. 日志查询模块,包括本地日志、设备日志等。
  5. 系统设置模块,包括系统设置(基本设置、视频参数、数据库设置、地图配置、串口配置等)、录像机管理、摄像机管理、轮询配置、录像计划、用户管理等。

5.2 基础功能

  1. 支持各种视频流(rtsp、rtmp、http等)、视频文件(mp4、rmvb、avi等)、本地USB摄像机播放。
  2. 支持多画面切换,包括1、4、6、8、9、13、16、25、36、64画面切换。
  3. 支持全屏切换,多种切换方式包括鼠标右键菜单、工具栏按钮、快捷键(alt+enter全屏,esc退出全屏)。
  4. 支持视频轮询,包括1、4、9、16画面轮询,可设置轮询分组(轮询预案)、轮询间隔、码流类型等。
  5. 支持onvif协议,包括设备搜索、云台控制、预置位、设备控制(图片参数、校对时间、系统重启,抓拍图片等)。
  6. 支持权限管理,不同的用户可以对应不同的模块权限,比如删除日志、关闭系统等。
  7. 数据库支持多种,包括sqlite、mysql、sqlserver、postgresql、oracle、人大金仓等。
  8. 本地USB摄像机支持设置分辨率、帧率等参数。
  9. 所有停靠模块都自动生成对应的菜单用来控制显示和隐藏,在标题栏右键可以弹出。
  10. 支持显示所有模块、隐藏所有模块、复位普通布局、复位全屏布局。
  11. 双击设备弹出实时预览视频,支持图片地图、在线地图、离线地图等。
  12. 摄像机节点拖曳到对应窗体播放视频,同时支持拖曳本地文件直接播放。
  13. 删除视频支持鼠标右键删除、悬浮条关闭删除、拖曳到视频监控面板外删除等多种方式。
  14. 图片地图上设备按钮可自由拖动,自动保存位置信息。百度地图上可以鼠标单击获取经纬度信息,用来更新设备位置。
  15. 视频监控面板窗体中任意通道支持拖曳交换,瞬间响应。
  16. 封装了百度地图,视图切换,运动轨迹,设备点位,鼠标按下获取经纬度等。
  17. 双击节点、拖曳节点、拖曳窗体交换位置等操作,均自动更新保存最后的播放地址,下次软件打开自动应用。
  18. 右下角音量条控件,失去焦点自动隐藏,音量条带静音图标。
  19. 支持视频截图,可指定单个或者对所有通道截图,底部小工具栏也有截图按钮。
  20. 支持超时自动隐藏鼠标指针、自动全屏机制。
  21. 支持onvif云台控制,可上下左右移动云台摄像机,包括复位和焦距调整等。
  22. 支持onvif预置位,可以添加、删除、修改预置位,可以调用起始位。
  23. 支持onvif图像参数设置,包括明亮度、对比度、饱和度、尖锐度等。
  24. 支持onvif其他操作,包括抓图、网络设置、校时、重启、事件订阅等。
  25. 支持任意onvif摄像机,包括但不限于海康、大华、宇视、天地伟业、华为等。
  26. 可保存视频,可选定时存储或者单文件存储,可选存储间隔时间。
  27. 可设置视频流通信方式tcp+udp,可设置视频解码是速度优先、质量优先、均衡等。
  28. 可设置软件中文名称、英文名称、LOGO图标等。
  29. 存储的视频文件支持导出到指定目录,支持批量上传到服务器。
  30. 完善的录像计划设置,支持每个通道7 * 24小时每半小时设置是否存储录像。

5.3 特色功能

  1. 主界面采用停靠窗体模式,各种组件以小模块的形式加入,可自定义任意模块加入。
  2. 停靠模块可拖动任意位置嵌入和悬浮,支持最大化全屏,支持多屏幕。
  3. 双重布局文件存储机制,正常模式、全屏模式都对应不同的布局方案,自动切换和保存,比如全屏模式可以突出几个模块透明显示在指定位置,更具科幻感现代化。
  4. 原创onvif协议机制,采用底层协议解析(udp广播搜索+http请求执行命令)更轻量易懂易学习拓展,不依赖任何第三方组件比如gsoap。
  5. 原创数据导入、导出、打印机制,跨平台不依赖任何组件,瞬间导出数据。
  6. 内置多个原创组件,宇宙超值超级牛逼,包括数据导入导出组件(导出到xls、pdf、打印)、数据库组件(数据库管理线程、自动清理数据线程、万能分页、数据请求等)、地图组件、视频监控组件、文件多线程收发组件、onvif通信组件、通用浏览器内核组件等。
  7. 自定义信息框+错误框+询问框+右下角提示框(包含多种格式)等。
  8. 精美换肤,高达17套皮肤样式随意更换,所有样式全部统一,包括菜单等。
  9. 视频控件悬浮条可以自行增加多个按钮,监控界面底部小工具栏也可自行增加按钮。
  10. 双击摄像机节点自动播放视频,双击节点自动依次添加视频,会自动跳到下一个,双击父节点自动添加该节点下的所有视频。可选主码流、子码流。
  11. 录像机管理、摄像机管理,可添加删除修改导入导出打印信息,立即应用新的设备信息生成树状列表,不需重启。
  12. 可选多种内核自由切换,ffmpeg、vlc、mpv等,均可在pro中设置。推荐用ffmpeg,跨平台最多,默认提供好了linux和mac平台上编译好的库。
  13. 支持硬解码,可设置硬解码类型(qsv、dxva2、d3d11va等)。
  14. 默认采用opengl绘制视频,超低的CPU资源占用,支持yuyv和nv12两种格式绘制,性能爆表。
  15. 标签和图形信息支持三种绘制方式,绘制到遮罩层、绘制到图片、源头绘制(对应信息可以存储到文件)。
  16. 高度可定制化,用户可以很方便的在此基础上衍生自己的功能,比如增加自定义模块,增加运行模式、机器人监控、无人机监控、挖掘机监控等。
  17. 支持xp、win7、win10、win11、linux、mac、各种国产系统(UOS、中标麒麟、银河麒麟等)、嵌入式linux等系统。
  18. 注释完整,项目结构清晰,超级详细完整的使用开发手册,精确到每个代码文件的功能说明,不断持续迭代版本。

http://wed.xjx100/news/238241.html

相关文章

第15章:索引的数据结构

一、为什么使用索引 1.索引是存储引擎用于快速找到记录的一种数据结构。相当于一本书的目录。在进行数据查找时&#xff0c;首先查看查询条件是否命中某条索引&#xff0c;符合则通过索引查找相关数据。如果不符合则需要全表扫描&#xff0c;一条一条查找记录&#xff0c;直到…

项目经理提高绩效的10个目标

作者 | Fred Wilson 一、项目经理的目的和目标是什么&#xff1f; 项目经理是任何团队的重要成员。他们孜孜不倦地工作&#xff0c;以确保项目按时、在预算范围内完成&#xff0c;并达到尽可能高的标准。 然而&#xff0c;有一些目标可以帮助提高项目经理管理团队和组织工作流…

通过extundelete实现CentOS6 ext4文件系统误删除文件的恢复

1.介质下载 路径&#xff1a; 链接&#xff1a;extundelete 提取码&#xff1a;ztj0 版本&#xff1a;extundelete.0.2.4 2.实验环境 1.CentOS6.8 系统版本命令&#xff1a; cat /etc/redhat-release 2.磁盘&#xff1a;/dev/sdb 磁盘查看命令&#xff1a; lsblk |g…

多个手动下载jar包网址+例子

以下是可以下载Java的jar包的一些网站以及一个可下载的jar包例子的下载链接&#xff1a; 网站名网址jar包例子下载地址Maven Central Repositoryhttps://search.maven.org/https://repo1.maven.org/maven2/com/google/code/gson/gson/2.8.5/gson-2.8.5.jarGradle Plugin Porta…

怎么样判断一个公司值不值得加入

&#xff08;点击即可收听&#xff09; 怎么样判断一个公司值不值得加入 对于刚毕业,初入职场的同学,对于人生当中的第一份工作,真的挺重要的 虽然第一份工作决定不了什么,但是第一份好的工作,对职业生涯起很大的作用 人生中遇到一位好的导师,工作当中,那些愿意指导,循循教导的…

【C++系列P1】带上这篇基础小宝典,进发C++!(持续更新ing~)

​​​​​​​ 前言 大家好吖&#xff0c;欢迎来到 YY 滴 C系列 &#xff0c;热烈欢迎&#xff01;(持续更新ing~&#xff09;本章主要内容面向刚刚学完C语言&#xff0c;准备或正在接触C的老铁。而往往C奇多的小特性和知识点让铁铁们头晕晕脑涨涨&#xff0c;因而本章收纳了…

v4L2应用开发学习!

一.什么是V4L2框架&#xff1f; V4L2英文全称是Video for Linux2&#xff0c;它是专门为视频设备设计的内核驱动。在做视频的开发中&#xff0c;一般我们操控V4L2的设备节点就可以直接对摄像头进行操作。通常V4L2在Linux的设备节点是**/dev/video0**。无论是MIPI摄像头还是UVC摄…

PyTorch-完整的模型训练套路

目录 1. 准备 1.1 使用Cifar10 1.2 item的用法 1.3 model的搭建 1.4 数据集、参数设置以及训练开始 1.5 测试集 1.6 使用tensorboard 1.7 保存每一轮的训练结果 2. 计算整体的正确率 3. 其他 3.1 train与eval 3.2 使用GPU训练 1. 准备 1.1 使用Cifar10 1.2 item的…