北京东城区做网站的公司/软件外包网

北京东城区做网站的公司,软件外包网,长沙装饰公司,代理网址怎么设置《Qt Modbus 服务端学习笔记》 1.因为项目的需要,要写一个modbus通信,csdn上感觉有些回答,代码是人工智能生成的,有些细节不对。我这个经过实测,是可以直接用的。 首先要包含Qt 的相关模块 Qt Modbus 模块主要包含以…

《Qt + Modbus 服务端学习笔记》

1.因为项目的需要,要写一个modbus通信,csdn上感觉有些回答,代码是人工智能生成的,有些细节不对。我这个经过实测,是可以直接用的。

首先要包含Qt 的相关模块

在这里插入图片描述

Qt Modbus 模块主要包含以下几类关键组件:

  • 设备类:如 QModbusTcpServerQModbusTcpClient,分别用于创建 Modbus TCP 服务器和客户端,提供了建立连接、断开连接等基础操作接口。

  • 数据单元类:例如 QModbusDataUnit,用于表示 Modbus 协议中的数据单元,可方便地操作和管理 Modbus 寄存器中的数据。

  • 协议数据单元类:像 QModbusPdu,它表示 Modbus 协议数据单元,用于处理 Modbus 请求和响应的协议层数据。

  • 初始化:在 ModeBusServer 类的构造函数里,初始化 QModbusTcpServer 和定时器,同时建立信号与槽的连接,以处理定时器超时、数据写入、状态改变等事件。

  • 启动与停止

    • startServer 函数会对输入参数进行检查,设定 Modbus 数据单元映射和连接参数,尝试连接设备,若成功就启动数据更新定时器。
    • stopServer 函数则停止定时器,断开服务器连接。
  • 数据更新:借助定时器,定时调用 updateData 函数。此函数从 SystemInfoCollector 获取系统信息,将其写入 Modbus 数据单元,再设置到服务器里。

  • 数据处理

    • printUpdateData 函数用于打印更新后的数据和解析出的系统信息。
    • handleRequest 函数处理客户端请求,记录请求信息。
    • onDataWritten 函数处理数据写入事件。

运行结果

在这里插入图片描述

