Onvif ライブラリのカプセル化と qt プロジェクトは onvif ライブラリを呼び出して、デバイス検索やコード ストリーム アドレスの取得などの機能を実現します

I.はじめに:

    この記事の OnvifManager プロジェクトは、vs2010 で開発およびコンパイルされています。onvif ライブラリのカプセル化と呼び出しを実現します。現在のプロジェクト インターフェイスは、onvif の検索、コード ストリーム アドレスの取得、デバイスの再起動インターフェイスを実現します。その他のインターフェイスは、後でプロジェクト コードを変更することで変更されます。qt プロジェクト myonvif は、OnvifManager によって生成されたダイナミック ライブラリを呼び出し、QTableview を使用して検索されたデバイス情報を表示し、コード ストリーム アドレスの取得とデバイスの再起動をサポートし、ワンクリック Web ページ アクセスをサポートします。

2. OnvifManager ダイナミック ライブラリ インターフェイスの説明

/************************************************ ****

  • デバイス検索インターフェース 1
  • @pUser ユーザー名の入力
  • @pPwd パスワード入力
  • @pLocalIP ローカル コンピュータの IP 入力
  • @vecDevInfo が検索したデバイス情報の出力
  • @searchタイムアウト入力
  • @戻り値 0: 成功 それ以外: 失敗
  • ************************************************* */
    int FF_Onvif_Discovery1(char *pUser, char *pPwd, char *pLocalIP,
    std::vector<ONVIF_DEVICE_INFO_T>& vecDevInfo, int nTimeout);

/************************************************ ****

  • デバイス検索インターフェース 2
  • @pUser ユーザー名の入力
  • @pPwd パスワード入力
  • @pLocalIP ローカル コンピュータの IP 入力
  • @検索タイムアウト
  • @戻り値:ONVFI_DISCOVERY_DEINFO_T構造体のデバイス情報
  • ************************************************* */
    ONVFI_DISCOVERY_DEINFO_T FF_Onvif_Discovery2(char *pUser, char *pPwd, char *pLocalIP, int nTimeout);

/************************************************ ****

  • ストリームアドレスを取得する
  • @pMediaXAddress メディア サービスのアドレス
  • @pUser ユーザー名の入力
  • @pPwd パスワード入力
  • @pOutUrl コードストリームアドレス出力
  • @nOutUrlLen コードストリームアドレス長入力
  • @戻り値: 0: 成功 それ以外: 失敗
  • ************************************************* */
    int FF_Onvif_GetStreamUrl(char *pMediaXAddress, char *pUser, char *pPwd,
    char *pOutUrl, int nOutUrlLen);

/************************************************ ****

  • デバイスを再起動します
  • @pDeviceXAddress デバイス サービス アドレス
  • @pUser ユーザー名の入力
  • @pPwd パスワード入力
  • ************************************************* */
    int FF_Onvif_Reboot(char *pDeviceXAddress, char *pUser, char *pPwd);

ライブラリ ヘッダー ファイル: OnvifManager.h コード

/**************************************************************************
Description:Onvif Lib
Author:ybLin
**************************************************************************/
#ifndef ONVIFMANAGER_H
#define ONVIFMANAGER_H

#include <windows.h>
#include <iostream>
#include <vector>
#include <list>
#include <string>

#ifdef __cplusplus
extern "C" {
#endif

#define MAX_DEV_LEN                     64

typedef struct onvif_device_info_t
{
    std::string sDevIP;
    std::string sMac;
    std::string sNetMask;
    std::string sGateWay;
    std::string sModel;
    std::string sVersion;
    std::string sManufacturer;

    std::string sDeviceXAddrs;
    std::string sMediaAddress;
    std::string Item;
    int nPort;

}ONVIF_DEVICE_INFO_T;

typedef struct onvif_devinfo_t
{
    int nPort;
    char sDevIP[64];
    char sMac[64];
    char sNetMask[64];
    char sGateWay[64];
    char sModel[64];
    char sVersion[64];
    char sManufacturer[64];
    char sDeviceXAddrs[128];
    char sMediaAddress[128];
    char Item[512];

}ONVIF_DEVINFO_T;

typedef struct onvif_disocvey_devinfo_t
{
    ONVIF_DEVINFO_T dev[MAX_DEV_LEN];
    int nDevNum;
    
}ONVFI_DISCOVERY_DEINFO_T;

//搜索接口1
extern  __declspec(dllexport) int WINAPI FF_Onvif_Discovery1(char *pUser, char *pPwd, char *pLocalIP,
                                                            std::vector<ONVIF_DEVICE_INFO_T>& vecDevInfo, int nTimeout);
//搜索接口2
extern  __declspec(dllexport) ONVFI_DISCOVERY_DEINFO_T WINAPI FF_Onvif_Discovery2(char *pUser, char *pPwd, char *pLocalIP, int nTimeout);

//获取码流地址
extern  __declspec(dllexport) int WINAPI FF_Onvif_GetStreamUrl(char *pMediaXAddress, char *pUser, char *pPwd,
                                                            char *pOutUrl, int nOutUrlLen);
//重启
extern  __declspec(dllexport) int WINAPI FF_Onvif_Reboot(char *pDeviceXAddress, char *pUser, char *pPwd);


#ifdef __cplusplus
}
#endif
#endif

