一、前言

本系统默认采用modbus协议,支持串口和网络rtu模式,后期还会引入其他通信协议比如mqtt等,可以在端口管理中下拉选择通信协议即可。

1.1 通信流程

  1. 整体的结构是:控制器挂在通信端口,一个控制器下有多个探测器节点,相当于主设备、子设备。
  2. 因为是需要遍历轮询,所以一个通信端口上的控制器地址不能重复。
  3. 不同通信端口,控制器地址可以重复,所以如果控制器数量较多可以分在不同的通信端口。
  4. 一个控制器可以挂多个探测器,控制器平时也在不断轮询探测器的数据并记录,等待上位机程序的轮询命令后,将探测器数据一起打包发回。
  5. 本软件只和控制器通信,不和探测器通信,控制器负责和探测器通信。为何这样设计?因为这种架构最通用,可接的设备数量也是最大的。
  6. 本系统默认按照标准modbus协议进行通信,modbus是标准的通信框架协议,支持串口和网络等通信方式,至于具体是通过串口还是网络通信根据设备厂家选择。
  7. modbus是通信协议框架,至于具体数据位的每个字节对应的数据含义,每个厂家不一样,都是厂家自定义,一般2个字节表示一个数据。
  8. 端口可以是串口和网络,在添加端口时候可选择不同通信解析协议。

1.2 协议解释

  1. 主机发送是软件发送数据给设备,主动发送。
  2. 从机应答是设备根据收到的数据后作出应答数据,被动回复。
  3. 一条发送命令会对应一条应答命令。
  4. 寄存器地址2字节,高位在前低位在后。
  5. 读取长度2字节,高位在前低位在后。
  6. 数据位2字节,高位在前低位在后。
  7. CRC校验2字节,低位在前高位在后。
  8. 功能码有 03(读只读寄存器)、04(读可读可写寄存器)、06(写读写寄存器)。
  9. 主机发送的功能码和从机应答的功能码相同。

1.2.1 主机发送

地址 功能码 寄存器地址 寄存器个数 CRC校验
01 03 00 00 00 04 44 09

1.2.2 从机应答

地址 功能码 长度 数据位1 数据位2 数据位3 数据位4 CRC校验
01 03 08 00 00 00 00 00 00 00 00 95 D7

1.2.3 读取长度

设备型号 长度 说明
FC1003-1 01
FC1003-8 08
FC1003-16 08 08 相当与两台FC1003-8,设备地址不同。
FC1003显示板 40 长度根据所接设备数量不同需要调整,最大为64个。
FC1003底板 04
FT2104P 01
SAMS-4128 08

1.2.4 数据举例

提示说明

  1. 以下举例数据CRC校验位统一用 XX XX 表示,懒得计算。
  2. 本系统中填写的地址都是从1开始计数,所以填1则表示从0开始读取。
  3. 如果寄存器地址 01 01 ,则0101=257,本系统中要填258,填258实际是-1=257=0101发送。
  4. 寄存器个数,也可以说是节点设备的数量。
  5. 一个数据位或者说一个节点的数据是2个字节数据。
  6. 读取长度1则会返回1个数据位共2字节数据。
  7. 读取长度2则会返回2个数据位共4字节数据。
  8. 读取长度3则会返回3个数据位共6字节数据。

示例数据1

  • 发送:01 03 00 00 00 02 XX XX
  • 解释:从寄存器地址0(00 00 = 0)开始,读取2个寄存器。
  • 返回:01 03 04 42 C7 FF EA XX XX
  • 解释:返回4字节数据 42 C7 FF EA ,对应寄存器地址 0、1 的数据。
  • 配置:控制器地址1,探测器地址1、2。

示例数据2

  • 发送:01 03 01 01 00 01 XX XX
  • 解释:从寄存器地址257(01 01 = 257)开始,读取1个寄存器。
  • 返回:01 03 02 02 EF XX XX
  • 解释:返回2字节数据 02 EF ,对应寄存器地址257的数据。
  • 配置:控制器地址1,探测器地址258。

示例数据3

  • 发送:AA 03 AA BB 00 04 XX XX
  • 解释:从寄存器地址43707(AA BB = 43707)开始,读取4个寄存器。
  • 返回:AA 03 08 55 AC 23 65 84 77 C3 3F XX XX
  • 解释:返回8字节数据 55 AC 23 65 84 77 C3 3F ,对应寄存器地址43707、43708、43709、43710的数据。
  • 配置:控制器地址170(AA = 170),探测器地址43708、43709、43710、43711。

二、功能特点

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

四、效果图











五、相关代码

