一、前言

设备面板展示数据,相对于表格展示,可能在一个页面中能够展示的设备数据量少一些,但是有些用户和场景,又需要这种面板的形式,可能更生动形象一些。尤其是经过这么些年的社会的毒打,我的原则是:用户是上帝和大爷,尽量站在用户的角度换位思考,只要是合理或者基本合理的需求,甚至说只要不是太过分,给钱就干。

其实这种面板展示数据的需求,从我刚开始工作的时候,编写的软件,就已经有了,比如一台主机对应一个设备面板,除了显示对应的数值(电压值、电流值等),每个面板上还有按钮提供用户交互操作。对于通用的物联网平台来说,需要进行交互的场景很少,绝大部分都是用来展示采集到的数据,所以本系统的面板就显示对于的数据,如果需要回控操作的话,双击对应面板弹出详细面板信息进行操作。

设备面板几个特色功能:

  • 不同状态不同颜色,正常采用全局样式颜色、离线采用禁用颜色、低报黄色、高报红色等。
  • 双击分两种,离线状态下双击立即重新采集该设备,在线状态下双击弹出详情面板。
  • 面板可选多种样式,普通样式,仪表样式等。

二、功能特点

2.1 软件模块

  1. 设备监控模块,包括数据监控(表格形式展示)、设备面板(面板形式展示)、地图监控(地图形式展示)、曲线监控(曲线形式展示)。
  2. 数据查询模块,包括报警记录、运行记录、操作记录。
  3. 系统设置模块,包括基本设置、端口管理、控制器管理、探测器管理、报警联动、类型设置等。
  4. 其他设置模块,包括用户管理、地图管理、位置调整、组态设计、设备调试等。

2.2 基础功能

  1. 设备数据采集,支持串口、网络,串口可设置串口号、波特率,网络可设置IP地址、通讯端口。
  2. 每个端口支持采集周期时间,默认1秒钟一个设备。
  3. 支持设置通讯超时次数,默认3次。
  4. 支持最大重连时间,用于重新读取离线的设备。
  5. 控制器信息,能够添加控制器名称,选择控制器地址、控制器型号,设置该控制器下面的探测器数量。
  6. 探测器信息,能够添加位号、探测器型号、气体种类、气体符号、高报值、低报值、缓冲值、清零值、是否启用、报警声音、背景地图、存储周期、数值换算小数点位数、报警延时时间、报警的类型(HH,LL,HL)等。
  7. 类型管理可配置控制器型号、探测器型号、气体种类、气体符号等。
  8. 地图支持导入和删除,所有的探测器在地图上的位置可自由拖动保存。
  9. 端口信息、控制器信息、探测器信息、类型信息、用户信息等,都支持导入、导出、导出到excel、打印。
  10. 运行记录、报警记录、操作记录,都支持多条件组合查询,比如时间段、控制器、探测器等,所有记录支持导出到excel/pdf和打印。
  11. 运行记录、报警记录、操作记录都可删除指定时间范围内的数据。
  12. 系统设置可选择对应表最大保存记录数,自动清理早期数据,留出足够的空间存储重要的数据。
  13. 报警短信转发,支持多个接收手机号码,可设定发送间隔,比如即时发送或者6个小时发送一次所有的报警信息,短信内容过长,自动拆分多条短信。
  14. 报警邮件转发,支持多个接收邮箱,可设定发送间隔,比如即时发送或者6个小时发送一次所有的报警信息,支持附件发送。
  15. 设置软件的中文标题、英文标题、logo路径、版权所有等。
  16. 开关设置开机运行、报警声音、自动登录、记住密码等。
  17. 报警声音可设置播放次数,界面风格样式提供18套皮肤文件选择。
  18. 用户管理,包括用户权限配置,不同用户可以有不同模块的权限。
  19. 用户登录和用户退出,可以记住密码和自动登录,超过三次报错提示并关闭程序。
  20. 四种监控模式,设备面板监控、地图监控、表格数据监控、曲线数据监控,可自由切换,四种模式下都实时展示采集到的数据,报警闪烁等。
  21. 报警继电器联动,一个位号可以跨串口联动多个模块和继电器号,支持多对多。

