• 534阅读
  • 0回复

Qt监控系统远程网络登录/请求设备列表/服务器查看实时流/回放视频/验证码请求 [复制链接]

上一主题 下一主题
离线liudianwu
 

只看楼主 倒序阅读 楼主  发表于: 01-09


## 一、前言说明
这几个功能是近期定制的功能,也非常具有代表性,核心就是之前登录和设备信息都是在本地,存放在数据中,数据库可以是本地或者远程的,现在需要改成通过网络API请求的方式,现在很多的服务器很强大,都提供了各种API接口,包括登录和拉取回放等,相当于直接对接这些服务器的接口去开发,为了做好这个功能,做了一些微调,以便作为一个典型二开的示例。

首先就是用户登录,第一步请求获取到验证码图片,然后用户填入用户名和密码,带上验证码,一起发送网络请求到服务器,登录成功会返回对应正常,失败会返回对应错误的原因,比如用户不存在,密码不正确,验证码不正确等,或者验证码过期,核心要点就是请求时候要带上各种需要的数据,每次登录错误都需要重新拉取更新验证码图片。

登陆成功后就去获取设备列表,一般这个列表都是json数据,多层次多分组的,根据收到的数据,解析后生成设备树,每个设备可能还需要根据获取到的视频流地址规则,重新组织外网可以访问的视频流地址,服务器上可能是zlm或者srs这种流媒体服务器负责推流,双击对应设备的时候,打开对应的视频流地址。

整体下来,在经过一些主要框架的调整后,这些功能二开起来非常便捷,封装了通用的网络请求函数,务必记得及时释放请求,通用的解析函数,同时相当于在工作模式中添加一种工作模式,pro中增加一个defines标记,单独搞个目录存放这个定制功能对应的类,定义了标记,则加载对应的目录的pri模块文件,随时都可以去掉,可以完美无缝的切入到现有的整个监控系统框架,总之这又是一次完美的二开实战。之前已经有了无人机监控、广播监控、智慧校园监控的二开经验,这次又增加了一个,完善了整个二开示例。

## 二、效果图