void DeviceClient::readValue()
{
//还没有连接上或者地址为空则不需要处理
int addrCount = addrs.count();
if (!isOk || addrCount == 0) {
return;
} //优先执行命令
if (doAddrs.count() > 0) {
QString type = doTypes.takeFirst();
quint8 addr = doAddrs.takeFirst();
QByteArray body = doBodys.takeFirst();
writeData(type, addr, body); //额外执行的命令可能比较多导致设备离线,这里需要更新所有设备的时间
for (int i = 0; i < addrs.count(); ++i) {
times[i] = QDateTime::currentDateTime();
} return;
} //暂停不需要轮询,更新最后的消息时间,不然时间久了会判断离线
if (pause) {
for (int i = 0; i < addrs.count(); ++i) {
times[i] = QDateTime::currentDateTime();
}
return;
} //如果没有一个在线的设备则不需要处理
bool existLive = false;
for (int i = 0; i < addrCount; ++i) {
if (onlines.at(i)) {
existLive = true;
break;
}
} if (!existLive) {
emit receiveInfo(portName, 255, "没有一个在线设备,跳过遍历");
return;
} //如果已经到了末尾则重新开始
if (currentIndex == addrCount) {
currentIndex = 0;
} //跳过离线的设备,加速读取,递归
if (!onlines.at(currentIndex)) {
currentIndex++;
readValue();
return;
} readValue(addrs.at(currentIndex));
currentIndex++;
} void DeviceClient::checkValue()
{
if (!isOk) {
return;
} QMutexLocker locker(&mutex);
readData(); //至少要多少个字节,保证下面取数据不出错
int size = buffer.size();
if (size < 5) {
return;
} //01 03 08 00 00 00 00 00 00 00 00 95 D7
//01 03 08 00 14 03 12 00 00 00 00 79 E6 //取出首字节,判断是否为当前地址集合中的地址
quint8 addr = buffer.at(0);
quint8 cmd = buffer.at(1);
quint8 len = buffer.at(2); //如果是错误码则直接解析错误信息
QList<quint8> cmds;
cmds << 0x03 << 0x04 << 0x06;
if (!cmds.contains(cmd)) {
emit receiveError(portName, addr, QString("数据出错: %1").arg(QUIHelper::byteArrayToHexStr(buffer)));
buffer.clear();
return;
} //如果数据过长则丢弃当前数据包,不然一旦产生了错误的数据会一直累积
if (size > 517) {
emit receiveError(portName, addr, QString("数据出错: %1").arg(QUIHelper::byteArrayToHexStr(buffer)));
buffer.clear();
return;
} //后面的数据长度必须大于等于长度数据位表示的长度
if ((cmd == 0x03 || cmd == 0x04 || cmd == 0x06) && size < len + 5) {
emit receiveError(portName, addr, QString("数据不全,等待完整数据再解析: %1").arg(QUIHelper::byteArrayToHexStr(buffer)));
return;
} //放在这里发出去数据是准确的完整的
emit receiveData(portName, addr, buffer); //过滤不存在的地址,防止索引越界
int index = addrs.indexOf(addr);
if (index < 0) {
emit receiveError(portName, addr, "地址出错: 当前地址不在设定的地址集合中");
buffer.clear();
return;
} //来过消息的设备,立马更新最后的消息时间,以及判断设备上线
times[index] = QDateTime::currentDateTime();
if (!onlines.at(index)) {
onlines[index] = true;
emit receiveOnline(portName, addr, true);
emit receiveInfo(portName, addr, "设备上线");
} //根据不同的cmd+不同的命令类型,取出对应的数据内容
if (cmd == 0x03) {
QString info;
if (currentType == "查询浓度值") {
QList<quint16> values;
//每个探测器状态1个寄存器=2字节
for (int i = 3; i < size - 2; i = i + 2) {
values << (float)QUIHelper::byteToUShort(buffer.mid(i, 2));
} QStringList list;
foreach (quint16 value, values) {
list << QString::number(value);
} info = QString("%1返回: %2").arg(currentType).arg(list.join(" "));
emit receiveValue(portName, addr, values);
} //发送对应的文字解析
if (!info.isEmpty()) {
emit receiveInfo(portName, addr, info);
}
} else if (cmd == 0x04) { } else if (cmd == 0x06) { } //重新赋值
buffer.clear();
}