2.3 特色功能

  1. 通信协议支持modbus_com、modbus_tcp_rtu,后期拓展mqtt等协议。
  2. 数据源除了真实的硬件设备采集,还可选数据库采集,这样用户可以安排其他程序员比如java程序员将前端采集好的数据放到数据库,本系统直接从数据库采集即可。数据库采集模式可以作为通用的系统使用,更适合多人多系统协作。
  3. 智能跳过超时的设备,加快对在线设备的采集速度,当设备数量很多的时候尤其有用。
  4. 对智能跳过的超时的设备,在设定的重连时间自动采集一次,以便探测设备是否又重新上线。
  5. 每个探测器可控是否启用,不启用则不会采集,也不会在界面显示,相当于运行阶段临时关闭。
  6. 探测器可设置缓冲值和报警延时时间,在该值附近波动产生的报警,不计入报警,只有持续处于报警值且超过报警延时时间才算真正报警,这样可以规避很多波动导致的误报。
  7. 探测器可设置存储周期,按照设定的时间来存储一条运行记录,可以按照重要程度对重要性高的设定存储周期短一些,不重要的设定大一些,这样可以节省不少的存储空间,也保证了重要的数据及时存储。
  8. 探测器可设置清零值,在一些高精度高灵敏的设备可能出厂的时候默认值未必是0,需要设定清零值来表示初始值。
  9. 探测器可设置小数点,用于计算后的真实数据控制小数点点位显示,相当于除以10、除以100、除以1000,这样大部分的探测器数据直接通过小数点位设置控制真实换算后的值,极个别的需要特殊转换的可以在通信协议中约定。
  10. 探测器报警的类型支持多种,有些设备是高于某个值高报,低于某个值低报,而有些设备是在最小值最大值范围内是高报,低于最小值低报,高于最大值正常。这样可以分情况处理,涵盖各种报警类型。
  11. 原创数据导入、导出、打印机制,跨平台不依赖任何组件,瞬间导出数据。
  12. 导出到excel的记录支持所有excel、wps等表格文件版本,不依赖excel等软件。
  13. 高报颜色、低报颜色、正常颜色、默认值颜色等,都可以自由设置。
  14. 支持云端数据同步,将本地采集到的数据实时同步到云端。
  15. 支持网络转发和网络接收,网络接收开启后,软件从udp接收数据进行解析。网络转发支持多个目标IP,这样就实现了本地采集的软件,自由将数据转到客户端,随时查看采集到的数据。
  16. 自动记住用户最后停留的界面以及其他配置信息,重启后自动应用。
  17. 报警自动切换到对应的地图,探测器按钮闪烁,表格数据对应颜色显示。
  18. 双击探测器图标,弹出对应探测器详细信息,可以根据需要定制回控操作。
  19. 数据库支持多种,包括sqlite、mysql、sqlserver、postgresql、oracle、人大金仓等。
  20. 本地设备采集到的数据实时上传到云端,以便手机APP或者web等其他方式提取。
  21. 自带设备模拟工具,支持不同型号的多个设备数据模拟,同时还带数据库数据模拟,以便在没有设备的时候测试数据。
  22. 标准modbus协议,各种控制器类型、探测器类型、种类、符号等全部自定义,非常灵活和强大,通信协议示例数据非常完整,通用各种modbus协议系统,适用于各种应用场景接入。
  23. 同时集成了串口通信、网络通信、数据库通信、数据导入导出打印、通信协议解析、界面UI、全局换肤等众多组件和知识点,非常适合新手入门和进阶。
  24. 支持xp、win7、win10、、win11、linux、mac、各种国产系统(UOS、中标麒麟、银河麒麟等)、嵌入式linux等系统。
  25. 注释完整,项目结构清晰,超级详细完整的使用开发手册,精确到每个代码文件的功能说明,不断持续迭代版本。

三、体验地址

  1. 国内站点:https://gitee.com/feiyangqingyun
  2. 国际站点:https://github.com/feiyangqingyun
  3. 个人主页:https://blog.csdn.net/feiyangqingyun
  4. 知乎主页:https://www.zhihu.com/people/feiyangqingyun
  5. 产品主页:https://blog.csdn.net/feiyangqingyun/article/details/97565652
  6. 在线文档:https://feiyangqingyun.gitee.io/qwidgetdemo/iotsystem/
  7. 体验地址:https://pan.baidu.com/s/1ZxG-oyUKe286LPMPxOrO2A 提取码:o05q 文件名:bin_iotsystem.zip。
  8. 文章导航:https://qtchina.blog.csdn.net/article/details/121330922

四、效果图



五、相关代码

