onvif-bridge:标准协议桥接
案例背景
onvif-bridge 是 NeoMind 生态中的标准协议桥接案例。ONVIF(Open Network Video Interface Forum)是网络视频设备的开放标准,定义了设备发现(WS-Discovery)、媒体流协商(RTSP URL 获取)、PTZ 控制、事件订阅等接口规范。覆盖 Profile S(流媒体)、Profile T(高级流媒体)、Profile G(视频存储)等多个 profile。
任何符合 ONVIF Profile S 的 IP 摄像头——海康、大华、安讯威、Tiandy——都可以通过 onvif-bridge 接入 NeoMind,无需厂商私有 SDK,无需适配层。
当前版本 2.7.6,核心代码分布在 5 个 Rust 源文件中约 2700 行:lib.rs(1646 行,Extension trait + 命令分发)、soap_client.rs(516 行,SOAP envelope + WS-Security)、discovery.rs(211 行,WS-Discovery UDP 多播)、ptz.rs(214 行,PTZ 命令)、types.rs(78 行,数据结构)。
它解决了什么问题? NeoMind 的前端需要统一管理异构 IP 摄像头。如果每个厂商都用自己的 SDK(海康 SDK、大华 SDK、Tiandy SDK),代码量爆炸、维护成本高、新厂商接入周期长。
onvif-bridge 把 ONVIF 标准协议封装为 NeoMind 的命令和指标,前端只需调用 discover / get_stream_uri / ptz_move 等统一命令,就能操作任何 ONVIF 兼容摄像头。这是开放标准驱动的集成策略——不是适配厂商,而是适配协议。
与 5 uink-rms-bridge 的对比预告:5 uink-rms-bridge 是厂商专有协议(封闭 SDK + 私有二进制协议),onvif-bridge 是标准协议(开放规范 + SOAP/WS-Discovery)。
两者代表 NeoMind 生态中两种截然不同的集成策略——「标准协议桥接」vs「专有协议桥接」——各自的适用场景、工程复杂度、维护成本差异巨大。本系列 5 会专门对比这两种策略。
与 NeoEyes 摄像头产品线的关系:NeoEyes NE101 / NE301 等硬件设备部分支持 ONVIF 协议栈,onvif-bridge 也可以作为这些自研设备的通用接入路径。当客户混部 NeoEyes 摄像头和第三方 ONVIF 摄像头时,onvif-bridge 提供统一的管理面板。
两大痛点驱动了手写而非依赖现成 crate:
- ONVIF 协议栈复杂——SOAP 1.2 envelope + WS-Security UsernameToken Profile + WS-Discovery UDP 多播,现成的 Rust crate(如
onvif-rs)维护滞后且不覆盖 PTZ/事件订阅,缺失的功能只能自己补 - 厂商实现差异大——某些设备 Probe 响应的 XML 命名空间前缀不规范(
SOAP-ENV:vss:vssoap:),某些设备 SOAP Fault 格式不标准,解析逻辑必须容忍这些差异
目标读者:
- 要接入第三方 IP 摄像头的集成商——你会看到从设备发现到 PTZ 控制的完整命令链路
- 想理解 SOAP / WS-Discovery / WS-Security 在 Rust 中如何手写的协议开发者——本案例没有依赖任何 ONVIF/SOAP crate,全部手写,是纯协议工程的极佳参考。
你将学到:
- WS-Discovery 多播发现的工程实现——UDP 多播 socket 绑定、TTL 控制、Probe/ProbeMatch 消息格式、macOS 多播陷阱
- SOAP 1.2 + WS-Security UsernameToken Profile 的 PasswordDigest 算法——SHA1(nonce+created+password) 的 Rust 实现和为什么选择 PasswordDigest 而非 PasswordText
- ONVIF 设备能力协商链路——GetDeviceInformation → GetProfiles → GetStreamUri → 可选 PTZ
- 纯后端桥接扩展的架构模式——无 frontend 组件、无 ONNX 模型、同步 HTTP、如何通过命令系统和虚拟指标与 NeoMind 主体集成
架构总览
onvif-bridge 是一个纯后端协议桥接扩展——没有 frontend 组件、没有 ONNX 模型、没有视频解码逻辑。它的职责是:用标准协议(WS-Discovery + SOAP)与 ONVIF 摄像头通信,把结果转化为 NeoMind 的命令返回值和虚拟指标。
扩展进程内通过 parking_lot::RwLock 管理 HashMap<String, OnvifDevice> 设备注册表,所有命令操作都围绕这个注册表展开。
模块职责拆分
| 模块 | 文件 | 行数 | 职 责 |
|---|---|---|---|
| 入口 + 分发 | src/lib.rs | 1646 | Extension trait 实现(metadata / metrics / commands / execute_command)、设备注册表(RwLock HashMap)、14 个命令处理函数、FFI 导出 |
| WS-Discovery | src/discovery.rs | 211 | UDP 多播 socket 构建、Probe 消息模板、ProbeMatch 解析(多命名空间容忍)、find_local_ipv4 本地 IP 检测 |
| SOAP 客户端 | src/soap_client.rs | 516 | SOAP envelope 构建、WS-Security UsernameToken(PasswordDigest)、ureq 同步 HTTP 发送、SOAP Fault 解析、设备能力协商函数群 |
| PTZ 控制 | src/ptz.rs | 214 | PTZ RelativeMove / AbsoluteMove / Stop / GotoHomePosition / GetPresets / GotoPreset 六个命令封装 |
| 数据结构 | src/types.rs | 78 | OnvifConfig / OnvifDevice / OnvifProfile / VideoEncoderConfig / PtzParams / DiscoveryMatch |
与 AI 推理扩展的架构对比
| 架构维度 | 2 yolo-device-inference | 3 yolo-video-v2 | 4 onvif-bridge |
|---|---|---|---|
| 核心职责 | 单帧 YOLO 推理 | 实时视频流推理 + 检测 | 标准协议桥接(发现 + 取流 URL + PTZ) |
| ONNX 模型 | 有 | 有 | 无 |
| Frontend 组件 | 无 | YoloVideoDisplay | 无(纯后端) |
| 视频解码 | 无(直接消费 image) | ffmpeg-next / nokhwa | 无 |