From d55a30f0a832d4d58b8b4d2fda14e7c2956d4aed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Wed, 27 Jul 2022 11:42:28 +0200 Subject: [PATCH] Update init mechanism of modbus-tool connection classes --- huawei/huaweifusionsolar.cpp | 10 +- huawei/huaweifusionsolar.h | 4 +- .../tools/connectiontool/modbusrtu.py | 167 ++++++++-------- .../tools/connectiontool/modbustcp.py | 180 ++++++++++-------- .../tools/connectiontool/toolcommon.py | 3 +- libnymea-modbus/tools/generate-connection.py | 117 ++++++++---- libnymea-modbus/tools/test-registers.json | 117 ++++++++++++ 7 files changed, 400 insertions(+), 198 deletions(-) create mode 100644 libnymea-modbus/tools/test-registers.json diff --git a/huawei/huaweifusionsolar.cpp b/huawei/huaweifusionsolar.cpp index 18aff94..9298378 100644 --- a/huawei/huaweifusionsolar.cpp +++ b/huawei/huaweifusionsolar.cpp @@ -40,17 +40,18 @@ HuaweiFusionSolar::HuaweiFusionSolar(const QHostAddress &hostAddress, uint port, } -void HuaweiFusionSolar::initialize() +bool HuaweiFusionSolar::initialize() { // No init registers defined. Nothing to be done and we are finished. - emit initializationFinished(); + emit initializationFinished(true); + return true; } -void HuaweiFusionSolar::update() +bool HuaweiFusionSolar::update() { // Make sure there is not an update still running if (!m_registersQueue.isEmpty()) - return; + return true; // Add the requests m_registersQueue.enqueue(HuaweiModbusTcpConnection::RegisterInverterActivePower); @@ -72,6 +73,7 @@ void HuaweiFusionSolar::update() m_currentRegisterRequest = -1; readNextRegister(); + return true; } void HuaweiFusionSolar::readNextRegister() diff --git a/huawei/huaweifusionsolar.h b/huawei/huaweifusionsolar.h index a208fbb..2f9de41 100644 --- a/huawei/huaweifusionsolar.h +++ b/huawei/huaweifusionsolar.h @@ -42,8 +42,8 @@ class HuaweiFusionSolar : public HuaweiModbusTcpConnection public: explicit HuaweiFusionSolar(const QHostAddress &hostAddress, uint port, quint16 slaveId, QObject *parent = nullptr); - virtual void initialize() override; - virtual void update() override; + virtual bool initialize() override; + virtual bool update() override; private: diff --git a/libnymea-modbus/tools/connectiontool/modbusrtu.py b/libnymea-modbus/tools/connectiontool/modbusrtu.py index 228fd88..f272b2c 100644 --- a/libnymea-modbus/tools/connectiontool/modbusrtu.py +++ b/libnymea-modbus/tools/connectiontool/modbusrtu.py @@ -86,22 +86,23 @@ def writePropertyUpdateMethodImplementationsRtu(fileDescriptor, className, regis writeLine(fileDescriptor, ' // Update registers from %s' % registerDefinition['description']) writeLine(fileDescriptor, ' qCDebug(dc%s()) << "--> Read \\"%s\\" register:" << %s << "size:" << %s;' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size'])) writeLine(fileDescriptor, ' ModbusRtuReply *reply = read%s();' % (propertyName[0].upper() + propertyName[1:])) - writeLine(fileDescriptor, ' if (reply) {') - writeLine(fileDescriptor, ' if (!reply->isFinished()) {') - writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::finished, this, [this, reply](){') - writeLine(fileDescriptor, ' if (reply->error() == ModbusRtuReply::NoError) {') - 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, ' }') - 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, ' }') - writeLine(fileDescriptor, ' } else {') + writeLine(fileDescriptor, ' if (!reply) {') writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading \\"%s\\" registers";' % (className, registerDefinition['description'])) + writeLine(fileDescriptor, ' return;') + writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' if (!reply->isFinished()) {') + writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::finished, this, [this, reply](){') + writeLine(fileDescriptor, ' if (reply->error() == ModbusRtuReply::NoError) {') + 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, ' }') + 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, ' }') writeLine(fileDescriptor, '}') writeLine(fileDescriptor) @@ -142,32 +143,33 @@ def writeBlockUpdateMethodImplementationsRtu(fileDescriptor, className, blockDef #Default to holdingRegister writeLine(fileDescriptor, ' ModbusRtuReply *reply = m_modbusRtuMaster->readHoldingRegister(m_slaveId, %s, %s);' % (blockStartAddress, blockSize)) - writeLine(fileDescriptor, ' if (reply) {') - writeLine(fileDescriptor, ' if (!reply->isFinished()) {') - writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::finished, this, [this, reply](){') - writeLine(fileDescriptor, ' if (reply->error() == ModbusRtuReply::NoError) {') - 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) {') + writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading block \\"%s\\" registers";' % (className, blockName)) + writeLine(fileDescriptor, ' return;') + writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' if (!reply->isFinished()) {') + writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::finished, this, [this, reply](){') + writeLine(fileDescriptor, ' if (reply->error() == ModbusRtuReply::NoError) {') + 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'] - 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, &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, ' } else {') - writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading block \\"%s\\" registers";' % (className, blockName)) + 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, '}') - writeLine(fileDescriptor) + writeLine(fileDescriptor) ############################################################## @@ -221,7 +223,7 @@ def writeInternalBlockReadMethodDeclarationsRtu(fileDescriptor, blockDefinitions if 'unit' in registerDefinition and registerDefinition['unit'] != '': writeLine(fileDescriptor, ' - %s [%s] - Address: %s, Size: %s' % (registerDefinition['description'], registerDefinition['unit'], registerDefinition['address'], registerDefinition['size'])) else: - writeLine(fileDescriptor, ' -- %s - Address: %s, Size: %s' % (registerDefinition['description'], registerDefinition['address'], registerDefinition['size'])) + writeLine(fileDescriptor, ' - %s - Address: %s, Size: %s' % (registerDefinition['description'], registerDefinition['address'], registerDefinition['size'])) writeLine(fileDescriptor, ' */' ) writeLine(fileDescriptor, ' ModbusRtuReply *readBlock%s();' % (blockName[0].upper() + blockName[1:])) writeLine(fileDescriptor) @@ -265,7 +267,7 @@ def writeInternalBlockReadMethodImplementationsRtu(fileDescriptor, className, bl ############################################################## def writeInitMethodImplementationRtu(fileDescriptor, className, registerDefinitions, blockDefinitions): - writeLine(fileDescriptor, 'void %s::initialize()' % (className)) + writeLine(fileDescriptor, 'bool %s::initialize()' % (className)) writeLine(fileDescriptor, '{') # First check if there are any init registers @@ -281,12 +283,15 @@ def writeInitMethodImplementationRtu(fileDescriptor, className, registerDefiniti break if initRequired: - writeLine(fileDescriptor, ' ModbusRtuReply *reply = nullptr;') - writeLine(fileDescriptor) - writeLine(fileDescriptor, ' if (!m_pendingInitReplies.isEmpty()) {') - writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Tried to initialize but there are still some init replies pending.";' % className) - writeLine(fileDescriptor, ' return;') + writeLine(fileDescriptor, ' if (m_initObject) {') + writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Tried to initialize but the init process is already running.";' % className) + writeLine(fileDescriptor, ' return false;') writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' // Parent object for the init process') + writeLine(fileDescriptor, ' m_initObject = new QObject(this);') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' ModbusRtuReply *reply = nullptr;') # Read individual registers for registerDefinition in registerDefinitions: @@ -297,26 +302,30 @@ def writeInitMethodImplementationRtu(fileDescriptor, className, registerDefiniti writeLine(fileDescriptor) writeLine(fileDescriptor, ' // Read %s' % registerDefinition['description']) writeLine(fileDescriptor, ' reply = read%s();' % (propertyName[0].upper() + propertyName[1:])) - writeLine(fileDescriptor, ' if (reply) {') - writeLine(fileDescriptor, ' if (!reply->isFinished()) {') - writeLine(fileDescriptor, ' m_pendingInitReplies.append(reply);') - writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::finished, this, [this, reply](){') - writeLine(fileDescriptor, ' if (reply->error() == ModbusRtuReply::NoError) {') - 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, ' }') - writeLine(fileDescriptor) - writeLine(fileDescriptor, ' m_pendingInitReplies.removeAll(reply);') - writeLine(fileDescriptor, ' verifyInitFinished();') - 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, ' }') - writeLine(fileDescriptor, ' } else {') + writeLine(fileDescriptor, ' if (!reply) {') writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading \\"%s\\" registers";' % (className, registerDefinition['description'])) + writeLine(fileDescriptor, ' finishInitialization(false);') + 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, ' m_pendingInitReplies.removeAll(reply);') + 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, ' }') # Read init blocks @@ -341,39 +350,45 @@ def writeInitMethodImplementationRtu(fileDescriptor, className, registerDefiniti writeLine(fileDescriptor) writeLine(fileDescriptor, ' // Read %s' % blockName) writeLine(fileDescriptor, ' reply = readBlock%s();' % (blockName[0].upper() + blockName[1:])) - writeLine(fileDescriptor, ' if (reply) {') - writeLine(fileDescriptor, ' if (!reply->isFinished()) {') - writeLine(fileDescriptor, ' m_pendingInitReplies.append(reply);') - writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::finished, this, [this, reply](){') - writeLine(fileDescriptor, ' if (reply->error() == ModbusRtuReply::NoError) {') - 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) {') + writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading block \\"%s\\" registers";' % (className, blockName)) + writeLine(fileDescriptor, ' finishInitialization(false);') + 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, ' m_pendingInitReplies.removeAll(reply);') + 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, ' m_pendingInitReplies.removeAll(reply);') - writeLine(fileDescriptor, ' verifyInitFinished();') - writeLine(fileDescriptor, ' }') - writeLine(fileDescriptor, ' });') + writeLine(fileDescriptor, ' verifyInitFinished();') + 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, ' } else {') - writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading block \\"%s\\" registers";' % (className, blockName)) + 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) else: writeLine(fileDescriptor, ' // No init registers defined. Nothing to be done and we are finished.') - writeLine(fileDescriptor, ' emit initializationFinished();') + writeLine(fileDescriptor, ' emit initializationFinished(true);') + writeLine(fileDescriptor, ' return true;') writeLine(fileDescriptor, '}') writeLine(fileDescriptor) diff --git a/libnymea-modbus/tools/connectiontool/modbustcp.py b/libnymea-modbus/tools/connectiontool/modbustcp.py index bf66b74..75c76c3 100644 --- a/libnymea-modbus/tools/connectiontool/modbustcp.py +++ b/libnymea-modbus/tools/connectiontool/modbustcp.py @@ -85,25 +85,26 @@ def writePropertyUpdateMethodImplementationsTcp(fileDescriptor, className, regis writeLine(fileDescriptor, ' // Update registers from %s' % registerDefinition['description']) writeLine(fileDescriptor, ' qCDebug(dc%s()) << "--> Read \\"%s\\" register:" << %s << "size:" << %s;' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size'])) writeLine(fileDescriptor, ' QModbusReply *reply = read%s();' % (propertyName[0].upper() + propertyName[1:])) - writeLine(fileDescriptor, ' if (reply) {') - 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, ' reply->deleteLater(); // Broadcast reply returns immediatly') - writeLine(fileDescriptor, ' }') - writeLine(fileDescriptor, ' } else {') + 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;') + 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, ' reply->deleteLater(); // Broadcast reply returns immediatly') writeLine(fileDescriptor, ' }') writeLine(fileDescriptor, '}') writeLine(fileDescriptor) @@ -132,31 +133,32 @@ def writeBlockUpdateMethodImplementationsTcp(fileDescriptor, className, blockDef writeLine(fileDescriptor, ' // Update register block \"%s\"' % blockName) writeLine(fileDescriptor, ' qCDebug(dc%s()) << "--> Read block \\"%s\\" registers from:" << %s << "size:" << %s;' % (className, blockName, blockStartAddress, blockSize)) writeLine(fileDescriptor, ' QModbusReply *reply = readBlock%s();' % (blockName[0].upper() + blockName[1:])) - writeLine(fileDescriptor, ' if (reply) {') - 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) {') + writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading block \\"%s\\" registers";' % (className, blockName)) + 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)) # 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, ' } else {') - writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading block \\"%s\\" registers";' % (className, blockName)) + 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, '}') writeLine(fileDescriptor) @@ -261,7 +263,7 @@ def writeInternalBlockReadMethodImplementationsTcp(fileDescriptor, className, bl ############################################################## def writeInitMethodImplementationTcp(fileDescriptor, className, registerDefinitions, blockDefinitions): - writeLine(fileDescriptor, 'void %s::initialize()' % (className)) + writeLine(fileDescriptor, 'bool %s::initialize()' % (className)) writeLine(fileDescriptor, '{') # First check if there are any init registers @@ -277,12 +279,15 @@ def writeInitMethodImplementationTcp(fileDescriptor, className, registerDefiniti break if initRequired: - writeLine(fileDescriptor, ' QModbusReply *reply = nullptr;') - writeLine(fileDescriptor) - writeLine(fileDescriptor, ' if (!m_pendingInitReplies.isEmpty()) {') - writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Tried to initialize but there are still some init replies pending.";' % className) - writeLine(fileDescriptor, ' return;') + writeLine(fileDescriptor, ' if (m_initObject) {') + writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Tried to initialize but the init process is already running.";' % className) + writeLine(fileDescriptor, ' return false;') writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' // Parent object for the init process') + writeLine(fileDescriptor, ' m_initObject = new QObject(this);') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' QModbusReply *reply = nullptr;') # Read individual registers for registerDefinition in registerDefinitions: @@ -294,29 +299,33 @@ def writeInitMethodImplementationTcp(fileDescriptor, className, registerDefiniti writeLine(fileDescriptor, ' // Read %s' % registerDefinition['description']) writeLine(fileDescriptor, ' qCDebug(dc%s()) << "--> Read init \\"%s\\" register:" << %s << "size:" << %s;' % (className, registerDefinition['description'], registerDefinition['address'], registerDefinition['size'])) writeLine(fileDescriptor, ' reply = read%s();' % (propertyName[0].upper() + propertyName[1:])) - writeLine(fileDescriptor, ' if (reply) {') - 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, this, [this, reply](){') - writeLine(fileDescriptor, ' if (reply->error() == QModbusDevice::NoError) {') - 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, ' }') - writeLine(fileDescriptor) - writeLine(fileDescriptor, ' m_pendingInitReplies.removeAll(reply);') - writeLine(fileDescriptor, ' verifyInitFinished();') - 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 reading \\"%s\\" registers from" << hostAddress().toString() << error << reply->errorString();' % (className, registerDefinition['description'])) - writeLine(fileDescriptor, ' });') - writeLine(fileDescriptor, ' } else {') - writeLine(fileDescriptor, ' reply->deleteLater(); // Broadcast reply returns immediatly') - writeLine(fileDescriptor, ' }') - writeLine(fileDescriptor, ' } else {') + writeLine(fileDescriptor, ' if (!reply) {') writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading \\"%s\\" registers from" << hostAddress().toString() << errorString();' % (className, registerDefinition['description'])) + writeLine(fileDescriptor, ' finishInitialization(false);') + 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, ' reply->deleteLater(); // Broadcast reply returns immediatly') writeLine(fileDescriptor, ' }') # Read init blocks @@ -342,40 +351,47 @@ def writeInitMethodImplementationTcp(fileDescriptor, className, registerDefiniti writeLine(fileDescriptor, ' // Read %s' % blockName) writeLine(fileDescriptor, ' qCDebug(dc%s()) << "--> Read init block \\"%s\\" registers from:" << %s << "size:" << %s;' % (className, blockName, blockStartAddress, blockSize)) writeLine(fileDescriptor, ' reply = readBlock%s();' % (blockName[0].upper() + blockName[1:])) - writeLine(fileDescriptor, ' if (reply) {') - writeLine(fileDescriptor, ' if (!reply->isFinished()) {') - writeLine(fileDescriptor, ' m_pendingInitReplies.append(reply);') - 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 init block \\"%s\\" register" << %s << "size:" << %s << blockValues;' % (className, blockName, blockStartAddress, blockSize)) + writeLine(fileDescriptor, ' if (!reply) {') + writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading block \\"%s\\" registers";' % (className, blockName)) + writeLine(fileDescriptor, ' finishInitialization(false);') + 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, ' 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, ' m_pendingInitReplies.removeAll(reply);') - writeLine(fileDescriptor, ' verifyInitFinished();') - writeLine(fileDescriptor, ' }') - writeLine(fileDescriptor, ' });') + writeLine(fileDescriptor, ' verifyInitFinished();') + 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, ' } else {') - writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Error occurred while reading block \\"%s\\" registers";' % (className, blockName)) + 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) else: writeLine(fileDescriptor, ' // No init registers defined. Nothing to be done and we are finished.') - writeLine(fileDescriptor, ' emit initializationFinished();') + writeLine(fileDescriptor, ' emit initializationFinished(true);') + 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 6b2cdcb..f7740d8 100644 --- a/libnymea-modbus/tools/connectiontool/toolcommon.py +++ b/libnymea-modbus/tools/connectiontool/toolcommon.py @@ -436,7 +436,7 @@ def writeRegistersDebugLine(fileDescriptor, debugObjectParamName, registerDefini def writeUpdateMethod(fileDescriptor, className, registerDefinitions, blockDefinitions): - writeLine(fileDescriptor, 'void %s::update()' % (className)) + writeLine(fileDescriptor, 'bool %s::update()' % (className)) writeLine(fileDescriptor, '{') for registerDefinition in registerDefinitions: propertyName = registerDefinition['id'] @@ -449,6 +449,7 @@ def writeUpdateMethod(fileDescriptor, className, registerDefinitions, blockDefin 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) diff --git a/libnymea-modbus/tools/generate-connection.py b/libnymea-modbus/tools/generate-connection.py index 76805b6..f7f66c9 100644 --- a/libnymea-modbus/tools/generate-connection.py +++ b/libnymea-modbus/tools/generate-connection.py @@ -44,7 +44,6 @@ def writeTcpHeaderFile(): writeLine(headerFile) writeLine(headerFile, '#include ') writeLine(headerFile, '#include ') - writeLine(headerFile) # Begin of class @@ -80,11 +79,6 @@ def writeTcpHeaderFile(): # Write block get/set method declarations writeBlocksUpdateMethodDeclarations(headerFile, registerJson['blocks']) - # Write init and update method declarations - writeLine(headerFile, ' virtual void initialize();') - writeLine(headerFile, ' virtual void update();') - writeLine(headerFile) - writePropertyUpdateMethodDeclarations(headerFile, registerJson['registers']) writeLine(headerFile) if 'blocks' in registerJson: @@ -103,9 +97,16 @@ def writeTcpHeaderFile(): writeLine(headerFile) + # Write init and update method declarations + writeLine(headerFile, ' virtual bool initialize();') + writeLine(headerFile, ' virtual bool update();') + writeLine(headerFile) + # Write registers value changed signals writeLine(headerFile, 'signals:') - writeLine(headerFile, ' void initializationFinished();') + writeLine(headerFile, ' void initializationFinished(bool success);') + writeLine(headerFile, ' void updateFinished();') + writeLine(headerFile) writeLine(headerFile, ' void endiannessChanged(ModbusDataUtils::ByteOrder endianness);') writeLine(headerFile) writePropertyChangedSignals(headerFile, registerJson['registers']) @@ -114,34 +115,35 @@ def writeTcpHeaderFile(): for blockDefinition in registerJson['blocks']: writePropertyChangedSignals(headerFile, blockDefinition['registers']) - writeLine(headerFile) + writeLine(headerFile) # Protected members writeLine(headerFile, 'protected:') - - writeLine(headerFile) writeProtectedPropertyMembers(headerFile, registerJson['registers']) if 'blocks' in registerJson: for blockDefinition in registerJson['blocks']: writeProtectedPropertyMembers(headerFile, blockDefinition['registers']) - writeLine(headerFile) + writeLine(headerFile) writePropertyProcessMethodDeclaration(headerFile, registerJson['registers']) if 'blocks' in registerJson: for blockDefinition in registerJson['blocks']: writePropertyProcessMethodDeclaration(headerFile, blockDefinition['registers']) - writeLine(headerFile) - # Private members writeLine(headerFile, 'private:') - writeLine(headerFile, ' quint16 m_slaveId = 1;') - writeLine(headerFile, ' QVector m_pendingInitReplies;') writeLine(headerFile, ' ModbusDataUtils::ByteOrder m_endianness = ModbusDataUtils::ByteOrder%s;' % endianness) + writeLine(headerFile, ' quint16 m_slaveId = 1;') writeLine(headerFile) + writeLine(headerFile, ' QVector m_pendingInitReplies;') + writeLine(headerFile, ' QVector m_pendingUpdateReplies;') + writeLine(headerFile) + writeLine(headerFile, ' QObject *m_initObject = nullptr;') writeLine(headerFile, ' void verifyInitFinished();') + writeLine(headerFile, ' void finishInitialization(bool success);') writeLine(headerFile) + writeLine(headerFile, ' void verifyUpdateFinished();') # End of class writeLine(headerFile) @@ -170,7 +172,7 @@ def writeTcpSourceFile(): writeLine(sourceFile, ' ModbusTCPMaster(hostAddress, port, parent),') writeLine(sourceFile, ' m_slaveId(slaveId)') writeLine(sourceFile, '{') - writeLine(sourceFile, ' ') + writeLine(sourceFile) writeLine(sourceFile, '}') writeLine(sourceFile) @@ -184,7 +186,7 @@ def writeTcpSourceFile(): writeLine(sourceFile, '{') writeLine(sourceFile, ' if (m_endianness == endianness)') writeLine(sourceFile, ' return;') - writeLine(sourceFile,) + writeLine(sourceFile) writeLine(sourceFile, ' m_endianness = endianness;') writeLine(sourceFile, ' emit endiannessChanged(m_endianness);') writeLine(sourceFile, '}') @@ -230,12 +232,33 @@ def writeTcpSourceFile(): writeLine(sourceFile, 'void %s::verifyInitFinished()' % (className)) writeLine(sourceFile, '{') writeLine(sourceFile, ' if (m_pendingInitReplies.isEmpty()) {') - writeLine(sourceFile, ' qCDebug(dc%s()) << "Initialization finished of %s" << hostAddress().toString();' % (className, className)) - writeLine(sourceFile, ' emit initializationFinished();') + writeLine(sourceFile, ' finishInitialization(true);') writeLine(sourceFile, ' }') writeLine(sourceFile, '}') writeLine(sourceFile) + writeLine(sourceFile, 'void %s::finishInitialization(bool success)' % (className)) + writeLine(sourceFile, '{') + writeLine(sourceFile, ' if (success) {') + writeLine(sourceFile, ' qCDebug(dc%s()) << "Initialization finished of %s" << hostAddress().toString() << "finished successfully";' % (className, className)) + writeLine(sourceFile, ' } else {') + writeLine(sourceFile, ' qCWarning(dc%s()) << "Initialization finished of %s" << hostAddress().toString() << "failed.";' % (className, className)) + writeLine(sourceFile, ' }') + writeLine(sourceFile) + writeLine(sourceFile, ' // Cleanup init') + writeLine(sourceFile, ' delete m_initObject;') + writeLine(sourceFile, ' m_initObject = nullptr;') + writeLine(sourceFile, ' m_pendingInitReplies.clear();') + writeLine(sourceFile) + writeLine(sourceFile, ' emit initializationFinished(success);') + writeLine(sourceFile, '}') + writeLine(sourceFile) + + writeLine(sourceFile, 'void %s::verifyUpdateFinished()' % (className)) + writeLine(sourceFile, '{') + writeLine(sourceFile, '}') + writeLine(sourceFile) + # Write the debug print debugObjectParamName = className[0].lower() + className[1:] writeLine(sourceFile, 'QDebug operator<<(QDebug debug, %s *%s)' % (className, debugObjectParamName)) @@ -289,7 +312,6 @@ def writeRtuHeaderFile(): writeLine(headerFile, ' explicit %s(ModbusRtuMaster *modbusRtuMaster, quint16 slaveId, QObject *parent = nullptr);' % className) writeLine(headerFile, ' ~%s() = default;' % className) writeLine(headerFile) - writeLine(headerFile, ' ModbusRtuMaster *modbusRtuMaster() const;') writeLine(headerFile, ' quint16 slaveId() const;') writeLine(headerFile) @@ -306,11 +328,6 @@ def writeRtuHeaderFile(): # Write block get/set method declarations writeBlocksUpdateMethodDeclarations(headerFile, registerJson['blocks']) - # Write init and update method declarations - writeLine(headerFile, ' virtual void initialize();') - writeLine(headerFile, ' virtual void update();') - writeLine(headerFile) - writePropertyUpdateMethodDeclarations(headerFile, registerJson['registers']) writeLine(headerFile) if 'blocks' in registerJson: @@ -327,10 +344,16 @@ def writeRtuHeaderFile(): writeLine(headerFile) writeInternalBlockReadMethodDeclarationsRtu(headerFile, registerJson['blocks']) + # Write init and update method declarations + writeLine(headerFile, ' virtual bool initialize();') + writeLine(headerFile, ' virtual bool update();') + writeLine(headerFile) # Write registers value changed signals writeLine(headerFile, 'signals:') - writeLine(headerFile, ' void initializationFinished();') + writeLine(headerFile, ' void initializationFinished(bool success);') + writeLine(headerFile, ' void updateFinished();') + writeLine(headerFile) writeLine(headerFile, ' void endiannessChanged(ModbusDataUtils::ByteOrder endianness);') writeLine(headerFile) writePropertyChangedSignals(headerFile, registerJson['registers']) @@ -342,7 +365,6 @@ def writeRtuHeaderFile(): # Protected members writeLine(headerFile, 'protected:') - writeProtectedPropertyMembers(headerFile, registerJson['registers']) if 'blocks' in registerJson: for blockDefinition in registerJson['blocks']: @@ -355,17 +377,22 @@ def writeRtuHeaderFile(): for blockDefinition in registerJson['blocks']: writePropertyProcessMethodDeclaration(headerFile, blockDefinition['registers']) - writeLine(headerFile) + writeLine(headerFile) # Private members writeLine(headerFile, 'private:') writeLine(headerFile, ' ModbusRtuMaster *m_modbusRtuMaster = nullptr;') - writeLine(headerFile, ' quint16 m_slaveId = 1;') - writeLine(headerFile, ' QVector m_pendingInitReplies;') writeLine(headerFile, ' ModbusDataUtils::ByteOrder m_endianness = ModbusDataUtils::ByteOrder%s;' % endianness) + writeLine(headerFile, ' quint16 m_slaveId = 1;') writeLine(headerFile) + writeLine(headerFile, ' QVector m_pendingInitReplies;') + writeLine(headerFile, ' QVector m_pendingUpdateReplies;') + writeLine(headerFile) + writeLine(headerFile, ' QObject *m_initObject = nullptr;') writeLine(headerFile, ' void verifyInitFinished();') + writeLine(headerFile, ' void finishInitialization(bool success);') writeLine(headerFile) + writeLine(headerFile, ' void verifyUpdateFinished();') # End of class writeLine(headerFile) @@ -396,7 +423,7 @@ def writeRtuSourceFile(): writeLine(sourceFile, ' m_modbusRtuMaster(modbusRtuMaster),') writeLine(sourceFile, ' m_slaveId(slaveId)') writeLine(sourceFile, '{') - writeLine(sourceFile, ' ') + writeLine(sourceFile, '') writeLine(sourceFile, '}') writeLine(sourceFile) @@ -409,11 +436,13 @@ def writeRtuSourceFile(): writeLine(sourceFile, '{') writeLine(sourceFile, ' return m_slaveId;') writeLine(sourceFile, '}') + writeLine(sourceFile) writeLine(sourceFile, 'ModbusDataUtils::ByteOrder %s::endianness() const' % (className)) writeLine(sourceFile, '{') writeLine(sourceFile, ' return m_endianness;') writeLine(sourceFile, '}') + writeLine(sourceFile) writeLine(sourceFile, 'void %s::setEndianness(ModbusDataUtils::ByteOrder endianness)' % (className)) writeLine(sourceFile, '{') @@ -423,6 +452,7 @@ def writeRtuSourceFile(): writeLine(sourceFile, ' m_endianness = endianness;') writeLine(sourceFile, ' emit endiannessChanged(m_endianness);') writeLine(sourceFile, '}') + writeLine(sourceFile) # Property get methods writePropertyGetSetMethodImplementationsRtu(sourceFile, className, registerJson['registers']) @@ -464,12 +494,33 @@ def writeRtuSourceFile(): writeLine(sourceFile, 'void %s::verifyInitFinished()' % (className)) writeLine(sourceFile, '{') writeLine(sourceFile, ' if (m_pendingInitReplies.isEmpty()) {') - writeLine(sourceFile, ' qCDebug(dc%s()) << "Initialization finished of %s";' % (className, className)) - writeLine(sourceFile, ' emit initializationFinished();') + writeLine(sourceFile, ' finishInitialization(true);') writeLine(sourceFile, ' }') writeLine(sourceFile, '}') writeLine(sourceFile) + writeLine(sourceFile, 'void %s::finishInitialization(bool success)' % (className)) + writeLine(sourceFile, '{') + writeLine(sourceFile, ' if (success) {') + writeLine(sourceFile, ' qCDebug(dc%s()) << "Initialization finished of %s finished successfully";' % (className, className)) + writeLine(sourceFile, ' } else {') + writeLine(sourceFile, ' qCWarning(dc%s()) << "Initialization finished of %s failed.";' % (className, className)) + writeLine(sourceFile, ' }') + writeLine(sourceFile) + writeLine(sourceFile, ' // Cleanup init') + writeLine(sourceFile, ' delete m_initObject;') + writeLine(sourceFile, ' m_initObject = nullptr;') + writeLine(sourceFile, ' m_pendingInitReplies.clear();') + writeLine(sourceFile) + writeLine(sourceFile, ' emit initializationFinished(success);') + writeLine(sourceFile, '}') + writeLine(sourceFile) + + writeLine(sourceFile, 'void %s::verifyUpdateFinished()' % (className)) + writeLine(sourceFile, '{') + writeLine(sourceFile, '}') + writeLine(sourceFile) + # Write the debug print debugObjectParamName = className[0].lower() + className[1:] writeLine(sourceFile, 'QDebug operator<<(QDebug debug, %s *%s)' % (className, debugObjectParamName)) diff --git a/libnymea-modbus/tools/test-registers.json b/libnymea-modbus/tools/test-registers.json new file mode 100644 index 0000000..197fc5d --- /dev/null +++ b/libnymea-modbus/tools/test-registers.json @@ -0,0 +1,117 @@ +{ + "className": "Test", + "protocol": "BOTH", + "endianness": "BigEndian", + "enums": [ + { + "name": "TestEnum", + "values": [ + { + "key": "Zero", + "value": 0 + }, + { + "key": "One", + "value": 1 + } + ] + } + ], + "blocks": [ + { + "id": "blockNameInit", + "readSchedule": "init", + "registers": [ + { + "id": "initBlockRegisterOne", + "address": 100, + "size": 2, + "type": "int32", + "registerType": "holdingRegister", + "readSchedule": "update", + "description": "Block register one", + "staticScaleFactor": -3, + "defaultValue": "0", + "access": "RO" + }, + { + "id": "initBlockRegisterTwo", + "address": 102, + "size": 2, + "type": "int32", + "registerType": "holdingRegister", + "readSchedule": "update", + "description": "Block register two", + "defaultValue": "0", + "access": "RO" + } + ] + }, + { + "id": "blockNameUpdate", + "readSchedule": "update", + "registers": [ + { + "id": "blockRegisterOne", + "address": 200, + "size": 2, + "type": "int32", + "registerType": "holdingRegister", + "readSchedule": "update", + "description": "Block register one", + "staticScaleFactor": -3, + "defaultValue": "0", + "access": "RO" + }, + { + "id": "blockRegisterTwo", + "address": 202, + "size": 2, + "type": "int32", + "registerType": "holdingRegister", + "readSchedule": "update", + "description": "Block register two", + "defaultValue": "0", + "access": "RO" + } + ] + } + ], + "registers": [ + { + "id": "nameRegister", + "address": 30, + "size": 10, + "type": "string", + "registerType": "holdingRegister", + "readSchedule": "init", + "description": "Name string register", + "access": "RO" + }, + { + "id": "unsignedLongWord", + "address": 1, + "size": 2, + "type": "int32", + "registerType": "holdingRegister", + "readSchedule": "update", + "description": "Unsigned long word register", + "unit": "kW", + "staticScaleFactor": -3, + "defaultValue": "0", + "access": "RO" + }, + { + "id": "unsignedWord", + "address": 3, + "size": 1, + "type": "uint16", + "registerType": "holdingRegister", + "readSchedule": "update", + "description": "Unsigned word register", + "unit": "s", + "defaultValue": "0", + "access": "RO" + } + ] +}