3. qt-demo プロジェクト myonvif

3.1 操作の概要

1) 検索ボタンをクリックし、データがロードされるまで待ちます。

ここに画像の説明を挿入

2) データの読み込みが完了しました(パスワードが間違っているため、デバイス情報が完全に読み込まれていません)

ここに画像の説明を挿入

3) テーブルデータ行をクリックしてサービスアドレスを取得します

ここに画像の説明を挿入

4) [ストリーム アドレスの取得] ボタンをクリックして、デバイスの rtsp ストリーム アドレスを取得します。

ここに画像の説明を挿入

5) [デバイスの再起動] をクリックして、指定したデバイスを再起動します。

ここに画像の説明を挿入

6) ウェブアクセス

ここに画像の説明を挿入

3.2 デモコアコード

メインウィンドウ.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QStandardItemModel>
#include <QRunnable>

namespace Ui {
class MainWindow;
}

enum COLUMN_NUM
{
    DCOLUMN_IP = 0,
    DCOLUMN_MAC_ADDRESS,
    DCOLUMN_PORT,
    DCOLUMN_NETMASK,
    DCOLUMN_GATEWAY,
    DCOLUMN_MANUFACTURER,
    DCOLUMN_MODEL,
    DCOLUMN_SOFT_VERSION,
    DCOLUMN_WEB
};

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    void initTableView();

signals:
    void sig_CloseWaitBox();

public slots:
    void on_fiterSingleClick(QModelIndex index); // 过滤单双击事件
    void on_tableViewClick(); //单击响应
    void slot_finshTask(bool bSuc);

private slots:
    void on_pushButton_Search_clicked();
    void on_pushButton_GetStreamUrl_clicked();
    void on_pushButton_Restart_clicked();

private:
    QStandardItemModel *m_tableModel;//表数据模型
    // 单双击区分
    bool m_bDBclick;
    QTimer *m_click; //单击的时候触发定时器
    QModelIndex m_bakIndex;

private:
    Ui::MainWindow *ui;
};

class COnvifDiscoveryTask :public QObject, public QRunnable
{
    Q_OBJECT
public:
    COnvifDiscoveryTask(QObject *parent, QString sUser, QString sPwd, QString sIP, QStandardItemModel *pTableModel): QObject(parent),
        m_sUser(sUser), m_sPwd(sPwd), m_sIP(sIP), m_tableModel(pTableModel) {}
    virtual ~COnvifDiscoveryTask() {}
    void run();

signals:
    void sig_finshTask(bool bSuc);

private:
    QString m_sUser;
    QString m_sPwd;
    QString m_sIP;
    QStandardItemModel *m_tableModel;
};

#endif // MAINWINDOW_H

メインウィンドウ.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QLinkedList>
#include <QStringList>
#include "OnvifManager.h"
#include <QMessageBox>
#include <QDebug>
#include <string.h>
#include <QTimer>
#include <QThreadPool>
#include <QDesktopServices>
#include <QUrl>
#include "CtWaitBox.h"