#include "frmdevicenode.h"
#include "ui_frmdevicenode.h"
#include "quihelper.h"
#include "iconhelper.h"
#include "dbquery.h"
#include "deviceserver.h"
#include "frmdevicecontrol.h" frmDeviceNode::frmDeviceNode(QWidget *parent) : QWidget(parent), ui(new Ui::frmDeviceNode)
{
ui->setupUi(this);
this->initForm();
this->initStyle();
//this->initControl();
} frmDeviceNode::~frmDeviceNode()
{
delete ui;
} bool frmDeviceNode::eventFilter(QObject *watched, QEvent *event)
{
//要区分在线离线的情况
//在线双击则弹出具体详情面板
//离线双击则重连当前端口下的所有设备
if (event->type() == QEvent::MouseButtonDblClick) {
if (!online) {
QString deviceName = this->property("deviceName").toString();
QString portName = DbQuery::getPortName(deviceName);
DeviceServer::Instance()->readValue(portName, 255, true);
} else {
QString positionID = this->property("positionID").toString();
frmDeviceControl::Instance()->setPositionID(positionID);
frmDeviceControl::Instance()->show();
}
} return QWidget::eventFilter(watched, event);
} void frmDeviceNode::initForm()
{
value = 0;
online = true;
alarm = false;
select = false;
this->installEventFilter(this); QFont font;
font.setPixelSize(QUIConfig::FontSize + 2);
ui->labNodeInfo->setFont(font);
ui->labNodeInfo->setFixedHeight(30); //设置图形字体
QFont iconFont = IconHelper::getIconFontAwesome();
ui->labNodeNamex->setFont(iconFont);
ui->labPositionIDx->setFont(iconFont);
ui->labNodeTypex->setFont(iconFont);
ui->labNodeValuex->setFont(iconFont); ui->labNodeNamex->setText(QChar(0xf132));
ui->labPositionIDx->setText(QChar(0xf015));
ui->labNodeTypex->setText(QChar(0xf124));
ui->labNodeValuex->setText(QChar(0xf0c3)); //通过弱属性控制样式
ui->devicePanel2->setProperty("form", "panel");
ui->deviceTitle1->setProperty("form", "panel");
ui->devicePanel1->setProperty("form", "panel");
ui->deviceTitle1->setProperty("flag", "paneltitle");
ui->devicePanel1->setProperty("flag", "panelcontrol"); //可以自行根据项目需要调整范围值小数点等
ui->gaugeSpeed->setUnit("");
ui->gaugeSpeed->setPrecision(0);
ui->gaugeSpeed->setDigitCount(3);
ui->gaugeSpeed->setRange(0, 200);
ui->gaugeSpeed->setValue(ui->gaugeSpeed->getMinValue());
} void frmDeviceNode::initStyle()
{
//根据不同的面板样式隐藏对应的面板
if (AppConfig::PanelStyle == 0) {
ui->widget1->setVisible(true);
ui->widget2->setVisible(false);
} else if (AppConfig::PanelStyle == 1) {
ui->widget1->setVisible(false);
ui->widget2->setVisible(true);
} QString textColor, bgColor;
if (alarm) {
//判断低报还是高报
QString positionID = this->property("positionID").toString();
int index = DbData::NodeInfo_PositionID.indexOf(positionID);
bool alarmLimit = DbData::NodeInfo_AlarmLimit.at(index);
bool alarmUpper = DbData::NodeInfo_AlarmUpper.at(index);
//bool alarmOther = DbData::NodeInfo_AlarmOther.at(index); //报警面板颜色
textColor = "#EEEEEE";
if (alarmLimit) {
bgColor = AppConfig::ColorLimit;
} else if (alarmUpper) {
bgColor = AppConfig::ColorUpper;
} else {
bgColor = AppConfig::ColorOther;
} //报警状态下的选中将颜色加个透明度
if (select) {
QColor color(bgColor);
bgColor = QString("rgba(%1,%2,%3,150)").arg(color.red()).arg(color.green()).arg(color.blue());
}
} else {
//选中面板颜色
textColor = online ? QUIConfig::TextColor : QUIConfig::BorderColor;
bgColor = select ? QUIConfig::DarkColorStart : QUIConfig::NormalColorStart;
} QStringList qss;
//仪表盘中的数码管禁用样式
qss << QString("QLCDNumber:disabled{background:%1;}").arg(QUIConfig::NormalColorStart);
//仪表样式中的节点信息标签
qss << QString("#labNodeInfo{color:%1;background:%2;}").arg(textColor).arg(alarm ? bgColor : QUIConfig::DarkColorEnd);
//仪表样式面板需要调整下颜色
if (AppConfig::PanelStyle == 1 && alarm) {
textColor = QUIConfig::TextColor;
bgColor = select ? QUIConfig::DarkColorStart : QUIConfig::NormalColorStart;
} //全局文字颜色
qss << QString("*{color:%1;}GaugeSpeed{qproperty-textColor:%1;}").arg(textColor);
//整体面板背景颜色
qss << QString("#deviceTitle1,#devicePanel1,#devicePanel2{background:%1;}").arg(bgColor);
this->setStyleSheet(qss.join(""));
} void frmDeviceNode::initControl()
{
QString positionID = this->property("positionID").toString();
QString nodeName = this->property("nodeName").toString();
QString nodeType = this->property("nodeType").toString();
QString nodeSign = this->property("nodeSign").toString(); ui->labNodeName->setText("名称: " + nodeName);
ui->labPositionID->setText("位号: " + positionID);
ui->labNodeType->setText("型号: " + nodeType);
ui->labNodeValue->setText(QString("数值: %1 %2").arg(value).arg(nodeSign)); ui->gaugeSpeed->setText(nodeSign);
ui->gaugeSpeed->setValue(value);
ui->labNodeInfo->setText(positionID + " -- " + nodeName);
} void frmDeviceNode::setValue(float value)
{
this->value = value;
QString nodeType = this->property("nodeType").toString();
QString nodeSign = this->property("nodeSign").toString(); //有两个传感器是开关量,数值是1 2显示时用正常和异常代替
if (nodeType == "SJ-0001" || nodeType == "JG-0001") {
ui->labNodeValue->setText(QString("数值: %1").arg(value == 1 ? "正常" : "异常"));
ui->gaugeSpeed->setValue(value == 1 ? ui->gaugeSpeed->getMinValue() : ui->gaugeSpeed->getMaxValue());
} else {
ui->labNodeValue->setText(QString("数值: %1 %2").arg(value).arg(nodeSign));
ui->gaugeSpeed->setValue(value);
}
} void frmDeviceNode::setOnline(bool online)
{
if (this->online != online) {
this->online = online;
if (!online) {
this->value = 0;
this->alarm = false;
this->select = false;
} this->setEnabled(online);
this->initStyle();
this->initControl();
}
} void frmDeviceNode::setAlarm(bool alarm)
{
//可能由低报转为高报所以这里不要做过滤判断
this->alarm = alarm;
this->initStyle();
} void frmDeviceNode::setSelect(bool select)
{
if (this->select != select) {
this->select = select;
this->initStyle();
}
}

