【Qt】Qt + Modbus 服务端学习条记

[复制链接]
发表于 2025-10-12 05:27:49 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
《Qt + Modbus 服务端学习条记》

1.由于项目标必要,要写一个modbus通讯,csdn上感觉有些答复,代码是人工智能天生的,有些细节不对。我这个颠末实测,是可以直接用的。
起主要包罗Qt 的干系模块

Qt Modbus 模块告急包罗以下几类关键组件:


  • 装备类:如 QModbusTcpServer 和 QModbusTcpClient,分别用于创建 Modbus TCP 服务器和客户端,提供了创建毗连、断开毗连等根本操纵接口。
  • 数据单位类:比方 QModbusDataUnit,用于表现 Modbus 协议中的数据单位,可方便地操纵和管理 Modbus 寄存器中的数据。
  • 协议数据单位类:像 QModbusPdu,它表现 Modbus 协议数据单位,用于处理处罚 Modbus 哀求和相应的协议层数据。
  • 初始化:在 ModeBusServer 类的构造函数里,初始化 QModbusTcpServer 和定时器,同时创建信号与槽的毗连,以处理处罚定时器超时、数据写入、状态改变等事故。
  • 启动与克制

    • startServer 函数会对输入参数举行查抄,设定 Modbus 数据单位映射和毗连参数,实验毗连装备,若乐成就启动数据更新定时器。
    • stopServer 函数则克制定时器,断开服务器毗连。

  • 数据更新:借助定时器,定时调用 updateData 函数。此函数从 SystemInfoCollector 获取体系信息,将其写入 Modbus 数据单位,再设置到服务器里。
  • 数据处理处罚

    • printUpdateData 函数用于打印更新后的数据和剖析出的体系信息。
    • handleRequest 函数处理处罚客户端哀求,纪录哀求信息。
    • onDataWritten 函数处理处罚数据写入事故。

