Use new modbus RTU hardware resource for the modbus commander plugin
Use new modbus RTU hardware resource for the modbus commander plugin Fix action abort for RTU actions and fix connected state fro child RTU things Fix modbus rtu client and make it work with the basic resource component Remove modbusrtu master from project file Remove custom modbus rtu master include
This commit is contained in:
parent
f0f9d7c245
commit
352413563f
@ -54,7 +54,6 @@ ModbusRTUMaster::ModbusRTUMaster(QString serialPort, uint baudrate, QSerialPort:
|
||||
connect(m_reconnectTimer, &QTimer::timeout, this, &ModbusRTUMaster::onReconnectTimer);
|
||||
}
|
||||
|
||||
|
||||
ModbusRTUMaster::~ModbusRTUMaster()
|
||||
{
|
||||
if (!m_modbusRtuSerialMaster) {
|
||||
|
||||
@ -31,6 +31,10 @@
|
||||
#include "integrationpluginmodbuscommander.h"
|
||||
#include "plugininfo.h"
|
||||
|
||||
#include "hardwaremanager.h"
|
||||
#include "hardware/modbus/modbusrtumaster.h"
|
||||
#include "hardware/modbus/modbusrtuhardwareresource.h"
|
||||
|
||||
#include <QSerialPort>
|
||||
|
||||
IntegrationPluginModbusCommander::IntegrationPluginModbusCommander()
|
||||
@ -39,8 +43,6 @@ IntegrationPluginModbusCommander::IntegrationPluginModbusCommander()
|
||||
|
||||
void IntegrationPluginModbusCommander::init()
|
||||
{
|
||||
connect(this, &IntegrationPluginModbusCommander::configValueChanged, this, &IntegrationPluginModbusCommander::onPluginConfigurationChanged);
|
||||
|
||||
m_slaveAddressParamTypeId.insert(coilThingClassId, coilThingSlaveAddressParamTypeId);
|
||||
m_slaveAddressParamTypeId.insert(inputRegisterThingClassId, inputRegisterThingSlaveAddressParamTypeId);
|
||||
m_slaveAddressParamTypeId.insert(discreteInputThingClassId, discreteInputThingSlaveAddressParamTypeId);
|
||||
@ -62,46 +64,49 @@ void IntegrationPluginModbusCommander::init()
|
||||
m_valueStateTypeId.insert(inputRegisterThingClassId, inputRegisterValueStateTypeId);
|
||||
m_valueStateTypeId.insert(discreteInputThingClassId, discreteInputValueStateTypeId);
|
||||
m_valueStateTypeId.insert(holdingRegisterThingClassId, holdingRegisterValueStateTypeId);
|
||||
|
||||
// Plugin configuration
|
||||
connect(this, &IntegrationPluginModbusCommander::configValueChanged, this, &IntegrationPluginModbusCommander::onPluginConfigurationChanged);
|
||||
|
||||
// Modbus RTU hardware resource
|
||||
connect(hardwareManager()->modbusRtuResource(), &ModbusRtuHardwareResource::modbusRtuMasterRemoved, this, [=](const QUuid &modbusUuid){
|
||||
qCDebug(dcModbusCommander()) << "Modbus RTU master has been removed" << modbusUuid.toString();
|
||||
|
||||
// Check if there is any device using this resource
|
||||
foreach (Thing *thing, m_modbusRtuMasters.keys()) {
|
||||
if (m_modbusRtuMasters.value(thing)->modbusUuid() == modbusUuid) {
|
||||
qCWarning(dcModbusCommander()) << "Hardware resource removed for" << thing << ". The thing will not be functional any more until a new resource has been configured for it.";
|
||||
m_modbusRtuMasters.remove(thing);
|
||||
thing->setStateValue(m_connectedStateTypeId[thing->thingClassId()], false);
|
||||
|
||||
// Set all child things disconnected
|
||||
foreach (Thing *childThing, myThings()) {
|
||||
if (childThing->parentId() == thing->id()) {
|
||||
thing->setStateValue(m_connectedStateTypeId[childThing->thingClassId()], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void IntegrationPluginModbusCommander::discoverThings(ThingDiscoveryInfo *info)
|
||||
{
|
||||
ThingClassId thingClassId = info->thingClassId();
|
||||
if (thingClassId == modbusRTUClientThingClassId) {
|
||||
Q_FOREACH(QSerialPortInfo port, QSerialPortInfo::availablePorts()) {
|
||||
qCDebug(dcModbusCommander()) << "Found serial port:" << port.systemLocation() << "manufacturer" << port.manufacturer() << "description" << port.description() << "serial number" << port.serialNumber();
|
||||
if (port.isBusy()) {
|
||||
qCDebug(dcModbusCommander()) << "Serial port ist busy, skipping.";
|
||||
continue;
|
||||
foreach (ModbusRtuMaster *modbusMaster, hardwareManager()->modbusRtuResource()->modbusRtuMasters()) {
|
||||
qCDebug(dcModbusCommander()) << "Found RTU master resource" << modbusMaster;
|
||||
if (modbusMaster->connected()) {
|
||||
ParamList parameters;
|
||||
ThingDescriptor thingDescriptor(thingClassId, "Modbus RTU master", modbusMaster->serialPort());
|
||||
parameters.append(Param(modbusRTUClientThingModbusMasterUuidParamTypeId, modbusMaster->modbusUuid()));
|
||||
thingDescriptor.setParams(parameters);
|
||||
info->addThingDescriptor(thingDescriptor);
|
||||
} else {
|
||||
qCWarning(dcModbusCommander()) << "Found configured resource" << modbusMaster << "but it is not connected. Skipping.";
|
||||
}
|
||||
QString manufacturer = port.manufacturer();
|
||||
if (manufacturer.isEmpty()) {
|
||||
manufacturer = "unknown";
|
||||
}
|
||||
QString description = port.description()+" Manufacturer: "+port.manufacturer();
|
||||
ThingDescriptor thingDescriptor(thingClassId, "Modbus RTU interface", description);
|
||||
ParamList parameters;
|
||||
QString serialPort = port.systemLocation();
|
||||
QString serialnumber = port.serialNumber();
|
||||
if (serialnumber.isEmpty()) {
|
||||
serialnumber = port.manufacturer()+QString::number(port.productIdentifier(), 16);
|
||||
|
||||
}
|
||||
qCDebug(dcModbusCommander()) << " - Serial number" << serialnumber;
|
||||
Q_FOREACH (Thing *exisingThing, myThings().filterByParam(modbusRTUClientThingClassId)) {
|
||||
thingDescriptor.setThingId(exisingThing->id());
|
||||
// Rediscovery is broken because of a missing unique device id
|
||||
// This is a workaround and doesnt work if multiple uart converters are attached.
|
||||
// ThingDiscoveryInfo may be extended to distinquish between discovery and rediscovery
|
||||
break;
|
||||
}
|
||||
parameters.append(Param(modbusRTUClientThingSerialPortParamTypeId, serialPort));
|
||||
parameters.append(Param(modbusRTUClientThingSerialnumberParamTypeId, serialnumber));
|
||||
thingDescriptor.setParams(parameters);
|
||||
info->addThingDescriptor(thingDescriptor);
|
||||
}
|
||||
|
||||
//FIXME missing info if it is a rediscovery
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
} else if (thingClassId == discreteInputThingClassId) {
|
||||
@ -112,7 +117,7 @@ void IntegrationPluginModbusCommander::discoverThings(ThingDiscoveryInfo *info)
|
||||
info->addThingDescriptor(descriptor);
|
||||
}
|
||||
if (clientThing->thingClassId() == modbusRTUClientThingClassId) {
|
||||
ThingDescriptor descriptor(thingClassId, "Discrete input", clientThing->name() + " " + clientThing->paramValue(modbusRTUClientThingSerialPortParamTypeId).toString());
|
||||
ThingDescriptor descriptor(thingClassId, "Discrete input", clientThing->name() + " " + clientThing->paramValue(modbusRTUClientThingModbusMasterUuidParamTypeId).toString());
|
||||
descriptor.setParentId(clientThing->id());
|
||||
info->addThingDescriptor(descriptor);
|
||||
}
|
||||
@ -128,7 +133,7 @@ void IntegrationPluginModbusCommander::discoverThings(ThingDiscoveryInfo *info)
|
||||
info->addThingDescriptor(descriptor);
|
||||
}
|
||||
if (clientThing->thingClassId() == modbusRTUClientThingClassId) {
|
||||
ThingDescriptor descriptor(thingClassId, "Coil", clientThing->name() + " " + clientThing->paramValue(modbusRTUClientThingSerialPortParamTypeId).toString());
|
||||
ThingDescriptor descriptor(thingClassId, "Coil", clientThing->name() + " " + clientThing->paramValue(modbusRTUClientThingModbusMasterUuidParamTypeId).toString());
|
||||
descriptor.setParentId(clientThing->id());
|
||||
info->addThingDescriptor(descriptor);
|
||||
}
|
||||
@ -143,7 +148,7 @@ void IntegrationPluginModbusCommander::discoverThings(ThingDiscoveryInfo *info)
|
||||
info->addThingDescriptor(descriptor);
|
||||
}
|
||||
if (clientThing->thingClassId() == modbusRTUClientThingClassId) {
|
||||
ThingDescriptor descriptor(thingClassId, "Holding register", clientThing->name() + " " + clientThing->paramValue(modbusRTUClientThingSerialPortParamTypeId).toString());
|
||||
ThingDescriptor descriptor(thingClassId, "Holding register", clientThing->name() + " " + clientThing->paramValue(modbusRTUClientThingModbusMasterUuidParamTypeId).toString());
|
||||
descriptor.setParentId(clientThing->id());
|
||||
info->addThingDescriptor(descriptor);
|
||||
}
|
||||
@ -159,7 +164,7 @@ void IntegrationPluginModbusCommander::discoverThings(ThingDiscoveryInfo *info)
|
||||
info->addThingDescriptor(descriptor);
|
||||
}
|
||||
if (clientThing->thingClassId() == modbusRTUClientThingClassId) {
|
||||
ThingDescriptor descriptor(thingClassId, "Input register", clientThing->name() + " " + clientThing->paramValue(modbusRTUClientThingSerialPortParamTypeId).toString());
|
||||
ThingDescriptor descriptor(thingClassId, "Input register", clientThing->name() + " " + clientThing->paramValue(modbusRTUClientThingModbusMasterUuidParamTypeId).toString());
|
||||
descriptor.setParentId(clientThing->id());
|
||||
info->addThingDescriptor(descriptor);
|
||||
}
|
||||
@ -215,74 +220,51 @@ void IntegrationPluginModbusCommander::setupThing(ThingSetupInfo *info)
|
||||
}
|
||||
});
|
||||
connect(thing, &Thing::settingChanged, thing, [thing, modbusTCPMaster] (const ParamTypeId ¶mTypeId, const QVariant &value) {
|
||||
if (paramTypeId == modbusTCPClientSettingsNumberOfRetriesParamTypeId) {
|
||||
qCDebug(dcModbusCommander()) << "Set number of retries" << thing->name() << value.toUInt();
|
||||
modbusTCPMaster->setNumberOfRetries(value.toUInt());
|
||||
} else if (paramTypeId == modbusTCPClientSettingsTimeoutParamTypeId) {
|
||||
qCDebug(dcModbusCommander()) << "Set timeout " << thing->name() << value.toUInt();
|
||||
modbusTCPMaster->setTimeout(value.toUInt());
|
||||
}
|
||||
});
|
||||
if (paramTypeId == modbusTCPClientSettingsNumberOfRetriesParamTypeId) {
|
||||
qCDebug(dcModbusCommander()) << "Set number of retries" << thing->name() << value.toUInt();
|
||||
modbusTCPMaster->setNumberOfRetries(value.toUInt());
|
||||
} else if (paramTypeId == modbusTCPClientSettingsTimeoutParamTypeId) {
|
||||
qCDebug(dcModbusCommander()) << "Set timeout " << thing->name() << value.toUInt();
|
||||
modbusTCPMaster->setTimeout(value.toUInt());
|
||||
}
|
||||
});
|
||||
modbusTCPMaster->connectDevice();
|
||||
|
||||
} else if (thing->thingClassId() == modbusRTUClientThingClassId) {
|
||||
QUuid modbusUuid = thing->paramValue(modbusRTUClientThingModbusMasterUuidParamTypeId).toUuid();
|
||||
|
||||
QString serialPort = thing->paramValue(modbusRTUClientThingSerialPortParamTypeId).toString();
|
||||
uint baudrate = thing->paramValue(modbusRTUClientThingBaudRateParamTypeId).toUInt();
|
||||
uint stopBits = thing->paramValue(modbusRTUClientThingStopBitsParamTypeId).toUInt();
|
||||
uint dataBits = thing->paramValue(modbusRTUClientThingDataBitsParamTypeId).toUInt();
|
||||
uint numberOfRetries = thing->setting(modbusRTUClientSettingsNumberOfRetriesParamTypeId).toUInt();
|
||||
uint timeout = thing->setting(modbusRTUClientSettingsTimeoutParamTypeId).toUInt();
|
||||
QSerialPort::Parity parity = QSerialPort::Parity::NoParity;
|
||||
QString parityString = thing->paramValue(modbusRTUClientThingParityParamTypeId).toString();
|
||||
if (parityString.contains("No")) {
|
||||
parity = QSerialPort::Parity::NoParity;
|
||||
} else if (parityString.contains("Even")) {
|
||||
parity = QSerialPort::Parity::EvenParity;
|
||||
} else if (parityString.contains("Odd")) {
|
||||
parity = QSerialPort::Parity::OddParity;
|
||||
}
|
||||
qCDebug(dcModbusCommander()) << "Setting up RTU client" << thing->name();
|
||||
qCDebug(dcModbusCommander()) << " baud:" << baudrate;
|
||||
qCDebug(dcModbusCommander()) << " stop bits:" << stopBits;
|
||||
qCDebug(dcModbusCommander()) << " data bits:" << dataBits;
|
||||
qCDebug(dcModbusCommander()) << " parity:" << parityString;
|
||||
qCDebug(dcModbusCommander()) << " number of retries:" << numberOfRetries;
|
||||
qCDebug(dcModbusCommander()) << " timeout:" << timeout;
|
||||
|
||||
|
||||
if (m_modbusRTUMasters.contains(thing)) {
|
||||
// In case of a rediscovery
|
||||
m_modbusRTUMasters.take(thing)->deleteLater();
|
||||
if (!hardwareManager()->modbusRtuResource()->available()) {
|
||||
qCWarning(dcModbusCommander()) << "Cannot set up thing" << thing << ". The modbus RTU hardware resource is not available.";
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable, QT_TR_NOOP("The modbus RTU hardware resource is not available"));
|
||||
return;
|
||||
}
|
||||
|
||||
ModbusRTUMaster *modbusRTUMaster = new ModbusRTUMaster(serialPort, baudrate, parity, dataBits, stopBits, this);
|
||||
modbusRTUMaster->setTimeout(timeout);
|
||||
modbusRTUMaster->setNumberOfRetries(numberOfRetries);
|
||||
connect(modbusRTUMaster, &ModbusRTUMaster::connectionStateChanged, this, &IntegrationPluginModbusCommander::onConnectionStateChanged);
|
||||
connect(modbusRTUMaster, &ModbusRTUMaster::requestExecuted, this, &IntegrationPluginModbusCommander::onRequestExecuted);
|
||||
connect(modbusRTUMaster, &ModbusRTUMaster::requestError, this, &IntegrationPluginModbusCommander::onRequestError);
|
||||
connect(modbusRTUMaster, &ModbusRTUMaster::receivedCoil, this, &IntegrationPluginModbusCommander::onReceivedCoil);
|
||||
connect(modbusRTUMaster, &ModbusRTUMaster::receivedDiscreteInput, this, &IntegrationPluginModbusCommander::onReceivedDiscreteInput);
|
||||
connect(modbusRTUMaster, &ModbusRTUMaster::receivedHoldingRegister, this, &IntegrationPluginModbusCommander::onReceivedHoldingRegister);
|
||||
connect(modbusRTUMaster, &ModbusRTUMaster::receivedInputRegister, this, &IntegrationPluginModbusCommander::onReceivedInputRegister);
|
||||
connect(modbusRTUMaster, &ModbusRTUMaster::connectionStateChanged, info, [info, modbusRTUMaster, this] (bool connected) {
|
||||
if (connected) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
m_modbusRTUMasters.insert(info->thing(), modbusRTUMaster);
|
||||
if (!hardwareManager()->modbusRtuResource()->hasModbusRtuMaster(modbusUuid)) {
|
||||
qCWarning(dcModbusCommander()) << "Cannot set up thing" << thing << ". The modbus RTU hardware resource" << modbusUuid.toString() << "does not exist any more. Reconfiguration required.";
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable, QT_TR_NOOP("Configured modbus RTU master could not be found. Please reconfigure the client and assign a new valid modbus RTU master."));
|
||||
return;
|
||||
}
|
||||
|
||||
ModbusRtuMaster *modbusMaster = hardwareManager()->modbusRtuResource()->getModbusRtuMaster(modbusUuid);
|
||||
qCDebug(dcModbusCommander()) << "Setting up" << thing << "using" << modbusMaster;
|
||||
m_modbusRtuMasters.insert(thing, modbusMaster);
|
||||
|
||||
connect(modbusMaster, &ModbusRtuMaster::connectedChanged, thing, [=](bool connected){
|
||||
qCDebug(dcModbusCommander()) << "Modbus RTU client" << modbusMaster << "connected changed" << connected;
|
||||
thing->setStateValue(modbusRTUClientConnectedStateTypeId, connected);
|
||||
|
||||
// Note: only set the connected state for the child things if disconnected.
|
||||
// The child things will be evaluated upon read requests if the slave is connected or not.
|
||||
if (!connected) {
|
||||
foreach (Thing *childThing, myThings()) {
|
||||
if (childThing->parentId() == thing->id()) {
|
||||
thing->setStateValue(m_connectedStateTypeId[childThing->thingClassId()], connected);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
connect(thing, &Thing::settingChanged, thing, [thing, modbusRTUMaster] (const ParamTypeId ¶mTypeId, const QVariant &value) {
|
||||
if (paramTypeId == modbusRTUClientSettingsNumberOfRetriesParamTypeId) {
|
||||
qCDebug(dcModbusCommander()) << "Set number of retries" << thing->name() << value.toUInt();
|
||||
modbusRTUMaster->setNumberOfRetries(value.toUInt());
|
||||
} else if (paramTypeId == modbusRTUClientSettingsTimeoutParamTypeId) {
|
||||
qCDebug(dcModbusCommander()) << "Set timeout " << thing->name() << value.toUInt();
|
||||
modbusRTUMaster->setTimeout(value.toUInt());
|
||||
}
|
||||
});
|
||||
modbusRTUMaster->connectDevice();
|
||||
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
} else if ((thing->thingClassId() == coilThingClassId)
|
||||
|| (thing->thingClassId() == discreteInputThingClassId)
|
||||
|| (thing->thingClassId() == holdingRegisterThingClassId)
|
||||
@ -362,9 +344,6 @@ void IntegrationPluginModbusCommander::thingRemoved(Thing *thing)
|
||||
if (thing->thingClassId() == modbusTCPClientThingClassId) {
|
||||
ModbusTCPMaster *modbus = m_modbusTCPMasters.take(thing);
|
||||
modbus->deleteLater();
|
||||
} else if (thing->thingClassId() == modbusRTUClientThingClassId) {
|
||||
ModbusRTUMaster *modbus = m_modbusRTUMasters.take(thing);
|
||||
modbus->deleteLater();
|
||||
}
|
||||
|
||||
if (myThings().empty()) {
|
||||
@ -392,12 +371,7 @@ void IntegrationPluginModbusCommander::onPluginConfigurationChanged(const ParamT
|
||||
void IntegrationPluginModbusCommander::onConnectionStateChanged(bool status)
|
||||
{
|
||||
auto modbus = sender();
|
||||
|
||||
if (m_modbusRTUMasters.values().contains(static_cast<ModbusRTUMaster *>(modbus))) {
|
||||
Thing *thing = m_modbusRTUMasters.key(static_cast<ModbusRTUMaster *>(modbus));
|
||||
qCDebug(dcModbusCommander()) << "Connections state changed" << thing->name() << status;
|
||||
thing->setStateValue(modbusRTUClientConnectedStateTypeId, status);
|
||||
} else if (m_modbusTCPMasters.values().contains(static_cast<ModbusTCPMaster *>(modbus))) {
|
||||
if (m_modbusTCPMasters.values().contains(static_cast<ModbusTCPMaster *>(modbus))) {
|
||||
Thing *thing = m_modbusTCPMasters.key(static_cast<ModbusTCPMaster *>(modbus));
|
||||
qCDebug(dcModbusCommander()) << "Connections state changed" << thing->name() << status;
|
||||
thing->setStateValue(modbusTCPClientConnectedStateTypeId, status);
|
||||
@ -439,20 +413,7 @@ void IntegrationPluginModbusCommander::onRequestError(QUuid requestId, const QSt
|
||||
void IntegrationPluginModbusCommander::onReceivedCoil(quint32 slaveAddress, quint32 modbusRegister, const QVector<quint16> &values)
|
||||
{
|
||||
auto modbus = sender();
|
||||
|
||||
if (m_modbusRTUMasters.values().contains(static_cast<ModbusRTUMaster *>(modbus))) {
|
||||
Thing *parent = m_modbusRTUMasters.key(static_cast<ModbusRTUMaster *>(modbus));
|
||||
foreach (Thing *thing, myThings().filterByParentId(parent->id())) {
|
||||
if (thing->thingClassId() == coilThingClassId) {
|
||||
if ((thing->paramValue(m_slaveAddressParamTypeId.value(thing->thingClassId())) == slaveAddress)
|
||||
&& (thing->paramValue(m_registerAddressParamTypeId.value(thing->thingClassId())) == modbusRegister)) {
|
||||
thing->setStateValue(m_valueStateTypeId.value(thing->thingClassId()), values[0]);
|
||||
thing->setStateValue(m_connectedStateTypeId.value(thing->thingClassId()), true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (m_modbusTCPMasters.values().contains(static_cast<ModbusTCPMaster *>(modbus))) {
|
||||
if (m_modbusTCPMasters.values().contains(static_cast<ModbusTCPMaster *>(modbus))) {
|
||||
Thing *parent = m_modbusTCPMasters.key(static_cast<ModbusTCPMaster *>(modbus));
|
||||
foreach (Thing *thing, myThings().filterByParentId(parent->id())) {
|
||||
if (thing->thingClassId() == coilThingClassId) {
|
||||
@ -471,19 +432,7 @@ void IntegrationPluginModbusCommander::onReceivedDiscreteInput(quint32 slaveAddr
|
||||
{
|
||||
auto modbus = sender();
|
||||
|
||||
if (m_modbusRTUMasters.values().contains(static_cast<ModbusRTUMaster *>(modbus))) {
|
||||
Thing *parent = m_modbusRTUMasters.key(static_cast<ModbusRTUMaster *>(modbus));
|
||||
foreach (Thing *thing, myThings().filterByParentId(parent->id())) {
|
||||
if (thing->thingClassId() == discreteInputThingClassId) {
|
||||
if ((thing->paramValue(m_slaveAddressParamTypeId.value(thing->thingClassId())) == slaveAddress)
|
||||
&& (thing->paramValue(m_registerAddressParamTypeId.value(thing->thingClassId())) == modbusRegister)) {
|
||||
thing->setStateValue(m_valueStateTypeId.value(thing->thingClassId()), values[0]);
|
||||
thing->setStateValue(m_connectedStateTypeId.value(thing->thingClassId()), true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (m_modbusTCPMasters.values().contains(static_cast<ModbusTCPMaster *>(modbus))) {
|
||||
if (m_modbusTCPMasters.values().contains(static_cast<ModbusTCPMaster *>(modbus))) {
|
||||
Thing *parent = m_modbusTCPMasters.key(static_cast<ModbusTCPMaster *>(modbus));
|
||||
foreach (Thing *thing, myThings().filterByParentId(parent->id())) {
|
||||
if (thing->thingClassId() == discreteInputThingClassId) {
|
||||
@ -502,19 +451,7 @@ void IntegrationPluginModbusCommander::onReceivedHoldingRegister(uint slaveAddre
|
||||
{
|
||||
auto modbus = sender();
|
||||
|
||||
if (m_modbusRTUMasters.values().contains(static_cast<ModbusRTUMaster *>(modbus))) {
|
||||
Thing *parent = m_modbusRTUMasters.key(static_cast<ModbusRTUMaster *>(modbus));
|
||||
foreach (Thing *thing, myThings().filterByParentId(parent->id())) {
|
||||
if (thing->thingClassId() == holdingRegisterThingClassId) {
|
||||
if ((thing->paramValue(m_slaveAddressParamTypeId.value(thing->thingClassId())) == slaveAddress)
|
||||
&& (thing->paramValue(m_registerAddressParamTypeId.value(thing->thingClassId())) == modbusRegister)) {
|
||||
thing->setStateValue(m_valueStateTypeId.value(thing->thingClassId()), values[0]);
|
||||
thing->setStateValue(m_connectedStateTypeId.value(thing->thingClassId()), true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (m_modbusTCPMasters.values().contains(static_cast<ModbusTCPMaster *>(modbus))) {
|
||||
if (m_modbusTCPMasters.values().contains(static_cast<ModbusTCPMaster *>(modbus))) {
|
||||
Thing *parent = m_modbusTCPMasters.key(static_cast<ModbusTCPMaster *>(modbus));
|
||||
foreach (Thing *thing, myThings().filterByParentId(parent->id())) {
|
||||
if (thing->thingClassId() == holdingRegisterThingClassId) {
|
||||
@ -533,19 +470,7 @@ void IntegrationPluginModbusCommander::onReceivedInputRegister(uint slaveAddress
|
||||
{
|
||||
auto modbus = sender();
|
||||
|
||||
if (m_modbusRTUMasters.values().contains(static_cast<ModbusRTUMaster *>(modbus))) {
|
||||
Thing *parent = m_modbusRTUMasters.key(static_cast<ModbusRTUMaster *>(modbus));
|
||||
foreach (Thing *thing, myThings().filterByParentId(parent->id())) {
|
||||
if (thing->thingClassId() == inputRegisterThingClassId) {
|
||||
if ((thing->paramValue(m_slaveAddressParamTypeId.value(thing->thingClassId())) == slaveAddress)
|
||||
&& (thing->paramValue(m_registerAddressParamTypeId.value(thing->thingClassId())) == modbusRegister)) {
|
||||
thing->setStateValue(m_valueStateTypeId.value(thing->thingClassId()), values[0]);
|
||||
thing->setStateValue(m_connectedStateTypeId.value(thing->thingClassId()), true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (m_modbusTCPMasters.values().contains(static_cast<ModbusTCPMaster *>(modbus))) {
|
||||
if (m_modbusTCPMasters.values().contains(static_cast<ModbusTCPMaster *>(modbus))) {
|
||||
Thing *parent = m_modbusTCPMasters.key(static_cast<ModbusTCPMaster *>(modbus));
|
||||
foreach (Thing *thing, myThings().filterByParentId(parent->id())) {
|
||||
if (thing->thingClassId() == inputRegisterThingClassId) {
|
||||
@ -592,23 +517,76 @@ void IntegrationPluginModbusCommander::readRegister(Thing *thing)
|
||||
}
|
||||
} else if (parent->thingClassId() == modbusRTUClientThingClassId) {
|
||||
|
||||
ModbusRTUMaster *modbus = m_modbusRTUMasters.value(parent);
|
||||
if (!modbus)
|
||||
ModbusRtuMaster *modbusMaster = m_modbusRtuMasters.value(parent);
|
||||
if (!modbusMaster)
|
||||
return;
|
||||
|
||||
if (!modbus->connected())
|
||||
if (!modbusMaster->connected())
|
||||
return; // Send requests only if the modbus interface is connected
|
||||
|
||||
if (thing->thingClassId() == coilThingClassId) {
|
||||
requestId = modbus->readCoil(slaveAddress, registerAddress);
|
||||
ModbusRtuReply *reply = modbusMaster->readCoil(slaveAddress, registerAddress);
|
||||
connect(reply, &ModbusRtuReply::finished, modbusMaster, [=](){
|
||||
if (reply->error() != ModbusRtuReply::NoError) {
|
||||
qCWarning(dcModbusCommander()) << "Failed to read coil from" << modbusMaster << "slave:" << slaveAddress << "register:" << registerAddress;
|
||||
thing->setStateValue(m_connectedStateTypeId[thing->thingClassId()], false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!reply->result().isEmpty()) {
|
||||
thing->setStateValue(m_valueStateTypeId.value(thing->thingClassId()), reply->result().at(0));
|
||||
}
|
||||
thing->setStateValue(m_connectedStateTypeId.value(thing->thingClassId()), true);
|
||||
});
|
||||
} else if (thing->thingClassId() == discreteInputThingClassId) {
|
||||
requestId = modbus->readDiscreteInput(slaveAddress, registerAddress);
|
||||
ModbusRtuReply *reply = modbusMaster->readDiscreteInput(slaveAddress, registerAddress);
|
||||
connect(reply, &ModbusRtuReply::finished, modbusMaster, [=](){
|
||||
if (reply->error() != ModbusRtuReply::NoError) {
|
||||
qCWarning(dcModbusCommander()) << "Failed to read discrete input from" << modbusMaster << "slave:" << slaveAddress << "register:" << registerAddress;
|
||||
thing->setStateValue(m_connectedStateTypeId[thing->thingClassId()], false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!reply->result().isEmpty()) {
|
||||
thing->setStateValue(m_valueStateTypeId.value(thing->thingClassId()), reply->result().at(0));
|
||||
}
|
||||
thing->setStateValue(m_connectedStateTypeId.value(thing->thingClassId()), true);
|
||||
});
|
||||
} else if (thing->thingClassId() == holdingRegisterThingClassId) {
|
||||
requestId = modbus->readHoldingRegister(slaveAddress, registerAddress);
|
||||
ModbusRtuReply *reply = modbusMaster->readHoldingRegister(slaveAddress, registerAddress);
|
||||
connect(reply, &ModbusRtuReply::finished, modbusMaster, [=](){
|
||||
if (reply->error() != ModbusRtuReply::NoError) {
|
||||
qCWarning(dcModbusCommander()) << "Failed to read holding register from" << modbusMaster << "slave:" << slaveAddress << "register:" << registerAddress;
|
||||
thing->setStateValue(m_connectedStateTypeId[thing->thingClassId()], false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!reply->result().isEmpty()) {
|
||||
thing->setStateValue(m_valueStateTypeId.value(thing->thingClassId()), reply->result().at(0));
|
||||
}
|
||||
thing->setStateValue(m_connectedStateTypeId.value(thing->thingClassId()), true);
|
||||
});
|
||||
} else if (thing->thingClassId() == inputRegisterThingClassId) {
|
||||
requestId = modbus->readInputRegister(slaveAddress, registerAddress);
|
||||
ModbusRtuReply *reply = modbusMaster->readInputRegister(slaveAddress, registerAddress);
|
||||
connect(reply, &ModbusRtuReply::finished, modbusMaster, [=](){
|
||||
if (reply->error() != ModbusRtuReply::NoError) {
|
||||
qCWarning(dcModbusCommander()) << "Failed to read input register from" << modbusMaster << "slave:" << slaveAddress << "register:" << registerAddress;
|
||||
thing->setStateValue(m_connectedStateTypeId[thing->thingClassId()], false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!reply->result().isEmpty()) {
|
||||
thing->setStateValue(m_valueStateTypeId.value(thing->thingClassId()), reply->result().at(0));
|
||||
}
|
||||
thing->setStateValue(m_connectedStateTypeId.value(thing->thingClassId()), true);
|
||||
});
|
||||
}
|
||||
|
||||
// Note: we don't want proceed with the method here, since we are not
|
||||
// working with the requestId any more on RTU
|
||||
return;
|
||||
}
|
||||
|
||||
if (!requestId.isNull()) {
|
||||
m_readRequests.insert(requestId, thing);
|
||||
QTimer::singleShot(5000, this, [requestId, this] {m_readRequests.remove(requestId);});
|
||||
@ -623,8 +601,10 @@ void IntegrationPluginModbusCommander::writeRegister(Thing *thing, ThingActionIn
|
||||
Thing *parent = myThings().findById(thing->parentId());
|
||||
if (!parent) {
|
||||
qCWarning(dcModbusCommander()) << "Could not find parent device" << thing->name();
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
return;
|
||||
}
|
||||
|
||||
uint registerAddress = thing->paramValue(m_registerAddressParamTypeId.value(thing->thingClassId())).toUInt();;
|
||||
uint slaveAddress = thing->paramValue(m_slaveAddressParamTypeId.value(thing->thingClassId())).toUInt();
|
||||
|
||||
@ -633,8 +613,11 @@ void IntegrationPluginModbusCommander::writeRegister(Thing *thing, ThingActionIn
|
||||
|
||||
if (parent->thingClassId() == modbusTCPClientThingClassId) {
|
||||
ModbusTCPMaster *modbus = m_modbusTCPMasters.value(parent);
|
||||
if (!modbus)
|
||||
if (!modbus) {
|
||||
qCWarning(dcModbusCommander()) << "Could not find modbus TCP master for" << thing;
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
return;
|
||||
}
|
||||
|
||||
if (thing->thingClassId() == coilThingClassId) {
|
||||
requestId = modbus->writeCoil(slaveAddress, registerAddress, action.param(coilValueActionValueParamTypeId).value().toBool());
|
||||
@ -643,15 +626,48 @@ void IntegrationPluginModbusCommander::writeRegister(Thing *thing, ThingActionIn
|
||||
}
|
||||
|
||||
} else if (parent->thingClassId() == modbusRTUClientThingClassId) {
|
||||
ModbusRTUMaster *modbus = m_modbusRTUMasters.value(parent);
|
||||
if (!modbus)
|
||||
ModbusRtuMaster *modbusMaster = m_modbusRtuMasters.value(parent);
|
||||
if (!modbusMaster) {
|
||||
qCWarning(dcModbusCommander()) << "Could not find modbus RTU master for" << thing;
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
return;
|
||||
}
|
||||
|
||||
if (thing->thingClassId() == coilThingClassId) {
|
||||
requestId = modbus->writeCoil(slaveAddress, registerAddress, action.param(coilValueActionValueParamTypeId).value().toBool());
|
||||
QVector<quint16> values;
|
||||
values.append(static_cast<quint16>(action.param(coilValueActionValueParamTypeId).value().toBool()));
|
||||
|
||||
ModbusRtuReply *reply = modbusMaster->writeCoils(slaveAddress, registerAddress, values);
|
||||
connect(info, &ThingActionInfo::aborted, reply, &ModbusRtuReply::deleteLater);
|
||||
connect(reply, &ModbusRtuReply::finished, modbusMaster, [=](){
|
||||
if (reply->error() != ModbusRtuReply::NoError) {
|
||||
qCWarning(dcModbusCommander()) << "Failed to write coils from" << modbusMaster << "slave:" << slaveAddress << "register:" << registerAddress << values << reply->errorString();
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
});
|
||||
} else if (thing->thingClassId() == holdingRegisterThingClassId) {
|
||||
requestId = modbus->writeHoldingRegister(slaveAddress, registerAddress, action.param(holdingRegisterValueActionValueParamTypeId).value().toUInt());
|
||||
QVector<quint16> values;
|
||||
values.append(static_cast<quint16>(action.param(holdingRegisterValueActionValueParamTypeId).value().toUInt()));
|
||||
|
||||
ModbusRtuReply *reply = modbusMaster->writeHoldingRegisters(slaveAddress, registerAddress, values);
|
||||
connect(info, &ThingActionInfo::aborted, reply, &ModbusRtuReply::deleteLater);
|
||||
connect(reply, &ModbusRtuReply::finished, modbusMaster, [=](){
|
||||
if (reply->error() != ModbusRtuReply::NoError) {
|
||||
qCWarning(dcModbusCommander()) << "Failed to write holding registers from" << modbusMaster << "slave:" << slaveAddress << "register:" << registerAddress << values << reply->errorString();
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
});
|
||||
}
|
||||
|
||||
// Note: we don't want proceed with the method here, since we are not
|
||||
// working with the requestId any more on RTU
|
||||
return;
|
||||
}
|
||||
|
||||
if (requestId.toString().isNull()){
|
||||
|
||||
@ -31,11 +31,11 @@
|
||||
#ifndef INTEGRATIONPLUGINMODBUSCOMMANDER_H
|
||||
#define INTEGRATIONPLUGINMODBUSCOMMANDER_H
|
||||
|
||||
#include "integrations/integrationplugin.h"
|
||||
#include "plugintimer.h"
|
||||
#include "integrations/integrationplugin.h"
|
||||
#include "hardware/modbus/modbusrtumaster.h"
|
||||
|
||||
#include "../modbus/modbustcpmaster.h"
|
||||
#include "../modbus/modbusrtumaster.h"
|
||||
|
||||
#include <QSerialPortInfo>
|
||||
#include <QUuid>
|
||||
@ -60,8 +60,9 @@ public:
|
||||
private:
|
||||
PluginTimer *m_refreshTimer = nullptr;
|
||||
|
||||
QHash<Thing*, ModbusRTUMaster*> m_modbusRTUMasters;
|
||||
//QHash<Thing*, ModbusRTUMaster*> m_modbusRTUMasters;
|
||||
QHash<Thing*, ModbusTCPMaster*> m_modbusTCPMasters;
|
||||
QHash<Thing *, ModbusRtuMaster *> m_modbusRtuMasters;
|
||||
QHash<QUuid, ThingActionInfo*> m_asyncActions;
|
||||
QHash<QUuid, Thing*> m_readRequests;
|
||||
|
||||
|
||||
@ -72,74 +72,15 @@
|
||||
"id": "776df314-6186-4eb5-b824-f0d916f6d9c3",
|
||||
"name": "modbusRTUClient",
|
||||
"displayName": "Modbus RTU client",
|
||||
"createMethods": ["discovery", "user"],
|
||||
"createMethods": ["discovery"],
|
||||
"interfaces": ["connectable"],
|
||||
"settingsTypes": [
|
||||
{
|
||||
"id": "b0af32f0-b8cc-4642-af5a-576732522b2c",
|
||||
"name": "timeout",
|
||||
"displayName": "Timeout",
|
||||
"type": "uint",
|
||||
"minValue": 10,
|
||||
"defaultValue": 100
|
||||
},
|
||||
{
|
||||
"id": "c4f16d6c-c1f2-4862-b0bd-6fae7193eaa8",
|
||||
"name": "numberOfRetries",
|
||||
"displayName": "Number of retries",
|
||||
"type": "uint",
|
||||
"defaultValue": 3
|
||||
}
|
||||
],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "ed49f7d8-ab18-4c37-9b80-1004b75dcb91",
|
||||
"name": "serialPort",
|
||||
"displayName": "Serial port",
|
||||
"type": "QString",
|
||||
"inputType": "TextLine",
|
||||
"defaultValue": "ttyAMA0"
|
||||
},
|
||||
{
|
||||
"id": "9908b01f-a76b-4b21-8242-b507c9252254",
|
||||
"name": "serialnumber",
|
||||
"displayName": "Serial number",
|
||||
"type": "QString",
|
||||
"name": "modbusMasterUuid",
|
||||
"displayName": "Modbus RTU master",
|
||||
"type": "QUuid",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "45dfc828-f238-4263-89a3-9b35cf5dea39",
|
||||
"name": "baudRate",
|
||||
"displayName": "Baud rate",
|
||||
"type": "uint",
|
||||
"defaultValue": 9600
|
||||
},
|
||||
{
|
||||
"id": "a27c664b-9f43-4573-a2cc-f65a8fa1a069",
|
||||
"name": "dataBits",
|
||||
"displayName": "Data bits",
|
||||
"type": "uint",
|
||||
"defaultValue": 8
|
||||
},
|
||||
{
|
||||
"id": "4ea8bcdf-d4c5-45a4-a54f-f10ac3f08a78",
|
||||
"name": "stopBits",
|
||||
"displayName": "Stop bits",
|
||||
"type": "uint",
|
||||
"defaultValue": 1
|
||||
},
|
||||
{
|
||||
"id": "72de1b08-2a27-49c5-90e0-8788c3ea1da3",
|
||||
"name": "parity",
|
||||
"displayName": "Parity",
|
||||
"type": "QString",
|
||||
"inputType": "TextLine",
|
||||
"allowedValues": [
|
||||
"No Parity",
|
||||
"Even Parity",
|
||||
"Odd Parity"
|
||||
],
|
||||
"defaultValue": "No Parity"
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
|
||||
@ -7,11 +7,9 @@ QT += \
|
||||
|
||||
SOURCES += \
|
||||
integrationpluginmodbuscommander.cpp \
|
||||
../modbus/modbustcpmaster.cpp \
|
||||
../modbus/modbusrtumaster.cpp \
|
||||
../modbus/modbustcpmaster.cpp
|
||||
|
||||
HEADERS += \
|
||||
integrationpluginmodbuscommander.h \
|
||||
../modbus/modbustcpmaster.h \
|
||||
../modbus/modbusrtumaster.h \
|
||||
../modbus/modbustcpmaster.h
|
||||
|
||||
|
||||
Reference in New Issue
Block a user