From 633b7e8423aa00938e47c04b91ddcbf7207b5b35 Mon Sep 17 00:00:00 2001 From: technyon Date: Sat, 14 Jan 2023 10:09:35 +0100 Subject: [PATCH 1/6] add retry mechanic --- NukiWrapper.cpp | 41 ++++++++++++++++++++++++++++++++++++++--- NukiWrapper.h | 3 +++ PreferencesKeys.h | 2 ++ Version.h | 2 +- WebCfgServer.cpp | 12 ++++++++++++ 5 files changed, 56 insertions(+), 4 deletions(-) diff --git a/NukiWrapper.cpp b/NukiWrapper.cpp index 46921a5..0ce774c 100644 --- a/NukiWrapper.cpp +++ b/NukiWrapper.cpp @@ -48,6 +48,14 @@ void NukiWrapper::initialize() _maxKeypadCodeCount = _preferences->getUInt(preference_max_keypad_code_count); _restartBeaconTimeout = _preferences->getInt(preference_restart_ble_beacon_lost); _hassEnabled = _preferences->getString(preference_mqtt_hass_discovery) != ""; + _nrOfRetries = _preferences->getInt(preference_command_nr_of_retries); + _retryDelay = _preferences->getInt(preference_command_retry_delay); + + if(_retryDelay <= 100) + { + _retryDelay = 100; + _preferences->putInt(preference_command_retry_delay, _retryDelay); + } if(_intervalLockstate == 0) { @@ -175,10 +183,37 @@ void NukiWrapper::update() Log->print(F("Lock action result: ")); Log->println(resultStr); - _nextLockAction = (NukiLock::LockAction)0xff; - if(_intervalLockstate > 10) + if(cmdResult == Nuki::CmdResult::Success) { - _nextLockStateUpdateTs = ts + 10 * 1000; + _nextLockAction = (NukiLock::LockAction) 0xff; + if (_intervalLockstate > 10) + { + _nextLockStateUpdateTs = ts + 10 * 1000; + } + } + else + { + if(_retryCount == -1) + { + _retryCount = _nrOfRetries; + } + else if(_retryCount == 0) + { + _nextLockAction = (NukiLock::LockAction) 0xff; + _retryCount = -1; + if (_intervalLockstate > 10) + { + _nextLockStateUpdateTs = ts + 10 * 1000; + } + return; + } + + Log->print(F("Last command failed, retrying after ")); + Log->print(_retryDelay); + Log->print(F(" milliseconds.")); + + --_retryCount; + _nextLockStateUpdateTs = millis() + _retryDelay; } } diff --git a/NukiWrapper.h b/NukiWrapper.h index 9e7c669..ef054b5 100644 --- a/NukiWrapper.h +++ b/NukiWrapper.h @@ -84,6 +84,9 @@ private: bool _keypadEnabled = false; bool _configRead = false; uint _maxKeypadCodeCount = 0; + int _nrOfRetries = 0; + int _retryDelay = 0; + int _retryCount = -1; unsigned long _nextLockStateUpdateTs = 0; unsigned long _nextBatteryReportTs = 0; unsigned long _nextConfigUpdateTs = 0; diff --git a/PreferencesKeys.h b/PreferencesKeys.h index c45f3ef..890bca2 100644 --- a/PreferencesKeys.h +++ b/PreferencesKeys.h @@ -27,6 +27,8 @@ #define preference_query_interval_keypad "kpInterval" #define preference_keypad_control_enabled "kpEnabled" #define preference_register_as_app "regAsApp" // true = register as hub; false = register as app +#define preference_command_nr_of_retries "nrRetry" +#define preference_command_retry_delay "nrRetry" #define preference_cred_user "crdusr" #define preference_cred_password "crdpass" #define preference_publish_authdata "pubauth" diff --git a/Version.h b/Version.h index 394f420..807b224 100644 --- a/Version.h +++ b/Version.h @@ -1,3 +1,3 @@ #pragma once -#define nuki_hub_version "6.10" \ No newline at end of file +#define nuki_hub_version "6.10-retry-1" \ No newline at end of file diff --git a/WebCfgServer.cpp b/WebCfgServer.cpp index a87bfaa..679fbc3 100644 --- a/WebCfgServer.cpp +++ b/WebCfgServer.cpp @@ -307,6 +307,16 @@ bool WebCfgServer::processArgs(String& message) _preferences->putBool(preference_keypad_control_enabled, (value == "1")); configChanged = true; } + else if(key == "NRTRY") + { + _preferences->putInt(preference_command_nr_of_retries, value.toInt()); + configChanged = true; + } + else if(key == "TRYDLY") + { + _preferences->putInt(preference_command_retry_delay, value.toInt()); + configChanged = true; + } else if(key == "PRDTMO") { _preferences->putInt(preference_presence_detection_timeout, value.toInt()); @@ -637,6 +647,8 @@ void WebCfgServer::buildNukiConfigHtml(String &response) printInputField(response, "KPINT", "Query interval keypad (seconds)", _preferences->getInt(preference_query_interval_keypad), 10); printCheckBox(response, "KPENA", "Enabled keypad control via MQTT", _preferences->getBool(preference_keypad_control_enabled)); } + printInputField(response, "NRTRY", "Number of retries if command failed", _preferences->getInt(preference_command_nr_of_retries), 10); + printInputField(response, "TRYDLY", "Delay between retries", _preferences->getInt(preference_command_retry_delay), 10); printCheckBox(response, "PUBAUTH", "Publish auth data (May reduce battery life)", _preferences->getBool(preference_publish_authdata)); printCheckBox(response, "GPLCK", "Enable control via GPIO", _preferences->getBool(preference_gpio_locking_enabled)); printInputField(response, "PRDTMO", "Presence detection timeout (seconds; -1 to disable)", _preferences->getInt(preference_presence_detection_timeout), 10); From 502f0c4b6e739dbcc2bb0fe4a62168382edc23f8 Mon Sep 17 00:00:00 2001 From: technyon Date: Sat, 14 Jan 2023 10:13:05 +0100 Subject: [PATCH 2/6] fix preference key --- PreferencesKeys.h | 2 +- WebCfgServer.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PreferencesKeys.h b/PreferencesKeys.h index 890bca2..92c177c 100644 --- a/PreferencesKeys.h +++ b/PreferencesKeys.h @@ -28,7 +28,7 @@ #define preference_keypad_control_enabled "kpEnabled" #define preference_register_as_app "regAsApp" // true = register as hub; false = register as app #define preference_command_nr_of_retries "nrRetry" -#define preference_command_retry_delay "nrRetry" +#define preference_command_retry_delay "rtryDelay" #define preference_cred_user "crdusr" #define preference_cred_password "crdpass" #define preference_publish_authdata "pubauth" diff --git a/WebCfgServer.cpp b/WebCfgServer.cpp index 679fbc3..054e2d9 100644 --- a/WebCfgServer.cpp +++ b/WebCfgServer.cpp @@ -648,7 +648,7 @@ void WebCfgServer::buildNukiConfigHtml(String &response) printCheckBox(response, "KPENA", "Enabled keypad control via MQTT", _preferences->getBool(preference_keypad_control_enabled)); } printInputField(response, "NRTRY", "Number of retries if command failed", _preferences->getInt(preference_command_nr_of_retries), 10); - printInputField(response, "TRYDLY", "Delay between retries", _preferences->getInt(preference_command_retry_delay), 10); + printInputField(response, "TRYDLY", "Delay between retries (milliseconds)", _preferences->getInt(preference_command_retry_delay), 10); printCheckBox(response, "PUBAUTH", "Publish auth data (May reduce battery life)", _preferences->getBool(preference_publish_authdata)); printCheckBox(response, "GPLCK", "Enable control via GPIO", _preferences->getBool(preference_gpio_locking_enabled)); printInputField(response, "PRDTMO", "Presence detection timeout (seconds; -1 to disable)", _preferences->getInt(preference_presence_detection_timeout), 10); From 81f65c3ff484a8b95d5906e6af19e5601f7e2473 Mon Sep 17 00:00:00 2001 From: technyon Date: Sat, 14 Jan 2023 13:54:53 +0100 Subject: [PATCH 3/6] fix retry counter --- MqttTopics.h | 1 + NetworkLock.cpp | 5 +++++ NetworkLock.h | 1 + NukiWrapper.cpp | 34 ++++++++++++++++++---------------- NukiWrapper.h | 2 +- Version.h | 2 +- 6 files changed, 27 insertions(+), 18 deletions(-) diff --git a/MqttTopics.h b/MqttTopics.h index 2b09c82..998222a 100644 --- a/MqttTopics.h +++ b/MqttTopics.h @@ -21,6 +21,7 @@ #define mqtt_topic_lock_action "/lock/action" #define mqtt_topic_lock_rssi "/lock/rssi" #define mqtt_topic_lock_address "/lock/address" +#define mqtt_topic_lock_retry "/lock/retry" #define mqtt_topic_config_button_enabled "/configuration/buttonEnabled" #define mqtt_topic_config_led_enabled "/configuration/ledEnabled" diff --git a/NetworkLock.cpp b/NetworkLock.cpp index e683e77..4a6e996 100644 --- a/NetworkLock.cpp +++ b/NetworkLock.cpp @@ -388,6 +388,11 @@ void NetworkLock::publishRssi(const int& rssi) publishInt(mqtt_topic_lock_rssi, rssi); } +void NetworkLock::publishRetry(const std::string& message) +{ + publishString(mqtt_topic_lock_retry, message.c_str()); +} + void NetworkLock::publishBleAddress(const std::string &address) { publishString(mqtt_topic_lock_address, address.c_str()); diff --git a/NetworkLock.h b/NetworkLock.h index b313b30..ca07013 100644 --- a/NetworkLock.h +++ b/NetworkLock.h @@ -28,6 +28,7 @@ public: void publishConfig(const NukiLock::Config& config); void publishAdvancedConfig(const NukiLock::AdvancedConfig& config); void publishRssi(const int& rssi); + void publishRetry(const std::string& message); void publishBleAddress(const std::string& address); void publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, char* lockAction, char* unlockAction, char* openAction, char* lockedState, char* unlockedState); void removeHASSConfig(char* uidString); diff --git a/NukiWrapper.cpp b/NukiWrapper.cpp index 0ce774c..99c46ff 100644 --- a/NukiWrapper.cpp +++ b/NukiWrapper.cpp @@ -185,6 +185,7 @@ void NukiWrapper::update() if(cmdResult == Nuki::CmdResult::Success) { + _retryCount = 0; _nextLockAction = (NukiLock::LockAction) 0xff; if (_intervalLockstate > 10) { @@ -193,27 +194,28 @@ void NukiWrapper::update() } else { - if(_retryCount == -1) + if(_retryCount < _nrOfRetries) { - _retryCount = _nrOfRetries; + Log->print(F("Last command failed, retrying after ")); + Log->print(_retryDelay); + Log->print(F(" milliseconds. Retry ")); + Log->print(_retryCount + 1); + Log->print(" of "); + Log->println(_nrOfRetries); + + _network->publishRetry(std::to_string(_retryCount + 1)); + + _nextLockStateUpdateTs = millis() + _retryDelay; + + ++_retryCount; } - else if(_retryCount == 0) + else { + Log->println(F("Maximum number of retries exceeded, aborting.")); + _network->publishRetry("failed"); + _retryCount = 0; _nextLockAction = (NukiLock::LockAction) 0xff; - _retryCount = -1; - if (_intervalLockstate > 10) - { - _nextLockStateUpdateTs = ts + 10 * 1000; - } - return; } - - Log->print(F("Last command failed, retrying after ")); - Log->print(_retryDelay); - Log->print(F(" milliseconds.")); - - --_retryCount; - _nextLockStateUpdateTs = millis() + _retryDelay; } } diff --git a/NukiWrapper.h b/NukiWrapper.h index ef054b5..f343252 100644 --- a/NukiWrapper.h +++ b/NukiWrapper.h @@ -86,7 +86,7 @@ private: uint _maxKeypadCodeCount = 0; int _nrOfRetries = 0; int _retryDelay = 0; - int _retryCount = -1; + int _retryCount = 0; unsigned long _nextLockStateUpdateTs = 0; unsigned long _nextBatteryReportTs = 0; unsigned long _nextConfigUpdateTs = 0; diff --git a/Version.h b/Version.h index 807b224..222ae51 100644 --- a/Version.h +++ b/Version.h @@ -1,3 +1,3 @@ #pragma once -#define nuki_hub_version "6.10-retry-1" \ No newline at end of file +#define nuki_hub_version "6.10-retry-2" \ No newline at end of file From 3cd57fb032ca0c3a59282485ea2eeb20e1ad00e6 Mon Sep 17 00:00:00 2001 From: technyon Date: Sat, 14 Jan 2023 18:17:21 +0100 Subject: [PATCH 4/6] add retry delay --- NukiWrapper.cpp | 6 ++++-- NukiWrapper.h | 1 + Version.h | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/NukiWrapper.cpp b/NukiWrapper.cpp index 99c46ff..a589578 100644 --- a/NukiWrapper.cpp +++ b/NukiWrapper.cpp @@ -171,7 +171,7 @@ void NukiWrapper::update() updateKeypad(); } - if(_nextLockAction != (NukiLock::LockAction)0xff) + if(_nextLockAction != (NukiLock::LockAction)0xff && ts > _nextRetryTs) { Nuki::CmdResult cmdResult = _nukiLock.lockAction(_nextLockAction, 0, 0); @@ -187,6 +187,7 @@ void NukiWrapper::update() { _retryCount = 0; _nextLockAction = (NukiLock::LockAction) 0xff; + _network->publishRetry("--"); if (_intervalLockstate > 10) { _nextLockStateUpdateTs = ts + 10 * 1000; @@ -205,7 +206,7 @@ void NukiWrapper::update() _network->publishRetry(std::to_string(_retryCount + 1)); - _nextLockStateUpdateTs = millis() + _retryDelay; + _nextRetryTs = millis() + _retryDelay; ++_retryCount; } @@ -214,6 +215,7 @@ void NukiWrapper::update() Log->println(F("Maximum number of retries exceeded, aborting.")); _network->publishRetry("failed"); _retryCount = 0; + _nextRetryTs = 0; _nextLockAction = (NukiLock::LockAction) 0xff; } } diff --git a/NukiWrapper.h b/NukiWrapper.h index f343252..70791f6 100644 --- a/NukiWrapper.h +++ b/NukiWrapper.h @@ -87,6 +87,7 @@ private: int _nrOfRetries = 0; int _retryDelay = 0; int _retryCount = 0; + unsigned long _nextRetryTs = 0; unsigned long _nextLockStateUpdateTs = 0; unsigned long _nextBatteryReportTs = 0; unsigned long _nextConfigUpdateTs = 0; diff --git a/Version.h b/Version.h index 222ae51..d7cd96c 100644 --- a/Version.h +++ b/Version.h @@ -1,3 +1,3 @@ #pragma once -#define nuki_hub_version "6.10-retry-2" \ No newline at end of file +#define nuki_hub_version "6.10-retry-3" \ No newline at end of file From a5c3e82cae90fc6516fc6b22b7797a7c9a54fb41 Mon Sep 17 00:00:00 2001 From: technyon Date: Sat, 14 Jan 2023 21:34:28 +0100 Subject: [PATCH 5/6] initialize retry parameters on first start --- NukiWrapper.cpp | 7 ++++++- NukiWrapper.h | 2 +- PreferencesKeys.h | 2 +- main.cpp | 14 +++++++++----- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/NukiWrapper.cpp b/NukiWrapper.cpp index a589578..00b66b3 100644 --- a/NukiWrapper.cpp +++ b/NukiWrapper.cpp @@ -34,7 +34,7 @@ NukiWrapper::~NukiWrapper() } -void NukiWrapper::initialize() +void NukiWrapper::initialize(const bool& firstStart) { _nukiLock.initialize(); @@ -51,6 +51,11 @@ void NukiWrapper::initialize() _nrOfRetries = _preferences->getInt(preference_command_nr_of_retries); _retryDelay = _preferences->getInt(preference_command_retry_delay); + if(firstStart) + { + _preferences->putInt(preference_command_nr_of_retries, 3); + _preferences->putInt(preference_command_retry_delay, 1000); + } if(_retryDelay <= 100) { _retryDelay = 100; diff --git a/NukiWrapper.h b/NukiWrapper.h index 70791f6..e3d0949 100644 --- a/NukiWrapper.h +++ b/NukiWrapper.h @@ -12,7 +12,7 @@ public: NukiWrapper(const std::string& deviceName, uint32_t id, BleScanner::Scanner* scanner, NetworkLock* network, Preferences* preferences); virtual ~NukiWrapper(); - void initialize(); + void initialize(const bool& firstStart); void update(); void lock(); diff --git a/PreferencesKeys.h b/PreferencesKeys.h index 92c177c..ba9d132 100644 --- a/PreferencesKeys.h +++ b/PreferencesKeys.h @@ -1,6 +1,6 @@ #pragma once -#define preference_started_befores "run" +#define preference_started_before "run" #define preference_deviceId "deviceId" #define preference_mqtt_broker "mqttbroker" #define preference_mqtt_broker_port "mqttport" diff --git a/main.cpp b/main.cpp index 05586df..4c450c0 100644 --- a/main.cpp +++ b/main.cpp @@ -140,14 +140,16 @@ void initEthServer(const NetworkDeviceType device) } } -void initPreferences() +bool initPreferences() { preferences = new Preferences(); preferences->begin("nukihub", false); - if(!preferences->getBool(preference_started_befores)) + bool firstStart = !preferences->getBool(preference_started_before); + + if(firstStart) { - preferences->putBool(preference_started_befores, true); + preferences->putBool(preference_started_before, true); preferences->putBool(preference_lock_enabled, true); } @@ -155,6 +157,8 @@ void initPreferences() { preferences->putInt(preference_restart_timer, -1); } + + return firstStart; } void setup() @@ -163,7 +167,7 @@ void setup() Serial.begin(115200); Log = &Serial; - initPreferences(); + bool firstStart = initPreferences(); if(preferences->getInt(preference_restart_timer) > 0) { @@ -196,7 +200,7 @@ void setup() if(lockEnabled) { nuki = new NukiWrapper("NukiHub", deviceId, bleScanner, networkLock, preferences); - nuki->initialize(); + nuki->initialize(firstStart); if(preferences->getBool(preference_gpio_locking_enabled)) { From aeeae9573d4ab9258ad7e53e1514c7578db6e661 Mon Sep 17 00:00:00 2001 From: technyon Date: Sat, 14 Jan 2023 21:44:54 +0100 Subject: [PATCH 6/6] implement retry mechanic for opener --- NetworkOpener.cpp | 5 +++++ NetworkOpener.h | 1 + NukiOpenerWrapper.cpp | 45 +++++++++++++++++++++++++++++++++++++------ NukiOpenerWrapper.h | 4 ++++ NukiWrapper.cpp | 4 ++-- Version.h | 2 +- 6 files changed, 52 insertions(+), 9 deletions(-) diff --git a/NetworkOpener.cpp b/NetworkOpener.cpp index 6b3dc84..38deea6 100644 --- a/NetworkOpener.cpp +++ b/NetworkOpener.cpp @@ -382,6 +382,11 @@ void NetworkOpener::publishRssi(const int &rssi) publishInt(mqtt_topic_lock_rssi, rssi); } +void NetworkOpener::publishRetry(const std::string& message) +{ + publishString(mqtt_topic_lock_retry, message.c_str()); +} + void NetworkOpener::publishBleAddress(const std::string &address) { publishString(mqtt_topic_lock_address, address.c_str()); diff --git a/NetworkOpener.h b/NetworkOpener.h index eb52a22..489de0d 100644 --- a/NetworkOpener.h +++ b/NetworkOpener.h @@ -29,6 +29,7 @@ public: void publishConfig(const NukiOpener::Config& config); void publishAdvancedConfig(const NukiOpener::AdvancedConfig& config); void publishRssi(const int& rssi); + void publishRetry(const std::string& message); void publishBleAddress(const std::string& address); void publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, char* lockAction, char* unlockAction, char* openAction, char* lockedState, char* unlockedState); void removeHASSConfig(char* uidString); diff --git a/NukiOpenerWrapper.cpp b/NukiOpenerWrapper.cpp index aa4025d..0e074c7 100644 --- a/NukiOpenerWrapper.cpp +++ b/NukiOpenerWrapper.cpp @@ -43,6 +43,8 @@ void NukiOpenerWrapper::initialize() _publishAuthData = _preferences->getBool(preference_publish_authdata); _restartBeaconTimeout = _preferences->getInt(preference_restart_ble_beacon_lost); _hassEnabled = _preferences->getString(preference_mqtt_hass_discovery) != ""; + _nrOfRetries = _preferences->getInt(preference_command_nr_of_retries); + _retryDelay = _preferences->getInt(preference_command_retry_delay); if(_intervalLockstate == 0) { @@ -142,22 +144,53 @@ void NukiOpenerWrapper::update() } } - if(_nextLockAction != (NukiOpener::LockAction)0xff) + if(_nextLockAction != (NukiOpener::LockAction)0xff && ts > _nextRetryTs) { - NukiOpener::CmdResult cmdResult = _nukiOpener.lockAction(_nextLockAction, 0, 0); + Nuki::CmdResult cmdResult = _nukiOpener.lockAction(_nextLockAction, 0, 0); char resultStr[15] = {0}; NukiOpener::cmdResultToString(cmdResult, resultStr); _network->publishCommandResult(resultStr); - Log->print(F("Opener lock action result: ")); + Log->print(F("Lock action result: ")); Log->println(resultStr); - _nextLockAction = (NukiOpener::LockAction)0xff; - if(_intervalLockstate > 10) + if(cmdResult == Nuki::CmdResult::Success) { - _nextLockStateUpdateTs = ts + 10 * 1000; + _retryCount = 0; + _nextLockAction = (NukiOpener::LockAction) 0xff; + _network->publishRetry("--"); + if (_intervalLockstate > 10) + { + _nextLockStateUpdateTs = ts + 10 * 1000; + } + } + else + { + if(_retryCount < _nrOfRetries) + { + Log->print(F("Opener: Last command failed, retrying after ")); + Log->print(_retryDelay); + Log->print(F(" milliseconds. Retry ")); + Log->print(_retryCount + 1); + Log->print(" of "); + Log->println(_nrOfRetries); + + _network->publishRetry(std::to_string(_retryCount + 1)); + + _nextRetryTs = millis() + _retryDelay; + + ++_retryCount; + } + else + { + Log->println(F("Opener: Maximum number of retries exceeded, aborting.")); + _network->publishRetry("failed"); + _retryCount = 0; + _nextRetryTs = 0; + _nextLockAction = (NukiOpener::LockAction) 0xff; + } } } diff --git a/NukiOpenerWrapper.h b/NukiOpenerWrapper.h index 434f0b1..59f216a 100644 --- a/NukiOpenerWrapper.h +++ b/NukiOpenerWrapper.h @@ -57,6 +57,10 @@ private: int _restartBeaconTimeout = 0; // seconds bool _publishAuthData = false; bool _clearAuthData = false; + int _nrOfRetries = 0; + int _retryDelay = 0; + int _retryCount = 0; + unsigned long _nextRetryTs = 0; NukiOpener::OpenerState _lastKeyTurnerState; NukiOpener::OpenerState _keyTurnerState; diff --git a/NukiWrapper.cpp b/NukiWrapper.cpp index 00b66b3..02ade66 100644 --- a/NukiWrapper.cpp +++ b/NukiWrapper.cpp @@ -202,7 +202,7 @@ void NukiWrapper::update() { if(_retryCount < _nrOfRetries) { - Log->print(F("Last command failed, retrying after ")); + Log->print(F("Lock: Last command failed, retrying after ")); Log->print(_retryDelay); Log->print(F(" milliseconds. Retry ")); Log->print(_retryCount + 1); @@ -217,7 +217,7 @@ void NukiWrapper::update() } else { - Log->println(F("Maximum number of retries exceeded, aborting.")); + Log->println(F("Lock: Maximum number of retries exceeded, aborting.")); _network->publishRetry("failed"); _retryCount = 0; _nextRetryTs = 0; diff --git a/Version.h b/Version.h index d7cd96c..9c9efe4 100644 --- a/Version.h +++ b/Version.h @@ -1,3 +1,3 @@ #pragma once -#define nuki_hub_version "6.10-retry-3" \ No newline at end of file +#define nuki_hub_version "6.11" \ No newline at end of file