• 37阅读
  • 0回复

Qt纯代码实现智能安防集中管理平台/楼宇对讲管理系统/门禁管理/视频监控 [复制链接]

上一主题 下一主题
离线liudianwu
 

图酷模式  只看楼主 倒序阅读 楼主  发表于: 12小时前


## 一、前言说明
这个项目很多年前就完成的,属于一个定制的项目,最初做的事楼宇对讲相关的功能,后面陆续增加了门禁和视频监控,这些模块加起来,慢慢的形成了一个智能安防集中管理平台的模样,但是确切的说又不够标准,因为本系统楼宇对讲部分,并不包含对讲的功能,而是楼宇对讲门禁系统将下面的状态发过来,在软件端展示,比如对讲状态,谁正在呼叫谁,哪里的门禁开启和关闭了,然后具备制作门禁卡的功能,其实就是通过USB的写入和读取,按照协议将卡的数据读取,然后下发到门禁设备,让门禁设备知道当前哪些卡是合法的卡,该卡刷完后会立即通知软件端,软件端这边已经关联了具体哪一户人家,然后记录存档以供查询。

视频监控这块复用的视频监控组件的功能,比较简单,主要就是添加视频流地址,然后显示视频流画面,然后就是还多了个报警联动功能,一旦某个地方触发了报警,可以打开对应的联动视频显示。如果需要更详细的视频监控功能,推荐使用视频监控系统,非常的全面和完善。

## 二、效果图



## 三、功能特点
1. 同时集成了楼宇对讲、住户报警、门禁控制、公共报警、视频监控等模块。
2. 系统管理部分包括系统配置、对讲配置、住户配置、公共配置、监控配置、地图管理、视频联动、用户管理、区域管理。
3. 图形化的实时对讲、室内报警、门禁设备界面,非常大气美观。
4. 设备状态内置地图模式、面板模式两种方式展示,非常强大。
5. 楼宇对讲设备和报警设备都支持地图上拖曳到正确位置,保存立即应用。
6. 支持报警视频联动,设备报警对应弹出报警视频。
7. 各种设备信息支持添加、删除、修改、打印、导入、导出、查询等,支持多条件组合查询。
8. 各种日志信息支持多条件组合模糊查询,查询的记录可导出和打印。
9. 可直接在软件上授权发卡,支持多对多发卡,一个卡号可以发到多个门禁设备,支持通卡(卡号下发到所有设备),可连续自动制卡,自动选中下一个用户进行制卡。
10. 可直接远程读取选中设备的卡号集合信息,进行统一的管理。
11. 所有卡号支持本地备份,一旦远程设备更换,可以重新下发卡号信息。
12. 支持过期卡号自动清理,被清理的卡号可以查询,可以指定楼栋、单元、过期时间查询卡号。
13. 支持公共部位报警接入,默认DS7400主机,能够识别布防、撤防、报警等信息。
14. 视频监控默认支持16通道显示,可切换到4通道、6通道、8通道、9通道、13通道显示,支持全屏和轮询。
15. 首页背景图、左上角logo、右上角项目名称可自定义,支持恢复出厂设置。
16. 亿级别本地海量数据存储,自动清空早期数据,永远保持最新的数据记录。
17. 每个模块都有开关可以后台自由控制启用或者禁用。
18. 集成了秘钥控制功能,可以控制设备数量以及运行时间。
19. 内置最牛逼的豪华版的输入法,高仿苹果电脑输入法,体验一级棒。
20. 纯Qt编写,支持任意Qt版本+任意编译器+任意系统,可运行在windws XP、win7、win8、win10、linux、mac OS、嵌入式linux等系统。

## 四、相关地址
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_TB.zip。

