From 8a0399f7c316c2590711c7b1da8ec3b58bd65385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Thu, 28 Jul 2022 15:00:19 +0200 Subject: [PATCH] Implement new update method for modbus TCP and improve readability of update methods --- .../tools/connectiontool/modbusrtu.py | 166 ++++++----- .../tools/connectiontool/modbustcp.py | 279 +++++++++++++----- .../tools/connectiontool/toolcommon.py | 30 +- libnymea-modbus/tools/generate-connection.py | 13 +- 4 files changed, 325 insertions(+), 163 deletions(-) diff --git a/libnymea-modbus/tools/connectiontool/modbusrtu.py b/libnymea-modbus/tools/connectiontool/modbusrtu.py index 88de585..be3609f 100644 --- a/libnymea-modbus/tools/connectiontool/modbusrtu.py +++ b/libnymea-modbus/tools/connectiontool/modbusrtu.py @@ -310,27 +310,30 @@ def writeInitMethodImplementationRtu(fileDescriptor, className, registerDefiniti writeLine(fileDescriptor, ' return false;') writeLine(fileDescriptor, ' }') writeLine(fileDescriptor) - writeLine(fileDescriptor, ' if (!reply->isFinished()) {') - writeLine(fileDescriptor, ' m_pendingInitReplies.append(reply);') - writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::finished, m_initObject, [this, reply](){') - writeLine(fileDescriptor, ' handleModbusError(reply->error());') - writeLine(fileDescriptor, ' m_pendingInitReplies.removeAll(reply);') - writeLine(fileDescriptor) - writeLine(fileDescriptor, ' if (reply->error() != ModbusRtuReply::NoError) {') - writeLine(fileDescriptor, ' finishInitialization(false);') - writeLine(fileDescriptor, ' return;') - writeLine(fileDescriptor, ' }') - writeLine(fileDescriptor) - writeLine(fileDescriptor, ' QVector values = reply->result();') - writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from \\"%s\\" register" << %s << "size:" << %s << values;' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size'])) - writeLine(fileDescriptor, ' process%sRegisterValues(values);' % (propertyName[0].upper() + propertyName[1:])) - writeLine(fileDescriptor, ' verifyInitFinished();') - writeLine(fileDescriptor, ' });') - writeLine(fileDescriptor) - writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::errorOccurred, m_initObject, [reply] (ModbusRtuReply::Error error){') - writeLine(fileDescriptor, ' qCWarning(dc%s()) << "ModbusRtu reply error occurred while updating \\"%s\\" registers" << error << reply->errorString();' % (className, registerDefinition['description'])) - writeLine(fileDescriptor, ' });') + writeLine(fileDescriptor, ' if (reply->isFinished()) {') + writeLine(fileDescriptor, ' finishInitialization(false); // Broadcast reply returns immediatly') + writeLine(fileDescriptor, ' return false;') writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' m_pendingInitReplies.append(reply);') + writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::finished, m_initObject, [this, reply](){') + writeLine(fileDescriptor, ' handleModbusError(reply->error());') + writeLine(fileDescriptor, ' m_pendingInitReplies.removeAll(reply);') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' if (reply->error() != ModbusRtuReply::NoError) {') + writeLine(fileDescriptor, ' finishInitialization(false);') + writeLine(fileDescriptor, ' return;') + writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' QVector values = reply->result();') + writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from \\"%s\\" register" << %s << "size:" << %s << values;' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size'])) + writeLine(fileDescriptor, ' process%sRegisterValues(values);' % (propertyName[0].upper() + propertyName[1:])) + writeLine(fileDescriptor, ' verifyInitFinished();') + writeLine(fileDescriptor, ' });') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::errorOccurred, m_initObject, [reply] (ModbusRtuReply::Error error){') + writeLine(fileDescriptor, ' qCWarning(dc%s()) << "ModbusRtu reply error occurred while updating \\"%s\\" registers" << error << reply->errorString();' % (className, registerDefinition['description'])) + writeLine(fileDescriptor, ' });') # Read init blocks for blockDefinition in blockDefinitions: @@ -360,35 +363,38 @@ def writeInitMethodImplementationRtu(fileDescriptor, className, registerDefiniti writeLine(fileDescriptor, ' return false;') writeLine(fileDescriptor, ' }') writeLine(fileDescriptor) - writeLine(fileDescriptor, ' if (!reply->isFinished()) {') - writeLine(fileDescriptor, ' m_pendingInitReplies.append(reply);') - writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::finished, m_initObject, [this, reply](){') - writeLine(fileDescriptor, ' handleModbusError(reply->error());') - writeLine(fileDescriptor, ' m_pendingInitReplies.removeAll(reply);') + writeLine(fileDescriptor, ' if (reply->isFinished()) {') + writeLine(fileDescriptor, ' finishInitialization(false); // Broadcast reply returns immediatly') + writeLine(fileDescriptor, ' return false;') + writeLine(fileDescriptor, ' }') writeLine(fileDescriptor) - writeLine(fileDescriptor, ' if (reply->error() != ModbusRtuReply::NoError) {') - writeLine(fileDescriptor, ' finishInitialization(false);') - writeLine(fileDescriptor, ' return;') - writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor, ' m_pendingInitReplies.append(reply);') + writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::finished, m_initObject, [this, reply](){') + writeLine(fileDescriptor, ' handleModbusError(reply->error());') + writeLine(fileDescriptor, ' m_pendingInitReplies.removeAll(reply);') writeLine(fileDescriptor) - writeLine(fileDescriptor, ' QVector blockValues = reply->result();') - writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from reading block \\"%s\\" register" << %s << "size:" << %s << blockValues;' % (className, blockName, blockStartAddress, blockSize)) + writeLine(fileDescriptor, ' if (reply->error() != ModbusRtuReply::NoError) {') + writeLine(fileDescriptor, ' finishInitialization(false);') + writeLine(fileDescriptor, ' return;') + writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' QVector blockValues = reply->result();') + writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from reading block \\"%s\\" register" << %s << "size:" << %s << blockValues;' % (className, blockName, blockStartAddress, blockSize)) # Start parsing the registers using offsets offset = 0 for i, blockRegister in enumerate(blockRegisters): propertyName = blockRegister['id'] propertyTyp = getCppDataType(blockRegister) - writeLine(fileDescriptor, ' process%sRegisterValues(blockValues.mid(%s, %s));' % (propertyName[0].upper() + propertyName[1:], offset, blockRegister['size'])) + writeLine(fileDescriptor, ' process%sRegisterValues(blockValues.mid(%s, %s));' % (propertyName[0].upper() + propertyName[1:], offset, blockRegister['size'])) offset += blockRegister['size'] - writeLine(fileDescriptor, ' verifyInitFinished();') - writeLine(fileDescriptor, ' });') + writeLine(fileDescriptor, ' verifyInitFinished();') + writeLine(fileDescriptor, ' });') writeLine(fileDescriptor) - writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::errorOccurred, m_initObject, [reply] (ModbusRtuReply::Error error){') - writeLine(fileDescriptor, ' qCWarning(dc%s()) << "ModbusRtu reply error occurred while updating block \\"%s\\" registers" << error << reply->errorString();' % (className, blockName)) - writeLine(fileDescriptor, ' });') - writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::errorOccurred, m_initObject, [reply] (ModbusRtuReply::Error error){') + writeLine(fileDescriptor, ' qCWarning(dc%s()) << "ModbusRtu reply error occurred while updating block \\"%s\\" registers" << error << reply->errorString();' % (className, blockName)) + writeLine(fileDescriptor, ' });') writeLine(fileDescriptor) else: @@ -411,7 +417,7 @@ def writeUpdateMethodRtu(fileDescriptor, className, registerDefinitions, blockDe updateRequired = True break - for blockDefinition in blockDefinitions: + for blockDefinition in blockDefinitions: if 'readSchedule' in blockDefinition and blockDefinition['readSchedule'] == 'update': updateRequired = True break @@ -443,32 +449,34 @@ def writeUpdateMethodRtu(fileDescriptor, className, registerDefinitions, blockDe writeLine(fileDescriptor, ' return false;') writeLine(fileDescriptor, ' }') writeLine(fileDescriptor) - writeLine(fileDescriptor, ' if (!reply->isFinished()) {') - writeLine(fileDescriptor, ' m_pendingUpdateReplies.append(reply);') - writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::finished, this, [this, reply](){') - writeLine(fileDescriptor, ' handleModbusError(reply->error());') - writeLine(fileDescriptor, ' m_pendingUpdateReplies.removeAll(reply);') - writeLine(fileDescriptor) - writeLine(fileDescriptor, ' if (reply->error() != ModbusRtuReply::NoError) {') - writeLine(fileDescriptor, ' verifyUpdateFinished();') - writeLine(fileDescriptor, ' return;') - writeLine(fileDescriptor, ' }') - writeLine(fileDescriptor) - writeLine(fileDescriptor, ' QVector values = reply->result();') - writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from \\"%s\\" register" << %s << "size:" << %s << values;' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size'])) - writeLine(fileDescriptor, ' process%sRegisterValues(values);' % (propertyName[0].upper() + propertyName[1:])) - writeLine(fileDescriptor, ' verifyUpdateFinished();') - writeLine(fileDescriptor, ' });') - writeLine(fileDescriptor) - writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){') - writeLine(fileDescriptor, ' qCWarning(dc%s()) << "ModbusRtu reply error occurred while updating \\"%s\\" registers" << error << reply->errorString();' % (className, registerDefinition['description'])) - writeLine(fileDescriptor, ' });') + writeLine(fileDescriptor, ' if (reply->isFinished()) {') + writeLine(fileDescriptor, ' return false; // Broadcast reply returns immediatly') writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' m_pendingUpdateReplies.append(reply);') + writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::finished, this, [this, reply](){') + writeLine(fileDescriptor, ' handleModbusError(reply->error());') + writeLine(fileDescriptor, ' m_pendingUpdateReplies.removeAll(reply);') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' if (reply->error() != ModbusRtuReply::NoError) {') + writeLine(fileDescriptor, ' verifyUpdateFinished();') + writeLine(fileDescriptor, ' return;') + writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' QVector values = reply->result();') + writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from \\"%s\\" register" << %s << "size:" << %s << values;' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size'])) + writeLine(fileDescriptor, ' process%sRegisterValues(values);' % (propertyName[0].upper() + propertyName[1:])) + writeLine(fileDescriptor, ' verifyUpdateFinished();') + writeLine(fileDescriptor, ' });') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){') + writeLine(fileDescriptor, ' qCWarning(dc%s()) << "ModbusRtu reply error occurred while updating \\"%s\\" registers" << error << reply->errorString();' % (className, registerDefinition['description'])) + writeLine(fileDescriptor, ' });') # Read init blocks for blockDefinition in blockDefinitions: blockName = blockDefinition['id'] - blockRegisters = blockDefinition['registers'] + blockRegisters = blockDefinition['registers'] if 'readSchedule' in blockDefinition and blockDefinition['readSchedule'] == 'update': blockStartAddress = 0 @@ -492,35 +500,37 @@ def writeUpdateMethodRtu(fileDescriptor, className, registerDefinitions, blockDe writeLine(fileDescriptor, ' return false;') writeLine(fileDescriptor, ' }') writeLine(fileDescriptor) - writeLine(fileDescriptor, ' if (!reply->isFinished()) {') - writeLine(fileDescriptor, ' m_pendingUpdateReplies.append(reply);') - writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::finished, this, [this, reply](){') - writeLine(fileDescriptor, ' handleModbusError(reply->error());') - writeLine(fileDescriptor, ' m_pendingUpdateReplies.removeAll(reply);') + writeLine(fileDescriptor, ' if (reply->isFinished()) {') + writeLine(fileDescriptor, ' return false; // Broadcast reply returns immediatly') + writeLine(fileDescriptor, ' }') writeLine(fileDescriptor) - writeLine(fileDescriptor, ' if (reply->error() != ModbusRtuReply::NoError) {') - writeLine(fileDescriptor, ' verifyUpdateFinished();') - writeLine(fileDescriptor, ' return;') - writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor, ' m_pendingUpdateReplies.append(reply);') + writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::finished, this, [this, reply](){') + writeLine(fileDescriptor, ' handleModbusError(reply->error());') + writeLine(fileDescriptor, ' m_pendingUpdateReplies.removeAll(reply);') writeLine(fileDescriptor) - writeLine(fileDescriptor, ' QVector blockValues = reply->result();') - writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from reading block \\"%s\\" register" << %s << "size:" << %s << blockValues;' % (className, blockName, blockStartAddress, blockSize)) + writeLine(fileDescriptor, ' if (reply->error() != ModbusRtuReply::NoError) {') + writeLine(fileDescriptor, ' verifyUpdateFinished();') + writeLine(fileDescriptor, ' return;') + writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' QVector blockValues = reply->result();') + writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from reading block \\"%s\\" register" << %s << "size:" << %s << blockValues;' % (className, blockName, blockStartAddress, blockSize)) # Start parsing the registers using offsets offset = 0 for i, blockRegister in enumerate(blockRegisters): propertyName = blockRegister['id'] propertyTyp = getCppDataType(blockRegister) - writeLine(fileDescriptor, ' process%sRegisterValues(blockValues.mid(%s, %s));' % (propertyName[0].upper() + propertyName[1:], offset, blockRegister['size'])) + writeLine(fileDescriptor, ' process%sRegisterValues(blockValues.mid(%s, %s));' % (propertyName[0].upper() + propertyName[1:], offset, blockRegister['size'])) offset += blockRegister['size'] - writeLine(fileDescriptor, ' verifyUpdateFinished();') - writeLine(fileDescriptor, ' });') + writeLine(fileDescriptor, ' verifyUpdateFinished();') + writeLine(fileDescriptor, ' });') writeLine(fileDescriptor) - writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){') - writeLine(fileDescriptor, ' qCWarning(dc%s()) << "ModbusRtu reply error occurred while updating block \\"%s\\" registers" << error << reply->errorString();' % (className, blockName)) - writeLine(fileDescriptor, ' });') - writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){') + writeLine(fileDescriptor, ' qCWarning(dc%s()) << "ModbusRtu reply error occurred while updating block \\"%s\\" registers" << error << reply->errorString();' % (className, blockName)) + writeLine(fileDescriptor, ' });') writeLine(fileDescriptor) else: diff --git a/libnymea-modbus/tools/connectiontool/modbustcp.py b/libnymea-modbus/tools/connectiontool/modbustcp.py index 75c76c3..a921788 100644 --- a/libnymea-modbus/tools/connectiontool/modbustcp.py +++ b/libnymea-modbus/tools/connectiontool/modbustcp.py @@ -90,22 +90,23 @@ def writePropertyUpdateMethodImplementationsTcp(fileDescriptor, className, regis writeLine(fileDescriptor, ' return;') writeLine(fileDescriptor, ' }') writeLine(fileDescriptor) - writeLine(fileDescriptor, ' if (!reply->isFinished()) {') - writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);') - writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, this, [this, reply](){') - writeLine(fileDescriptor, ' if (reply->error() == QModbusDevice::NoError) {') - writeLine(fileDescriptor, ' const QModbusDataUnit unit = reply->result();') - writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from \\"%s\\" register" << %s << "size:" << %s << unit.values();' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size'])) - writeLine(fileDescriptor, ' process%sRegisterValues(unit.values());' % (propertyName[0].upper() + propertyName[1:])) - writeLine(fileDescriptor, ' }') - writeLine(fileDescriptor, ' });') - writeLine(fileDescriptor) - writeLine(fileDescriptor, ' connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){') - writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Modbus reply error occurred while updating \\"%s\\" registers from" << hostAddress().toString() << error << reply->errorString();' % (className, registerDefinition['description'])) - writeLine(fileDescriptor, ' });') - writeLine(fileDescriptor, ' } else {') + writeLine(fileDescriptor, ' if (reply->isFinished()) {') writeLine(fileDescriptor, ' reply->deleteLater(); // Broadcast reply returns immediatly') + writeLine(fileDescriptor, ' return;') writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);') + writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, this, [this, reply](){') + writeLine(fileDescriptor, ' if (reply->error() == QModbusDevice::NoError) {') + writeLine(fileDescriptor, ' const QModbusDataUnit unit = reply->result();') + writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from \\"%s\\" register" << %s << "size:" << %s << unit.values();' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size'])) + writeLine(fileDescriptor, ' process%sRegisterValues(unit.values());' % (propertyName[0].upper() + propertyName[1:])) + writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor, ' });') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' connect(reply, &QModbusReply::errorOccurred, this, [this, reply] (QModbusDevice::Error error){') + writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Modbus reply error occurred while updating \\"%s\\" registers from" << hostAddress().toString() << error << reply->errorString();' % (className, registerDefinition['description'])) + writeLine(fileDescriptor, ' });') writeLine(fileDescriptor, '}') writeLine(fileDescriptor) @@ -138,28 +139,31 @@ def writeBlockUpdateMethodImplementationsTcp(fileDescriptor, className, blockDef writeLine(fileDescriptor, ' return;') writeLine(fileDescriptor, ' }') writeLine(fileDescriptor) - writeLine(fileDescriptor, ' if (!reply->isFinished()) {') - writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, this, [this, reply](){') - writeLine(fileDescriptor, ' if (reply->error() == QModbusDevice::NoError) {') - writeLine(fileDescriptor, ' const QModbusDataUnit unit = reply->result();') - writeLine(fileDescriptor, ' const QVector blockValues = unit.values();') - writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from reading block \\"%s\\" register" << %s << "size:" << %s << blockValues;' % (className, blockName, blockStartAddress, blockSize)) + writeLine(fileDescriptor, ' if (reply->isFinished()) {') + writeLine(fileDescriptor, ' reply->deleteLater(); // Broadcast reply returns immediatly') + writeLine(fileDescriptor, ' return;') + writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, this, [this, reply](){') + writeLine(fileDescriptor, ' if (reply->error() == QModbusDevice::NoError) {') + writeLine(fileDescriptor, ' const QModbusDataUnit unit = reply->result();') + writeLine(fileDescriptor, ' const QVector blockValues = unit.values();') + writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from reading block \\"%s\\" register" << %s << "size:" << %s << blockValues;' % (className, blockName, blockStartAddress, blockSize)) # Start parsing the registers using offsets offset = 0 for i, blockRegister in enumerate(blockRegisters): propertyName = blockRegister['id'] propertyTyp = getCppDataType(blockRegister) - writeLine(fileDescriptor, ' process%sRegisterValues(blockValues.mid(%s, %s));' % (propertyName[0].upper() + propertyName[1:], offset, blockRegister['size'])) + writeLine(fileDescriptor, ' process%sRegisterValues(blockValues.mid(%s, %s));' % (propertyName[0].upper() + propertyName[1:], offset, blockRegister['size'])) offset += blockRegister['size'] - writeLine(fileDescriptor, ' }') - writeLine(fileDescriptor, ' });') + writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor, ' });') writeLine(fileDescriptor) - writeLine(fileDescriptor, ' connect(reply, &QModbusReply::errorOccurred, this, [reply] (QModbusDevice::Error error){') - writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Modbus reply error occurred while updating block \\"%s\\" registers" << error << reply->errorString();' % (className, blockName)) - writeLine(fileDescriptor, ' });') - writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor, ' connect(reply, &QModbusReply::errorOccurred, this, [reply] (QModbusDevice::Error error){') + writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Modbus reply error occurred while updating block \\"%s\\" registers" << error << reply->errorString();' % (className, blockName)) + writeLine(fileDescriptor, ' });') writeLine(fileDescriptor, '}') writeLine(fileDescriptor) @@ -273,7 +277,7 @@ def writeInitMethodImplementationTcp(fileDescriptor, className, registerDefiniti initRequired = True break - for blockDefinition in blockDefinitions: + for blockDefinition in blockDefinitions: if 'readSchedule' in blockDefinition and blockDefinition['readSchedule'] == 'init': initRequired = True break @@ -305,33 +309,34 @@ def writeInitMethodImplementationTcp(fileDescriptor, className, registerDefiniti writeLine(fileDescriptor, ' return false;') writeLine(fileDescriptor, ' }') writeLine(fileDescriptor) - writeLine(fileDescriptor, ' if (!reply->isFinished()) {') - writeLine(fileDescriptor, ' m_pendingInitReplies.append(reply);') - writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);') - writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, m_initObject, [this, reply](){') - writeLine(fileDescriptor, ' m_pendingInitReplies.removeAll(reply);') - writeLine(fileDescriptor, ' if (reply->error() != QModbusDevice::NoError) {') - writeLine(fileDescriptor, ' finishInitialization(false);') - writeLine(fileDescriptor, ' return;') - writeLine(fileDescriptor, ' }') - writeLine(fileDescriptor) - writeLine(fileDescriptor, ' const QModbusDataUnit unit = reply->result();') - writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from init \\"%s\\" register" << %s << "size:" << %s << unit.values();' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size'])) - writeLine(fileDescriptor, ' process%sRegisterValues(unit.values());' % (propertyName[0].upper() + propertyName[1:])) - writeLine(fileDescriptor, ' verifyInitFinished();') - writeLine(fileDescriptor, ' });') - writeLine(fileDescriptor) - writeLine(fileDescriptor, ' connect(reply, &QModbusReply::errorOccurred, m_initObject, [this, reply] (QModbusDevice::Error error){') - writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Modbus reply error occurred while reading \\"%s\\" registers from" << hostAddress().toString() << error << reply->errorString();' % (className, registerDefinition['description'])) - writeLine(fileDescriptor, ' });') - writeLine(fileDescriptor, ' } else {') + writeLine(fileDescriptor, ' if (reply->isFinished()) {') writeLine(fileDescriptor, ' reply->deleteLater(); // Broadcast reply returns immediatly') + writeLine(fileDescriptor, ' return false;') writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' m_pendingInitReplies.append(reply);') + writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);') + writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, m_initObject, [this, reply](){') + writeLine(fileDescriptor, ' m_pendingInitReplies.removeAll(reply);') + writeLine(fileDescriptor, ' if (reply->error() != QModbusDevice::NoError) {') + writeLine(fileDescriptor, ' finishInitialization(false);') + writeLine(fileDescriptor, ' return;') + writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' const QModbusDataUnit unit = reply->result();') + writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from init \\"%s\\" register" << %s << "size:" << %s << unit.values();' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size'])) + writeLine(fileDescriptor, ' process%sRegisterValues(unit.values());' % (propertyName[0].upper() + propertyName[1:])) + writeLine(fileDescriptor, ' verifyInitFinished();') + writeLine(fileDescriptor, ' });') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' connect(reply, &QModbusReply::errorOccurred, m_initObject, [this, reply] (QModbusDevice::Error error){') + writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Modbus reply error occurred while reading \\"%s\\" registers from" << hostAddress().toString() << error << reply->errorString();' % (className, registerDefinition['description'])) + writeLine(fileDescriptor, ' });') # Read init blocks for blockDefinition in blockDefinitions: blockName = blockDefinition['id'] - blockRegisters = blockDefinition['registers'] + blockRegisters = blockDefinition['registers'] if 'readSchedule' in blockDefinition and blockDefinition['readSchedule'] == 'init': blockStartAddress = 0 @@ -357,35 +362,38 @@ def writeInitMethodImplementationTcp(fileDescriptor, className, registerDefiniti writeLine(fileDescriptor, ' return false;') writeLine(fileDescriptor, ' }') writeLine(fileDescriptor) - writeLine(fileDescriptor, ' if (!reply->isFinished()) {') - writeLine(fileDescriptor, ' m_pendingInitReplies.append(reply);') - writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);') - writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, m_initObject, [this, reply](){') - writeLine(fileDescriptor, ' m_pendingInitReplies.removeAll(reply);') - writeLine(fileDescriptor, ' if (reply->error() != QModbusDevice::NoError) {') - writeLine(fileDescriptor, ' finishInitialization(false);') - writeLine(fileDescriptor, ' return;') - writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor, ' if (reply->isFinished()) {') + writeLine(fileDescriptor, ' reply->deleteLater(); // Broadcast reply returns immediatly') + writeLine(fileDescriptor, ' return false;') + writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' m_pendingInitReplies.append(reply);') + writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);') + writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, m_initObject, [this, reply](){') + writeLine(fileDescriptor, ' m_pendingInitReplies.removeAll(reply);') + writeLine(fileDescriptor, ' if (reply->error() != QModbusDevice::NoError) {') + writeLine(fileDescriptor, ' finishInitialization(false);') + writeLine(fileDescriptor, ' return;') + writeLine(fileDescriptor, ' }') - writeLine(fileDescriptor, ' const QModbusDataUnit unit = reply->result();') - writeLine(fileDescriptor, ' const QVector blockValues = unit.values();') - writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from reading init block \\"%s\\" register" << %s << "size:" << %s << blockValues;' % (className, blockName, blockStartAddress, blockSize)) + writeLine(fileDescriptor, ' const QModbusDataUnit unit = reply->result();') + writeLine(fileDescriptor, ' const QVector blockValues = unit.values();') + writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from reading init block \\"%s\\" register" << %s << "size:" << %s << blockValues;' % (className, blockName, blockStartAddress, blockSize)) # Start parsing the registers using offsets offset = 0 for i, blockRegister in enumerate(blockRegisters): propertyName = blockRegister['id'] propertyTyp = getCppDataType(blockRegister) - writeLine(fileDescriptor, ' process%sRegisterValues(blockValues.mid(%s, %s));' % (propertyName[0].upper() + propertyName[1:], offset, blockRegister['size'])) + writeLine(fileDescriptor, ' process%sRegisterValues(blockValues.mid(%s, %s));' % (propertyName[0].upper() + propertyName[1:], offset, blockRegister['size'])) offset += blockRegister['size'] - writeLine(fileDescriptor, ' verifyInitFinished();') - writeLine(fileDescriptor, ' });') + writeLine(fileDescriptor, ' verifyInitFinished();') + writeLine(fileDescriptor, ' });') writeLine(fileDescriptor) - writeLine(fileDescriptor, ' connect(reply, &QModbusReply::errorOccurred, m_initObject, [reply] (QModbusDevice::Error error){') - writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Modbus reply error occurred while updating block \\"%s\\" registers" << error << reply->errorString();' % (className, blockName)) - writeLine(fileDescriptor, ' });') - writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor, ' connect(reply, &QModbusReply::errorOccurred, m_initObject, [reply] (QModbusDevice::Error error){') + writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Modbus reply error occurred while updating block \\"%s\\" registers" << error << reply->errorString();' % (className, blockName)) + writeLine(fileDescriptor, ' });') writeLine(fileDescriptor) else: @@ -395,3 +403,138 @@ def writeInitMethodImplementationTcp(fileDescriptor, className, registerDefiniti writeLine(fileDescriptor, ' return true;') writeLine(fileDescriptor, '}') writeLine(fileDescriptor) + + +def writeUpdateMethodTcp(fileDescriptor, className, registerDefinitions, blockDefinitions): + writeLine(fileDescriptor, 'bool %s::update()' % (className)) + writeLine(fileDescriptor, '{') + + # First check if there are any init registers + updateRequired = False + for registerDefinition in registerDefinitions: + if registerDefinition['readSchedule'] == 'update': + updateRequired = True + break + + for blockDefinition in blockDefinitions: + if 'readSchedule' in blockDefinition and blockDefinition['readSchedule'] == 'update': + updateRequired = True + break + + if updateRequired: + writeLine(fileDescriptor, ' if (!connected())') + writeLine(fileDescriptor, ' return false;') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' if (!m_pendingUpdateReplies.isEmpty()) {') + writeLine(fileDescriptor, ' qCDebug(dc%s()) << "Tried to update but there are still some update replies pending. Waiting for them to be finished...";' % className) + writeLine(fileDescriptor, ' return true;') + writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' QModbusReply *reply = nullptr;') + + # Read individual registers + for registerDefinition in registerDefinitions: + propertyName = registerDefinition['id'] + propertyTyp = getCppDataType(registerDefinition) + + if 'readSchedule' in registerDefinition and registerDefinition['readSchedule'] == 'update': + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' // Read %s' % registerDefinition['description']) + writeLine(fileDescriptor, ' reply = read%s();' % (propertyName[0].upper() + propertyName[1:])) + writeLine(fileDescriptor, ' if (!reply) {') + writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading \\"%s\\" registers from" << hostAddress().toString() << errorString();' % (className, registerDefinition['description'])) + writeLine(fileDescriptor, ' return false;') + writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' if (reply->isFinished()) {') + writeLine(fileDescriptor, ' reply->deleteLater(); // Broadcast reply returns immediatly') + writeLine(fileDescriptor, ' return false;') + writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' m_pendingUpdateReplies.append(reply);') + writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);') + writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, m_initObject, [this, reply](){') + writeLine(fileDescriptor, ' m_pendingUpdateReplies.removeAll(reply);') + writeLine(fileDescriptor, ' if (reply->error() != QModbusDevice::NoError) {') + writeLine(fileDescriptor, ' verifyUpdateFinished();') + writeLine(fileDescriptor, ' return;') + writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' const QModbusDataUnit unit = reply->result();') + writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from init \\"%s\\" register" << %s << "size:" << %s << unit.values();' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size'])) + writeLine(fileDescriptor, ' process%sRegisterValues(unit.values());' % (propertyName[0].upper() + propertyName[1:])) + writeLine(fileDescriptor, ' verifyUpdateFinished();') + writeLine(fileDescriptor, ' });') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' connect(reply, &QModbusReply::errorOccurred, m_initObject, [this, reply] (QModbusDevice::Error error){') + writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Modbus reply error occurred while reading \\"%s\\" registers from" << hostAddress().toString() << error << reply->errorString();' % (className, registerDefinition['description'])) + writeLine(fileDescriptor, ' });') + + # Read init blocks + for blockDefinition in blockDefinitions: + blockName = blockDefinition['id'] + blockRegisters = blockDefinition['registers'] + + if 'readSchedule' in blockDefinition and blockDefinition['readSchedule'] == 'update': + blockStartAddress = 0 + registerCount = 0 + blockSize = 0 + registerType = "" + + for i, blockRegister in enumerate(blockRegisters): + if i == 0: + blockStartAddress = blockRegister['address'] + registerType = blockRegister['registerType'] + + registerCount += 1 + blockSize += blockRegister['size'] + + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' // Read %s' % blockName) + writeLine(fileDescriptor, ' reply = readBlock%s();' % (blockName[0].upper() + blockName[1:])) + writeLine(fileDescriptor, ' if (!reply) {') + writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading block \\"%s\\" registers";' % (className, blockName)) + writeLine(fileDescriptor, ' return false;') + writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' if (reply->isFinished()) {') + writeLine(fileDescriptor, ' reply->deleteLater(); // Broadcast reply returns immediatly') + writeLine(fileDescriptor, ' return false;') + writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' m_pendingUpdateReplies.append(reply);') + writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, reply, &QModbusReply::deleteLater);') + writeLine(fileDescriptor, ' connect(reply, &QModbusReply::finished, m_initObject, [this, reply](){') + writeLine(fileDescriptor, ' m_pendingUpdateReplies.removeAll(reply);') + writeLine(fileDescriptor, ' if (reply->error() != QModbusDevice::NoError) {') + writeLine(fileDescriptor, ' verifyUpdateFinished();') + writeLine(fileDescriptor, ' return;') + writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' const QModbusDataUnit unit = reply->result();') + writeLine(fileDescriptor, ' const QVector blockValues = unit.values();') + writeLine(fileDescriptor, ' qCDebug(dc%s()) << "<-- Response from reading init block \\"%s\\" register" << %s << "size:" << %s << blockValues;' % (className, blockName, blockStartAddress, blockSize)) + + # Start parsing the registers using offsets + offset = 0 + for i, blockRegister in enumerate(blockRegisters): + propertyName = blockRegister['id'] + propertyTyp = getCppDataType(blockRegister) + writeLine(fileDescriptor, ' process%sRegisterValues(blockValues.mid(%s, %s));' % (propertyName[0].upper() + propertyName[1:], offset, blockRegister['size'])) + offset += blockRegister['size'] + + writeLine(fileDescriptor, ' verifyUpdateFinished();') + writeLine(fileDescriptor, ' });') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' connect(reply, &QModbusReply::errorOccurred, m_initObject, [reply] (QModbusDevice::Error error){') + writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Modbus reply error occurred while updating block \\"%s\\" registers" << error << reply->errorString();' % (className, blockName)) + writeLine(fileDescriptor, ' });') + writeLine(fileDescriptor) + + else: + writeLine(fileDescriptor, ' // No update registers defined. Nothing to be done and we are finished.') + writeLine(fileDescriptor, ' emit updateFinished();') + + writeLine(fileDescriptor, ' return true;') + writeLine(fileDescriptor, '}') + writeLine(fileDescriptor) diff --git a/libnymea-modbus/tools/connectiontool/toolcommon.py b/libnymea-modbus/tools/connectiontool/toolcommon.py index f7740d8..ea52f20 100644 --- a/libnymea-modbus/tools/connectiontool/toolcommon.py +++ b/libnymea-modbus/tools/connectiontool/toolcommon.py @@ -435,23 +435,23 @@ def writeRegistersDebugLine(fileDescriptor, debugObjectParamName, registerDefini writeLine(fileDescriptor, ' debug.nospace().noquote() << %s << "\\n";' % (line)) -def writeUpdateMethod(fileDescriptor, className, registerDefinitions, blockDefinitions): - writeLine(fileDescriptor, 'bool %s::update()' % (className)) - writeLine(fileDescriptor, '{') - for registerDefinition in registerDefinitions: - propertyName = registerDefinition['id'] - if 'readSchedule' in registerDefinition and registerDefinition['readSchedule'] == 'update': - writeLine(fileDescriptor, ' update%s();' % (propertyName[0].upper() + propertyName[1:])) +# def writeUpdateMethod(fileDescriptor, className, registerDefinitions, blockDefinitions): +# writeLine(fileDescriptor, 'bool %s::update()' % (className)) +# writeLine(fileDescriptor, '{') +# for registerDefinition in registerDefinitions: +# propertyName = registerDefinition['id'] +# if 'readSchedule' in registerDefinition and registerDefinition['readSchedule'] == 'update': +# writeLine(fileDescriptor, ' update%s();' % (propertyName[0].upper() + propertyName[1:])) - # Add the update block methods - for blockDefinition in blockDefinitions: - blockName = blockDefinition['id'] - if 'readSchedule' in blockDefinition and blockDefinition['readSchedule'] == 'update': - writeLine(fileDescriptor, ' update%sBlock();' % (blockName[0].upper() + blockName[1:])) +# # Add the update block methods +# for blockDefinition in blockDefinitions: +# blockName = blockDefinition['id'] +# if 'readSchedule' in blockDefinition and blockDefinition['readSchedule'] == 'update': +# writeLine(fileDescriptor, ' update%sBlock();' % (blockName[0].upper() + blockName[1:])) - writeLine(fileDescriptor, ' return true;') - writeLine(fileDescriptor, '}') - writeLine(fileDescriptor) +# writeLine(fileDescriptor, ' return true;') +# writeLine(fileDescriptor, '}') +# writeLine(fileDescriptor) def writePropertyChangedSignals(fileDescriptor, registerDefinitions): diff --git a/libnymea-modbus/tools/generate-connection.py b/libnymea-modbus/tools/generate-connection.py index 75985fc..5366191 100644 --- a/libnymea-modbus/tools/generate-connection.py +++ b/libnymea-modbus/tools/generate-connection.py @@ -172,7 +172,13 @@ def writeTcpSourceFile(): writeLine(sourceFile, ' ModbusTCPMaster(hostAddress, port, parent),') writeLine(sourceFile, ' m_slaveId(slaveId)') writeLine(sourceFile, '{') - writeLine(sourceFile) + writeLine(sourceFile, ' connect(this, &ModbusTCPMaster::connectionStateChanged, this, [this](bool status){') + writeLine(sourceFile, ' if (status) {') + writeLine(sourceFile, ' // Cleanup before starting to initialize') + writeLine(sourceFile, ' m_pendingInitReplies.clear();') + writeLine(sourceFile, ' m_pendingUpdateReplies.clear();') + writeLine(sourceFile, ' }') + writeLine(sourceFile, ' });') writeLine(sourceFile, '}') writeLine(sourceFile) @@ -204,7 +210,7 @@ def writeTcpSourceFile(): blocks = registerJson['blocks'] writeInitMethodImplementationTcp(sourceFile, className, registerJson['registers'], blocks) - writeUpdateMethod(sourceFile, className, registerJson['registers'], blocks) + writeUpdateMethodTcp(sourceFile, className, registerJson['registers'], blocks) # Write update methods writePropertyUpdateMethodImplementationsTcp(sourceFile, className, registerJson['registers']) @@ -256,6 +262,9 @@ def writeTcpSourceFile(): writeLine(sourceFile, 'void %s::verifyUpdateFinished()' % (className)) writeLine(sourceFile, '{') + writeLine(sourceFile, ' if (m_pendingUpdateReplies.isEmpty()) {') + writeLine(sourceFile, ' emit updateFinished();') + writeLine(sourceFile, ' }') writeLine(sourceFile, '}') writeLine(sourceFile)