using namespace std;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    initTableView();

    connect(this, &MainWindow::sig_CloseWaitBox,
            CtWaitBox::getInstance(), &CtWaitBox::onWaitBoxClose);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::initTableView()
{
    m_tableModel = new QStandardItemModel(this);
    ui->tableView->setModel(m_tableModel);

    QStringList lables;
    lables << QObject::tr("IP") << QObject::tr("Mac")
           << QObject::tr("Port") << QObject::tr("NetMask")
           << QObject::tr("Gateway") << QObject::tr("Manufacturer")
           << QObject::tr("Model") << QObject::tr("Version") << QObject::tr("Web");
    m_tableModel->setHorizontalHeaderLabels(lables);
    //ui->tableView->horizontalHeader()->setSectionResizeMode(DCOLUMN_WEB, QHeaderView::Fixed);

    int width = 840;
    ui->tableView->setColumnWidth(DCOLUMN_IP, qRound(0.13*width));
    ui->tableView->setColumnWidth(DCOLUMN_MAC_ADDRESS, qRound(0.13*width));
    ui->tableView->setColumnWidth(DCOLUMN_PORT, qRound(0.05*width));
    ui->tableView->setColumnWidth(DCOLUMN_NETMASK, qRound(0.13*width));
    ui->tableView->setColumnWidth(DCOLUMN_GATEWAY, qRound(0.13*width));
    ui->tableView->setColumnWidth(DCOLUMN_MANUFACTURER, qRound(0.12*width));
    ui->tableView->setColumnWidth(DCOLUMN_MODEL, qRound(0.12*width));
    ui->tableView->setColumnWidth(DCOLUMN_SOFT_VERSION, qRound(0.12*width));
    ui->tableView->setColumnWidth(DCOLUMN_WEB, qRound(0.05*width));

    m_click = new QTimer(this);
    m_click->setSingleShot(true);
    m_bDBclick = false;
    connect(ui->tableView, &QTableView::clicked,
            this, &MainWindow::on_fiterSingleClick); //单击检测
    connect(m_click, &QTimer::timeout,
            this, &MainWindow::on_tableViewClick); // 处理单击

}

void MainWindow::on_fiterSingleClick(QModelIndex index)
{
    if(m_bDBclick)
    {
        m_bDBclick = false;
    }
    else
    {
        m_click->start(200); // double click interval 200ms
        m_bakIndex = index;
    }
}

void MainWindow::on_tableViewClick()
{
    int nRow = m_bakIndex.row();//选中数据的行
    int nCol = m_bakIndex.column();//选中数据的列

    QString sIP = m_tableModel->item(nRow, DCOLUMN_IP)->text();
    QString sPort = m_tableModel->item(nRow, DCOLUMN_PORT)->text();
    QString sMediaAddr = QString("http://%1:%2/onvif/Media").arg(sIP).arg(sPort);
    QString sDevAddr = QString("http://%1:%2/onvif/device_service").arg(sIP).arg(sPort);

    ui->lineEdit_MediaAddress->setText(sMediaAddr);
    ui->lineEdit_devAddress->setText(sDevAddr);

    if(nCol == DCOLUMN_WEB)
    {
        QString sUrl = QString("http://%1:%2").arg(sIP).arg(sPort);
        QDesktopServices::openUrl(QUrl(sUrl));
    }
}

void MainWindow::slot_finshTask(bool bSuc)
{
    Q_UNUSED(bSuc)
    emit sig_CloseWaitBox();
}

void MainWindow::on_pushButton_Search_clicked()
{
    QString sUserName = ui->lineEdit_User->text();
    if(sUserName.isEmpty())
    {
        QMessageBox::critical(this, "myOnvif", "错误:用户名不能为空.");
        return;
    }

    QString sPwd = ui->lineEdit_Pwd->text();
    if(sPwd.isEmpty())
    {
        QMessageBox::critical(this, "myOnvif", "错误:密码不能为空.");
        return;
    }

    QString sIP = ui->lineEdit_IP->text();
    if(sIP.isEmpty())
    {
        QMessageBox::critical(this, "myOnvif", "错误:本机IP不能为空.");
        return;
    }

    COnvifDiscoveryTask* pTask = new COnvifDiscoveryTask(NULL, sUserName, sPwd, sIP, m_tableModel);
    connect(pTask, SIGNAL(sig_finshTask(bool)),
            this, SLOT(slot_finshTask(bool)));
    QThreadPool::globalInstance()->start(pTask);

    CtWaitBox::loading(true, geometry().x()+geometry().width()/2-100, geometry().y()+geometry().height()/2-100, 60, true);
}

void MainWindow::on_pushButton_GetStreamUrl_clicked()
{
    char sUrl[128] = {0};
    QString sMediaAddr = ui->lineEdit_MediaAddress->text();
    if(sMediaAddr.isEmpty())
    {
        QMessageBox::critical(this, "myOnvif", tr("媒体服务地址不能为空"));
        return;
    }

    QString sUser = ui->lineEdit_User->text();
    if(sUser.isEmpty())
    {
        QMessageBox::critical(this, "myOnvif", tr("用户名不能为空"));
        return;
    }

    QString sPwd = ui->lineEdit_Pwd->text();
    if(sPwd.isEmpty())
    {
        QMessageBox::critical(this, "myOnvif", "密码不能为空");
        return;
    }

    if(FF_Onvif_GetStreamUrl(sMediaAddr.toLatin1().data(), sUser.toLatin1().data(), sPwd.toLatin1().data(), sUrl, sizeof(sUrl)) != 0)
    {
        QMessageBox::critical(this, "myOnvif", "错误:获取码流地址失败.");
    }
    else
    {
        QString sRtspUrl = QString(sUrl);
        ui->lineEdit_Url->setText(sRtspUrl);
    }
}

