|
|
|
#include "modbusmaster.h"
|
|
|
|
#include <QModbusTcpClient>
|
|
|
|
#include <QModbusRtuSerialMaster>
|
|
|
|
|
|
|
|
#include "serialportexception.h"
|
|
|
|
|
|
|
|
modBusMaster::modBusMaster(QObject *parent) : QObject(parent)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
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 _serverId)
|
|
|
|
{
|
|
|
|
serialPort=_serialPort;
|
|
|
|
serverId=_serverId;
|
|
|
|
if (!modbusDevice)
|
|
|
|
return;
|
|
|
|
if (modbusDevice->state() != QModbusDevice::ConnectedState)
|
|
|
|
{
|
|
|
|
modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter,
|
|
|
|
serialPort);
|
|
|
|
#if QT_CONFIG(modbus_serialport)
|
|
|
|
modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter,
|
|
|
|
modbusSettings.parity);
|
|
|
|
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,
|
|
|
|
modbusSettings.baud);
|
|
|
|
modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter,
|
|
|
|
modbusSettings.dataBits);
|
|
|
|
modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter,
|
|
|
|
modbusSettings.stopBits);
|
|
|
|
#endif
|
|
|
|
modbusDevice->setTimeout(modbusSettings.responseTime);
|
|
|
|
modbusDevice->setNumberOfRetries(modbusSettings.numberOfRetries);
|
|
|
|
}
|
|
|
|
if (!modbusDevice->connectDevice())
|
|
|
|
{
|
|
|
|
throw serialPortException(modbusDevice->errorString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void modBusMaster::close()
|
|
|
|
{
|
|
|
|
if (modbusDevice)
|
|
|
|
modbusDevice->disconnectDevice();
|
|
|
|
delete modbusDevice;
|
|
|
|
}
|
|
|
|
|
|
|
|
void modBusMaster::stop()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void modBusMaster::readRequest(QModbusDataUnit::RegisterType registerType, int startAddress, quint16 readSize)
|
|
|
|
{
|
|
|
|
|
|
|
|
auto table =registerType;
|
|
|
|
Q_ASSERT(startAddress >= 0 && startAddress < 10);
|
|
|
|
reply=modbusDevice->sendReadRequest(QModbusDataUnit(table, startAddress, readSize), serverId) ;
|
|
|
|
if (reply)
|
|
|
|
{
|
|
|
|
if (!reply->isFinished())
|
|
|
|
connect(reply, &QModbusReply::finished, this, &modBusMaster::readReady);
|
|
|
|
else
|
|
|
|
delete reply; // broadcast replies return immediately
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw serialPortException(modbusDevice->errorString());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void modBusMaster::writeRequest(QModbusDataUnit::RegisterType registerType, int startAddress, quint16 readSize)
|
|
|
|
{
|
|
|
|
auto table =registerType;
|
|
|
|
Q_ASSERT(startAddress >= 0 && startAddress < 10);
|
|
|
|
QModbusDataUnit writeUnit = QModbusDataUnit(table, startAddress, readSize);
|
|
|
|
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, serverId)) {
|
|
|
|
if (!reply->isFinished()) {
|
|
|
|
connect(reply, &QModbusReply::finished, this, [this, reply]() {
|
|
|
|
if (reply->error() == QModbusDevice::ProtocolError) {
|
|
|
|
throw serialPortException("Write response error: %1 (Mobus exception: 0x%2)");
|
|
|
|
} else if (reply->error() != QModbusDevice::NoError) {
|
|
|
|
throw serialPortException("Write response error: %1 (code: 0x%2)");
|
|
|
|
|
|
|
|
}
|
|
|
|
reply->deleteLater();
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
// broadcast replies return immediately
|
|
|
|
reply->deleteLater();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
throw serialPortException(tr("Write error: ") + modbusDevice->errorString());
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
void modBusMaster::readReady()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|