I.はじめに
カメラの検索モジュールは、新たに、時間はまだ純粋なQtの基礎となる通信のようなONVIFまで来ていないとき、それは数ヶ月を出てきた前に、このモジュールが必要であり、ビデオ監視システムは、開始後に追加されますサポートPTZ制御とデバイス情報を検索し、その直後に2件の検索監視システムサポートのほとんど、監視システムに追加し、1を加えて、検索アプライアンスの方法で独自のプロトコルSDK、唯一自分のデバイスに検索です一つは、国際標準プロトコルで、ほとんどのネットワークカメラのためのプロトコルは、市場をサポートONVIF、私は、わずか70ドルONVIF安いカメラを買っコンテンツONVIF、またはより一般的に3基本的に使用されています点:そのようなより多くの情報機器を取得するビデオストリームアドレスとして検索装置、PTZ制御、プリセット位置及び制御。
カメラの検索機能は直接カメラ管理で行われ、上部にある検索ボタンは、通常の放送検索要素の2種類を検索し、検索切換ボタンは、表示され、検索要素に地域を隠すために使用されるブロードキャストおよびユニキャスト検索を提供している検索機能を見ることができませんあなたは、カード検索を指定して、ユニキャストではなく、同じネットワークセグメント内の一部に適用される検索が、デバイスは、ユーザー名とユーザーパスワードが正しく記入されている必要があり、あなたはIPカメラの検索ユニキャストを指定する必要がある、てpingを実行することができますする必要があり、対応するカメラであります代わりに、カメラのWebログインユーザのユーザ情報ONVIF、。デバイスが左側に一覧表示され、検索、およびデバイスアドレス、メディアアドレス、先頭アドレス、メインストリームのアドレス、サブストリームアドレス5フィールドは空白になって、すべての概要を取得するには、ボタンをクリックする必要がありますこれらの情報は、一般的に、使用されたカメラシステムは、工場出荷時のデフォルトのユーザー名とパスワードでも均一であり、限りユーザーに一度情報セットなど、すべての異なる個々のユーザー名とパスワードを別々に設定するために得るためにクリックすることができます現在のボタンを取得し、[OK]をクリックします。自動的にすべてのカメラのチェックを選択するボタンを追加するには、[追加]ボタンをクリックし、すべての機器のデフォルトの検索がチェックされ、クリックデバイスを追加し、現在だけで、現在フォーカスのために使用されています。
ページングコンポーネントのオープンソースアドレス:https://gitee.com/feiyangqingyun/QWidgetDemo https://github.com/feiyangqingyun/QWidgetDemo
ファイル名:dbpage
経験住所:https://gitee.com/feiyangqingyun/QWidgetExe https://github.com/feiyangqingyun/QWidgetExe
ファイル名:bin_video_system.zip
第二に、機能特性
- 1 + 4 + 6 + 8 + 9 + 13 + 16画面切り替えを含む等16画面切り替え、フルスクリーン切り替えをサポートします。
- サポートALT +は、全画面表示を終了するには、フルスクリーン、Escキーを入力します。
- カスタムエラーメッセージボックス+ボックス+ +クエリボックスボックス右下隅。
- 無償交換のスキンスタイルの17セットは、すべてのメニューを含むすべてのスタイルで統一します。
- PTZダッシュボードホバーハイライト、8つの方向正確な同定。
- 画面のツールバーの下(分割画面切り替えなどのサウンド+のテーマ設定)がハイライトさを上に移動しました。
- あなたは、設定ファイル内のソフトウェア左上隅のロゴ+中国+英語のソフトウェア名の名前を変更することができます。
- 封入百度マップ、三次元のスイッチポイント装置、ダウンマウスは、緯度と経度を取得します。
- スタックフォームは、各フォームは、独自のコードを書きやすい別のQWidgetのです。
- トップマウスの右ボタンメニュー、あなたが動的に時間を制御することができ、パネルCPU + + +表示パネル+パネル右下のパネルの右上隅と隠されたサポートデフォルトレイアウトの復元の左隅を下げるの角を左に。
- ツールバーのアイコンは、いくつかの小さなアイコンのオンとオフ配置することができます。
- 再起動回復後のストレッチ右ドラッグ、および自動メモリ幅と高さ位置を、左。
- ダブルクリックするノードに続くカメラノードの自動再生ビデオは、自動的に動画を追加]をダブルクリックし、自動的に親ノードが自動的にそのノード内のすべての動画に追加されますダブルクリックし、次のいずれかにジャンプします。
- カメラノードとローカルのドラッグファイルをサポートすることは、直接遊んでいる間、対応する形式のビデオ再生にドラッグします。
- ビデオ画面フォームのサポートドラッグ交換、インスタント応答。
- 二重ノード+ +ボックスはボックスのノード交換位置を形成し、それが自動的にurl.txt更新されます。
- 自動メモリ、url.txtからの映像に対応した最後のチャンネルを16チャンネルのビデオ再生をロードするためのサポート、ソフトウェアが自動的に開いて再生を開始します。
- ボリュームバーコントロールの右下隅に自動的に非表示に、縞模様の音量ミュートアイコンをフォーカスを失いました。
- 地図を統合百度は、デバイス、自動的に地図を生成し、ズーム三次元マップサポートの対応する位置に追加することができ、地図スタイルセレクタ、12のスタイルの合計を提供します。
- 自動的に削除された外部チャネルビデオ形式にビデオをドラッグします。
- 現在のすべてのビデオを削除する+右マウスボタン、スクリーンショット+現在のすべてのビデオ。
- 管理VCR、ビデオカメラの管理、インポートおよびエクスポートアドオンは、直ちに、印刷情報を修正、削除、再起動せずに新しい情報生成デバイスツリーのリストを適用します。
- プロファイルにロードマップを自由に開くことができます。
- コアビデオ再生のオプションの4種類のスイッチ、VLC + ffmpegの+ easyplayer +カンSDKに無料で、プロで設定することができます。
- 図1は、16 + 4 + 9 +ピクチャポーリング、ポーリング及びポーリング間隔は再びポーリングボタンのクリック、クリックストップポーリングを開始ツールバー直接メイン画面の右下に、セットのストリームタイプであってもよい設けられていてもよいです。
- デフォルトは10秒以上、自動非表示にマウスポインタの操作ではありません。
- 検索要素ONVIFサポート機器、カメラONVIFいずれかをサポートし、大規模な有馬カンアルバート世界Huawei社、およびPTZコントロールONVIFのサポートを含むがこれらに限定されません。
- 高度にカスタマイズ可能な、ユーザーが簡単にLinuxシステムをサポートするため、これに基づいてその機能を導出することができます。
第三に、レンダリング
第四に、コアコード
#include "frmconfigsearch.h"
#include "ui_frmconfigsearch.h"
#include "quiwidget.h"
#include "onviffunction.h"
#include "onvifmedia.h"
frmConfigSearch::frmConfigSearch(QWidget *parent) : QWidget(parent), ui(new Ui::frmConfigSearch)
{
ui->setupUi(this);
this->initForm();
this->initTable();
}
frmConfigSearch::~frmConfigSearch()
{
delete ui;
}
void frmConfigSearch::initForm()
{
//设置默认的用户名和密码+本机IP,可以自行更改
ui->txtUserName->setText("admin");
ui->txtUserPwd->setText("admin");
ui->cboxLocalIP->addItems(OnvifFunction::getLocalIps());
//实例化onvif搜索,绑定信号槽
onvifSearch = new OnvifSearch(this);
connect(onvifSearch, SIGNAL(receiveDevice(OnvifSearch::DeviceInfo)), this, SLOT(receiveDevice(OnvifSearch::DeviceInfo)));
}
void frmConfigSearch::initTable()
{
QList<QString> columnNames;
columnNames << "" << "地址" << "用户名称" << "用户密码" << "厂家" << "设备地址" << "媒体地址" << "云台地址" << "主码流" << "子码流";
QList<int> columnWidths;
columnWidths << 21 << 50 << 80 << 80 << 80 << 300 << 300 << 300 << 350 << 350;
ui->tableWidget->setStyleSheet("QCheckBox{padding:0px 0px 0px 3px;}");
//设置列数和列宽
int columnCount = columnWidths.count();
ui->tableWidget->setColumnCount(columnCount);
for (int i = 0; i < columnCount; i++) {
ui->tableWidget->setColumnWidth(i, columnWidths.at(i));
}
//设置行高
ui->tableWidget->setRowCount(99);
for (int i = 0; i < ui->tableWidget->rowCount(); i++) {
ui->tableWidget->setRowHeight(i, 25);
}
ui->tableWidget->setHorizontalHeaderLabels(columnNames);
ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
//ui->tableWidget->setAlternatingRowColors(true);
ui->tableWidget->verticalHeader()->setVisible(true);
ui->tableWidget->verticalHeader()->setHighlightSections(false);
ui->tableWidget->horizontalHeader()->setHighlightSections(false);
ui->tableWidget->horizontalHeader()->setStretchLastSection(true);
ui->tableWidget->verticalHeader()->setDefaultSectionSize(22);
ui->tableWidget->setColumnHidden(1, true);
ui->tableWidget->setColumnHidden(2, true);
ui->tableWidget->setColumnHidden(3, true);
ui->tableWidget->horizontalHeader()->setSortIndicator(1, Qt::AscendingOrder);
//增加一个全选按钮
ckAll = new QCheckBox(ui->tableWidget);
connect(ckAll, SIGNAL(stateChanged(int)), this, SLOT(stateChanged(int)));
ckAll->move(23, 5);
ckAll->setChecked(true);
}
void frmConfigSearch::clear()
{
qDeleteAll(devices);
devices.clear();
ui->tableWidget->clearContents();
}
void frmConfigSearch::stateChanged(int arg1)
{
for(int row = 0; row < devices.count(); row++) {
QCheckBox *itemCk = (QCheckBox *)ui->tableWidget->cellWidget(row, 0);
if (itemCk > 0) {
itemCk->setChecked(arg1 != 0);
}
}
}
void frmConfigSearch::receiveDevice(const OnvifSearch::DeviceInfo &deviceInfo)
{
int deviceCount = devices.count();
QString addr = deviceInfo.addr;
QString ip = deviceInfo.ip;
QTableWidgetItem *itemName = new QTableWidgetItem(deviceInfo.name);
QTableWidgetItem *itemAddr = new QTableWidgetItem(deviceInfo.addr);
//复选框,如果勾选了全选则自动选中当前设备
QCheckBox *itemCk = new QCheckBox(this);
itemCk->setChecked(ckAll->isChecked());
//取IP地址末尾位数作为排序依据
QStringList list = ip.split(".");
QString lastAddr = list.last();
QTableWidgetItem *itemLastAddr = new QTableWidgetItem;
itemLastAddr->setData(Qt::DisplayRole, lastAddr.toInt());
ui->tableWidget->setCellWidget(deviceCount, 0, itemCk);
ui->tableWidget->setItem(deviceCount, 1, itemLastAddr);
ui->tableWidget->setItem(deviceCount, 4, itemName);
ui->tableWidget->setItem(deviceCount, 5, itemAddr);
OnvifDevice *device = new OnvifDevice(this);
device->setDeviceUrl(addr);
//将当前广播搜索返回的设备信息一起打包发给设备类
QMap<QString, QString> info;
info.insert("addr", deviceInfo.addr);
info.insert("ip", deviceInfo.ip);
info.insert("name", deviceInfo.name);
info.insert("location", deviceInfo.location);
info.insert("hardware", deviceInfo.hardware);
device->setDeviceInfo(info);
devices << device;
ui->tableWidget->sortByColumn(1);
}
void frmConfigSearch::on_btnSearchAll_clicked()
{
clear();
QString localIP = ui->cboxLocalIP->currentText();
QString deviceIP = ui->txtDeviceIP->text();
onvifSearch->search(localIP, deviceIP, false);
}
void frmConfigSearch::on_btnSearchOne_clicked()
{
clear();
QString localIP = ui->cboxLocalIP->currentText();
QString deviceIP = ui->txtDeviceIP->text();
onvifSearch->search(localIP, deviceIP, true);
}
void frmConfigSearch::on_btnMediaAll_clicked()
{
QString userName = ui->txtUserName->text().trimmed();
QString userPwd = ui->txtUserPwd->text().trimmed();
QString userInfo = QString("rtsp://%1:%2@").arg(userName).arg(userPwd);
int count = devices.count();
foreach (OnvifDevice *device, devices) {
//找到当前设备所在行
QString url = device->getDeviceUrl();
int row = -1;
for (int i = 0; i < count; i++) {
QString addr = ui->tableWidget->item(i, 5)->text();
if (url == addr) {
row = i;
break;
}
}
if (row >= 0) {
//先设置用户名和密码
device->setUser(userName, userPwd);
//如果没有获取到地址则说明设备可能是 onvif1.0 重新发送1.0对应的请求数据
device->getServices();
if (device->getMediaUrl().isEmpty() || device->getPtzUrl().isEmpty()) {
device->getCapabilities();
}
//获取概要文件profile
QString rtspMain, rtspSub;
QStringList tokens = device->getMedia();
if (tokens.count() > 0) {
rtspMain = device->getRtspUri(tokens.at(0));
rtspMain = rtspMain.replace("rtsp://", userInfo);
//如果有第二个token则为子码流
if (tokens.count() > 1) {
rtspSub = device->getRtspUri(tokens.at(1));
rtspSub = rtspSub.replace("rtsp://", userInfo);
}
}
//返回的数据添加到表格中
QTableWidgetItem *itemUserName = new QTableWidgetItem(userName);
QTableWidgetItem *itemUserPwd = new QTableWidgetItem(userPwd);
QTableWidgetItem *itemMediaUri = new QTableWidgetItem(device->getMediaUrl());
QTableWidgetItem *itemPtzUri = new QTableWidgetItem(device->getPtzUrl());
QTableWidgetItem *itemRtspMain = new QTableWidgetItem(rtspMain);
QTableWidgetItem *itemRtspSub = new QTableWidgetItem(rtspSub);
ui->tableWidget->setItem(row, 2, itemUserName);
ui->tableWidget->setItem(row, 3, itemUserPwd);
ui->tableWidget->setItem(row, 6, itemMediaUri);
ui->tableWidget->setItem(row, 7, itemPtzUri);
ui->tableWidget->setItem(row, 8, itemRtspMain);
ui->tableWidget->setItem(row, 9, itemRtspSub);
}
}
}
void frmConfigSearch::on_btnMediaOne_clicked()
{
int row = ui->tableWidget->currentRow();
if (row < 0) {
QUIHelper::showMessageBoxError("请先选中设备!", 3);
return;
}
QCheckBox *itemCk = (QCheckBox *)ui->tableWidget->cellWidget(row, 0);
if (itemCk <= 0) {
QUIHelper::showMessageBoxError("设备地址不能为空!", 3);
return;
}
QString userName = ui->txtUserName->text().trimmed();
QString userPwd = ui->txtUserPwd->text().trimmed();
QString userInfo = QString("rtsp://%1:%2@").arg(userName).arg(userPwd);
QString addr = ui->tableWidget->item(row, 5)->text();
foreach (OnvifDevice *device, devices) {
if (device->getDeviceUrl() == addr) {
//先设置用户名和密码
device->setUser(userName, userPwd);
//如果没有获取到地址则说明设备可能是 onvif1.0 重新发送1.0对应的请求数据
device->getServices();
if (device->getMediaUrl().isEmpty() || device->getPtzUrl().isEmpty()) {
device->getCapabilities();
}
//获取概要文件profile
QString rtspMain, rtspSub;
QStringList tokens = device->getMedia();
if (tokens.count() > 0) {
rtspMain = device->getRtspUri(tokens.at(0));
rtspMain = rtspMain.replace("rtsp://", userInfo);
//如果有第二个token则为子码流
if (tokens.count() > 1) {
rtspSub = device->getRtspUri(tokens.at(1));
rtspSub = rtspSub.replace("rtsp://", userInfo);
}
}
//返回的数据添加到表格中
QTableWidgetItem *itemUserName = new QTableWidgetItem(userName);
QTableWidgetItem *itemUserPwd = new QTableWidgetItem(userPwd);
QTableWidgetItem *itemMediaUri = new QTableWidgetItem(device->getMediaUrl());
QTableWidgetItem *itemPtzUri = new QTableWidgetItem(device->getPtzUrl());
QTableWidgetItem *itemRtspMain = new QTableWidgetItem(rtspMain);
QTableWidgetItem *itemRtspSub = new QTableWidgetItem(rtspSub);
ui->tableWidget->setItem(row, 2, itemUserName);
ui->tableWidget->setItem(row, 3, itemUserPwd);
ui->tableWidget->setItem(row, 6, itemMediaUri);
ui->tableWidget->setItem(row, 7, itemPtzUri);
ui->tableWidget->setItem(row, 8, itemRtspMain);
ui->tableWidget->setItem(row, 9, itemRtspSub);
break;
}
}
}
void frmConfigSearch::on_btnAddAll_clicked()
{
//找出勾选的,过滤没有视频流地址的
QList<QStringList> deviceInfos;
int deviceCount = devices.count();
for(int row = 0; row < deviceCount; row++) {
QCheckBox *itemCk = (QCheckBox *)ui->tableWidget->cellWidget(row, 0);
if (itemCk > 0) {
QTableWidgetItem *item = ui->tableWidget->item(row, 8);
if (item > 0) {
QString rtspMain = item->text();
if (itemCk->isChecked() && !rtspMain.isEmpty()) {
QStringList deviceInfo;
QString userName = ui->tableWidget->item(row, 2)->text();
QString userPwd = ui->tableWidget->item(row, 3)->text();
QString ipcType = ui->tableWidget->item(row, 4)->text();
QString onvifAddr = ui->tableWidget->item(row, 5)->text();
QString mediaAddr = ui->tableWidget->item(row, 6)->text();
QString ptzAddr = ui->tableWidget->item(row, 7)->text();
QString rtspSub = ui->tableWidget->item(row, 9)->text();
deviceInfo << userName << userPwd << ipcType << onvifAddr << mediaAddr << ptzAddr << rtspMain << rtspSub;
deviceInfos << deviceInfo;
}
}
}
}
emit addDevices(deviceInfos);
}
void frmConfigSearch::on_btnAddOne_clicked()
{
int row = ui->tableWidget->currentRow();
if (row < 0) {
QUIHelper::showMessageBoxError("请先选中设备!", 3);
return;
}
QList<QStringList> deviceInfos;
QTableWidgetItem *item = ui->tableWidget->item(row, 8);
if (item > 0) {
QString rtspMain = item->text();
if (!rtspMain.isEmpty()) {
QStringList deviceInfo;
QString userName = ui->tableWidget->item(row, 2)->text();
QString userPwd = ui->tableWidget->item(row, 3)->text();
QString ipcType = ui->tableWidget->item(row, 4)->text();
QString onvifAddr = ui->tableWidget->item(row, 5)->text();
QString mediaAddr = ui->tableWidget->item(row, 6)->text();
QString ptzAddr = ui->tableWidget->item(row, 7)->text();
QString rtspSub = ui->tableWidget->item(row, 9)->text();
deviceInfo << userName << userPwd << ipcType << onvifAddr << mediaAddr << ptzAddr << rtspMain << rtspSub;
deviceInfos << deviceInfo;
}
}
emit addDevices(deviceInfos);
}