Introduce check reachability retries again

This commit is contained in:
Simon Stürz 2022-08-09 11:14:26 +02:00
parent 8e5a639591
commit 761ff94610
7 changed files with 215 additions and 68 deletions

View File

@ -37,6 +37,10 @@ NYMEA_LOGGING_CATEGORY(dcHuaweiFusionSolar, "HuaweiFusionSolar")
HuaweiFusionSolar::HuaweiFusionSolar(const QHostAddress &hostAddress, uint port, quint16 slaveId, QObject *parent) :
HuaweiFusionModbusTcpConnection(hostAddress, port, slaveId, parent)
{
// Note: sometimes right after the discovery / setup the check fails the first time due to server busy error,
// this is a very slow or busy device since it returns quiet often that error. Don't faile with the first busy error...
setCheckReachableRetries(3);
connect(this, &HuaweiFusionModbusTcpConnection::connectionStateChanged, this, [=](bool connected){
if (!connected) {
m_registersQueue.clear();
@ -97,13 +101,14 @@ bool HuaweiFusionSolar::update()
// Add the requests to queue, begin with power values, since they are most important
m_registersQueue.enqueue(HuaweiFusionModbusTcpConnection::RegisterInverterActivePower);
m_registersQueue.enqueue(HuaweiFusionModbusTcpConnection::RegisterPowerMeterActivePower);
if (m_battery1Available)
m_registersQueue.enqueue(HuaweiFusionModbusTcpConnection::RegisterLunaBattery1Power);
if (m_battery2Available)
m_registersQueue.enqueue(HuaweiFusionModbusTcpConnection::RegisterLunaBattery2Power);
m_registersQueue.enqueue(HuaweiFusionModbusTcpConnection::RegisterPowerMeterActivePower);
m_registersQueue.enqueue(HuaweiFusionModbusTcpConnection::RegisterInverterEnergyProduced);
m_registersQueue.enqueue(HuaweiFusionModbusTcpConnection::RegisterInverterDeviceStatus);
m_registersQueue.enqueue(HuaweiFusionModbusTcpConnection::RegisterLunaBattery1Status);
@ -122,6 +127,11 @@ bool HuaweiFusionSolar::update()
return true;
}
double HuaweiFusionSolar::actualInverterPower() const
{
return m_actualInverterPower;
}
void HuaweiFusionSolar::readNextRegister()
{
// Check if currently a reply is pending
@ -157,10 +167,11 @@ void HuaweiFusionSolar::readNextRegister()
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Inverter active power\" register" << 32080 << "size:" << 2 << "valueCount:" << unit.valueCount() << unit.values() << unit.values().count();
if (unit.values().count() != 2) {
qCWarning(dcHuaweiFusionSolar()) << "<-- Received invalid values count. Requested" << 2 << "but received" << unit.values().count();
if (!valuesAreVaild(unit.values(), 2)) {
qCWarning(dcHuaweiFusionSolar()) << "<-- Received invalid values. Requested" << 2 << "but received" << unit.values();
} else {
processInverterActivePowerRegisterValues(unit.values());
calculatActualInverterPower();
}
}
@ -202,8 +213,8 @@ void HuaweiFusionSolar::readNextRegister()
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Inverter device status\" register" << 32089 << "size:" << 1 << "valueCount:" << unit.valueCount() << unit.values() << unit.values().count();
if (unit.values().count() != 1) {
qCWarning(dcHuaweiFusionSolar()) << "<-- Received invalid values count. Requested" << 1 << "but received" << unit.values().count();
if (!valuesAreVaild(unit.values(), 1)) {
qCWarning(dcHuaweiFusionSolar()) << "<-- Received invalid values. Requested" << 1 << "but received" << unit.values();
} else {
processInverterDeviceStatusRegisterValues(unit.values());
}
@ -246,8 +257,8 @@ void HuaweiFusionSolar::readNextRegister()
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Inverter energy produced\" register" << 32106 << "size:" << 2 << "valueCount:" << unit.valueCount() << unit.values() << unit.values().count();
if (unit.values().count() != 2) {
qCWarning(dcHuaweiFusionSolar()) << "<-- Received invalid values count. Requested" << 2 << "but received" << unit.values().count();
if (!valuesAreVaild(unit.values(), 2)) {
qCWarning(dcHuaweiFusionSolar()) << "<-- Received invalid values. Requested" << 2 << "but received" << unit.values();
} else {
processInverterEnergyProducedRegisterValues(unit.values());
}
@ -288,10 +299,9 @@ void HuaweiFusionSolar::readNextRegister()
handleModbusError(reply->error());
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Power meter active power\" register" << 37113 << "size:" << 2 << "valueCount:" << unit.valueCount() << unit.values() << unit.values().count();
if (unit.values().count() != 2) {
qCWarning(dcHuaweiFusionSolar()) << "<-- Received invalid values count. Requested" << 2 << "but received" << unit.values().count();
if (!valuesAreVaild(unit.values(), 2)) {
qCWarning(dcHuaweiFusionSolar()) << "<-- Received invalid values. Requested" << 2 << "but received" << unit.values();
} else {
processPowerMeterActivePowerRegisterValues(unit.values());
}
@ -334,8 +344,8 @@ void HuaweiFusionSolar::readNextRegister()
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Luna 2000 Battery 1 status\" register" << 37000 << "size:" << 1 << "valueCount:" << unit.valueCount() << unit.values() << unit.values().count();
if (unit.values().count() != 1) {
qCWarning(dcHuaweiFusionSolar()) << "<-- Received invalid values count. Requested" << 1 << "but received" << unit.values().count();
if (!valuesAreVaild(unit.values(), 1)) {
qCWarning(dcHuaweiFusionSolar()) << "<-- Received invalid values. Requested" << 1 << "but received" << unit.values();
} else {
processLunaBattery1StatusRegisterValues(unit.values());
}
@ -377,10 +387,11 @@ void HuaweiFusionSolar::readNextRegister()
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Luna 2000 Battery 1 power\" register" << 37001 << "size:" << 2 << "valueCount:" << unit.valueCount() << unit.values() << unit.values().count();
if (unit.values().count() != 2) {
qCWarning(dcHuaweiFusionSolar()) << "<-- Received invalid values count. Requested" << 2 << "but received" << unit.values().count();
if (!valuesAreVaild(unit.values(), 2)) {
qCWarning(dcHuaweiFusionSolar()) << "<-- Received invalid values. Requested" << 2 << "but received" << unit.values();
} else {
processLunaBattery1PowerRegisterValues(unit.values());
calculatActualInverterPower();
}
}
finishRequest();
@ -420,8 +431,8 @@ void HuaweiFusionSolar::readNextRegister()
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Luna 2000 Battery 1 state of charge\" register" << 37004 << "size:" << 1 << "valueCount:" << unit.valueCount() << unit.values() << unit.values().count();
if (unit.values().count() != 1) {
qCWarning(dcHuaweiFusionSolar()) << "<-- Received invalid values count. Requested" << 1 << "but received" << unit.values().count();
if (!valuesAreVaild(unit.values(), 1)) {
qCWarning(dcHuaweiFusionSolar()) << "<-- Received invalid values. Requested" << 1 << "but received" << unit.values();
} else {
processLunaBattery1SocRegisterValues(unit.values());
}
@ -464,8 +475,8 @@ void HuaweiFusionSolar::readNextRegister()
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Luna 2000 Battery 2 status\" register" << 37741 << "size:" << 1 << "valueCount:" << unit.valueCount() << unit.values() << unit.values().count();
if (unit.values().count() != 1) {
qCWarning(dcHuaweiFusionSolar()) << "<-- Received invalid values count. Requested" << 1 << "but received" << unit.values().count();
if (!valuesAreVaild(unit.values(), 1)) {
qCWarning(dcHuaweiFusionSolar()) << "<-- Received invalid values count. Requested" << 1 << "but received" << unit.values();
} else {
processLunaBattery2StatusRegisterValues(unit.values());
}
@ -507,10 +518,11 @@ void HuaweiFusionSolar::readNextRegister()
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Luna 2000 Battery 2 power\" register" << 37743 << "size:" << 2 << "valueCount:" << unit.valueCount() << unit.values() << unit.values().count();
if (unit.values().count() != 2) {
qCWarning(dcHuaweiFusionSolar()) << "<-- Received invalid values count. Requested" << 2 << "but received" << unit.values().count();
if (!valuesAreVaild(unit.values(), 1)) {
qCWarning(dcHuaweiFusionSolar()) << "<-- Received invalid values count. Requested" << 2 << "but received" << unit.values();
} else {
processLunaBattery2PowerRegisterValues(unit.values());
calculatActualInverterPower();
}
}
finishRequest();
@ -550,8 +562,8 @@ void HuaweiFusionSolar::readNextRegister()
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
qCDebug(dcHuaweiFusionSolar()) << "<-- Response from \"Luna 2000 Battery 2 state of charge\" register" << 37738 << "size:" << 1 << "valueCount:" << unit.valueCount() << unit.values() << unit.values().count();
if (unit.values().count() != 1) {
qCWarning(dcHuaweiFusionSolar()) << "<-- Received invalid values count. Requested" << 1 << "but received" << unit.values().count();
if (!valuesAreVaild(unit.values(), 1)) {
qCWarning(dcHuaweiFusionSolar()) << "<-- Received invalid values. Requested" << 1 << "but received" << unit.values();
} else {
processLunaBattery2SocRegisterValues(unit.values());
}
@ -574,6 +586,45 @@ void HuaweiFusionSolar::readNextRegister()
}
}
bool HuaweiFusionSolar::valuesAreVaild(const QVector<quint16> &values, int readSize)
{
if (values.count() != readSize)
return false;
// According to the documentation:
// 0x7FFF: invalid value of the floating point type returned by one register
// 0xFFFF: invalid value of a type other than the floating point type returned by one register
// 0xFFFFFFFF: invalid value returned by two registers
if (values.count() == 2) {
bool floatingPointValid = (values.at(0) != 0x7fff && values.at(1) != 0xffff);
bool otherTypesValid = (values.at(0) != 0xffff && values.at(1) != 0xffff);
return floatingPointValid && otherTypesValid;
}
if (values.count() == 1)
return values.at(0) != 0x7fff && values.at(0) != 0xffff;
return true;
}
void HuaweiFusionSolar::calculatActualInverterPower()
{
double actualPower = m_inverterActivePower * -1000.0;
if (m_battery1Available)
actualPower += m_lunaBattery1Power;
if (m_battery2Available)
actualPower += m_lunaBattery2Power;
qCDebug(dcHuaweiFusionSolar()) << "Inverter power:" << m_inverterActivePower << "W Battery 1:" << m_lunaBattery1Power << "W Battery 2:" << m_lunaBattery2Power << "W -->" << "Actual inverter power:" << actualPower << "W";
if (m_actualInverterPower != actualPower)
return;
m_actualInverterPower = actualPower;
emit actualInverterPowerChanged(m_actualInverterPower);
}
void HuaweiFusionSolar::finishRequest()
{
m_currentRegisterRequest = -1;

View File

@ -46,6 +46,13 @@ public:
bool initialize() override;
virtual bool update() override;
// The inverter shows the pv power AND the power of the connected batteries if they discharge.
// This power values represents the power taking the batteries into account.
double actualInverterPower() const;
signals:
void actualInverterPowerChanged(double actualInverterPower);
private:
QQueue<HuaweiFusionModbusTcpConnection::Registers> m_registersQueue;
QModbusReply *m_initReply = nullptr;
@ -56,10 +63,14 @@ private:
bool m_battery1Available = true;
bool m_battery2Available = true;
double m_actualInverterPower = 0;
QString exceptionToString(QModbusPdu::ExceptionCode exception);
private slots:
void readNextRegister();
bool valuesAreVaild(const QVector<quint16> &values, int readSize);
void calculatActualInverterPower();
};

View File

@ -37,12 +37,7 @@ HuaweiFusionSolarDiscovery::HuaweiFusionSolarDiscovery(NetworkDeviceDiscovery *n
m_port(port),
m_modbusAddress(modbusAddress)
{
m_gracePeriodTimer.setSingleShot(true);
m_gracePeriodTimer.setInterval(3000);
connect(&m_gracePeriodTimer, &QTimer::timeout, this, [this](){
qCDebug(dcHuawei()) << "Discovery: Grace period timer triggered.";
finishDiscovery();
});
}
@ -71,7 +66,11 @@ void HuaweiFusionSolarDiscovery::startDiscovery()
}
}
m_gracePeriodTimer.start();
// Finish with some delay so the last added network device information objects still can be checked.
QTimer::singleShot(3000, this, [this](){
qCDebug(dcHuawei()) << "Discovery: Grace period timer triggered.";
finishDiscovery();
});
});
}
@ -108,20 +107,18 @@ void HuaweiFusionSolarDiscovery::checkNetworkDevice(const NetworkDeviceInfo &net
return;
}
m_discoveryResults.append(networkDeviceInfo);
qCDebug(dcHuawei()) << "Discovery: --> Found" << networkDeviceInfo;
m_discoveryResults.append(networkDeviceInfo);
// Done with this connection
cleanupConnection(connection);
});
// Initializing...
if (!connection->initialize()) {
qCDebug(dcHuawei()) << "Discovery: Unable to initialize connection on" << networkDeviceInfo.address().toString() << "Continue...";;
cleanupConnection(connection);
}
// Initializing...
});
// If we get any error...skip this host...
@ -138,9 +135,12 @@ void HuaweiFusionSolarDiscovery::checkNetworkDevice(const NetworkDeviceInfo &net
cleanupConnection(connection);
});
// Try to connect, maybe it works, maybe not,
// but retry only once to communicate with the device for reachability check...
connection->setCheckReachableRetries(1);
// Try to connect, maybe it works, maybe not...
connection->connectDevice();
}
void HuaweiFusionSolarDiscovery::cleanupConnection(HuaweiFusionSolar *connection)
@ -160,7 +160,6 @@ void HuaweiFusionSolarDiscovery::finishDiscovery()
qCInfo(dcHuawei()) << "Discovery: Finished the discovery process. Found" << m_discoveryResults.count()
<< "inverters in" << QTime::fromMSecsSinceStartOfDay(durationMilliSeconds).toString("mm:ss.zzz");
m_gracePeriodTimer.stop();
emit discoveryFinished();
}

