#include "modbusmanager.h" #include #include 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::readRegisters() { if (!modbusDevice || modbusDevice->state() != QModbusDevice::ConnectedState) return; // 获取所有已注册的寄存器ID QStringList regIds = registerManager->getAllRegisteredRegisters(); QMap> regMap; // 按类型分组存储地址 // 分组寄存器地址 for (const QString &id : regIds) { if (id.startsWith("D") || id.startsWith("M")) { bool ok; int addr = id.mid(1).toInt(&ok); if (ok && addr >= 0 && addr <= 4000) { regMap[id.left(1)].insert(addr); } } } // 读取D寄存器 (保持寄存器) if (regMap.contains("D")) { readRegisterGroup(QModbusDataUnit::HoldingRegisters, regMap["D"].values()); } // 读取M寄存器 (线圈) if (regMap.contains("M")) { readRegisterGroup(QModbusDataUnit::Coils, regMap["M"].values()); } } void ModbusManager::readRegisterGroup(QModbusDataUnit::RegisterType type, const QList &addresses) { if (addresses.isEmpty()) return; QList sortedAddrs = addresses; std::sort(sortedAddrs.begin(), sortedAddrs.end()); // 合并连续地址范围 int start = sortedAddrs.first(); int end = start; for (int i = 1; i < sortedAddrs.size(); i++) { if (sortedAddrs[i] == end + 1) { end = sortedAddrs[i]; } else { readAddressRange(type, start, end - start + 1); start = sortedAddrs[i]; end = start; } } readAddressRange(type, start, end - start + 1); } void ModbusManager::readAddressRange(QModbusDataUnit::RegisterType type, int startAddr, int count) { const int MAX_REG_PER_REQUEST = 120; for (int offset = 0; offset < count; offset += MAX_REG_PER_REQUEST) { int readCount = qMin(MAX_REG_PER_REQUEST, count - offset); QModbusDataUnit unit(type, startAddr + offset, 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(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(); }); } }