## 五、相关代码
```cpp
#include "taskserver.h"
#include "qthelper.h"
#include "ntpclient.h"

SINGLETON_IMPL(TaskServer)
TaskServer::TaskServer(QObject *parent) : QObject(parent)
{
    checkNtpCount = 0;
    timerTask = new QTimer(this);
    timerTask->setInterval(3000);
    connect(timerTask, SIGNAL(timeout()), this, SLOT(checkTask()));

    timerDefence = new QTimer(this);
    timerDefence->setInterval(1000);
    connect(timerDefence, SIGNAL(timeout()), this, SLOT(checkDefence()));

    timerSize = new QTimer(this);
    timerSize->setInterval(60 * 1000);
    connect(timerSize, SIGNAL(timeout()), this, SLOT(checkSize()));

    process = new QProcess(this);
    connect(process, SIGNAL(readyRead()), this, SLOT(readData()));
}

TaskServer::~TaskServer()
{
    this->stop();
}

void TaskServer::checkTask()
{
    //当开启Ntp校时,且还未超过校对次数,且当前年份小于2016,则重新校时
    if (AppConfig::UseNtp && checkNtpCount < 10 && QDate::currentDate().year() < 2017) {
        NtpClient::Instance()->getDateTime();
        checkNtpCount++;
    }

    int count = DbData::TaskInfo_Action.count();

    for (int i = 0; i < count; ++i) {
        QString action = DbData::TaskInfo_Action.at(i);
        QString subsystem = DbData::TaskInfo_Subsystem.at(i);
        QString triggerTime = DbData::TaskInfo_TriggerTime.at(i);

        if (!taskDo.contains(action)) {
            QTime old = QTime::fromString(triggerTime, "HH:mm:ss");
            QTime now = QTime::currentTime();
            qint64 timeout = old.secsTo(now);

            int offset = 5;
            if (timeout >= 0 && timeout < offset) {
                //重启命令定位精准即时重启,规定秒之内才重启一次
                if (action == "重启") {
                    qDebug() << TIMEMS << "timeout restart";
                    appendAction(action);
#ifdef Q_OS_ARM
                    AppFun::reboot();
#endif
                }
            } else if (timeout >= offset) {
                int subSystem = subsystem.right(1).toInt();
                if (action == "布防") {
                    appendAction(action);
                    //API::deviceArmingBySub(subSystem);
                } else if (action == "撤防") {
                    appendAction(action);
                    //API::deviceDisarmingBySub(subSystem);
                } else if (action == "故障旁路") {
                    appendAction(action);
                    //API::deviceBypassBySub(subSystem);
                }
            }
        }
    }
}

void TaskServer::checkDefence()
{
    int count = DbData::DelayDefence.count();

    for (int i = 0; i < count; ++i) {
        QStringList list = DbData::DelayDefence.at(i).split("|");
        QString type = list.at(0);

        if (type == "Arming") {
            //取出布防的时间,将超过时间的任务移除
            QString time = list.at(2);
            QDateTime old = QDateTime::fromString(time, "yyyy-MM-dd HH:mm:ss");
            QDateTime now = QDateTime::currentDateTime();

            if (old.secsTo(now) >= AppConfig::DelayTimeArming) {
                qDebug() << TIMEMS << "remove task" << list;
                DbData::DelayDefence.removeAt(i);
                break;
            }
        }
    }
}

void TaskServer::checkSize()
{
#ifndef __arm__
    return;
#endif

    process->start("df", QStringList() << "-h");
}

void TaskServer::readData()
{
    while (!process->atEnd()) {
        QString result = QLatin1String(process->readLine());
        if (result.startsWith("/dev/")) {
            QString dev, use, free, all;
            int percent = 0;
            QStringList list = result.split(" ");
            int index = 0;

            for (int i = 0; i < list.count(); ++i) {
                QString s = list.at(i).trimmed();
                if (s == "") {
                    continue;
                }

                index++;
                if (index == 1) {
                    dev = s;
                } else if (index == 2) {
                    all = s;
                } else if (index == 3) {
                    use = s;
                } else if (index == 4) {
                    free = s;
                } else if (index == 5) {
                    percent = s.left(s.length() - 1).toInt();
                    break;
                }
            }

            if (all.endsWith("G")) {
                AppData::IsFullSize = (percent > 100);
            }
        }
    }
}

void TaskServer::appendAction(const QString &action)
{
    taskDo.append(action);
    QtHelper::writeInfo("自动执行任务: " + action);
}

void TaskServer::start()
{
    timerTask->start();
    timerDefence->start();
    timerSize->start();
}

void TaskServer::stop()
{
    timerTask->stop();
    timerDefence->stop();
    timerSize->stop();
}

bool TaskServer::existTaskDefence(const QString &type, const QString &value)
{
    bool exist = false;
    int count = DbData::DelayDefence.count();

    for (int i = 0; i < count; ++i) {
        QStringList list = DbData::DelayDefence.at(i).split("|");
        QString currentType = list.at(0);
        QString currentValue = list.at(1);

        if (currentType == type) {
            //如果长度为0则说明是全部布防或者子系统布防
            if (type == "Arming" && currentValue.length() == 1) {
                exist = true;
            } else if (currentValue == value) {
                currentValue == value;
            }

            break;
        }
    }

    return exist;
}

void TaskServer::appendErrorDefenceID(const QString &defenceID)
{
    if (!errorDefenceID.contains(defenceID)) {
        errorDefenceID.append(defenceID);
    }
}

void TaskServer::removeErrorDefenceID(const QString &defenceID)
{
    errorDefenceID.removeOne(defenceID);
}

void TaskServer::clearErrorDefenceID(const QString &defenceID)
{
    int busStatusCount = DbData::BusStatus.count();

    //DbData::BusStatus 存储含义 防区号|设备地址|设备索引|防区状态(0-正常,1-报警,3-离线)|左防区攀爬报警|右防区攀爬报警|是否校验过离线|最后一次消息时间
    for (int i = 0; i < busStatusCount; ++i) {
        QStringList list = DbData::BusStatus.at(i).split("|");
        QString strDefenceID = list.at(0);
        quint8 addr = list.at(1).toInt();
        quint8 index = list.at(2).toInt();

        //将当前防区重置为正常状态
        if (strDefenceID == defenceID) {
            QString strStatus = QString("%1|%2|%3|%4|%5|%6|%7|%8").arg(defenceID).arg(addr).arg(index).arg(0).arg(0).arg(0).arg(0).arg(DATETIME);
            DbData::BusStatus = strStatus;
            break;
        }
    }
}

void TaskServer::clearErrorDefenceID()
{
    int busStatusCount = DbData::BusStatus.count();

    //DbData::BusStatus 存储含义 防区号|设备地址|设备索引|防区状态(0-正常,1-报警,3-离线)|左防区攀爬报警|右防区攀爬报警|是否校验过离线|最后一次消息时间
    for (int i = 0; i < busStatusCount; ++i) {
        QStringList list = DbData::BusStatus.at(i).split("|");
        QString defenceID = list.at(0);
        quint8 addr = list.at(1).toInt();
        quint8 index = list.at(2).toInt();

        //重置为正常状态
        QString strStatus = QString("%1|%2|%3|%4|%5|%6|%7|%8").arg(defenceID).arg(addr).arg(index).arg(0).arg(0).arg(0).arg(0).arg(DATETIME);
        DbData::BusStatus = strStatus;
    }
}

void TaskServer::changeError()
{
    int busStatusCount = DbData::BusStatus.count();

    //DbData::BusStatus 存储含义 防区号|设备地址|设备索引|防区状态(0-正常,1-报警,3-离线)|左防区攀爬报警|右防区攀爬报警|是否校验过离线|最后一次消息时间
    for (int i = 0; i < busStatusCount; ++i) {
        QStringList list = DbData::BusStatus.at(i).split("|");
        QString defenceID = list.at(0);

        if (errorDefenceID.contains(defenceID)) {
            quint8 addr = list.at(1).toInt();
            quint8 index = list.at(2).toInt();

            //重置为故障状态
            QString strStatus = QString("%1|%2|%3|%4|%5|%6|%7|%8").arg(defenceID).arg(addr).arg(index).arg(1).arg(0).arg(0).arg(0).arg(DATETIME);
            DbData::BusStatus = strStatus;
        }
    }
}

void TaskServer::changeStatus()
{
    int busStatusCount = DbData::BusStatus.count();

    //DbData::BusStatus 存储含义 防区号|设备地址|设备索引|防区状态(0-正常,1-报警,3-离线)|左防区攀爬报警|右防区攀爬报警|是否校验过离线|最后一次消息时间
    for (int i = 0; i < busStatusCount; ++i) {
        QStringList list = DbData::BusStatus.at(i).split("|");
        QString defenceID = list.at(0);
        quint8 addr = list.at(1).toInt();
        quint8 index = list.at(2).toInt();
        quint8 leftDragAlarm = list.at(4).toInt();
        quint8 rightDragAlarm = list.at(5).toInt();
        quint8 isCheck = list.at(6).toInt();

        //故障防区链表中的防区需要置为故障
        quint8 status = errorDefenceID.contains(defenceID) ? 1 : 0;
        QString strStatus = QString("%1|%2|%3|%4|%5|%6|%7|%8").arg(defenceID).arg(addr).arg(index)
                            .arg(status).arg(leftDragAlarm).arg(rightDragAlarm).arg(isCheck).arg(DATETIME);
        DbData::BusStatus = strStatus;
    }
}
```
欢迎关注微信公众号:Qt实战/Qt入门和进阶(各种开源作品、经验整理、项目实战技巧,专注Qt/C++软件开发,视频监控、物联网、工业控制、嵌入式软件、国产化系统应用软件开发) QQ:517216493  WX:feiyangqingyun  QQ群:751439350
快速回复
限100 字节
 
上一个 下一个