View File

@ -55,7 +55,6 @@ private:
quint16 m_port;
quint16 m_modbusAddress;
QTimer m_gracePeriodTimer;
QDateTime m_startDateTime;
NetworkDeviceInfos m_networkDeviceInfos;

View File

@ -278,35 +278,35 @@ def writeTestReachabilityImplementationsRtu(fileDescriptor, className, registerD
writeLine(fileDescriptor, 'void %s::testReachability()' % (className))
writeLine(fileDescriptor, '{')
writeLine(fileDescriptor, ' if (m_testRechableReply)')
writeLine(fileDescriptor, ' if (m_checkRechableReply)')
writeLine(fileDescriptor, ' return;')
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()) << "--> Test reachability by reading \\"%s\\" register:" << %s << "size:" << %s;' % (className, checkReachableRegister['description'], checkReachableRegister['address'], checkReachableRegister['size']))
writeLine(fileDescriptor, ' m_testRechableReply = read%s();' % (propertyName[0].upper() + propertyName[1:]))
writeLine(fileDescriptor, ' if (!m_testRechableReply) {')
writeLine(fileDescriptor, ' m_checkRechableReply = read%s();' % (propertyName[0].upper() + propertyName[1:]))
writeLine(fileDescriptor, ' if (!m_checkRechableReply) {')
writeLine(fileDescriptor, ' qCDebug(dc%s()) << "Error occurred verifying reachability by reading \\"%s\\" register";' % (className, checkReachableRegister['description']))
writeLine(fileDescriptor, ' emit checkReachabilityFailed();')
writeLine(fileDescriptor, ' onReachabilityCheckFailed();')
writeLine(fileDescriptor, ' return;')
writeLine(fileDescriptor, ' }')
writeLine(fileDescriptor)
writeLine(fileDescriptor, ' if (m_testRechableReply->isFinished()) {')
writeLine(fileDescriptor, ' m_testRechableReply = nullptr;')
writeLine(fileDescriptor, ' emit checkReachabilityFailed();')
writeLine(fileDescriptor, ' if (m_checkRechableReply->isFinished()) {')
writeLine(fileDescriptor, ' m_checkRechableReply = nullptr;')
writeLine(fileDescriptor, ' onReachabilityCheckFailed();')
writeLine(fileDescriptor, ' return;')
writeLine(fileDescriptor, ' }')
writeLine(fileDescriptor)
writeLine(fileDescriptor, ' connect(m_testRechableReply, &ModbusRtuReply::finished, this, [this](){')
writeLine(fileDescriptor, ' connect(m_checkRechableReply, &ModbusRtuReply::finished, this, [this](){')
writeLine(fileDescriptor, ' // Note: we don\'t care about the result here, only the error')
writeLine(fileDescriptor, ' handleModbusError(m_testRechableReply->error());')
writeLine(fileDescriptor, ' if (m_testRechableReply->error() != ModbusRtuReply::NoError)')
writeLine(fileDescriptor, ' emit checkReachabilityFailed();')
writeLine(fileDescriptor, ' handleModbusError(m_checkRechableReply->error());')
writeLine(fileDescriptor, ' if (m_checkRechableReply->error() != ModbusRtuReply::NoError)')
writeLine(fileDescriptor, ' onReachabilityCheckFailed();')
writeLine(fileDescriptor)
writeLine(fileDescriptor, ' m_testRechableReply = nullptr;')
writeLine(fileDescriptor, ' m_checkRechableReply = nullptr;')
writeLine(fileDescriptor, ' });')
writeLine(fileDescriptor)
writeLine(fileDescriptor, ' connect(m_testRechableReply, &ModbusRtuReply::errorOccurred, this, [this] (ModbusRtuReply::Error error){')
writeLine(fileDescriptor, ' qCDebug(dc%s()) << "ModbusRtu reply error occurred while verifying reachability by reading \\"%s\\" register" << error << m_testRechableReply->errorString();' % (className, checkReachableRegister['description']))
writeLine(fileDescriptor, ' connect(m_checkRechableReply, &ModbusRtuReply::errorOccurred, this, [this] (ModbusRtuReply::Error error){')
writeLine(fileDescriptor, ' qCDebug(dc%s()) << "ModbusRtu reply error occurred while verifying reachability by reading \\"%s\\" register" << error << m_checkRechableReply->errorString();' % (className, checkReachableRegister['description']))
writeLine(fileDescriptor, ' });')
writeLine(fileDescriptor, '}')
writeLine(fileDescriptor)

