您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# Qt Onvif信息获取方法是什么
## 目录
1. [ONVIF协议概述](#onvif协议概述)
2. [Qt与ONVIF开发环境搭建](#qt与onvif开发环境搭建)
3. [ONVIF设备发现机制](#onvif设备发现机制)
4. [设备能力信息获取](#设备能力信息获取)
5. [媒体流地址获取](#媒体流地址获取)
6. [PTZ控制实现](#ptz控制实现)
7. [常见问题与解决方案](#常见问题与解决方案)
8. [完整代码示例](#完整代码示例)
<a id="onvif协议概述"></a>
## 1. ONVIF协议概述
ONVIF(Open Network Video Interface Forum)是网络视频设备领域的国际标准化协议,它定义了:
- 网络视频设备的发现机制
- 设备管理接口
- 媒体配置接口
- PTZ控制接口
- 事件处理机制
协议基于以下核心技术:
- **SOAP**:简单对象访问协议
- **WS-Discovery**:设备发现协议
- **XML**:数据交换格式
- **HTTP/RTSP**:传输协议
典型应用场景包括:
- 安防监控系统集成
- 多厂商设备兼容
- 智能视频分析平台
<a id="qt与onvif开发环境搭建"></a>
## 2. Qt与ONVIF开发环境搭建
### 2.1 开发环境要求
- Qt 5.15+(推荐使用MSVC或MinGW编译器)
- ONVIF WSDL文件(可从官网下载)
- gSOAP工具包(版本2.8+)
### 2.2 关键组件安装
```bash
# 安装gSOAP(Ubuntu示例)
sudo apt-get install gsoap libgsoap-dev
# Windows版本需要手动编译
wsdl2h -c -o onvif.h \
https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl \
https://www.onvif.org/ver20/media/wsdl/media.wsdl \
https://www.onvif.org/ver20/ptz/wsdl/ptz.wsdl
soapcpp2 -j -CL -I/usr/local/share/gsoap/import onvif.h
# 在.pro文件中添加
INCLUDEPATH += $$PWD/gsoap
LIBS += -lgsoap++
设备发现采用UDP多播方式: - 目标地址:239.255.255.250 - 端口:3702 - 协议版本:SOAP 1.2
#include <QUdpSocket>
#include <QNetworkInterface>
void discoverDevices() {
QUdpSocket socket;
const QString probeMsg =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
"<e:Envelope xmlns:e=\"http://www.w3.org/2003/05/soap-envelope\""
" xmlns:w=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\""
" xmlns:d=\"http://schemas.xmlsoap.org/ws/2005/04/discovery\">"
"<e:Header><w:MessageID>uuid:%1</w:MessageID>"
"<w:To>urn:schemas-xmlsoap-org:ws:2005:04:discovery</w:To>"
"<w:Action>http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</w:Action>"
"</e:Header><e:Body><d:Probe><d:Types>dn:NetworkVideoTransmitter</d:Types>"
"</d:Probe></e:Body></e:Envelope>";
QByteArray datagram = probeMsg.arg(QUuid::createUuid().toString()).toUtf8();
socket.writeDatagram(datagram, QHostAddress("239.255.255.250"), 3702);
}
void readPendingDatagrams() {
while (socket->hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(socket->pendingDatagramSize());
socket->readDatagram(datagram.data(), datagram.size());
QDomDocument doc;
if (doc.setContent(datagram)) {
QDomNodeList matches = doc.elementsByTagName("wsdd:ProbeMatches");
for (int i = 0; i < matches.count(); ++i) {
QDomElement element = matches.at(i).toElement();
QString xaddr = element.firstChildElement("XAddrs").text();
// 解析设备端点地址
}
}
}
}
#include "soapDeviceBindingProxy.h"
#include "wsseapi.h"
void getCapabilities(const QString &endpoint) {
DeviceBindingProxy proxy;
proxy.soap_endpoint = endpoint.toStdString().c_str();
_tds__GetCapabilities req;
_tds__GetCapabilitiesResponse resp;
// 添加WS-Security头
soap_wsse_add_UsernameTokenDigest(proxy.soap, nullptr, "username", "password");
if (proxy.GetCapabilities(&req, resp) {
qDebug() << "Device Service:" << resp.Capabilities->Device->XAddr;
qDebug() << "Media Service:" << resp.Capabilities->Media->XAddr;
}
}
字段 | 说明 |
---|---|
Device->XAddr | 设备管理服务地址 |
Media->XAddr | 媒体服务地址 |
PTZ->XAddr | PTZ控制服务地址 |
Analytics->XAddr | 分析服务地址 |
Events->XAddr | 事件服务地址 |
void getProfiles(const QString &mediaEndpoint) {
MediaBindingProxy proxy;
proxy.soap_endpoint = mediaEndpoint.toStdString().c_str();
_trt__GetProfiles req;
_trt__GetProfilesResponse resp;
if (proxy.GetProfiles(&req, resp) == SOAP_OK) {
for (auto profile : resp.Profiles) {
qDebug() << "Profile Token:" << profile->token;
}
}
}
QString getStreamUri(const QString &mediaEndpoint, const QString &profileToken) {
MediaBindingProxy proxy;
proxy.soap_endpoint = mediaEndpoint.toStdString().c_str();
_trt__GetStreamUri request;
request.ProfileToken = profileToken.toStdString();
request.StreamSetup = new tt__StreamSetup();
request.StreamSetup->Stream = tt__StreamType__RTP_Unicast;
request.StreamSetup->Transport = new tt__Transport();
request.StreamSetup->Transport->Protocol = tt__TransportProtocol__RTSP;
_trt__GetStreamUriResponse response;
if (proxy.GetStreamUri(&request, response) == SOAP_OK) {
return QString::fromStdString(response.MediaUri->Uri);
}
return "";
}
void ptzControl(const QString &ptzEndpoint,
const QString &profileToken,
float pan, float tilt, float zoom) {
PTZBindingProxy proxy;
proxy.soap_endpoint = ptzEndpoint.toStdString().c_str();
_tptz__ContinuousMove req;
req.ProfileToken = profileToken.toStdString();
req.Velocity = new tt__PTZSpeed();
req.Velocity->PanTilt = new tt__Vector2D();
req.Velocity->PanTilt->x = pan;
req.Velocity->PanTilt->y = tilt;
req.Velocity->Zoom = new tt__Vector1D();
req.Velocity->Zoom->x = zoom;
_tptz__ContinuousMoveResponse resp;
proxy.ContinuousMove(&req, resp);
}
操作 | 方法 |
---|---|
添加预置位 | SetPreset |
调用预置位 | GotoPreset |
删除预置位 | RemovePreset |
现象:返回401 Unauthorized
解决方案:
// 添加WS-Security头
soap_wsse_add_UsernameTokenDigest(proxy.soap, nullptr,
username.toStdString().c_str(),
password.toStdString().c_str());
现象:请求被拒绝
解决方案:
#include "plugin/wsaapi.h"
// 添加时间戳头
soap_wsa_add_Timestamp(proxy.soap, "TimeRequest", 10);
现象:长时间运行内存增长
解决方案:
// 定期清理SOAP上下文
soap_destroy(proxy.soap);
soap_end(proxy.soap);
// onvifdiscover.h
#include <QObject>
#include <QUdpSocket>
class OnvifDiscover : public QObject {
Q_OBJECT
public:
explicit OnvifDiscover(QObject *parent = nullptr);
void startDiscovery();
signals:
void deviceFound(const QString &xaddr);
private slots:
void readPendingDatagrams();
private:
QUdpSocket *socket;
};
// onvifdiscover.cpp
#include "onvifdiscover.h"
OnvifDiscover::OnvifDiscover(QObject *parent)
: QObject(parent) {
socket = new QUdpSocket(this);
connect(socket, &QUdpSocket::readyRead,
this, &OnvifDiscover::readPendingDatagrams);
}
void OnvifDiscover::startDiscovery() {
const QString probeMsg = "..."; // 同前文probe消息
socket->writeDatagram(probeMsg.toUtf8(),
QHostAddress("239.255.255.250"), 3702);
}
void OnvifDiscover::readPendingDatagrams() {
// 解析逻辑同前文
}
本文详细介绍了在Qt环境下实现ONVIF协议通信的完整流程,包括: 1. 设备发现机制的实现 2. 能力信息的获取方法 3. 媒体流地址的解析 4. PTZ控制的具体实现
通过上述方法,开发者可以构建兼容ONVIF标准的视频监控管理系统。实际开发中还需注意: - 多线程处理网络请求 - 异常处理机制 - 设备兼容性测试 - 性能优化
建议参考ONVIF官方文档(https://www.onvif.org)获取最新的协议规范更新。 “`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。