ONVIF协议全解析:版本、Profile与关键流程实现
一、ONvif版本详解
1. 版本演进与核心更新
版本 | 发布时间 | 核心特性 |
---|---|---|
ONVIF 1.0 | 2008 | 初始版本,支持设备发现、基础媒体流(RTSP)。 |
ONVIF 2.0 | 2010 | 引入Profile S(视频设备)、Profile G(存储设备),支持PTZ控制。 |
ONVIF 2.4 | 2014 | 新增Profile C(IO设备),扩展报警输入/输出功能。 |
ONVIF 2018 | 2018 | 发布Profile T(高级视频设备),支持H.265、元数据、视频分析。 |
ONVIF 2021 | 2021 | 强制TLS加密,增强事件订阅模型,支持OAuth 2.0。 |
2. 版本兼容性策略
- 命名空间动态适配:不同版本接口的命名空间不同(如
ver10
、ver20
),需生成多版本代码。 - 功能降级:通过
GetCapabilities
接口检测设备能力,自动切换功能(如H.264→H.265)。 - 鉴权兼容:支持WS-Security Digest(2.0+)和Basic Auth(1.0旧设备)。
二、Profile详解:功能与适用场景
1. Profile S(基础视频流设备)
- 适用设备:网络摄像头(IPC)、视频编码器。
- 核心功能:
- 设备发现(WS-Discovery)。
- 实时视频流(RTSP/RTP)。
- PTZ云台控制(预置位、巡航)。
- 事件订阅(移动侦测、报警输入)。
- 必选接口:
DeviceService
、MediaService
、PTZService
、EventService
。
2. Profile T(高级视频设备)
- 适用设备:支持智能分析的高端IPC。
- 扩展功能:
- H.265/HEVC编码。
- 多码流传输(主码流+子码流)。
- 元数据叠加(人脸框、结构化数据)。
- 视频分析(区域入侵、人数统计)。
- 必选接口:在Profile S基础上增加
AnalyticsService
。
3. Profile G(存储设备扩展)
- 适用设备:支持本地存储的IPC或NVR。
- 核心功能:
- 存储管理(SD卡、NAS)。
- 录像检索与回放。
- 视频片段下载。
- 必选接口:
RecordingService
、ReplayService
。
4. Profile C(输入输出设备)
- 适用设备:带报警输入/输出接口的IPC或门禁设备。
- 核心功能:
- 报警触发(红外传感器、门磁信号)。
- 联动输出(控制继电器、灯光)。
- 必选接口:
DeviceIOService
。
三、关键流程实现与C++代码示例
1. 设备发现(WS-Discovery)
流程:
- 客户端发送UDP多播Probe请求(端口3702)。
- 设备响应ProbeMatch消息,返回服务地址(
XAddrs
)和支持的Profile。
设备端代码:
#include <wsddapi.h>
// 响应Probe请求
int onvif_probe_handler(struct soap *soap, const char *message_id, ...) {
struct wsdd__ProbeMatchesType resp;
resp.ProbeMatch->XAddrs = "http://192.168.1.100/onvif/device_service";
resp.ProbeMatch->Scopes = "onvif://www.onvif.org/Profile/S";
return soap_wsdd_ProbeMatches(soap, NULL, message_id, endpoint, &resp);
}
// 启动WS-Discovery服务
soap_wsdd_listen(soap, -1);
客户端代码:
soap_wsdd_search(soap, SOAP_WSDD_ADHOC, "dn:NetworkVideoTransmitter", NULL);
2. 鉴权(WS-Security)
流程:
- 客户端生成
UsernameToken
(包含Nonce、Timestamp、PasswordDigest)。 - 服务端校验密码哈希和时间戳。
客户端添加安全头:
#include <wsseapi.h>
soap_wsse_add_UsernameTokenDigest(proxy.soap, "user", "admin", "password");
设备端校验密码:
int validate_user(struct soap *soap, const char *username, const char *password) {
if (strcmp(username, "admin") == 0 && strcmp(password, "123456") == 0)
return SOAP_OK;
return SOAP_FAULT;
}
3. 媒体流获取(GetStreamUri)
设备端实现:
int MediaServiceService::GetStreamUri(...) {
resp->MediaUri->Uri = "rtsp://192.168.1.100:554/live/main";
return SOAP_OK;
}
客户端调用:
MediaBindingProxy proxy;
_trt__GetStreamUri req;
req.StreamSetup->Stream = tt__StreamType__RTP_Unicast;
proxy.GetStreamUri(&req, resp);
string rtspUrl = resp.MediaUri->Uri; // 播放RTSP流
4. 事件订阅(Event Subscription)
客户端订阅事件:
EventBindingProxy proxy;
_tev__CreatePullPointSubscription req;
proxy.CreatePullPointSubscription(&req, resp);
string subscriptionId = resp.SubscriptionReference.Address;
设备端推送事件:
void send_event(struct soap *soap, const char *topic, const char *message) {
soap_wsdd_event_ProbeMatches(soap, NULL, topic, message, &resp);
}
5. PTZ控制(ContinuousMove)
客户端调用云台转动:
PTZBindingProxy proxy;
_tptz__ContinuousMove req;
req.Velocity->PanTilt->x = 0.5; // 水平速度
req.Velocity->PanTilt->y = 0.3; // 垂直速度
proxy.ContinuousMove(&req, resp);
四、多版本与多Profile兼容实现
1. 动态生成多版本代码
# 生成2.0版本代码
wsdl2h -c -s -o onvif_2.0.h devicemgmt-2.0.wsdl media-2.0.wsdl
soapcpp2 -j -CL onvif_2.0.h
# 生成2018版本代码
wsdl2h -c -s -o onvif_2018.h devicemgmt-2018.wsdl media-2018.wsdl
soapcpp2 -j -CL onvif_2018.h
2. 运行时动态适配
// 根据命名空间选择代理类
if (namespace_uri.find("ver10") != string::npos) {
auto proxy = new DeviceBindingProxy_2_0(SOAP_C_UTFSTRING);
} else if (namespace_uri.find("ver20") != string::npos) {
auto proxy = new DeviceBindingProxy_2018(SOAP_C_UTFSTRING);
}
五、验证与调试工具
- ONVIF Test Tool:官方工具验证Profile合规性。
- Wireshark:抓包分析SOAP消息和RTSP流。
- VLC/FFmpeg:测试RTSP流播放。
- ONVIF Device Manager:可视化测试设备发现和PTZ控制。
六、总结
- 版本选择:优先支持主流版本(如2018 Profile T),兼顾旧设备(2.0 Profile S)。
- Profile实现:根据设备类型选择Profile,逐步扩展功能。
- 关键流程:设备发现→鉴权→媒体流→事件→PTZ控制,通过gSOAP生成代码快速实现。
- 兼容性:动态适配命名空间,检测设备能力,降级处理。