当前位置: 首页 > news >正文

[笔记]ONVIF服务端实现[进行中...]

1.文档搜索:

从:https://www.cnblogs.com/liwen01/p/17337916.html

跳转到了:ONVIF协议网络摄像机(IPC)客户端程序开发(1):专栏开篇_onvif 许振坪-CSDN博客

1.1原生代码支持:

https://gstreamer.freedesktop.org/documentation/gst-rtsp-server/rtsp-onvif-server.html?gi-language=c 

我大概知道ONVIF的服务端涉及两个端口:

  1. 摄像头发现端口:udp 239.255.255.250:3702
  2. ONVIF协议侦听端口。 

大概率gstreamer能搞定后一个。前一个是个udp端口
 

2.ONVIF协议的分类:

Profile S:「网络摄像机」的技术规格,包括如何发送音视频流,音视频编码器配置,PTZ控制、中继控制等。
Profile C:「门禁控制系统(PACS)设备」的技术规格。
Profile G:「视频储存和录像」的技术规格,包括视频储存,搜索,检索,以及媒体播放功能的技术规格。
Profile A:「常见的例行门禁控制功能」的技术规范,适用于负责授予和撤销员工凭证、创建和更新计划表,以及对系统内门禁控制权限进行更改的安保人员、接待员或人力资源专员等用户。
Profile Q:「传输层安全性(TLS)」的技术规格,该安全通信协议使ONVIF合标设备能够以不受篡改和窃听威胁的方式在网络上与客户通讯。

S是等级最低的,在它之前似乎还有个T。这里是S的协议文档

然后我看到的文档里推荐下载这个:https://download.csdn.net/download/benkaoya/9818513

大概是中文版。

2.1 设备发现

参阅:https://blog.csdn.net/benkaoya/article/details/72476120

多播地址(Multicast Address)有很多,各个行业都不一样,IPC摄像头用的是239.255.255.250(端口3702)。多播地址的范围和分类可以见官方IANA(互联网地址分配机构)的说明:IPv4 Multicast Address Space Registry。 

import socket
import struct# 组播地址和端口
MULTICAST_GROUP = '239.255.255.250'
PORT = 3702def discover_onvif_devices():# 创建一个 UDP 套接字sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)# 设置多播 TTLsock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32)# 允许重用地址sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)# 绑定到本地端口sock.bind(('', 3702))# 加入组播组mreq = struct.pack("4sl", socket.inet_aton(MULTICAST_GROUP), socket.INADDR_ANY)sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)# 构造 SSDP 请求ssdp_request = ('M-SEARCH * HTTP/1.1\r\n''HOST: 239.255.255.250:3702\r\n''MAN: "ssdp:discover"\r\n''MX: 1\r\n''ST: urn:schemas-xmlsoap-org:ws:2005:04:discovery\r\n''USER-AGENT: Python/1.0\r\n''X-User-Agent: redsonic\r\n''X-User-Agent: intel/1.0\r\n''\r\n')# 发送请求到多播地址sock.sendto(ssdp_request.encode(), (MULTICAST_GROUP , PORT))while True:try:# 设置接收超时时间sock.settimeout(10.0)# 接收响应response, _ = sock.recvfrom(1024)print(f'Received response:\n{response.decode()}')except socket.timeout:break# 退出组播组sock.setsockopt(socket.IPPROTO_IP, socket.IP_DROP_MEMBERSHIP, mreq)# 关闭套接字sock.close()if __name__ == "__main__":discover_onvif_devices()

对于多播的地址,理论上upd客户端是能够收到回应的。

但是它只能收到自己发送的信息。

使用另一个ONVIF客户端,抓包,抓到的是其他的东西:

<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsd="http://schemas.xmlsoap.org/ws/2005/04/discovery" xmlns:wsdp="http://schemas.xmlsoap.org/ws/2006/02/devprof"><soap:Header><wsa:To>urn:schemas-xmlsoap-org:ws:2005:04:discovery</wsa:To><wsa:Action>http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</wsa:Action><wsa:MessageID>urn:uuid:f3d90f52-4758-42ba-b3fc-d6785f0d6e4d</wsa:MessageID></soap:Header><soap:Body><wsd:Probe><wsd:Types>wsdp:Device</wsd:Types></wsd:Probe></soap:Body></soap:Envelope>

使用网络调试助手,同样没有回应。

3.实现:

作者推荐使用gSoap工具来提供ONVIF协议的解析。

而chatgpt的推荐是使用客户端工具,阅读源码来反向构建其服务程序:

  1. onvif-py

    • 这个库有一个模块化结构,可以用来创建一个支持 ONVIF 协议的服务端。但它主要是作为一个 ONVIF 客户端库,因此你需要阅读源代码来了解如何使用它来创建服务端。这需要一定的编程知识。
  2. onvif_zm(用于 ZoneMinder):

    • 这个库原本是为 ZoneMinder 设计的,用于实现与 ONVIF 设备的通讯。虽然它是作为客户端库,但了解其工作原理后,你可以参考其代码来构建服务端。
  3. onvif.server

    • 这个库是 ONVIF 服务器的一个实现,它支持标准的 ONVIF 服务如 Discovery、Device、Media、PTZ、Event 等。这个库提供了创建和管理 ONVIF 服务器所需的所有基本功能。