View File

@ -280,36 +280,36 @@ def writeTestReachabilityImplementationsTcp(fileDescriptor, className, registerD
writeLine(fileDescriptor, 'void %s::testReachability()' % (className))
writeLine(fileDescriptor, '{')
writeLine(fileDescriptor, ' if (m_testRechableReply)')
writeLine(fileDescriptor, ' if (m_checkRechableReply)')
writeLine(fileDescriptor, ' return;')
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()) << "--> Test reachability by reading \\"%s\\" register:" << %s << "size:" << %s;' % (className, checkReachableRegister['description'], checkReachableRegister['address'], checkReachableRegister['size']))
writeLine(fileDescriptor, ' m_testRechableReply = read%s();' % (propertyName[0].upper() + propertyName[1:]))
writeLine(fileDescriptor, ' if (!m_testRechableReply) {')
writeLine(fileDescriptor, ' m_checkRechableReply = read%s();' % (propertyName[0].upper() + propertyName[1:]))
writeLine(fileDescriptor, ' if (!m_checkRechableReply) {')
writeLine(fileDescriptor, ' qCDebug(dc%s()) << "Error occurred verifying reachability by reading \\"%s\\" register";' % (className, checkReachableRegister['description']))
writeLine(fileDescriptor, ' emit checkReachabilityFailed();')
writeLine(fileDescriptor, ' onReachabilityCheckFailed();')
writeLine(fileDescriptor, ' return;')
writeLine(fileDescriptor, ' }')
writeLine(fileDescriptor)
writeLine(fileDescriptor, ' if (m_testRechableReply->isFinished()) {')
writeLine(fileDescriptor, ' m_testRechableReply->deleteLater(); // Broadcast reply returns immediatly')
writeLine(fileDescriptor, ' m_testRechableReply = nullptr;')
writeLine(fileDescriptor, ' emit checkReachabilityFailed();')
writeLine(fileDescriptor, ' if (m_checkRechableReply->isFinished()) {')
writeLine(fileDescriptor, ' m_checkRechableReply->deleteLater(); // Broadcast reply returns immediatly')
writeLine(fileDescriptor, ' m_checkRechableReply = nullptr;')
writeLine(fileDescriptor, ' onReachabilityCheckFailed();')
writeLine(fileDescriptor, ' return;')
writeLine(fileDescriptor, ' }')
writeLine(fileDescriptor)
writeLine(fileDescriptor, ' connect(m_testRechableReply, &QModbusReply::finished, this, [this](){')
writeLine(fileDescriptor, ' handleModbusError(m_testRechableReply->error());')
writeLine(fileDescriptor, ' if (m_testRechableReply->error() != QModbusDevice::NoError)')
writeLine(fileDescriptor, ' emit checkReachabilityFailed();')
writeLine(fileDescriptor, ' connect(m_checkRechableReply, &QModbusReply::finished, this, [this](){')
writeLine(fileDescriptor, ' handleModbusError(m_checkRechableReply->error());')
writeLine(fileDescriptor, ' if (m_checkRechableReply->error() != QModbusDevice::NoError)')
writeLine(fileDescriptor, ' onReachabilityCheckFailed();')
writeLine(fileDescriptor)
writeLine(fileDescriptor, ' m_testRechableReply->deleteLater();')
writeLine(fileDescriptor, ' m_testRechableReply = nullptr;')
writeLine(fileDescriptor, ' m_checkRechableReply->deleteLater();')
writeLine(fileDescriptor, ' m_checkRechableReply = nullptr;')
writeLine(fileDescriptor, ' });')
writeLine(fileDescriptor)
writeLine(fileDescriptor, ' connect(m_testRechableReply, &QModbusReply::errorOccurred, this, [this] (QModbusDevice::Error error){')
writeLine(fileDescriptor, ' qCDebug(dc%s()) << "Modbus reply error occurred while verifying reachability by reading \\"%s\\" register" << error << m_testRechableReply->errorString();' % (className, checkReachableRegister['description']))
writeLine(fileDescriptor, ' connect(m_checkRechableReply, &QModbusReply::errorOccurred, this, [this] (QModbusDevice::Error error){')
writeLine(fileDescriptor, ' qCDebug(dc%s()) << "Modbus reply error occurred while verifying reachability by reading \\"%s\\" register" << error << m_checkRechableReply->errorString();' % (className, checkReachableRegister['description']))
writeLine(fileDescriptor, ' });')
writeLine(fileDescriptor, '}')
writeLine(fileDescriptor)

