|
- #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;
-
- // 获取所有已注册的寄存器ID
- QStringList regIds = registerManager->getAllRegisteredRegisters();
- QMap<QString, QSet<int>> 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<int> &addresses)
- {
- if (addresses.isEmpty()) return;
-
- QList<int> 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<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();
- });
- }
- }
|