#ifndef MODEBUSSERVER_H
#define MODEBUSSERVER_H#include <QObject>
#include <QModbusTcpServer>
#include <QModbusDataUnit>
#include <QTimer>
#include <QMap>
#include <memory> // 包含 std::unique_ptr 所在的头文件
#include <iostream>
#include <QDateTime>#include "SystemInfoCollector.h"
//解决中文乱码
#pragma execution_character_set("utf-8")class ModeBusServer : public QObject
{Q_OBJECT
public:explicit ModeBusServer(QObject* parent = nullptr);~ModeBusServer();void startServer(quint16 deviceID, const QString& ipAddress, quint16 port);void stopServer();void printUpdateData(QModbusDataUnit& unit);signals:void statusUpdated(const QString& message);void dataUpdated(const QModbusDataUnit& data);void requestReceived(const QModbusPdu& request, QModbusDataUnit::RegisterType table, int address, int size);private slots:void updateData();void writeSystemInfoToModbus(QModbusDataUnit& unit, SystemInfo& info);void handleRequest(const QModbusPdu& request, QModbusDataUnit::RegisterType table, int address, int size);void sendDataPeriodically();void onDataWritten(QModbusDataUnit::RegisterType table, int address, int size);
private:std::unique_ptr<QModbusTcpServer> m_modbusServer;std::unique_ptr<QTimer> m_dataUpdateTimer;std::unique_ptr<QTimer> m_sendDataTimer;QMap<int, quint16> m_dataCache; // 数据缓存quint16 m_holdingRegistersSize = 100;int m_deviceID;int m_valueIndex;SystemInfoCollector m_infoCollector;
};#endif // MODEBUSSERVER_H#include "modeBusServer.h"
#include <QDebug>
ModeBusServer::ModeBusServer(QObject* parent): QObject(parent),m_modbusServer(std::make_unique<QModbusTcpServer>(this)),m_dataUpdateTimer(std::make_unique<QTimer>(this)),m_sendDataTimer(std::make_unique<QTimer>(this))
{connect(m_dataUpdateTimer.get(), &QTimer::timeout, this, &ModeBusServer::updateData);connect(this, &ModeBusServer::statusUpdated, this, [&](const QString& statusUpdateStr) {qDebug() << statusUpdateStr;});// 修改连接,使用新的槽函数connect(m_modbusServer.get(), &QModbusTcpServer::dataWritten, this, &ModeBusServer::onDataWritten);connect(m_modbusServer.get(), &QModbusTcpServer::stateChanged, this, [this](int state) {if (state == QModbusDevice::ConnectedState) {qDebug() << "Server connected";}else if (state == QModbusDevice::UnconnectedState) {qDebug() << "Server disconnected";}});
}
ModeBusServer::~ModeBusServer()
{stopServer();
}
void ModeBusServer::startServer(quint16 deviceID, const QString& ipAddress, quint16 port)
{if (port == 0 || deviceID == 0 || ipAddress.isEmpty()) {emit statusUpdated("Invalid parameters.");return;}m_deviceID = deviceID;QModbusDataUnitMap reg;reg.insert(QModbusDataUnit::HoldingRegisters, { QModbusDataUnit::HoldingRegisters, 0, m_holdingRegistersSize });m_modbusServer->setMap(reg);m_modbusServer->setConnectionParameter(QModbusDevice::NetworkAddressParameter, ipAddress);m_modbusServer->setConnectionParameter(QModbusDevice::NetworkPortParameter, port);m_modbusServer->setServerAddress(deviceID);if (m_modbusServer->connectDevice()) {emit statusUpdated("Server started on " + ipAddress + ":" + QString::number(port));m_dataUpdateTimer->start(500);}else {emit statusUpdated("Server start failed: " + m_modbusServer->errorString());}
}
void ModeBusServer::stopServer()
{m_dataUpdateTimer->stop();m_modbusServer->disconnectDevice();emit statusUpdated("Server stopped.");
}
void ModeBusServer::printUpdateData(QModbusDataUnit& unit)
{for (int i = 0; i < unit.valueCount(); ++i) {m_dataCache[i] = unit.value(i); // 更新缓存}qDebug() << QString("%1号设备").arg(m_deviceID) << "寄存器数据:" << unit.values();SystemInfo info1 = m_infoCollector.parseSystemInfo(unit.values());qDebug() << "Memory Usage:" << info1.memoryUsage << "%";qDebug() << "CPU Usage:" << info1.cpuUsage << "%";qDebug() << "Boot Time:" << info1.bootTime.toString(Qt::ISODate);qDebug() << "Up Time:" << info1.upTime << "seconds";}
// 更新数据
void ModeBusServer::updateData()
{m_valueIndex = 0;QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, 0, 10);SystemInfo info;// 将系统信息写入 Modbus 数据单元writeSystemInfoToModbus(unit, info);bool  isSetDataSuccess = m_modbusServer->setData(unit);//设置数据if (isSetDataSuccess){m_dataCache.clear(); // 清空缓存printUpdateData(unit);emit dataUpdated(unit);}else{qDebug() << "Failed to update data: " << m_modbusServer->errorString();}}
// 将 SystemInfo 数据写入 QModbusDataUnit
void ModeBusServer::writeSystemInfoToModbus(QModbusDataUnit& unit, SystemInfo& info) {info = m_infoCollector.getSystemInfo();// 写入内存占用率quint16 memoryUsageInt = static_cast<quint16>(info.memoryUsage * 100); // 转换为整数unit.setValue(m_valueIndex++, memoryUsageInt & 0xFFFF);// 写入 CPU 占用率quint16 cpuUsageInt = static_cast<quint16>(info.cpuUsage * 100); // 转换为整数unit.setValue(m_valueIndex++, cpuUsageInt & 0xFFFF);// 写入开机时间(时间戳)qint64 bootTimestamp = info.bootTime.toSecsSinceEpoch();unit.setValue(m_valueIndex++, static_cast<quint16>(bootTimestamp & 0xFFFF));unit.setValue(m_valueIndex++, static_cast<quint16>((bootTimestamp >> 16) & 0xFFFF));// 写入运行时间unit.setValue(m_valueIndex++, static_cast<quint16>(info.upTime & 0xFFFF));unit.setValue(m_valueIndex++, static_cast<quint16>((info.upTime >> 16) & 0xFFFF));}
void ModeBusServer::handleRequest(const QModbusPdu& request, QModbusDataUnit::RegisterType table, int address, int size)
{emit requestReceived(request, table, address, size);qDebug() << "Request received: Function Code" << request.functionCode() << ", Type" << table << ", Address" << address << ", Size" << size;
}
void ModeBusServer::sendDataPeriodically()
{qDebug() << "Periodic Data Send:";for (auto it = m_dataCache.begin(); it != m_dataCache.end(); ++it) {qDebug() << "Address" << it.key() << "@" << it.value();}
}
// 实现新增的槽函数
void ModeBusServer::onDataWritten(QModbusDataUnit::RegisterType table, int address, int size)
{// 处理数据写入事件,可根据需要扩展qDebug() << "写入数据类型" << table << "从地址" << address << "开始。" << "数据长度:" << size;}}
}
// 实现新增的槽函数
void ModeBusServer::onDataWritten(QModbusDataUnit::RegisterType table, int address, int size)
{// 处理数据写入事件,可根据需要扩展qDebug() << "写入数据类型" << table << "从地址" << address << "开始。" << "数据长度:" << size;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/73990.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CherryStudio + 火山引擎DeepSeek R1 告别服务器繁忙

CherryStudio 火山引擎DeepSeek R1 告别服务器繁忙 一、下载CherryStudio并安装 CherryStudio是功能强大的多模型桌面客户端&#xff0c;支持Windows、macOS和Linux系统。集成了多种主流的大语言模型&#xff08;如OpenAI、DeepSeek、Gemini等&#xff09;以及本地模型运行功…

Unity TextMeshPro中显示建筑特殊符号

示例&#xff1a;显示效果如图 实现步骤 1、下载 SJQY 字体库 2、导入字体&#xff1a;将 SJQY 字体文件&#xff08;如 .ttf 或 .otf 文件&#xff09;导入到 Unity 项目的 Assets 文件夹中。 3、创建 TMP 字体资产 方法一 方法二 选择刚导入的字体文件&#xff0c;在…

Windows Docker 报错: has no HTTPS proxy,换源

pull python 3.7报错&#xff1a; 尝试拉取Docker 测试库hello world也失败 尝试使用临时镜像源&#xff0c;可以成功拉取&#xff1a; sudo docker pull docker.m.daocloud.io/hello-world说明确实是网络问题&#xff0c;需要配置镜像源&#xff0c;为了方便&#xff0c;在d…

Git远程拉取和推送配置

Git进行远程代码拉取和推送时候提示配置user.name 和 user.email 背景&#xff1a;换新电脑后使用Git进行代码拉取和推送过程中&#xff0c;提示“Make sure you configure your “user.name” and “user.email” in git.”。这个配置针对git的正常使用仅需要配置一次&#xf…

详解string类+迭代器

迭代器 概念&#xff1a;在 C 中&#xff0c;迭代器是访问容器&#xff08;如数组、列表、向量、字符串等&#xff09;元素的一种方式。迭代器提供了一种统一的接口&#xff0c;使得你可以使用相同的代码来遍历不同类型的容器。迭代器本质上是一个指针或者指针的封装&#xff0…

小红书不绑定手机号会显示ip吗

小红书作为一个生活方式分享平台&#xff0c;拥有庞大的用户群体。在小红书上&#xff0c;用户可以分享自己的生活点滴、购物心得、美食体验等&#xff0c;与其他用户进行互动交流。最近&#xff0c;不少用户对于小红书是否会在不绑定手机号的情况下显示IP属地产生了疑问&#…

Web-Machine-N7靶机实战攻略

1.安装并开启靶机 下载VirtualBox&#xff1a;https://www.virtualbox.org 导入虚拟机 设置为桥接模式 2.获取靶机IP Kali设为桥接模式 3.访问靶机 4.获取敏感目录文件和端口 gobuster dir -u http://172.16.2.68 -w /usr/share/wordlists/dirbuster/directory-list-2.3-me…

Linux|fork命令及其使用的写时拷贝技术

fork复制进程 fork通过以下步骤来复制进程&#xff1a; 分配新的进程控制块&#xff1a;内核为新进程分配一个新的进程控制块&#xff08;PCB&#xff09;&#xff0c;用于存储进程的相关信息&#xff0c;如进程 ID、状态、寄存器值、内存指针等。复制进程地址空间&#xff1…

TCP、UDP协议的应用、ServerSocket和Socket、DatagramSocket和DatagramPacket

DAY13.1 Java核心基础 TCP协议 TCP 协议是面向连接的运算层协议&#xff0c;比较复杂&#xff0c;应用程序在使用TCP协议之前必须建立连接&#xff0c;才能传输数据&#xff0c;数据传输完毕之后需要释放连接 就好比现实生活中的打电话&#xff0c;首先确保电话打通了才能进…

Web爬虫利器FireCrawl:全方位助力AI训练与高效数据抓取

Web爬虫利器FireCrawl&#xff1a;全方位助力AI训练与高效数据抓取 一、FireCrawl 项目简介二、主要功能三、FireCrawl应用场景1. 大语言模型训练2. 检索增强生成&#xff08;RAG&#xff09;&#xff1a;3. 数据驱动的开发项目4. SEO 与内容优化5. 在线服务与工具集成 四、安装…

【C#】CS学习之Modbus通讯

摘要 本文详细描述了如何在在C#的Winform应用程序中使用NModbus库实现Modbus通讯&#xff0c;包括读取保持寄存器、以及相应的UI界面设计和事件处理。 前言 ​应用场景 Modbus 从站广泛应用于工业自动化领域&#xff1a; 1、传感器数据采集&#xff08;如温度、压力等&#xf…

windows环境下NER Python项目环境配置(内含真的从头安的perl配置)

注意 本文是基于完整项目的环境配置&#xff0c;即本身可运行项目你拿来用 其中有一些其他问题&#xff0c;知道的忽略即可 导入pycharm基本包怎么下就不说了&#xff08;这个都问&#xff1f;给你一拳o(&#xff40;ω*)o&#xff09; 看perl跳转第5条 1.predict报错多个设备…

使用DDR4控制器实现多通道数据读写(四)

在创建完DDR4的仿真模型后&#xff0c;我们为了实现异步时钟的读写&#xff0c;板卡中在PL端提供了一组差分时钟&#xff0c;可以用它通过vivado中的Clock Wizard IP核生成多个时钟&#xff0c;在这里生成两个输出时钟&#xff0c;分别作为用户的读写时钟&#xff0c;这样就可以…

企业数字化20项目规划建设方案微服务场景与数据应用(50页PPT)(文末有下载方式)

资料解读&#xff1a;企业数字化 2.0 项目规划建设方案微服务场景与数据应用 详细资料请看本解读文章的最后内容。 在数字化浪潮的席卷下&#xff0c;企业数字化转型已成为提升竞争力、实现可持续发展的关键路径。这份《企业数字化 2.0 项目规划建设方案微服务场景与数据应用》…

蓝桥杯之AT24C02的页写页读

一、原理&#xff1a; 1、页写&#xff1a;一次性向AT24C02里的多个数据存储单元地址写入多个数据 &#xff08;1&#xff09;在AT24C02的页写模式下&#xff0c;每次写入数据后&#xff0c;存储单元地址会自动加1。 &#xff08;2&#xff09;一页有8个数据存储单元&#xff…

【C++网络编程】第2篇:简单的TCP服务器与客户端

一、TCP通信流程回顾 1. 服务器端流程 1. 创建Socket → socket() 2. 绑定地址和端口 → bind() 3. 开始监听 → listen() 4. 接受客户端连接 → accept() 5. 接收/发送数据 → recv()/send() 6. 关闭连接 → closesocket()2. 客户端流程 1. 创建Socket → socket() 2. 连接…

Spring IoC DI入门

一、Spring&#xff0c;Spring Boot和Spring MVC的联系及区别 Spring是另外两个框架的基础&#xff0c;是Java生态系统的核心框架&#xff0c;而SpringMVC是Spring 的子模块&#xff0c;专注于 Web 层开发&#xff0c;基于 MVC 设计模式&#xff08;模型-视图-控制器&#xff…

【uniapp】记录tabBar不显示踩坑记录

由于很久没有使用uniapp了&#xff0c;官方文档看着又杂乱&#xff0c;底部tab导航栏一直没显示&#xff0c;苦思许久&#xff0c;没有发现原因&#xff0c;最后网上搜到帖子&#xff0c;list里的第一个数据&#xff0c;pages 的第一个 path 必须与 tabBar 的第一个 pagePath 相…

Zabbix安装(保姆级教程)

Zabbix 是一款开源的企业级监控解决方案&#xff0c;能够监控网络的多个参数以及服务器、虚拟机、应用程序、服务、数据库、网站和云的健康状况和完整性。它提供了灵活的通知机制&#xff0c;允许用户为几乎任何事件配置基于电子邮件的告警&#xff0c;从而能够快速响应服务器问…

穿透递归的本质:从无限梦境到可控魔法的蜕变之路

穿透递归的本质&#xff1a;从无限梦境到可控魔法的蜕变之路&#xff08;C实现&#xff09; 一、递归&#xff1a;程序员的盗梦空间 在计算机科学的宇宙中&#xff0c;递归是最接近魔法本质的编程范式。它像一面镜子中的镜子&#xff0c;引导我们通过自我相似性破解复杂问题。…