Qt编写物联网管理平台36-通信协议的更多相关文章

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

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

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

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

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

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

  4. 基于SpringBoot+SSM实现的Dota2资料库智能管理平台

    Dota2资料库智能管理平台的设计与实现 摘    要 当今社会,游戏产业蓬勃发展,如PC端的绝地求生.坦克世界.英雄联盟,再到移动端的王者荣耀.荒野行动的火爆.都离不开科学的游戏管理系统,游戏管理系 ...

  5. Qt编写项目作品大全(自定义控件+输入法+大屏电子看板+视频监控+楼宇对讲+气体安全等)

    一.自定义控件大全 (一).控件介绍 超过160个精美控件,涵盖了各种仪表盘.进度条.进度球.指南针.曲线图.标尺.温度计.导航条.导航栏,flatui.高亮按钮.滑动选择器.农历等.远超qwt集成的 ...

  6. Qt编写气体安全管理系统10-数据导出

    一.前言 数据导出一般指导出到excel表格,可能有部分用户还需要导出到pdf,因为pdf基本上不可编辑,防止用户重新编辑导出的数据,excel可能绝大部分用过电脑的人都知道,广为流行,主要就是微软的 ...

  7. 使用Qt编写模块化插件式应用程序

    动态链接库技术使软件工程师们兽血沸腾,它使得应用系统(程序)可以以二进制模块的形式灵活地组建起来.比起源码级别的模块化,二进制级别的模块划分使得各模块更加独立,各模块可以分别编译和链接,模块的升级不会 ...

  8. 容器、容器集群管理平台与 Kubernetes 技术漫谈

    原文:https://www.kubernetes.org.cn/4786.html 我们为什么使用容器? 我们为什么使用虚拟机(云主机)? 为什么使用物理机? 这一系列的问题并没有一个统一的标准答案 ...

  9. Qt编写的开源帖子集合(懒人专用)

    回顾自己学习Qt以来九年了,在这九年多时间里面,从本论坛学习不到不少的东西,今天特意整了一下自己开源过的资源的帖子,整理一起方便大家直接跳转下载,不统计不知道,一统计吓一跳,不知不觉开源了这么多代码, ...

  10. 国内物联网平台(8):中移物联网开放平台OneNet

    国内物联网平台(8)——中移物联网开放平台OneNet 马智 平台定位 OneNET是中移物联网有限公司搭建的开放.共赢设备云平台,为各种跨平台物联网应用.行业解决方案,提供简便的云端接入.存储.计算 ...

随机推荐

  1. 解决 -Code 安装似乎损坏。请重新安装

    问题: 1. 安装插件  fix VSCode Checksums 2. ctrl+shift+P打开命令面板 3. 输入 Fix Checksums: Apply 4.  重新启动VSCode

  2. 在 Vue 实例中编写生命周期hook 或者其它 option/propertie 时,为什么不适用箭头函数 ?

    首先,箭头函数没有自己的 this 环境变量 会沿用作用域使用父级this : 由Vue 管理的函数 ,如果写成箭头函数 this 就不在是 Vue 实例 了 :

  3. 001 (Python+水论文合集)为什么录这个合集,这个合集会讲哪些内容?

    博客配套视频链接: https://space.bilibili.com/383551518?spm_id_from=333.1007.0.0 b 站直接看 配套 github 链接:https:// ...

  4. 洛谷P1644跳马问题

    跳马问题 题目链接 题目背景 在爱与愁的故事第一弹第三章出来前先练练四道基本的回溯/搜索题吧-- 题目描述 中国象棋半张棋盘如图 \(1\) 所示.马自左下角 \((0,0)\) 向右上角 \((m, ...

  5. 【2024.08.15】NOIP2024暑假集训模拟赛(13)

    [2024.08.15]NOIP2024暑假集训模拟赛(13) T1 先找能构成回文的最长前缀和后缀(长度相同的),然后在任意一边的基础上扩展,看能否接一个回文串. #include<bits/ ...

  6. OpenAI使用AI编程给出了数数问题的解决方案 —— 如何解决ChatGPT不会数数的问题

    总所周知的一个问题,那就是ChatGPT不会数数,不过今天突然发现OpenAI给出了一个神奇的解决方法,那就是AI编程. 问题案例如下: The text provided will be analy ...

  7. axios获取上传进度报错xhr.upload.addEventListener is not a function

    错误问题 Vue:xhr.upload.addEventListener is not a function 这个问题是因为mockjs改动了axios里面XMLHttpRequest对象致使的 根据 ...

  8. 推荐UML插件Green UML、AmaterasUML

    项目上要求release时需要同时给出详细的类关系图,可惜本人之前只是使用XMind手工画过很简单的类关系图(只是类的继承关系),可苦了我呀. 这两天一直在网上查找能够在Eclipse 已有的代码基础 ...

  9. Java深度历险(三)——Java线程​:基本概念、可见性与同步

    开发高性能并发应用不是一件容易的事情.这类应用的例子包括高性能Web服务器.游戏服务器和搜索引擎爬虫等.这样的应用可能需要同时处理成千上万个请求.对于这样的应用,一般采用多线程或事件驱动的架构.对于J ...

  10. JAVA WEB和Tomcat各组件概念

    概述 本篇文章是https://juejin.cn/post/7055306172265414663,这篇文章的再总结,剔除了与Java安全研究没太大关系的内容,对JAVAWEB中的Servlet.F ...