## 三、相关代码
```cpp
#include "frmmain.h"
#include "zlogin.h"
#include "ui_zlogin.h"
#include "qthelper.h"
#include "zhttphelper.h"
#include "zmediahelper.h"

ZLogin::ZLogin(QWidget *parent) : QDialog(parent), ui(new Ui::ZLogin)
{
    ui->setupUi(this);
    this->initForm();
    QtHelper::setFormInCenter(this);
    QMetaObject::invokeMethod(this, "initCode", Qt::QueuedConnection);
}

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

bool ZLogin::eventFilter(QObject *watched, QEvent *event)
{
    //单击验证码标签重新加载
    if (watched == ui->labImage && event->type() == QEvent::MouseButtonRelease) {
        this->initCode();
    }

    return QWidget::eventFilter(watched, event);
}

void ZLogin::initForm()
{
    //图片文件不存在则设置为图形字体
    QtHelper::setIconBtn(ui->btnLogin, ":/image/btn_ok.png", 0xf00c);
    QtHelper::setIconBtn(ui->btnClose, ":/image/btn_close.png", 0xf00d);

    //初始化无边框窗体
    QtHelper::setFramelessForm(this, ui->widgetTitle, ui->labIco, ui->btnMenu_Close, false);

    ui->labName->setText(AppConfig::TitleCn);
    ui->labName->setStyleSheet(QString("border-image:url(:/image/bg_banner.jpg);font:22px;color:%1;").arg(GlobalConfig::TextColor));
    this->setWindowTitle(ui->labTitle->text());

    ui->btnLogin->setDefault(true);
    ui->labImage->installEventFilter(this);

    ui->txtUserName->setText(AppConfig::LastLoginer);
    ui->txtUserPwd->setPlaceholderText("请输入密码");
    ui->txtUserCode->setPlaceholderText("请输入验证码");

#if 1
    ui->txtUserName->setText("ceshi-01");
    ui->txtUserPwd->setText("ceshi-01@zafu");
    ui->txtUserCode->setFocus();
#endif

    //关联关闭按钮退出
    connect(ui->btnMenu_Close, SIGNAL(clicked()), this, SLOT(close()));
    connect(ui->btnClose, SIGNAL(clicked()), this, SLOT(close()));

    //收到退出信号/本窗体只是隐藏/收到退出信号后发送登出请求
    connect(AppEvent::Instance(), SIGNAL(exitAll()), this, SLOT(exitAll()));

    //需要定时重新获取用户信息/保证token不被过期/证明自己还活着
    QTimer *timerGet = new QTimer(this);
    connect(timerGet, SIGNAL(timeout()), this, SLOT(getInfo()));
    timerGet->start(5 * 60 * 1000);    
}

void ZLogin::initCode()
{
    QString base64;
    ZHttpHelper::getCodeImage(uuid, base64);
    ui->txtUserCode->clear();
    if (!base64.isEmpty()) {
        QPixmap pixmap;
        pixmap.loadFromData(QByteArray::fromBase64(base64.toUtf8()));
        pixmap = pixmap.scaled(ui->labImage->size() - QSize(2, 2)/*, Qt::KeepAspectRatio*/);
        ui->labImage->setPixmap(pixmap);
    }
}

void ZLogin::getInfo()
{
    if (!OtherConfig::HttpToken.isEmpty()) {
        ZHttpHelper::getUserInfo();
    }
}

void ZLogin::exitAll()
{
    ZHttpHelper::logout();
}

void ZLogin::on_btnLogin_clicked()
{
    QString userName = ui->txtUserName->text().trimmed();
    if (userName.isEmpty()) {
        QtHelper::showMessageBoxError("用户名称不能为空, 请重新输入!", 3, true);
        ui->txtUserName->setFocus();
        return;
    }

    QString userPwd = ui->txtUserPwd->text().trimmed();
    if (userPwd.isEmpty()) {
        QtHelper::showMessageBoxError("用户密码不能为空, 请重新输入!", 3, true);
        ui->txtUserPwd->setFocus();
        return;
    }

    QString userCode = ui->txtUserCode->text().trimmed();
    if (userCode.isEmpty()) {
        QtHelper::showMessageBoxError("验证码不能为空, 请重新输入!", 3, true);
        ui->txtUserCode->setFocus();
        return;
    }

    //调用网络请求登录
    if (ZHttpHelper::login(userName, userPwd, userCode, uuid)) {
        //记录最后登录用户
        AppConfig::LastLoginer = userName;
        AppConfig::writeConfig();

        //通过网络请求获取一堆数据
        ZHttpHelper::getUserInfo();
        ZHttpHelper::getDeviceInfo();
        ZHttpHelper::getStreamInfo();

        //主动将媒体信息插入到本地数据库
        ZMediaHelper::saveDeviceGroup();
        ZMediaHelper::initDeviceInfo();

        //隐藏登录界面并弹出主界面
        this->hide();
        frmMain *form = new frmMain;
        form->show();
        form->activateWindow();
    } else {
        //登录失败后要重新刷新验证码
        this->initCode();
    }
}
```

## 四、相关地址
1. 国内站点:[https://gitee.com/feiyangqingyun](https://gitee.com/feiyangqingyun)
2. 国际站点:[https://github.com/feiyangqingyun](https://github.com/feiyangqingyun)
3. 个人作品:[https://blog.csdn.net/feiyangqingyun/article/details/97565652](https://blog.csdn.net/feiyangqingyun/article/details/97565652)
4. 文件地址:[https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g](https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g) 提取码:01jf 文件名:bin_video_system。
欢迎关注微信公众号:Qt实战/Qt入门和进阶(各种开源作品、经验整理、项目实战技巧,专注Qt/C++软件开发,视频监控、物联网、工业控制、嵌入式软件、国产化系统应用软件开发) QQ:517216493  WX:feiyangqingyun  QQ群:751439350
快速回复
限100 字节
 
上一个 下一个