运行结果

  1. #ifndef MODEBUSSERVER_H
  2. #define MODEBUSSERVER_H
  3. #include <QObject>
  4. #include <QModbusTcpServer>
  5. #include <QModbusDataUnit>
  6. #include <QTimer>
  7. #include <QMap>
  8. #include <memory> // 包含 std::unique_ptr 所在的头文件
  9. #include <iostream>
  10. #include <QDateTime>
  11. #include "SystemInfoCollector.h"
  12. //解决中文乱码
  13. #pragma execution_character_set("utf-8")
  14. class ModeBusServer : public QObject
  15. {
  16.     Q_OBJECT
  17. public:
  18.     explicit ModeBusServer(QObject* parent = nullptr);
  19.     ~ModeBusServer();
  20.     void startServer(quint16 deviceID, const QString& ipAddress, quint16 port);
  21.     void stopServer();
  22.     void printUpdateData(QModbusDataUnit& unit);
  23. signals:
  24.     void statusUpdated(const QString& message);
  25.     void dataUpdated(const QModbusDataUnit& data);
  26.     void requestReceived(const QModbusPdu& request, QModbusDataUnit::RegisterType table, int address, int size);
  27. private slots:
  28.     void updateData();
  29.     void writeSystemInfoToModbus(QModbusDataUnit& unit, SystemInfo& info);
  30.     void handleRequest(const QModbusPdu& request, QModbusDataUnit::RegisterType table, int address, int size);
  31.     void sendDataPeriodically();
  32.     void onDataWritten(QModbusDataUnit::RegisterType table, int address, int size);
  33. private:
  34.     std::unique_ptr<QModbusTcpServer> m_modbusServer;
  35.     std::unique_ptr<QTimer> m_dataUpdateTimer;
  36.     std::unique_ptr<QTimer> m_sendDataTimer;
  37.     QMap<int, quint16> m_dataCache; // 数据缓存
  38.     quint16 m_holdingRegistersSize = 100;
  39.     int m_deviceID;
  40.     int m_valueIndex;
  41.     SystemInfoCollector m_infoCollector;
  42. };
  43. #endif // MODEBUSSERVER_H
  44. #include "modeBusServer.h"
  45. #include <QDebug>
  46. ModeBusServer::ModeBusServer(QObject* parent)
  47.         : QObject(parent),
  48.         m_modbusServer(std::make_unique<QModbusTcpServer>(this)),
  49.         m_dataUpdateTimer(std::make_unique<QTimer>(this)),
  50.         m_sendDataTimer(std::make_unique<QTimer>(this))
  51. {
  52.         connect(m_dataUpdateTimer.get(), &QTimer::timeout, this, &ModeBusServer::updateData);
  53.         connect(this, &ModeBusServer::statusUpdated, this, [&](const QString& statusUpdateStr) {
  54.                 qDebug() << statusUpdateStr;
  55.                 });
  56.         // 修改连接,使用新的槽函数
  57.         connect(m_modbusServer.get(), &QModbusTcpServer::dataWritten, this, &ModeBusServer::onDataWritten);
  58.         connect(m_modbusServer.get(), &QModbusTcpServer::stateChanged, this, [this](int state) {
  59.                 if (state == QModbusDevice::ConnectedState) {
  60.                         qDebug() << "Server connected";
  61.                 }
  62.                 else if (state == QModbusDevice::UnconnectedState) {
  63.                         qDebug() << "Server disconnected";
  64.                 }
  65.                 });
  66. }
  67. ModeBusServer::~ModeBusServer()
  68. {
  69.         stopServer();
  70. }
  71. void ModeBusServer::startServer(quint16 deviceID, const QString& ipAddress, quint16 port)
  72. {
  73.         if (port == 0 || deviceID == 0 || ipAddress.isEmpty()) {
  74.                 emit statusUpdated("Invalid parameters.");
  75.                 return;
  76.         }
  77.         m_deviceID = deviceID;
  78.         QModbusDataUnitMap reg;
  79.         reg.insert(QModbusDataUnit::HoldingRegisters, { QModbusDataUnit::HoldingRegisters, 0, m_holdingRegistersSize });
  80.         m_modbusServer->setMap(reg);
  81.         m_modbusServer->setConnectionParameter(QModbusDevice::NetworkAddressParameter, ipAddress);
  82.         m_modbusServer->setConnectionParameter(QModbusDevice::NetworkPortParameter, port);
  83.         m_modbusServer->setServerAddress(deviceID);
  84.         if (m_modbusServer->connectDevice()) {
  85.                 emit statusUpdated("Server started on " + ipAddress + ":" + QString::number(port));
  86.                 m_dataUpdateTimer->start(500);
  87.         }
  88.         else {
  89.                 emit statusUpdated("Server start failed: " + m_modbusServer->errorString());
  90.         }
  91. }
  92. void ModeBusServer::stopServer()
  93. {
  94.         m_dataUpdateTimer->stop();
  95.         m_modbusServer->disconnectDevice();
  96.         emit statusUpdated("Server stopped.");
  97. }
  98. void ModeBusServer::printUpdateData(QModbusDataUnit& unit)
  99. {
  100.                 for (int i = 0; i < unit.valueCount(); ++i) {
  101.                         m_dataCache[i] = unit.value(i); // 更新缓存
  102.                 }
  103.                 qDebug() << QString("%1号设备").arg(m_deviceID) << "寄存器数据:" << unit.values();
  104.                 SystemInfo info1 = m_infoCollector.parseSystemInfo(unit.values());
  105.                 qDebug() << "Memory Usage:" << info1.memoryUsage << "%";
  106.                 qDebug() << "CPU Usage:" << info1.cpuUsage << "%";
  107.                 qDebug() << "Boot Time:" << info1.bootTime.toString(Qt::ISODate);
  108.                 qDebug() << "Up Time:" << info1.upTime << "seconds";
  109. }
  110. // 更新数据
  111. void ModeBusServer::updateData()
  112. {
  113.         m_valueIndex = 0;
  114.         QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, 0, 10);
  115.         SystemInfo info;
  116.         // 将系统信息写入 Modbus 数据单元
  117.         writeSystemInfoToModbus(unit, info);
  118.         bool  isSetDataSuccess = m_modbusServer->setData(unit);
  119.         //设置数据
  120.         if (isSetDataSuccess)
  121.         {
  122.                 m_dataCache.clear(); // 清空缓存
  123.                 printUpdateData(unit);
  124.                 emit dataUpdated(unit);
  125.         }
  126.         else
  127.         {
  128.                 qDebug() << "Failed to update data: " << m_modbusServer->errorString();
  129.         }
  130. }
  131. // 将 SystemInfo 数据写入 QModbusDataUnit
  132. void ModeBusServer::writeSystemInfoToModbus(QModbusDataUnit& unit, SystemInfo& info) {
  133.         info = m_infoCollector.getSystemInfo();
  134.         // 写入内存占用率
  135.         quint16 memoryUsageInt = static_cast<quint16>(info.memoryUsage * 100); // 转换为整数
  136.         unit.setValue(m_valueIndex++, memoryUsageInt & 0xFFFF);
  137.         // 写入 CPU 占用率
  138.         quint16 cpuUsageInt = static_cast<quint16>(info.cpuUsage * 100); // 转换为整数
  139.         unit.setValue(m_valueIndex++, cpuUsageInt & 0xFFFF);
  140.         // 写入开机时间(时间戳)
  141.         qint64 bootTimestamp = info.bootTime.toSecsSinceEpoch();
  142.         unit.setValue(m_valueIndex++, static_cast<quint16>(bootTimestamp & 0xFFFF));
  143.         unit.setValue(m_valueIndex++, static_cast<quint16>((bootTimestamp >> 16) & 0xFFFF));
  144.         // 写入运行时间
  145.         unit.setValue(m_valueIndex++, static_cast<quint16>(info.upTime & 0xFFFF));
  146.         unit.setValue(m_valueIndex++, static_cast<quint16>((info.upTime >> 16) & 0xFFFF));
  147. }
  148. void ModeBusServer::handleRequest(const QModbusPdu& request, QModbusDataUnit::RegisterType table, int address, int size)
  149. {
  150.         emit requestReceived(request, table, address, size);
  151.         qDebug() << "Request received: Function Code" << request.functionCode() << ", Type" << table << ", Address" << address << ", Size" << size;
  152. }
  153. void ModeBusServer::sendDataPeriodically()
  154. {
  155.         qDebug() << "Periodic Data Send:";
  156.         for (auto it = m_dataCache.begin(); it != m_dataCache.end(); ++it) {
  157.                 qDebug() << "Address" << it.key() << "@" << it.value();
  158.         }
  159. }
  160. // 实现新增的槽函数
  161. void ModeBusServer::onDataWritten(QModbusDataUnit::RegisterType table, int address, int size)
  162. {
  163.         // 处理数据写入事件,可根据需要扩展
  164.         qDebug() << "写入数据类型" << table << "从地址" << address << "开始。" << "数据长度:" << size;
  165. }
  166.         }
  167. }
  168. // 实现新增的槽函数
  169. void ModeBusServer::onDataWritten(QModbusDataUnit::RegisterType table, int address, int size)
  170. {
  171.         // 处理数据写入事件,可根据需要扩展
  172.         qDebug() << "写入数据类型" << table << "从地址" << address << "开始。" << "数据长度:" << size;
  173. }
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表