From e05ff0fdd00fdd86b27491961b1a3e5942bc98ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Ole=20Sch=C3=BCmann?= Date: Sun, 5 Oct 2025 21:12:29 +0700 Subject: [PATCH] Refactor retry handling (#702) * add NukiRetryHandler * apply retry wrapper to opener wrapper * apply retry wrapper to all opener communication * apply retry wrapper to all lock communication * remove commented out code * replace millis() with espMillis() in wrapper classes --- clion/CMakeLists.txt | 1 + src/Config.h | 4 +- src/NukiNetwork.cpp | 2 +- src/NukiOpenerWrapper.cpp | 218 +++++++++---------------------- src/NukiOpenerWrapper.h | 2 + src/NukiWrapper.cpp | 237 ++++++++++------------------------ src/NukiWrapper.h | 5 +- src/util/NukiRetryHandler.cpp | 52 ++++++++ src/util/NukiRetryHandler.h | 22 ++++ 9 files changed, 214 insertions(+), 329 deletions(-) create mode 100644 src/util/NukiRetryHandler.cpp create mode 100644 src/util/NukiRetryHandler.h diff --git a/clion/CMakeLists.txt b/clion/CMakeLists.txt index 6d4274d..26d9d92 100644 --- a/clion/CMakeLists.txt +++ b/clion/CMakeLists.txt @@ -48,6 +48,7 @@ set(SRCFILES ../lib/BleScanner/src/BleScanner.cpp ../lib/MqttLogger/src/MqttLogger.cpp ../src/util/NetworkUtil.cpp + ../src/util/NukiRetryHandler.cpp ../src/enums/NetworkDeviceType.h ../src/util/NetworkDeviceInstantiator.cpp ../src/HomeAssistantDiscovery.cpp diff --git a/src/Config.h b/src/Config.h index d3ea328..9fc0337 100644 --- a/src/Config.h +++ b/src/Config.h @@ -5,8 +5,8 @@ #define NUKI_HUB_VERSION "9.13" #define NUKI_HUB_VERSION_INT (uint32_t)913 #define NUKI_HUB_BUILD "unknownbuildnr" -#define NUKI_HUB_DATE "2025-10-02" -#define NUKI_HUB_DATE "2025-10-02" +#define NUKI_HUB_DATE "2025-10-05" +#define NUKI_HUB_DATE "2025-10-05" #define GITHUB_LATEST_RELEASE_URL (char*)"https://github.com/technyon/nuki_hub/releases/latest" #define GITHUB_OTA_MANIFEST_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/manifest.json" diff --git a/src/NukiNetwork.cpp b/src/NukiNetwork.cpp index 5f18801..1ebc77d 100644 --- a/src/NukiNetwork.cpp +++ b/src/NukiNetwork.cpp @@ -806,7 +806,7 @@ bool NukiNetwork::reconnect(bool force) if (_device->mqttConnected()) { Log->println("MQTT connected"); - _mqttConnectedTs = millis(); + _mqttConnectedTs = espMillis(); _mqttConnectionState = 1; if (esp_task_wdt_status(NULL) == ESP_OK) { diff --git a/src/NukiOpenerWrapper.cpp b/src/NukiOpenerWrapper.cpp index 3fa75c5..01aef05 100644 --- a/src/NukiOpenerWrapper.cpp +++ b/src/NukiOpenerWrapper.cpp @@ -75,6 +75,9 @@ void NukiOpenerWrapper::initialize() _hassEnabled = _preferences->getBool(preference_mqtt_hass_enabled, false); readSettings(); +#ifndef NUKI_HUB_UPDATER + _nukiRetryHandler = new NukiRetryHandler("Opener", _gpio, _gpio->getPinsWithRole(PinRole::OutputHighBluetoothCommError), _nrOfRetries, _retryDelay); +#endif } void NukiOpenerWrapper::readSettings() @@ -287,44 +290,35 @@ void NukiOpenerWrapper::update() if(_nextLockAction != (NukiOpener::LockAction)0xff) { int retryCount = 0; - Nuki::CmdResult cmdResult = (Nuki::CmdResult)-1; - while(retryCount < _nrOfRetries + 1 && cmdResult != Nuki::CmdResult::Success) + Nuki::CmdResult result = _nukiRetryHandler->retryComm([&]() { - cmdResult = _nukiOpener.lockAction(_nextLockAction, 0, 0); - char resultStr[15] = {0}; - NukiOpener::cmdResultToString(cmdResult, resultStr); + Nuki::CmdResult cmdResult; + cmdResult = _nukiOpener.lockAction(_nextLockAction, 0, 0); + char resultStr[15] = {0}; + NukiLock::cmdResultToString(cmdResult, resultStr); + _network->publishCommandResult(resultStr); - _network->publishCommandResult(resultStr); + Log->print("Opener lock action result: "); + Log->println(resultStr); - Log->print("Opener action result: "); - Log->println(resultStr); + if(cmdResult != Nuki::CmdResult::Success) + { + _network->publishRetry(std::to_string(retryCount + 1)); - if(cmdResult != Nuki::CmdResult::Success) - { - setCommErrorPins(HIGH); - Log->print("Opener: Last command failed, retrying after "); - Log->print(_retryDelay); - Log->print(" milliseconds. Retry "); - Log->print(retryCount + 1); - Log->print(" of "); - Log->println(_nrOfRetries); + if (esp_task_wdt_status(NULL) == ESP_OK) + { + esp_task_wdt_reset(); + } - _network->publishRetry(std::to_string(retryCount + 1)); + ++retryCount; + } + postponeBleWatchdog(); - if (esp_task_wdt_status(NULL) == ESP_OK) - { - esp_task_wdt_reset(); - } - vTaskDelay(_retryDelay / portTICK_PERIOD_MS); + return cmdResult; + }); - ++retryCount; - } - postponeBleWatchdog(); - } - setCommErrorPins(LOW); - - if(cmdResult == Nuki::CmdResult::Success) + if(result == Nuki::CmdResult::Success) { _nextLockAction = (NukiOpener::LockAction) 0xff; _network->publishRetry("--"); @@ -509,16 +503,12 @@ bool NukiOpenerWrapper::updateKeyTurnerState() { bool updateStatus = false; Nuki::CmdResult result = (Nuki::CmdResult)-1; - int retryCount = 0; + Log->println("Querying opener state"); - while(result != Nuki::CmdResult::Success && retryCount < _nrOfRetries + 1) + result = _nukiRetryHandler->retryComm([&]() { - Log->print("Result (attempt "); - Log->print(retryCount + 1); - Log->print("): "); - result =_nukiOpener.requestOpenerState(&_keyTurnerState); - ++retryCount; - } + return _nukiOpener.requestOpenerState(&_keyTurnerState); + }); char resultStr[15]; memset(&resultStr, 0, sizeof(resultStr)); @@ -621,28 +611,18 @@ bool NukiOpenerWrapper::updateKeyTurnerState() void NukiOpenerWrapper::updateBatteryState() { Nuki::CmdResult result = (Nuki::CmdResult)-1; - int retryCount = 0; + Log->print("Querying opener battery state: "); - while(retryCount < _nrOfRetries + 1) + result = _nukiRetryHandler->retryComm([&]() { - Log->print("Querying opener battery state: "); - result = _nukiOpener.requestBatteryReport(&_batteryReport); + Nuki::CmdResult cmdResult = _nukiOpener.requestBatteryReport(&_batteryReport); if (esp_task_wdt_status(NULL) == ESP_OK) { esp_task_wdt_reset(); } - vTaskDelay(250 / portTICK_PERIOD_MS); - if(result != Nuki::CmdResult::Success) - { - ++retryCount; - } - else - { - break; - } - } + return cmdResult; + }); - NukiOpenerHelper::printCommandResult(result); if(result == Nuki::CmdResult::Success) { _network->publishBatteryReport(_batteryReport); @@ -693,21 +673,11 @@ void NukiOpenerWrapper::updateConfig() const int pinStatus = _preferences->getInt(preference_opener_pin_status, (int)NukiPinState::NotConfigured); Nuki::CmdResult result = (Nuki::CmdResult)-1; - int retryCount = 0; - while(retryCount < _nrOfRetries + 1) + result = _nukiRetryHandler->retryComm([&]() { - result = _nukiOpener.verifySecurityPin(); - - if(result != Nuki::CmdResult::Success) - { - ++retryCount; - } - else - { - break; - } - } + return _nukiOpener.verifySecurityPin(); + }); if(result != Nuki::CmdResult::Success) { @@ -781,22 +751,11 @@ void NukiOpenerWrapper::updateAuthData(bool retrieved) if(!retrieved) { Nuki::CmdResult result = (Nuki::CmdResult)-1; - int retryCount = 0; - while(retryCount < _nrOfRetries + 1) + result = _nukiRetryHandler->retryComm([&]() { - Log->print("Retrieve log entries: "); - result = _nukiOpener.retrieveLogEntries(0, _preferences->getInt(preference_authlog_max_entries, MAX_AUTHLOG), 1, false); - - if(result != Nuki::CmdResult::Success) - { - ++retryCount; - } - else - { - break; - } - } + return _nukiOpener.retrieveLogEntries(0, _preferences->getInt(preference_authlog_max_entries, MAX_AUTHLOG), 1, false); + }); Log->println(result); NukiOpenerHelper::printCommandResult(result); @@ -871,22 +830,11 @@ void NukiOpenerWrapper::updateKeypad(bool retrieved) if(!retrieved) { Nuki::CmdResult result = (Nuki::CmdResult)-1; - int retryCount = 0; - while(retryCount < _nrOfRetries + 1) + result = _nukiRetryHandler->retryComm([&]() { - Log->print("Querying opener keypad: "); - result = _nukiOpener.retrieveKeypadEntries(0, _preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD)); - - if(result != Nuki::CmdResult::Success) - { - ++retryCount; - } - else - { - break; - } - } + return _nukiOpener.retrieveKeypadEntries(0, _preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD)); + }); NukiOpenerHelper::printCommandResult(result); if(result == Nuki::CmdResult::Success) @@ -951,24 +899,13 @@ void NukiOpenerWrapper::updateTimeControl(bool retrieved) if(!retrieved) { Nuki::CmdResult result = (Nuki::CmdResult)-1; - int retryCount = 0; + Log->print("Querying opener timecontrol: "); - while(retryCount < _nrOfRetries + 1) + result = _nukiRetryHandler->retryComm([&]() { - Log->print("Querying opener timecontrol: "); - result = _nukiOpener.retrieveTimeControlEntries(); + return _nukiOpener.retrieveTimeControlEntries(); + }); - if(result != Nuki::CmdResult::Success) - { - ++retryCount; - } - else - { - break; - } - } - - NukiOpenerHelper::printCommandResult(result); if(result == Nuki::CmdResult::Success) { _waitTimeControlUpdateTs = espMillis() + 5000; @@ -1028,31 +965,21 @@ void NukiOpenerWrapper::updateAuth(bool retrieved) if(!retrieved) { Nuki::CmdResult result = (Nuki::CmdResult)-1; - int retryCount = 0; + Log->print("Querying opener authorization: "); - while(retryCount < _nrOfRetries) + result = _nukiRetryHandler->retryComm([&]() { - Log->print("Querying opener authorization: "); - result = _nukiOpener.retrieveAuthorizationEntries(0, _preferences->getInt(preference_auth_max_entries, MAX_AUTH)); + Nuki::CmdResult cmdResult = _nukiOpener.retrieveAuthorizationEntries(0, _preferences->getInt(preference_auth_max_entries, MAX_AUTH)); if (esp_task_wdt_status(NULL) == ESP_OK) { esp_task_wdt_reset(); } - vTaskDelay(250 / portTICK_PERIOD_MS); - if(result != Nuki::CmdResult::Success) - { - ++retryCount; - } - else - { - break; - } - } + return cmdResult; + }); - NukiOpenerHelper::printCommandResult(result); if(result == Nuki::CmdResult::Success) { - _waitAuthUpdateTs = millis() + 5000; + _waitAuthUpdateTs = espMillis() + 5000; } } else @@ -3687,22 +3614,12 @@ void NukiOpenerWrapper::notify(Nuki::EventType eventType) void NukiOpenerWrapper::readConfig() { Nuki::CmdResult result = (Nuki::CmdResult)-1; - int retryCount = 0; - while(retryCount < _nrOfRetries + 1) + result = _nukiRetryHandler->retryComm([&]() { - result = _nukiOpener.requestConfig(&_nukiConfig); - _nukiConfigValid = result == Nuki::CmdResult::Success; - - if(!_nukiConfigValid) - { - ++retryCount; - } - else - { - break; - } - } + return _nukiOpener.requestConfig(&_nukiConfig); + }); + _nukiConfigValid = result == Nuki::CmdResult::Success; char resultStr[20]; NukiOpener::cmdResultToString(result, resultStr); @@ -3717,22 +3634,12 @@ void NukiOpenerWrapper::readConfig() void NukiOpenerWrapper::readAdvancedConfig() { Nuki::CmdResult result = (Nuki::CmdResult)-1; - int retryCount = 0; - while(retryCount < _nrOfRetries + 1) + result = _nukiRetryHandler->retryComm([&]() { - result = _nukiOpener.requestAdvancedConfig(&_nukiAdvancedConfig); - _nukiAdvancedConfigValid = result == Nuki::CmdResult::Success; - - if(!_nukiAdvancedConfigValid) - { - ++retryCount; - } - else - { - break; - } - } + return _nukiOpener.requestAdvancedConfig(&_nukiAdvancedConfig); + }); + _nukiAdvancedConfigValid = result == Nuki::CmdResult::Success; char resultStr[20]; NukiOpener::cmdResultToString(result, resultStr); @@ -3819,7 +3726,10 @@ void NukiOpenerWrapper::updateTime() nukiTime.minute = tm.tm_min; nukiTime.second = tm.tm_sec; - Nuki::CmdResult cmdResult = _nukiOpener.updateTime(nukiTime); + Nuki::CmdResult cmdResult = _nukiRetryHandler->retryComm([&]() + { + return _nukiOpener.updateTime(nukiTime); + }); char resultStr[15] = {0}; NukiOpener::cmdResultToString(cmdResult, resultStr); diff --git a/src/NukiOpenerWrapper.h b/src/NukiOpenerWrapper.h index 988b2ce..b019e7f 100644 --- a/src/NukiOpenerWrapper.h +++ b/src/NukiOpenerWrapper.h @@ -7,6 +7,7 @@ #include "BleScanner.h" #include "Gpio.h" #include "NukiDeviceId.h" +#include "util/NukiRetryHandler.h" class NukiOpenerWrapper : public NukiOpener::SmartlockEventHandler { @@ -85,6 +86,7 @@ private: NukiNetworkOpener* _network = nullptr; Preferences* _preferences = nullptr; Gpio* _gpio = nullptr; + NukiRetryHandler* _nukiRetryHandler = nullptr; std::vector _pinsCommError; diff --git a/src/NukiWrapper.cpp b/src/NukiWrapper.cpp index e56944f..41b9c0f 100644 --- a/src/NukiWrapper.cpp +++ b/src/NukiWrapper.cpp @@ -10,6 +10,7 @@ #include #include "esp_sntp.h" #include "util/NukiHelper.h" +#include "util/NukiRetryHandler.h" NukiWrapper* nukiInst = nullptr; @@ -46,9 +47,6 @@ NukiWrapper::NukiWrapper(const std::string& deviceName, NukiDeviceId* deviceId, network->setAuthCommandReceivedCallback(nukiInst->onAuthCommandReceivedCallback); _gpio->addCallback(NukiWrapper::gpioActionCallback); -#ifndef NUKI_HUB_UPDATER - _pinsCommError = _gpio->getPinsWithRole(PinRole::OutputHighBluetoothCommError); -#endif } @@ -80,6 +78,10 @@ void NukiWrapper::initialize() _hassEnabled = _preferences->getBool(preference_mqtt_hass_enabled, false); readSettings(); + +#ifndef NUKI_HUB_UPDATER + _nukiRetryHandler = new NukiRetryHandler("Lock", _gpio, _gpio->getPinsWithRole(PinRole::OutputHighBluetoothCommError), _nrOfRetries, _retryDelay); +#endif } void NukiWrapper::readSettings() @@ -307,43 +309,35 @@ void NukiWrapper::update(bool reboot) if(_nextLockAction != (NukiLock::LockAction)0xff) { int retryCount = 0; - Nuki::CmdResult cmdResult; - while(retryCount < _nrOfRetries + 1 && cmdResult != Nuki::CmdResult::Success) + Nuki::CmdResult result = _nukiRetryHandler->retryComm([&]() { - cmdResult = _nukiLock.lockAction(_nextLockAction, 0, 0); - char resultStr[15] = {0}; - NukiLock::cmdResultToString(cmdResult, resultStr); - _network->publishCommandResult(resultStr); + Nuki::CmdResult cmdResult; + cmdResult = _nukiLock.lockAction(_nextLockAction, 0, 0); + char resultStr[15] = {0}; + NukiLock::cmdResultToString(cmdResult, resultStr); + _network->publishCommandResult(resultStr); - Log->print("Lock action result: "); - Log->println(resultStr); + Log->print("Lock action result: "); + Log->println(resultStr); - if(cmdResult != Nuki::CmdResult::Success) - { - setCommErrorPins(HIGH); - Log->print("Lock: Last command failed, retrying after "); - Log->print(_retryDelay); - Log->print(" milliseconds. Retry "); - Log->print(retryCount + 1); - Log->print(" of "); - Log->println(_nrOfRetries); + if(cmdResult != Nuki::CmdResult::Success) + { + _network->publishRetry(std::to_string(retryCount + 1)); - _network->publishRetry(std::to_string(retryCount + 1)); + if (esp_task_wdt_status(NULL) == ESP_OK) + { + esp_task_wdt_reset(); + } - if (esp_task_wdt_status(NULL) == ESP_OK) - { - esp_task_wdt_reset(); - } - vTaskDelay(_retryDelay / portTICK_PERIOD_MS); + ++retryCount; + } + postponeBleWatchdog(); - ++retryCount; - } - postponeBleWatchdog(); - } - setCommErrorPins(LOW); + return cmdResult; + }); - if(cmdResult == Nuki::CmdResult::Success) + if(result == Nuki::CmdResult::Success) { _nextLockAction = (NukiLock::LockAction) 0xff; _network->publishRetry("--"); @@ -544,14 +538,10 @@ bool NukiWrapper::updateKeyTurnerState() Log->println("Querying lock state"); - while(result != Nuki::CmdResult::Success && retryCount < _nrOfRetries + 1) + result = _nukiRetryHandler->retryComm([&]() { - Log->print("Result (attempt "); - Log->print(retryCount + 1); - Log->print("): "); - result =_nukiLock.requestKeyTurnerState(&_keyTurnerState); - ++retryCount; - } + return _nukiLock.requestKeyTurnerState(&_keyTurnerState); + }); char resultStr[15]; memset(&resultStr, 0, sizeof(resultStr)); @@ -636,24 +626,11 @@ void NukiWrapper::updateBatteryState() Log->println("Querying lock battery state"); - while(retryCount < _nrOfRetries + 1) + result = _nukiRetryHandler->retryComm([&]() { - Log->print("Result (attempt "); - Log->print(retryCount + 1); - Log->print("): "); - result = _nukiLock.requestBatteryReport(&_batteryReport); + return _nukiLock.requestBatteryReport(&_batteryReport); + }); - if(result != Nuki::CmdResult::Success) - { - ++retryCount; - } - else - { - break; - } - } - - NukiHelper::printCommandResult(result); if(result == Nuki::CmdResult::Success) { _network->publishBatteryReport(_batteryReport); @@ -703,20 +680,11 @@ void NukiWrapper::updateConfig() const int pinStatus = _preferences->getInt(preference_lock_pin_status, (int)NukiPinState::NotConfigured); Nuki::CmdResult result = (Nuki::CmdResult)-1; - int retryCount = 0; - while(retryCount < _nrOfRetries + 1) + result = _nukiRetryHandler->retryComm([&]() { - result = _nukiLock.verifySecurityPin(); - if(result != Nuki::CmdResult::Success) - { - ++retryCount; - } - else - { - break; - } - } + return _nukiLock.verifySecurityPin(); + }); if(result != Nuki::CmdResult::Success) { @@ -946,20 +914,12 @@ void NukiWrapper::updateAuthData(bool retrieved) { Nuki::CmdResult result = (Nuki::CmdResult)-1; int retryCount = 0; + Log->print("Retrieving log entries: "); - while(retryCount < _nrOfRetries + 1) + result = _nukiRetryHandler->retryComm([&]() { - Log->print("Retrieve log entries: "); - result = _nukiLock.retrieveLogEntries(0, _preferences->getInt(preference_authlog_max_entries, MAX_AUTHLOG), 1, false); - if(result != Nuki::CmdResult::Success) - { - ++retryCount; - } - else - { - break; - } - } + return _nukiLock.retrieveLogEntries(0, _preferences->getInt(preference_authlog_max_entries, MAX_AUTHLOG), 1, false); + }); NukiHelper::printCommandResult(result); if(result == Nuki::CmdResult::Success) @@ -1034,22 +994,13 @@ void NukiWrapper::updateKeypad(bool retrieved) { Nuki::CmdResult result = (Nuki::CmdResult)-1; int retryCount = 0; + Log->print("Querying lock keypad: "); - while(retryCount < _nrOfRetries + 1) + result = _nukiRetryHandler->retryComm([&]() { - Log->print("Querying lock keypad: "); - result = _nukiLock.retrieveKeypadEntries(0, _preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD)); - if(result != Nuki::CmdResult::Success) - { - ++retryCount; - } - else - { - break; - } - } + return _nukiLock.retrieveKeypadEntries(0, _preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD)); + }); - NukiHelper::printCommandResult(result); if(result == Nuki::CmdResult::Success) { _waitKeypadUpdateTs = espMillis() + 5000; @@ -1111,22 +1062,13 @@ void NukiWrapper::updateTimeControl(bool retrieved) if(!retrieved) { + Log->print("Querying lock timecontrol: "); Nuki::CmdResult result = (Nuki::CmdResult)-1; - int retryCount = 0; - while(retryCount < _nrOfRetries + 1) + result = _nukiRetryHandler->retryComm([&]() { - Log->print("Querying lock timecontrol: "); - result = _nukiLock.retrieveTimeControlEntries(); - if(result != Nuki::CmdResult::Success) - { - ++retryCount; - } - else - { - break; - } - } + return _nukiLock.retrieveTimeControlEntries(); + }); NukiHelper::printCommandResult(result); if(result == Nuki::CmdResult::Success) @@ -1187,32 +1129,23 @@ void NukiWrapper::updateAuth(bool retrieved) if(!retrieved) { + Log->print("Querying lock authorization: "); Nuki::CmdResult result = (Nuki::CmdResult)-1; - int retryCount = 0; - while(retryCount < _nrOfRetries) + result = _nukiRetryHandler->retryComm([&]() { - Log->print("Querying lock authorization: "); - result = _nukiLock.retrieveAuthorizationEntries(0, _preferences->getInt(preference_auth_max_entries, MAX_AUTH)); + Nuki::CmdResult cmdResult = _nukiLock.retrieveAuthorizationEntries(0, _preferences->getInt(preference_auth_max_entries, MAX_AUTH)); if (esp_task_wdt_status(NULL) == ESP_OK) { esp_task_wdt_reset(); } - vTaskDelay(250 / portTICK_PERIOD_MS); - if(result != Nuki::CmdResult::Success) - { - ++retryCount; - } - else - { - break; - } - } + return cmdResult; + }); NukiHelper::printCommandResult(result); if(result == Nuki::CmdResult::Success) { - _waitAuthUpdateTs = millis() + 5000; + _waitAuthUpdateTs = espMillis() + 5000; } } else @@ -4074,33 +4007,22 @@ void NukiWrapper::notify(Nuki::EventType eventType) void NukiWrapper::readConfig() { Nuki::CmdResult result = (Nuki::CmdResult)-1; - int retryCount = 0; - while(retryCount < _nrOfRetries + 1) + result = _nukiRetryHandler->retryComm([&]() { - result = _nukiLock.requestConfig(&_nukiConfig); - _nukiConfigValid = result == Nuki::CmdResult::Success; - - char resultStr[20]; - NukiLock::cmdResultToString(result, resultStr); - Log->print("Lock config result: "); - Log->println(resultStr); + Nuki::CmdResult cmdResult = _nukiLock.requestConfig(&_nukiConfig); if(result != Nuki::CmdResult::Success) { - ++retryCount; - Log->println("Failed to retrieve lock config, retrying in 1s"); if (esp_task_wdt_status(NULL) == ESP_OK) { esp_task_wdt_reset(); } - vTaskDelay(1000 / portTICK_PERIOD_MS); } - else - { - break; - } - } + + return cmdResult; + }); + _nukiConfigValid = result == Nuki::CmdResult::Success; } void NukiWrapper::readAdvancedConfig() @@ -4108,31 +4030,19 @@ void NukiWrapper::readAdvancedConfig() Nuki::CmdResult result = (Nuki::CmdResult)-1; int retryCount = 0; - while(retryCount < _nrOfRetries + 1) + result = _nukiRetryHandler->retryComm([&]() { - result = _nukiLock.requestAdvancedConfig(&_nukiAdvancedConfig); - _nukiAdvancedConfigValid = result == Nuki::CmdResult::Success; - - char resultStr[20]; - NukiLock::cmdResultToString(result, resultStr); - Log->print("Lock advanced config result: "); - Log->println(resultStr); - + Nuki::CmdResult cmdResult = _nukiLock.requestAdvancedConfig(&_nukiAdvancedConfig); if(result != Nuki::CmdResult::Success) { - ++retryCount; - Log->println("Failed to retrieve lock advanced config, retrying in 1s"); if (esp_task_wdt_status(NULL) == ESP_OK) { esp_task_wdt_reset(); } - vTaskDelay(1000 / portTICK_PERIOD_MS); } - else - { - break; - } - } + return cmdResult; + }); + _nukiAdvancedConfigValid = result == Nuki::CmdResult::Success; } bool NukiWrapper::hasDoorSensor() const @@ -4158,14 +4068,6 @@ const std::string NukiWrapper::hardwareVersion() const return _hardwareVersion; } -void NukiWrapper::setCommErrorPins(const uint8_t& value) -{ - for (uint8_t pin : _pinsCommError) - { - _gpio->setPinOutput(pin, value); - } -} - void NukiWrapper::disableWatchdog() { _restartBeaconTimeout = -1; @@ -4223,11 +4125,8 @@ void NukiWrapper::updateTime() nukiTime.minute = tm.tm_min; nukiTime.second = tm.tm_sec; - Nuki::CmdResult cmdResult = _nukiLock.updateTime(nukiTime); - - char resultStr[15] = {0}; - NukiLock::cmdResultToString(cmdResult, resultStr); - - Log->print("Lock time update result: "); - Log->println(resultStr); + Nuki::CmdResult cmdResult = _nukiRetryHandler->retryComm([&]() + { + return _nukiLock.updateTime(nukiTime); + }); } \ No newline at end of file diff --git a/src/NukiWrapper.h b/src/NukiWrapper.h index 3163c27..be98b1b 100644 --- a/src/NukiWrapper.h +++ b/src/NukiWrapper.h @@ -10,6 +10,7 @@ #include "NukiDeviceId.h" #include "NukiOfficial.h" #include "EspMillis.h" +#include "util/NukiRetryHandler.h" class NukiWrapper : public Nuki::SmartlockEventHandler { @@ -48,7 +49,6 @@ public: const std::string firmwareVersion() const; const std::string hardwareVersion() const; - void setCommErrorPins(const uint8_t& value); void notify(Nuki::EventType eventType) override; @@ -93,8 +93,7 @@ private: NukiNetworkLock* _network = nullptr; NukiOfficial* _nukiOfficial = nullptr; Gpio* _gpio = nullptr; - - std::vector _pinsCommError; + NukiRetryHandler* _nukiRetryHandler = nullptr; Preferences* _preferences; int _intervalLockstate = 0; // seconds diff --git a/src/util/NukiRetryHandler.cpp b/src/util/NukiRetryHandler.cpp new file mode 100644 index 0000000..3fceb4e --- /dev/null +++ b/src/util/NukiRetryHandler.cpp @@ -0,0 +1,52 @@ +#include "NukiRetryHandler.h" +#include "Logger.h" + +NukiRetryHandler::NukiRetryHandler(std::string reference, Gpio* gpio, std::vector pinsCommError, int nrOfRetries, int retryDelay) +: _reference(reference), + _gpio(gpio), + _pinsCommError(pinsCommError), + _nrOfRetries(nrOfRetries), + _retryDelay(retryDelay) +{ +} + +const Nuki::CmdResult NukiRetryHandler::retryComm(std::function func) +{ + Nuki::CmdResult cmdResult = Nuki::CmdResult::Error; + + int retryCount = 0; + + while(retryCount < _nrOfRetries + 1 && cmdResult != Nuki::CmdResult::Success) + { + cmdResult = func(); + + if (cmdResult != Nuki::CmdResult::Success) + { + setCommErrorPins(HIGH); + ++retryCount; + + Log->print(_reference.c_str()); + Log->print(": Last command failed, retrying after "); + Log->print(_retryDelay); + Log->print(" milliseconds. Retry "); + Log->print(retryCount); + Log->print(" of "); + Log->println(_nrOfRetries); + + vTaskDelay(_retryDelay / portTICK_PERIOD_MS); + } + } + setCommErrorPins(LOW); + + return cmdResult; +} + +void NukiRetryHandler::setCommErrorPins(const uint8_t& value) +{ + for (uint8_t pin : _pinsCommError) + { + _gpio->setPinOutput(pin, value); + } +} + + diff --git a/src/util/NukiRetryHandler.h b/src/util/NukiRetryHandler.h new file mode 100644 index 0000000..dde60b1 --- /dev/null +++ b/src/util/NukiRetryHandler.h @@ -0,0 +1,22 @@ +#pragma once +#include +#include "NukiDataTypes.h" +#include "NukiPublisher.h" + +class NukiRetryHandler +{ +public: + NukiRetryHandler(std::string reference, Gpio* gpio, std::vector pinsCommError, int nrOfRetries, int retryDelay); + + const Nuki::CmdResult retryComm(std::function func); + + +private: + void setCommErrorPins(const uint8_t& value); + + std::string _reference; + Gpio* _gpio = nullptr; + int _nrOfRetries = 0; + int _retryDelay = 0; + std::vector _pinsCommError; +};