Qt编写物联网管理平台33-设备面板的更多相关文章

  1. EMQ插件组合实现物联网边缘平台的设备通信管理

    上一篇随笔我简单的记录了我对EMQ插件开发的了解过程,最后发现还是可以组合复用已有插件,因此这篇随笔用于记录使用的情况以及是否达到预期. 首先测试mysql认证插件的使用方式: emqx_auth_m ...

  2. 年底奉献-QT编写视频监管平台(开源)

    忙忙碌碌又是一年,算算自己毕业四年半,一直在现在这家公司做研发外加总经理助理,研发起初用的VB.NET,而后全面转为C#,最后又全面转为QT,都是由于项目需要,算下来自己搞QT编程也已经四年了,201 ...

  3. Qt+imx6编写的楼宇对讲管理平台

    第一个初步版本. 1:楼宇对讲模块.住户报警模块.门禁控制模块.系统设置模块. 2:实时对讲信息卡片式展示,通话记录表格展示. 3:设备面板展示,实时显示上下线报警等信息. 4:设备查询.记录查询.运 ...

  4. 自学华为IoT物联网_10 IoT联接管理平台配置及开发实验1

    点击返回自学华为IoT物流网 自学华为IoT物联网_10 IoT联接管理平台配置及开发实验1 实验1:OceanConnect平台实验             通过基本的编程操作与配置,帮助读者熟悉O ...

  5. Qt编写气体安全管理系统29-跨平台

    一.前言 Qt的跨平台特性是非常厉害的,本来作为C++来说,跨平台的特性比JAVA还要好,只不过学习难度更大,所以大家更理解的跨平台是JAVA,Qt的跨平台特性是我见过的所有开发环境和语言中最厉害的, ...

  6. Qt编写气体安全管理系统24-地图管理

    一.前言 地图管理的主要功能是将系统中的地图文件做添加和删除,支持常见的jpg.png.bmp等格式图片,图片分辨率建议小于1080P,最好是和目标客户端电脑分辨率一致,这样在拉伸缩放的时候会比较清晰 ...

  7. Qt编写气体安全管理系统20-控制器管理

    一.前言 控制器管理,主要就是对控制器进行添加删除和修改,其中包括编号.端口名称.控制器名称.控制器地址.控制器型号.探测器数量这几个字段,端口名称表示当前控制器所属哪个端口,一个系统中可以有好多个端 ...

  8. Qt编写气体安全管理系统19-端口管理

    一.前言 所有设备的信息配置,主要就三大点:端口管理.控制器管理.探测器管理,整个硬件系统的架构是有多个不同的通信端口(主要是串口和网络),每个通信端口下面挂着多个控制器(每个控制器都有唯一的地址,从 ...

  9. 自学华为IoT物联网_08 IoT连接管理平台介绍

    点击返回自学华为IoT物流网 自学华为IoT物联网_08 IoT连接管理平台介绍 一.IoT连接管理平台的由来 1.1  物联网产业发展面临的挑战 新业务上线周期长,应用碎片化,开发周期长,场频上市慢 ...

  10. Qt编写气体安全管理系统21-探测器管理

    一.前言 探测器在整个系统中是最核心的关键的硬件,终端节点硬件,安装有探测芯片装置,负责探测前端对应气体浓度,并记录值,等待控制器轮训数据回复,控制器信息表也是字段最多的,要存储位号.控制器名称.探测 ...

随机推荐

  1. 三、Spring Boot集成Spring Security之securityFilterChain过滤器链详解

    二.默认过滤器链 1.默认配置系统启动日志 2.默认配置的过滤器及顺序如下 org.springframework.security.web.session.DisableEncodeUrlFilte ...

  2. 一个查询IP地理信息和CDN提供商的离线终端工具

    一个查询IP地理信息和CDN提供商的离线终端工具 Nali 功能 支持多种数据库 纯真 IPv4 离线数据库 ZX IPv6 离线数据库 Geoip2 城市数据库 (可选) IPIP 数据库 (可选) ...

  3. 最详细CentOS7.6安装openGauss5.0.3教程

    一.环境准备 1.1 主机信息 项目 内容 操作系统 CentOS7.6 IP 192.168.4.201 主机名 opgs201 CPU 8core 内存 16GB 磁盘1 100GB 1.2 操作 ...

  4. docker对的tomcat、mysql、redis、nginx的安装

    本章篇章主要讲解了docker对常用软件的安装说明 总体步骤:搜索镜像.拉取镜像.查看镜像.启动镜像.停止容器.移除容器 tomcat docker seacher tomcat//也可以在docke ...

  5. KubeSphere 社区双周报 | OpenFunction v0.8.0 发布 | 2022-12-09

    KubeSphere 从诞生的第一天起便秉持着开源.开放的理念,并且以社区的方式成长,如今 KubeSphere 已经成为全球最受欢迎的开源容器平台之一.这些都离不开社区小伙伴的共同努力,你们为 Ku ...

  6. js常用函数-02 _关于$(function () { })的运行时机

    js常用函数-02 _关于$(function () { })的运行时机 代码模式: $(function() { //执行操作 }); 查找到的结果: (function() {}),即 $(doc ...

  7. 解决mysql的语句中group_concat长度限制问题

    在mysql中,有个函数叫"group_concat",平常使用可能发现不了问题,在处理大数据的时候,会发现内容被截取了.其实MYSQL内部对这个是有设置的,默认不设置的长度是10 ...

  8. WebDriver常用属性和方法

    除了上一篇的元素定位方法,Selenium中的WebDriver类中还有一些常用的属性和方法 一.常用的属性 1.下表列出了WebDriver的常用属性 # 属性 属性描述 用途 1 driver.n ...

  9. js 数字计算的精度问题

    〇.js 的数值计算存在结果不精确的情况 最近接触财务相关系统,页面上会有一些简单的计算,就发现其实是非常简单的计算,但 js 计算出来的结果却不是预期值,可能带上一大串 0 或 9,导致计算结果错误 ...

  10. NOIP2023模拟9联测30 T4 金牌

    NOIP2023模拟9联测30 T4 金牌 LCA 还能 \(O(1)\)-- 思路 思路非常简单,可考试就是想歪成统计指数了-- 将一条穿过 \((x,y)\) 的路径 \((u,v)\) 分为 \ ...