From 86c730a0da2c5e48e7142082e330139d574d34be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Fri, 29 Jul 2022 10:18:21 +0200 Subject: [PATCH] Introduce checkReachableRegister and update all related plugins --- alphainnotec/alphainnotec-registers.json | 2 + bgetech/sdm630-registers.json | 1 + huawei/huawei-registers.json | 2 + inepro/pro380-registers.json | 2 + libnymea-modbus/tools/README.md | 5 ++ .../tools/connectiontool/modbusrtu.py | 56 +++++++++++++++++-- .../tools/connectiontool/modbustcp.py | 6 +- libnymea-modbus/tools/generate-connection.py | 44 +++++++++++++-- libnymea-modbus/tools/test-registers.json | 2 + .../integrationpluginphoenixconnect.cpp | 16 ++++-- phoenixconnect/phoenixconnect-registers.json | 2 + schrack/cion-registers.json | 2 + stiebeleltron/stiebel-eltron-registers.json | 2 + 13 files changed, 123 insertions(+), 19 deletions(-) diff --git a/alphainnotec/alphainnotec-registers.json b/alphainnotec/alphainnotec-registers.json index 2068ce0..fd59bfa 100644 --- a/alphainnotec/alphainnotec-registers.json +++ b/alphainnotec/alphainnotec-registers.json @@ -2,6 +2,8 @@ "className": "AlphaInnotec", "protocol": "TCP", "endianness": "BigEndian", + "errorLimitUntilNotReachable": 30, + "checkReachableRegister": "smartGrid", "enums": [ { "name": "SystemStatus", diff --git a/bgetech/sdm630-registers.json b/bgetech/sdm630-registers.json index 6436ff4..17378ab 100644 --- a/bgetech/sdm630-registers.json +++ b/bgetech/sdm630-registers.json @@ -3,6 +3,7 @@ "protocol": "RTU", "endianness": "BigEndian", "errorLimitUntilNotReachable": 15, + "checkReachableRegister": "totalCurrentPower", "registers": [ { "id": "totalCurrentPower", diff --git a/huawei/huawei-registers.json b/huawei/huawei-registers.json index e0b585d..25629a4 100644 --- a/huawei/huawei-registers.json +++ b/huawei/huawei-registers.json @@ -2,6 +2,8 @@ "className": "Huawei", "protocol": "TCP", "endianness": "BigEndian", + "errorLimitUntilNotReachable": 15, + "checkReachableRegister": "inverterActivePower", "enums": [ { "name": "InverterDeviceStatus", diff --git a/inepro/pro380-registers.json b/inepro/pro380-registers.json index 0c9fe50..05f03ee 100644 --- a/inepro/pro380-registers.json +++ b/inepro/pro380-registers.json @@ -2,6 +2,8 @@ "className": "Pro380", "protocol": "RTU", "endianness": "BigEndian", + "errorLimitUntilNotReachable": 15, + "checkReachableRegister": "totalEnergyConsumed", "blocks": [ { "id": "phasesVoltage", diff --git a/libnymea-modbus/tools/README.md b/libnymea-modbus/tools/README.md index 3b5b169..d2387d0 100644 --- a/libnymea-modbus/tools/README.md +++ b/libnymea-modbus/tools/README.md @@ -21,6 +21,7 @@ The basic structure of the modbus register JSON looks like following example: "protocol": "BOTH", "endianness": "BigEndian", "errorLimitUntilNotReachable": 10, + "checkReachableRegister": "registerPropertyName", "enums": [ { "name": "NameOfEnum", @@ -124,6 +125,10 @@ For modbus RTU it can be the case that the hardware resource is connected, but t Depending on your device the amount of errors in a row can vary and can be specified using the `errorLimitUntilNotReachable` property. If not specified, a default of `10` will be assumend. +In order to check if the device is reachable, a register can be defined by the developer as a test register. +For this purpose the `checkReachableRegister` property has been introduced. The property describes the `id` of the register which will be used for testing the communication. The register should be mandatory on the device +and only one register in size to speed up things. During the check the response data will be ignored, only the communication will be tested. The register must be *readable* and be defined in the `registers` section of your JSON file. + ## Endianness When converting multiple registers to one data type (i.e. 2 registers uint16 values to one uint32), the order of the registers are important to align with the endianness of the data receiving. diff --git a/libnymea-modbus/tools/connectiontool/modbusrtu.py b/libnymea-modbus/tools/connectiontool/modbusrtu.py index be3609f..8783185 100644 --- a/libnymea-modbus/tools/connectiontool/modbusrtu.py +++ b/libnymea-modbus/tools/connectiontool/modbusrtu.py @@ -73,7 +73,6 @@ def writePropertyGetSetMethodImplementationsRtu(fileDescriptor, className, regis ############################################################## - def writePropertyUpdateMethodImplementationsRtu(fileDescriptor, className, registerDefinitions): for registerDefinition in registerDefinitions: if 'readSchedule' in registerDefinition and registerDefinition['readSchedule'] == 'init': @@ -268,6 +267,38 @@ def writeInternalBlockReadMethodImplementationsRtu(fileDescriptor, className, bl ############################################################## +def writeVerifyReachabilityImplementationsRtu(fileDescriptor, className, registerDefinitions, checkReachableRegister): + + propertyName = checkReachableRegister['id'] + propertyTyp = getCppDataType(checkReachableRegister) + + writeLine(fileDescriptor, 'void %s::verifyReachability()' % (className)) + writeLine(fileDescriptor, '{') + writeLine(fileDescriptor, ' // Try to read the check reachability register %s in order to verify if the communication is working or not.' % checkReachableRegister['id']) + writeLine(fileDescriptor, ' qCDebug(dc%s()) << "--> Verify reachability by reading \\"%s\\" register:" << %s << "size:" << %s;' % (className, checkReachableRegister['description'], checkReachableRegister['address'], checkReachableRegister['size'])) + writeLine(fileDescriptor, ' ModbusRtuReply *reply = read%s();' % (propertyName[0].upper() + propertyName[1:])) + writeLine(fileDescriptor, ' if (!reply) {') + writeLine(fileDescriptor, ' qCDebug(dc%s()) << "Error occurred verifying reachability by reading \\"%s\\" register";' % (className, checkReachableRegister['description'])) + writeLine(fileDescriptor, ' return;') + writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' if (reply->isFinished()) {') + writeLine(fileDescriptor, ' return;') + writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::finished, this, [this, reply](){') + writeLine(fileDescriptor, ' // Note: we don\'t care about the result here, only the error') + writeLine(fileDescriptor, ' handleModbusError(reply->error());') + writeLine(fileDescriptor, ' });') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' connect(reply, &ModbusRtuReply::errorOccurred, this, [reply] (ModbusRtuReply::Error error){') + writeLine(fileDescriptor, ' qCDebug(dc%s()) << "ModbusRtu reply error occurred while verifying reachability by reading \\"%s\\" register" << error << reply->errorString();' % (className, checkReachableRegister['description'])) + writeLine(fileDescriptor, ' });') + writeLine(fileDescriptor, '}') + writeLine(fileDescriptor) + +############################################################## + def writeInitMethodImplementationRtu(fileDescriptor, className, registerDefinitions, blockDefinitions): writeLine(fileDescriptor, 'bool %s::initialize()' % (className)) writeLine(fileDescriptor, '{') @@ -303,6 +334,7 @@ def writeInitMethodImplementationRtu(fileDescriptor, className, registerDefiniti if 'readSchedule' in registerDefinition and registerDefinition['readSchedule'] == 'init': writeLine(fileDescriptor) 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, ' qCWarning(dc%s()) << "Error occurred while reading \\"%s\\" registers";' % (className, registerDefinition['description'])) @@ -326,7 +358,7 @@ def writeInitMethodImplementationRtu(fileDescriptor, className, registerDefiniti 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, ' qCDebug(dc%s()) << "<-- Response from \\"%s\\" init 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, ' });') @@ -356,6 +388,7 @@ def writeInitMethodImplementationRtu(fileDescriptor, className, registerDefiniti writeLine(fileDescriptor) 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, ' qCWarning(dc%s()) << "Error occurred while reading block \\"%s\\" registers";' % (className, blockName)) @@ -379,7 +412,7 @@ def writeInitMethodImplementationRtu(fileDescriptor, className, registerDefiniti 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)) + 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 @@ -423,16 +456,25 @@ def writeUpdateMethodRtu(fileDescriptor, className, registerDefinitions, blockDe break if updateRequired: - writeLine(fileDescriptor, ' if (!m_reachable) {') - writeLine(fileDescriptor, ' qCWarning(dc%s()) << "Tried to update but the connection is not reachable.";' % className) + writeLine(fileDescriptor, ' if (!m_modbusRtuMaster->connected()) {') + writeLine(fileDescriptor, ' qCDebug(dc%s()) << "Tried to update the registers but the hardware resource seems not to be connected.";' % className) writeLine(fileDescriptor, ' return false;') writeLine(fileDescriptor, ' }') 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, ' qCDebug(dc%s()) << "Tried to update the registers 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, ' // Hardware resource available but communication not working. ') + writeLine(fileDescriptor, ' // Try to read the check reachability register to re-evaluatoe the communication... ') + writeLine(fileDescriptor, ' if (m_modbusRtuMaster->connected() && !m_communicationWorking) {') + writeLine(fileDescriptor, ' verifyReachability();') + writeLine(fileDescriptor, ' return false;') + writeLine(fileDescriptor, ' }') + writeLine(fileDescriptor) + writeLine(fileDescriptor, ' ModbusRtuReply *reply = nullptr;') # Read individual registers @@ -443,6 +485,7 @@ def writeUpdateMethodRtu(fileDescriptor, className, registerDefinitions, blockDe if 'readSchedule' in registerDefinition and registerDefinition['readSchedule'] == 'update': writeLine(fileDescriptor) writeLine(fileDescriptor, ' // Read %s' % registerDefinition['description']) + writeLine(fileDescriptor, ' qCDebug(dc%s()) << "--> Read \\"%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, ' qCWarning(dc%s()) << "Error occurred while reading \\"%s\\" registers";' % (className, registerDefinition['description'])) @@ -494,6 +537,7 @@ def writeUpdateMethodRtu(fileDescriptor, className, registerDefinitions, blockDe writeLine(fileDescriptor) writeLine(fileDescriptor, ' // Read %s' % blockName) + writeLine(fileDescriptor, ' qCDebug(dc%s()) << "--> Read 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, ' qCWarning(dc%s()) << "Error occurred while reading block \\"%s\\" registers";' % (className, blockName)) diff --git a/libnymea-modbus/tools/connectiontool/modbustcp.py b/libnymea-modbus/tools/connectiontool/modbustcp.py index a921788..a843a90 100644 --- a/libnymea-modbus/tools/connectiontool/modbustcp.py +++ b/libnymea-modbus/tools/connectiontool/modbustcp.py @@ -440,6 +440,7 @@ def writeUpdateMethodTcp(fileDescriptor, className, registerDefinitions, blockDe if 'readSchedule' in registerDefinition and registerDefinition['readSchedule'] == 'update': writeLine(fileDescriptor) writeLine(fileDescriptor, ' // Read %s' % registerDefinition['description']) + writeLine(fileDescriptor, ' qCDebug(dc%s()) << "--> Read \\"%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, ' qCWarning(dc%s()) << "Error occurred while reading \\"%s\\" registers from" << hostAddress().toString() << errorString();' % (className, registerDefinition['description'])) @@ -461,7 +462,7 @@ def writeUpdateMethodTcp(fileDescriptor, className, registerDefinitions, blockDe 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, ' 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, ' verifyUpdateFinished();') writeLine(fileDescriptor, ' });') @@ -492,6 +493,7 @@ def writeUpdateMethodTcp(fileDescriptor, className, registerDefinitions, blockDe writeLine(fileDescriptor) writeLine(fileDescriptor, ' // Read %s' % blockName) writeLine(fileDescriptor, ' reply = readBlock%s();' % (blockName[0].upper() + blockName[1:])) + writeLine(fileDescriptor, ' qCDebug(dc%s()) << "--> Read block \\"%s\\" registers from:" << %s << "size:" << %s;' % (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 false;') @@ -513,7 +515,7 @@ def writeUpdateMethodTcp(fileDescriptor, className, registerDefinitions, blockDe 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, ' 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 diff --git a/libnymea-modbus/tools/generate-connection.py b/libnymea-modbus/tools/generate-connection.py index 5366191..266830d 100644 --- a/libnymea-modbus/tools/generate-connection.py +++ b/libnymea-modbus/tools/generate-connection.py @@ -413,6 +413,7 @@ def writeRtuHeaderFile(): writeLine(headerFile) writeLine(headerFile, ' void handleModbusError(ModbusRtuReply::Error error);') writeLine(headerFile, ' void evaluateReachableState();') + writeLine(headerFile, ' void verifyReachability();') # End of class @@ -446,11 +447,12 @@ def writeRtuSourceFile(): writeLine(sourceFile, '{') writeLine(sourceFile, ' connect(m_modbusRtuMaster, &ModbusRtuMaster::connectedChanged, this, [=](bool connected){') writeLine(sourceFile, ' if (connected) {') - writeLine(sourceFile, ' qCDebug(dc%s()) << "Modbus RTU resource" << m_modbusRtuMaster->serialPort() << "connected again. TODO: Test if the connection is reachable...";' % (className)) + writeLine(sourceFile, ' qCDebug(dc%s()) << "Modbus RTU resource" << m_modbusRtuMaster->serialPort() << "connected again. Start testing if the connection is reachable...";' % (className)) writeLine(sourceFile, ' m_pendingInitReplies.clear();') writeLine(sourceFile, ' m_pendingUpdateReplies.clear();') writeLine(sourceFile, ' m_communicationWorking = false;') writeLine(sourceFile, ' m_communicationFailedCounter = 0;') + writeLine(sourceFile, ' verifyReachability();') writeLine(sourceFile, ' } else {') writeLine(sourceFile, ' qCWarning(dc%s()) << "Modbus RTU resource" << m_modbusRtuMaster->serialPort() << "disconnected. The connection is not reachable any more.";' % (className)) writeLine(sourceFile, ' m_communicationWorking = false;') @@ -597,6 +599,8 @@ def writeRtuSourceFile(): writeLine(sourceFile, '}') writeLine(sourceFile) + writeVerifyReachabilityImplementationsRtu(sourceFile, className, registerJson['registers'], checkReachableRegister) + # Write the debug print debugObjectParamName = className[0].lower() + className[1:] writeLine(sourceFile, 'QDebug operator<<(QDebug debug, %s *%s)' % (className, debugObjectParamName)) @@ -648,7 +652,7 @@ if args.verboseOutput: logger.debug("Verbose output enabled") if not 'className' in registerJson: - logger.warning('Classname missing. Please specify the classname in the json file or pass it to the generatori using -c .') + logger.warning('Error: Class name property missing. Please specify the \"classname\" property in the json file.') exit(1) classNamePrefix = registerJson['className'] @@ -661,11 +665,39 @@ errorLimitUntilNotReachable = 10 if 'errorLimitUntilNotReachable' in registerJson: errorLimitUntilNotReachable = registerJson['errorLimitUntilNotReachable'] -logger.debug('Scrip path: %s' % scriptPath) +# Check if the developer has specified an +checkReachableRegister = {} +if not 'checkReachableRegister' in registerJson: + logger.warning('Error: There is no checkReachableRegister specified. Please specify the \"checkReachableRegister\" property in the register JSON and set it to the \"id\" of a mandatory readable register which should be used for testing the communication.') + exit(1) + +checkReachableRegister = registerJson['checkReachableRegister'] +registerExists = False +# Make sure this is an existing and readable register +for registerDefinition in registerJson['registers']: + if registerDefinition['id'] == checkReachableRegister: + if not 'R' in registerDefinition['access']: + logger.warning('Error: The specified \"checkReachableRegister\" is not readable. Please select a manadtory readable register as checkReachableRegister.') + exit(1) + + checkReachableRegister = registerDefinition + registerExists = True + break + +if not registerExists: + logger.warning('Error: Could not find the given \"checkReachableRegister\". Please make sure the specified register matches the \"id\" of a defined register.') + exit(1) +else: + logger.debug('Verified successfully checkReachableRegister: %s' % checkReachableRegister['id']) + + +# Inform about parsed and validated configs if debugging enabled +logger.debug('Script path: %s' % scriptPath) logger.debug('Output directory: %s' % outputDirectory) logger.debug('Class name prefix: %s' % classNamePrefix) logger.debug('Endianness: %s' % endianness) logger.debug('Error limit until not reachable: %s' % errorLimitUntilNotReachable) +logger.debug('Check reachable register: %s' % checkReachableRegister['id']) protocol = 'TCP' if 'protocol' in registerJson: @@ -678,7 +710,7 @@ if 'blocks' in registerJson: writeTcp = protocol in ["TCP", "BOTH"] writeRtu = protocol in ["RTU", "BOTH"] if not writeTcp and not writeRtu: - logger.warning('Invalid protocol definition. Please use TCP, RTU or BOTH.') + logger.warning('Error: Invalid protocol definition. Please use TCP, RTU or BOTH in the register JSON file.') exit(1) headerFiles = [] @@ -725,8 +757,8 @@ projectIncludeFilePath = os.path.join(outputDirectory, projectIncludeFileName) # Note: we write the project file only if the registers # file has been modified since the project has been modified the last time. -# This prevents qt-creator to retrigger qmake runs on it's own by changing the -# project file which retriggers a qmake run and so on... +# This prevents qt-creator to retrigger qmake runs on it's own if the pri file is open +# by changing the project file which retriggers a qmake run and so on... if os.path.exists(projectIncludeFilePath): timestampRegistersJson = os.path.getmtime(registerJsonFilePath) timestampProjectInclude = os.path.getmtime(projectIncludeFilePath) diff --git a/libnymea-modbus/tools/test-registers.json b/libnymea-modbus/tools/test-registers.json index 197fc5d..6440992 100644 --- a/libnymea-modbus/tools/test-registers.json +++ b/libnymea-modbus/tools/test-registers.json @@ -2,6 +2,8 @@ "className": "Test", "protocol": "BOTH", "endianness": "BigEndian", + "checkReachableRegister": "unsignedLongWord", + "errorLimitUntilNotReachable": 10, "enums": [ { "name": "TestEnum", diff --git a/phoenixconnect/integrationpluginphoenixconnect.cpp b/phoenixconnect/integrationpluginphoenixconnect.cpp index 8cc6515..8487bbc 100644 --- a/phoenixconnect/integrationpluginphoenixconnect.cpp +++ b/phoenixconnect/integrationpluginphoenixconnect.cpp @@ -128,11 +128,17 @@ void IntegrationPluginPhoenixConnect::setupThing(ThingSetupInfo *info) } }); - connect(connection, &PhoenixModbusTcpConnection::initializationFinished, info, [this, thing, connection, monitor, info]{ - qCDebug(dcPhoenixContact()) << "Phoenix wallbox initialized. Firmware version:" << connection->firmwareVersion(); - m_connections.insert(thing, connection); - m_monitors.insert(thing, monitor); - info->finish(Thing::ThingErrorNoError); + connect(connection, &PhoenixModbusTcpConnection::initializationFinished, info, [this, thing, connection, monitor, info](bool success){ + if (success) { + qCDebug(dcPhoenixContact()) << "Phoenix wallbox initialized. Firmware version:" << connection->firmwareVersion(); + m_connections.insert(thing, connection); + m_monitors.insert(thing, monitor); + info->finish(Thing::ThingErrorNoError); + } else { + hardwareManager()->networkDeviceDiscovery()->unregisterMonitor(monitor); + connection->deleteLater(); + info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Could not initialize the communication with the wallbox.")); + } }); connect(connection, &PhoenixModbusTcpConnection::initializationFinished, thing, [thing, connection]{ diff --git a/phoenixconnect/phoenixconnect-registers.json b/phoenixconnect/phoenixconnect-registers.json index fc5888f..5a5a49f 100644 --- a/phoenixconnect/phoenixconnect-registers.json +++ b/phoenixconnect/phoenixconnect-registers.json @@ -2,6 +2,8 @@ "className": "Phoenix", "protocol": "TCP", "endianness": "LittleEndian", + "errorLimitUntilNotReachable": 20, + "checkReachableRegister": "chargingCurrent", "enums": [ { "name": "ErrorCode", diff --git a/schrack/cion-registers.json b/schrack/cion-registers.json index a796b9b..f7e9350 100644 --- a/schrack/cion-registers.json +++ b/schrack/cion-registers.json @@ -2,6 +2,8 @@ "className": "Cion", "protocol": "RTU", "endianness": "LittleEndian", + "errorLimitUntilNotReachable": 10, + "checkReachableRegister": "chargingEnabled", "blocks": [ { "id": "e3", diff --git a/stiebeleltron/stiebel-eltron-registers.json b/stiebeleltron/stiebel-eltron-registers.json index 771e95b..746ce0a 100644 --- a/stiebeleltron/stiebel-eltron-registers.json +++ b/stiebeleltron/stiebel-eltron-registers.json @@ -2,6 +2,8 @@ "className": "StiebelEltron", "protocol": "TCP", "endianness": "BigEndian", + "errorLimitUntilNotReachable": 40, + "checkReachableRegister": "outdoorTemperature", "enums": [ { "name": "OperatingMode",