#include "ModbusMaster.h" #include #include #include #include "SerialportException.h" enum { NumColumn = 0, CoilsColumn = 1, HoldingColumn = 2, ColumnCount = 3, RowCount = 10 }; modBusMaster::modBusMaster(QObject *parent) : QObject(parent) { m_coils.resize(2); m_holdingRegisters.resize(2); } void modBusMaster::init() { close(); modbusDevice = nullptr; modbusDevice = new QModbusRtuSerialMaster(this); connect(modbusDevice, &QModbusClient::errorOccurred, [this](QModbusDevice::Error) { throw serialPortException(modbusDevice->errorString()); }); if (!modbusDevice) throw serialPortException("Could not create Modbus master."); } void modBusMaster::open(QString serialPort , int slaveAddress) { _serialPort = serialPort; _slaveAddress = slaveAddress; if (!modbusDevice) return; if (modbusDevice->state() != QModbusDevice::ConnectedState) { modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter, serialPort); modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, _modbusSettings.modbusSetting.parity); modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, _modbusSettings.modbusSetting.baud); modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, _modbusSettings.modbusSetting.dataBits); modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, _modbusSettings.modbusSetting.stopBits); modbusDevice->setTimeout(_modbusSettings.modbusSetting.responseTime); modbusDevice->setNumberOfRetries(_modbusSettings.modbusSetting.numberOfRetries); emit modbusConnectionState(true); } if (!modbusDevice->connectDevice()) { throw serialPortException(modbusDevice->errorString()); } } void modBusMaster::close() { if (modbusDevice) modbusDevice->disconnectDevice(); delete modbusDevice; } void modBusMaster::stop() { if (modbusDevice) modbusDevice->disconnectDevice(); emit modbusConnectionState(false); } void modBusMaster::setSingleCoil(int startAddress,bool coilFlag) { if (!modbusDevice) return; m_coils.setBit(0,coilFlag); writeRequest(QModbusDataUnit::RegisterType::Coils, startAddress, 1); } void modBusMaster::setMultipleCoil(int startAddress, quint16 writeSize, QBitArray coilFlags) { if (!modbusDevice) return; m_coils = coilFlags; writeRequest(QModbusDataUnit::RegisterType::Coils, startAddress, writeSize); } void modBusMaster::setSingleRegister(int startAddress, quint16 registerValue) { if (!modbusDevice) return; m_holdingRegisters[0]=registerValue; writeRequest(QModbusDataUnit::RegisterType::HoldingRegisters, startAddress, 1); } void modBusMaster::setMultipleRegister(int startAddress, quint16 writeSize , QVector registerValues) { if (!modbusDevice) return; m_holdingRegisters = registerValues; writeRequest(QModbusDataUnit::RegisterType::HoldingRegisters, startAddress, writeSize); } void modBusMaster::getCoil(int startAddress, quint16 readSize) { if (!modbusDevice) return; readRequest(QModbusDataUnit::RegisterType::Coils, startAddress, readSize); } void modBusMaster::getInputCoil(int startAddress, quint16 readSize) { if (!modbusDevice) return; readRequest(QModbusDataUnit::RegisterType::DiscreteInputs, startAddress, readSize); } void modBusMaster::getInputRegister(int startAddress, quint16 readSize) { if (!modbusDevice) return; readRequest(QModbusDataUnit::RegisterType::InputRegisters, startAddress, readSize); } void modBusMaster::getHoldingRegister(int startAddress, quint16 readSize) { if (!modbusDevice) return; readRequest(QModbusDataUnit::RegisterType::HoldingRegisters, startAddress, readSize); } auto modBusMaster::readRequest(QModbusDataUnit::RegisterType registerType, int startAddress, quint16 readSize) -> std::size_t { auto table =registerType; reply=modbusDevice->sendReadRequest(QModbusDataUnit(table, startAddress, readSize), _slaveAddress) ; if (reply) { while(!reply->isFinished()) { } if(!checkForError(reply)) { if(table == (QModbusDataUnit::Coils | QModbusDataUnit::DiscreteInputs)) { return retriveGetCoilValues(reply); } else { } } } else { throw serialPortException(modbusDevice->errorString()); } reply->deleteLater(); } void modBusMaster::writeRequest(QModbusDataUnit::RegisterType registerType, int startAddress, quint16 writeSize) { qDebug() << " ---- setSingleCoil coilFlag writeRequest "; auto table =registerType; Q_ASSERT(startAddress >= 0 && startAddress < 10); QModbusDataUnit writeUnit = QModbusDataUnit(table, startAddress, writeSize); qDebug() << " ---- writeUnit.valueCount()" << writeUnit.valueCount(); for (int i = 0; i < writeUnit.valueCount(); i++) { if (table == QModbusDataUnit::Coils) writeUnit.setValue(i, m_coils[i + writeUnit.startAddress()]); else writeUnit.setValue(i, m_holdingRegisters[i + writeUnit.startAddress()]); } if (auto *reply = modbusDevice->sendWriteRequest(writeUnit, _slaveAddress)) { if (!reply->isFinished()) { connect(reply, &QModbusReply::finished, this, [reply]() { if (reply->error() == QModbusDevice::ProtocolError) { throw serialPortException(tr("Write response error: %1 (Mobus exception: 0x%2)") .arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16)); } else if (reply->error() != QModbusDevice::NoError) { throw serialPortException(tr("Write response error: %1 (code: 0x%2)"). arg(reply->errorString()).arg(reply->error(), -1, 16)); } reply->deleteLater(); }); } else { // broadcast replies return immediately reply->deleteLater(); } } else { throw serialPortException(tr("Write error: ") + modbusDevice->errorString()); } } bool modBusMaster::checkForError(QModbusReply *_reply) { if (_reply->error() == QModbusDevice::NoError) { return false; } else if (_reply->error() == QModbusDevice::ProtocolError) { throw serialPortException(tr("Read response error: %1 (Mobus exception: 0x%2)"). arg(reply->errorString()). arg(reply->rawResult().exceptionCode(), -1, 16)); } else { throw serialPortException(tr("Read response error: %1 (code: 0x%2)"). arg(reply->errorString()). arg(reply->error(), -1, 16)); } } QBitArray modBusMaster::retriveGetCoilValues(QModbusReply *_reply) { QBitArray coils; coils.resize(2); const QModbusDataUnit unit = _reply->result(); auto num = unit.valueCount(); coils.resize(static_cast(num)); for (uint i = 0; i < unit.valueCount(); i++) { coils.setBit((unit.value(i))); } return coils ; } QVector modBusMaster::retriveGetRegisterValues(QModbusReply *_reply) { QVector registerValues; registerValues.resize(2); const QModbusDataUnit unit = _reply->result(); auto num = unit.valueCount(); registerValues.resize(static_cast(num)); for (uint i = 0; i < unit.valueCount(); i++) { registerValues[i]=unit.value(i); } return registerValues ; }