void MainWindow::on_pushButton_Restart_clicked()
{
    QString sDevAddr = ui->lineEdit_devAddress->text();
    if(sDevAddr.isEmpty())
    {
        QMessageBox::critical(this, "myOnvif", "设备服务地址不能为空");
        return;
    }

    QString sUser = ui->lineEdit_User->text();
    if(sUser.isEmpty())
    {
        QMessageBox::critical(this, "myOnvif", "用户名不能为空");
        return;
    }

    QString sPwd = ui->lineEdit_Pwd->text();
    if(sPwd.isEmpty())
    {
        QMessageBox::critical(this, "myOnvif", "密码不能为空");
        return;
    }

    if(FF_Onvif_Reboot(sDevAddr.toLatin1().data(), sUser.toLatin1().data(), sPwd.toLatin1().data()) == 0)
        QMessageBox::information(this, "myOnvif", "重启成功");
    else
        QMessageBox::critical(this, "myOnvif", "重启失败.");
}

void COnvifDiscoveryTask::run()
{
    if(m_tableModel->rowCount() > 0)
    {
        m_tableModel->removeRows(0, m_tableModel->rowCount());
    }

    ONVFI_DISCOVERY_DEINFO_T devInfos = FF_Onvif_Discovery2(m_sUser.toLatin1().data(), m_sPwd.toLatin1().data(), m_sIP.toLatin1().data(), 5);

    qDebug() << "devInfos.nDevNum:" << devInfos.nDevNum;
    //数据
    for(int i = 0; i < devInfos.nDevNum; i++)
    {
        qDebug() << "Dev" << i << " IP:" << devInfos.dev[i].sDevIP;
        qDebug() << "Dev" << i << " Port:" << devInfos.dev[i].nPort;
        qDebug() << "Dev" << i << " Mac:" << devInfos.dev[i].sMac;
        qDebug() << "Dev" << i << " NetMask:" << devInfos.dev[i].sNetMask;
        qDebug() << "Dev" << i << " GateWay:" << devInfos.dev[i].sGateWay;
        qDebug() << "Dev" << i << " Manufacturer:" << devInfos.dev[i].sManufacturer;
        qDebug() << "Dev" << i << " Model:" << devInfos.dev[i].sModel;
        qDebug() << "Dev" << i << " Version:" << devInfos.dev[i].sVersion;
        qDebug() << "\r\n"<< endl;

        m_tableModel->insertRow(i, QModelIndex());
        m_tableModel->setData(m_tableModel->index(i, DCOLUMN_IP), devInfos.dev[i].sDevIP);
        m_tableModel->setData(m_tableModel->index(i, DCOLUMN_MAC_ADDRESS), devInfos.dev[i].sMac);
        m_tableModel->setData(m_tableModel->index(i, DCOLUMN_PORT), devInfos.dev[i].nPort);
        m_tableModel->setData(m_tableModel->index(i, DCOLUMN_NETMASK), devInfos.dev[i].sNetMask);
        m_tableModel->setData(m_tableModel->index(i, DCOLUMN_GATEWAY), devInfos.dev[i].sGateWay);
        m_tableModel->setData(m_tableModel->index(i, DCOLUMN_MANUFACTURER), devInfos.dev[i].sManufacturer);
        m_tableModel->setData(m_tableModel->index(i, DCOLUMN_MODEL), devInfos.dev[i].sModel);
        m_tableModel->setData(m_tableModel->index(i, DCOLUMN_SOFT_VERSION), devInfos.dev[i].sVersion);
        m_tableModel->setData(m_tableModel->index(i, DCOLUMN_WEB), QImage(":/image/web.png"), Qt::DecorationRole);

        // 设置全部列居中显示
        for(int j = DCOLUMN_IP; j < DCOLUMN_WEB; j++)
        {
            m_tableModel->item(i, j)->setTextAlignment(Qt::AlignCenter);
        }
    }

    emit sig_finshTask(true);
}

4. ダウンロード

エクスペリエンス アドレスのダウンロード: https://download.csdn.net/download/linyibin_123/88036919
onvif ライブラリのソース コードおよび qt-demo プロジェクトのソース コードのダウンロード: https://download.csdn.net/download/linyibin_123/88036934

おすすめ

転載: blog.csdn.net/linyibin_123/article/details/131664369