View File

@ -71,6 +71,9 @@ def writeTcpHeaderFile():
writeLine(headerFile, ' ModbusDataUtils::ByteOrder endianness() const;')
writeLine(headerFile, ' void setEndianness(ModbusDataUtils::ByteOrder endianness);')
writeLine(headerFile)
writeLine(headerFile, ' uint checkReachableRetries() const;')
writeLine(headerFile, ' void setCheckReachableRetries(uint checkReachableRetries);')
writeLine(headerFile)
# Write registers get method declarations
writePropertyGetSetMethodDeclarationsTcp(headerFile, registerJson['registers'])
@ -108,6 +111,7 @@ def writeTcpHeaderFile():
writeLine(headerFile, 'signals:')
writeLine(headerFile, ' void reachableChanged(bool reachable);')
writeLine(headerFile, ' void checkReachabilityFailed();')
writeLine(headerFile, ' void checkReachableRetriesChanged(uint checkReachableRetries);')
writeLine(headerFile)
writeLine(headerFile, ' void initializationFinished(bool success);')
writeLine(headerFile, ' void updateFinished();')
@ -145,7 +149,11 @@ def writeTcpHeaderFile():
writeLine(headerFile, 'private:')
writeLine(headerFile, ' ModbusDataUtils::ByteOrder m_endianness = ModbusDataUtils::ByteOrder%s;' % endianness)
writeLine(headerFile, ' quint16 m_slaveId = 1;')
writeLine(headerFile)
writeLine(headerFile, ' bool m_reachable = false;')
writeLine(headerFile, ' QModbusReply *m_checkRechableReply = nullptr;')
writeLine(headerFile, ' uint m_checkReachableRetries = 0;')
writeLine(headerFile, ' uint m_checkReachableRetriesCount = 0;')
writeLine(headerFile, ' bool m_communicationWorking = false;')
writeLine(headerFile, ' quint8 m_communicationFailedMax = %s;' % (errorLimitUntilNotReachable))
writeLine(headerFile, ' quint8 m_communicationFailedCounter = 0;')
@ -159,7 +167,7 @@ def writeTcpHeaderFile():
writeLine(headerFile)
writeLine(headerFile, ' void verifyUpdateFinished();')
writeLine(headerFile)
writeLine(headerFile, ' QModbusReply *m_testRechableReply = nullptr;')
writeLine(headerFile, ' void onReachabilityCheckFailed();')
writeLine(headerFile, ' void evaluateReachableState();')
# End of class
@ -180,6 +188,8 @@ def writeTcpSourceFile():
writeLine(sourceFile)
writeLine(sourceFile, '#include "%s"' % headerFileName)
writeLine(sourceFile, '#include <loggingcategories.h>')
writeLine(sourceFile, '#include <math.h>')
writeLine(sourceFile, '#include <QTimer>')
writeLine(sourceFile)
writeLine(sourceFile, 'NYMEA_LOGGING_CATEGORY(dc%s, "%s")' % (className, className))
writeLine(sourceFile)
@ -197,11 +207,13 @@ def writeTcpSourceFile():
writeLine(sourceFile, ' m_pendingUpdateReplies.clear();')
writeLine(sourceFile, ' m_communicationWorking = false;')
writeLine(sourceFile, ' m_communicationFailedCounter = 0;')
writeLine(sourceFile, ' m_checkReachableRetriesCount = 0;')
writeLine(sourceFile, ' testReachability();')
writeLine(sourceFile, ' } else {')
writeLine(sourceFile, ' qCWarning(dc%s()) << "Modbus TCP connection diconnected from" << m_hostAddress.toString() << ". The connection is not reachable any more.";' % (className))
writeLine(sourceFile, ' m_communicationWorking = false;')
writeLine(sourceFile, ' m_communicationFailedCounter = 0;')
writeLine(sourceFile, ' m_checkReachableRetriesCount = 0;')
writeLine(sourceFile, ' }')
writeLine(sourceFile)
writeLine(sourceFile, ' evaluateReachableState();')
@ -215,6 +227,22 @@ def writeTcpSourceFile():
writeLine(sourceFile, '}')
writeLine(sourceFile)
writeLine(sourceFile, 'uint %s::checkReachableRetries() const' % (className))
writeLine(sourceFile, '{')
writeLine(sourceFile, ' return m_checkReachableRetries;')
writeLine(sourceFile, '}')
writeLine(sourceFile)
writeLine(sourceFile, 'void %s::setCheckReachableRetries(uint checkReachableRetries)' % (className))
writeLine(sourceFile, '{')
writeLine(sourceFile, ' if (m_checkReachableRetries == checkReachableRetries)')
writeLine(sourceFile, ' return;')
writeLine(sourceFile)
writeLine(sourceFile, ' m_checkReachableRetries = checkReachableRetries;')
writeLine(sourceFile, ' emit checkReachableRetriesChanged(m_checkReachableRetries);')
writeLine(sourceFile, '}')
writeLine(sourceFile)
writeLine(sourceFile, 'ModbusDataUtils::ByteOrder %s::endianness() const' % (className))
writeLine(sourceFile, '{')
writeLine(sourceFile, ' return m_endianness;')
@ -324,6 +352,21 @@ def writeTcpSourceFile():
writeLine(sourceFile, '}')
writeLine(sourceFile)
writeLine(sourceFile, 'void %s::onReachabilityCheckFailed()' % (className))
writeLine(sourceFile, '{')
writeLine(sourceFile, ' m_checkReachableRetriesCount++;')
writeLine(sourceFile)
writeLine(sourceFile, ' if (m_checkReachableRetriesCount <= m_checkReachableRetries) {')
writeLine(sourceFile, ' qCDebug(dc%s()) << "Reachability test failed. Retry in on second" << m_checkReachableRetriesCount << "/" << m_checkReachableRetries;' % (className))
writeLine(sourceFile, ' QTimer::singleShot(1000, this, &%s::testReachability);' % (className))
writeLine(sourceFile, ' return;')
writeLine(sourceFile, ' }')
writeLine(sourceFile)
writeLine(sourceFile, ' // The test reachability method failed, not retrying any more')
writeLine(sourceFile, ' emit checkReachabilityFailed();')
writeLine(sourceFile, '}')
writeLine(sourceFile)
writeLine(sourceFile, 'void %s::evaluateReachableState()' % (className))
writeLine(sourceFile, '{')
writeLine(sourceFile, ' bool reachable = m_communicationWorking && connected();')
@ -332,6 +375,7 @@ def writeTcpSourceFile():
writeLine(sourceFile)
writeLine(sourceFile, ' m_reachable = reachable;')
writeLine(sourceFile, ' emit reachableChanged(m_reachable);')
writeLine(sourceFile, ' m_checkReachableRetriesCount = 0;')
writeLine(sourceFile, '}')
writeLine(sourceFile)
@ -395,6 +439,9 @@ def writeRtuHeaderFile():
writeLine(headerFile)
writeLine(headerFile, ' bool reachable() const;')
writeLine(headerFile)
writeLine(headerFile, ' uint checkReachableRetries() const;')
writeLine(headerFile, ' void setCheckReachableRetries(uint checkReachableRetries);')
writeLine(headerFile)
writeLine(headerFile, ' ModbusDataUtils::ByteOrder endianness() const;')
writeLine(headerFile, ' void setEndianness(ModbusDataUtils::ByteOrder endianness);')
writeLine(headerFile)
@ -433,6 +480,7 @@ def writeRtuHeaderFile():
writeLine(headerFile, 'signals:')
writeLine(headerFile, ' void reachableChanged(bool reachable);')
writeLine(headerFile, ' void checkReachabilityFailed();')
writeLine(headerFile, ' void checkReachableRetriesChanged(uint checkReachableRetries);')
writeLine(headerFile)
writeLine(headerFile, ' void initializationFinished(bool success);')
writeLine(headerFile, ' void updateFinished();')
@ -471,7 +519,11 @@ def writeRtuHeaderFile():
writeLine(headerFile, ' ModbusRtuMaster *m_modbusRtuMaster = nullptr;')
writeLine(headerFile, ' ModbusDataUtils::ByteOrder m_endianness = ModbusDataUtils::ByteOrder%s;' % endianness)
writeLine(headerFile, ' quint16 m_slaveId = 1;')
writeLine(headerFile)
writeLine(headerFile, ' bool m_reachable = false;')
writeLine(headerFile, ' ModbusRtuReply *m_checkRechableReply = nullptr;')
writeLine(headerFile, ' uint m_checkReachableRetries = 0;')
writeLine(headerFile, ' uint m_checkReachableRetriesCount = 0;')
writeLine(headerFile, ' bool m_communicationWorking = false;')
writeLine(headerFile, ' quint8 m_communicationFailedMax = %s;' % (errorLimitUntilNotReachable))
writeLine(headerFile, ' quint8 m_communicationFailedCounter = 0;')
@ -485,7 +537,7 @@ def writeRtuHeaderFile():
writeLine(headerFile)
writeLine(headerFile, ' void verifyUpdateFinished();')
writeLine(headerFile)
writeLine(headerFile, ' ModbusRtuReply *m_testRechableReply = nullptr;')
writeLine(headerFile, ' void onReachabilityCheckFailed();')
writeLine(headerFile, ' void evaluateReachableState();')
@ -508,6 +560,7 @@ def writeRtuSourceFile():
writeLine(sourceFile, '#include "%s"' % headerFileName)
writeLine(sourceFile, '#include <loggingcategories.h>')
writeLine(sourceFile, '#include <math.h>')
writeLine(sourceFile, '#include <QTimer>')
writeLine(sourceFile)
writeLine(sourceFile, 'NYMEA_LOGGING_CATEGORY(dc%s, "%s")' % (className, className))
writeLine(sourceFile)
@ -525,11 +578,13 @@ def writeRtuSourceFile():
writeLine(sourceFile, ' m_pendingUpdateReplies.clear();')
writeLine(sourceFile, ' m_communicationWorking = false;')
writeLine(sourceFile, ' m_communicationFailedCounter = 0;')
writeLine(sourceFile, ' m_checkReachableRetriesCount = 0;')
writeLine(sourceFile, ' testReachability();')
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;')
writeLine(sourceFile, ' m_communicationFailedCounter = 0;')
writeLine(sourceFile, ' m_checkReachableRetriesCount = 0;')
writeLine(sourceFile, ' }')
writeLine(sourceFile)
writeLine(sourceFile, ' evaluateReachableState();')
@ -554,6 +609,22 @@ def writeRtuSourceFile():
writeLine(sourceFile, '}')
writeLine(sourceFile)
writeLine(sourceFile, 'uint %s::checkReachableRetries() const' % (className))
writeLine(sourceFile, '{')
writeLine(sourceFile, ' return m_checkReachableRetries;')
writeLine(sourceFile, '}')
writeLine(sourceFile)
writeLine(sourceFile, 'void %s::setCheckReachableRetries(uint checkReachableRetries)' % (className))
writeLine(sourceFile, '{')
writeLine(sourceFile, ' if (m_checkReachableRetries == checkReachableRetries)')
writeLine(sourceFile, ' return;')
writeLine(sourceFile)
writeLine(sourceFile, ' m_checkReachableRetries = checkReachableRetries;')
writeLine(sourceFile, ' emit checkReachableRetriesChanged(m_checkReachableRetries);')
writeLine(sourceFile, '}')
writeLine(sourceFile)
writeLine(sourceFile, 'ModbusDataUtils::ByteOrder %s::endianness() const' % (className))
writeLine(sourceFile, '{')
writeLine(sourceFile, ' return m_endianness;')
@ -664,6 +735,21 @@ def writeRtuSourceFile():
writeLine(sourceFile, '}')
writeLine(sourceFile)
writeLine(sourceFile, 'void %s::onReachabilityCheckFailed()' % (className))
writeLine(sourceFile, '{')
writeLine(sourceFile, ' m_checkReachableRetriesCount++;')
writeLine(sourceFile)
writeLine(sourceFile, ' if (m_checkReachableRetriesCount <= m_checkReachableRetries) {')
writeLine(sourceFile, ' qCDebug(dc%s()) << "Reachability test failed. Retry in on second" << m_checkReachableRetriesCount << "/" << m_checkReachableRetries;' % (className))
writeLine(sourceFile, ' QTimer::singleShot(1000, this, &%s::testReachability);' % (className))
writeLine(sourceFile, ' return;')
writeLine(sourceFile, ' }')
writeLine(sourceFile)
writeLine(sourceFile, ' // The test reachability method failed, not retrying any more')
writeLine(sourceFile, ' emit checkReachabilityFailed();')
writeLine(sourceFile, '}')
writeLine(sourceFile)
writeLine(sourceFile, 'void %s::evaluateReachableState()' % (className))
writeLine(sourceFile, '{')
writeLine(sourceFile, ' bool reachable = m_communicationWorking && m_modbusRtuMaster->connected();')
@ -672,6 +758,7 @@ def writeRtuSourceFile():
writeLine(sourceFile)
writeLine(sourceFile, ' m_reachable = reachable;')
writeLine(sourceFile, ' emit reachableChanged(m_reachable);')
writeLine(sourceFile, ' m_checkReachableRetriesCount = 0;')
writeLine(sourceFile, '}')
writeLine(sourceFile)