|
- #include "modbusmanager.h"
- #include <QModbusDataUnit>
- #include <QDebug>
-
- ModbusManager::ModbusManager(RegisterManager* regManager, QObject *parent)
- : QObject(parent), registerManager(regManager)
- {
- modbusDevice = new QModbusRtuSerialMaster(this);
- pollTimer = new QTimer(this);
-
- connect(modbusDevice, &QModbusClient::errorOccurred, this,
- [this](QModbusDevice::Error) {
- emit errorOccurred(modbusDevice->errorString());
- });
-
- connect(pollTimer, &QTimer::timeout, this, &ModbusManager::readRegisters);
- }
-
- ModbusManager::~ModbusManager()
- {
- stopSimulation();
- disconnectDevice();
- }
-
- bool ModbusManager::connectToDevice(const QString& portName,
- QSerialPort::BaudRate baudRate,
- QSerialPort::DataBits dataBits,
- QSerialPort::Parity parity,
- QSerialPort::StopBits stopBits)
- {
- if (modbusDevice->state() != QModbusDevice::UnconnectedState) {
- disconnectDevice();
- }
-
- modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter, portName);
- modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, baudRate);
- modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, dataBits);
- modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, parity);
- modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, stopBits);
-
- if (!modbusDevice->connectDevice()) {
- emit errorOccurred(tr("连接失败: %1").arg(modbusDevice->errorString()));
- return false;
- }
-
- emit connectionStatusChanged(true);
- return true;
- }
-
- void ModbusManager::disconnectDevice()
- {
- if (modbusDevice->state() != QModbusDevice::UnconnectedState) {
- modbusDevice->disconnectDevice();
- emit connectionStatusChanged(false);
- }
- }
-
- void ModbusManager::startSimulation(int interval)
- {
- pollTimer->start(interval);
- }
-
- void ModbusManager::stopSimulation()
- {
- pollTimer->stop();
- }
-
- void ModbusManager::readRegisters()
- {
- if (!modbusDevice || modbusDevice->state() != QModbusDevice::ConnectedState)
- return;
-
- // 读取所有D寄存器 (保持寄存器)
- readRegisterGroup(QModbusDataUnit::HoldingRegisters, 0, 4000);
-
- // 读取所有M寄存器 (线圈)
- readRegisterGroup(QModbusDataUnit::Coils, 0, 4000);
- }
-
- void ModbusManager::readRegisterGroup(QModbusDataUnit::RegisterType type, int startAddr, int count)
- {
- const int MAX_REG_PER_REQUEST = 125; // Modbus RTU限制
-
- for (int addr = startAddr; addr < count; addr += MAX_REG_PER_REQUEST) {
- int readCount = qMin(MAX_REG_PER_REQUEST, count - addr);
-
- QModbusDataUnit unit(type, addr, readCount);
-
- if (auto *reply = modbusDevice->sendReadRequest(unit, slaveAddress)) {
- QString regType = (type == QModbusDataUnit::HoldingRegisters) ? "D" : "M";
- pendingRequests[reply] = regType;
- connect(reply, &QModbusReply::finished, this, &ModbusManager::processModbusReply);
- }
- }
- }
-
- void ModbusManager::processModbusReply()
- {
- auto *reply = qobject_cast<QModbusReply*>(sender());
- if (!reply) return;
-
- if (reply->error() == QModbusDevice::NoError) {
- const QModbusDataUnit unit = reply->result();
- QString regType = pendingRequests.value(reply);
-
- int startAddr = unit.startAddress();
-
- for (uint i = 0; i < unit.valueCount(); i++) {
- int regAddr = startAddr + i;
- quint16 value = unit.value(i);
-
- QString regId = QString("%1%2").arg(regType).arg(regAddr);
-
- // 更新图元状态
- registerManager->updateRegisterValue(regId, value);
- }
- } else {
- emit errorOccurred(tr("Modbus错误: %1").arg(reply->errorString()));
- }
-
- pendingRequests.remove(reply);
- reply->deleteLater();
- }
-
- void ModbusManager::writeRegister(const QString& registerId, quint16 value)
- {
- if (registerId.isEmpty()) return;
-
- QModbusDataUnit::RegisterType regType = registerId.startsWith("D")
- ? QModbusDataUnit::HoldingRegisters
- : QModbusDataUnit::Coils;
-
- int regAddr = registerId.mid(1).toInt();
-
- QModbusDataUnit writeUnit(regType, regAddr, 1);
- writeUnit.setValue(0, value);
-
- if (auto *reply = modbusDevice->sendWriteRequest(writeUnit, slaveAddress)) {
- connect(reply, &QModbusReply::finished, this, [this, reply]() {
- if (reply->error() != QModbusDevice::NoError) {
- emit errorOccurred(tr("写入失败: %1").arg(reply->errorString()));
- }
- reply->deleteLater();
- });
- }
- }
|