4.FAQ 

4.1 什么是gSoap?

gSOAP 是一个开源的 C 语言库,用于开发 Web 服务和客户端。它简化了 SOAP(Simple Object Access Protocol)和 XML 相关的通信,使得在 C 语言应用程序中实现 Web 服务变得更容易。gSOAP 提供了自动化的工具来生成 C 语言的客户端和服务器端代码,从而支持 Web 服务的创建和消费。

以下是 gSOAP 的一些关键特点:

  1. SOAP 支持:gSOAP 实现了 SOAP 1.1 和 SOAP 1.2 协议,使得开发人员可以通过简单的接口来创建和解析 SOAP 消息。

  2. WSDL 支持:gSOAP 可以从 WSDL(Web Services Description Language)文件自动生成 C 语言代码,简化了 Web 服务的客户端和服务器端的开发。

  3. 轻量级:gSOAP 设计为一个轻量级库,适合嵌入式和资源有限的环境。

  4. 高效:gSOAP 具有高效的解析和序列化功能,可以处理大量的数据交换。

  5. 灵活性:它支持多种数据格式,包括 XML 和 JSON。

  6. 跨平台:gSOAP 是跨平台的,可以在多种操作系统上使用,包括 Windows、Linux 和 macOS。

  7. XML 和 JSON 处理:除了 SOAP,gSOAP 还提供对 XML 和 JSON 数据格式的处理支持。

使用 gSOAP,可以快速地将现有的 C 语言应用程序与 Web 服务集成,实现分布式计算和数据交换。

相关文章:

  • 1.Spring Boot 简介(Spring MVC+Mybatis-plus)
  • oracle 查询锁表
  • JS 鼠标拖动实现移动滚动条的滚动效果
  • pageoffice常见问题处理
  • 算法 —— 暴力枚举
  • Godot入门 04平台设计
  • UE4-构建光照后导入的静态网格体变黑
  • c++中的scanf
  • Midjourney绘画提示词精选
  • 使用 nmcli 管理网络连接
  • 【Python机器学习】决策树的构造——信息增益
  • 网络安全自学从入门到精通的制胜攻略!!!
  • 【调色板软件】免费、开源的调色板软件,焰火十二卷,提供了多种功能来生成一组调和色彩NO.108
  • vue3+vite 实现动态引入某个文件夹下的组件 - glob-import的使用
  • Unity UGUI 之 自动布局组件
  • (十五)java多线程之并发集合ArrayBlockingQueue
  • “Material Design”设计规范在 ComponentOne For WinForm 的全新尝试!
  • 【159天】尚学堂高琪Java300集视频精华笔记(128)
  • 【EOS】Cleos基础
  • 【跃迁之路】【444天】程序员高效学习方法论探索系列(实验阶段201-2018.04.25)...
  • 【跃迁之路】【641天】程序员高效学习方法论探索系列(实验阶段398-2018.11.14)...
  • echarts花样作死的坑
  • es6--symbol
  • httpie使用详解
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • JDK 6和JDK 7中的substring()方法
  • Puppeteer:浏览器控制器
  • PyCharm搭建GO开发环境(GO语言学习第1课)
  • SegmentFault 技术周刊 Vol.27 - Git 学习宝典:程序员走江湖必备
  • 阿里云ubuntu14.04 Nginx反向代理Nodejs
  • 关于springcloud Gateway中的限流
  • 基于遗传算法的优化问题求解
  • 记一次和乔布斯合作最难忘的经历
  • 使用 Docker 部署 Spring Boot项目
  • 使用Tinker来调试Laravel应用程序的数据以及使用Tinker一些总结
  • 使用权重正则化较少模型过拟合
  • 思维导图—你不知道的JavaScript中卷
  • 自定义函数
  • Nginx实现动静分离
  • SAP CRM里Lead通过工作流自动创建Opportunity的原理讲解 ...
  • 阿里云重庆大学大数据训练营落地分享
  • 我们雇佣了一只大猴子...
  • ​ArcGIS Pro 如何批量删除字段
  • ​DB-Engines 12月数据库排名: PostgreSQL有望获得「2020年度数据库」荣誉?
  • ​如何在iOS手机上查看应用日志
  • #mysql 8.0 踩坑日记
  • #ubuntu# #git# repository git config --global --add safe.directory
  • #免费 苹果M系芯片Macbook电脑MacOS使用Bash脚本写入(读写)NTFS硬盘教程
  • (1)Nginx简介和安装教程
  • (2024,RWKV-5/6,RNN,矩阵值注意力状态,数据依赖线性插值,LoRA,多语言分词器)Eagle 和 Finch
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (el-Date-Picker)操作(不使用 ts):Element-plus 中 DatePicker 组件的使用及输出想要日期格式需求的解决过程
  • (el-Transfer)操作(不使用 ts):Element-plus 中 Select 组件动态设置 options 值需求的解决过程
  • (九)c52学习之旅-定时器
  • (十二)springboot实战——SSE服务推送事件案例实现