From b55164919b5aa11b9f0bf549f9374c298f61e23a Mon Sep 17 00:00:00 2001 From: iranl Date: Sun, 17 Nov 2024 20:43:08 +0100 Subject: [PATCH 1/3] Reboot Nuki --- README.md | 2 ++ src/HomeAssistantDiscovery.cpp | 61 ++++++++++++++++++++++++++++++++-- src/NukiNetworkLock.cpp | 1 + src/NukiNetworkOpener.cpp | 1 + src/NukiOpenerWrapper.cpp | 17 ++++++++-- src/NukiOpenerWrapper.h | 2 +- src/NukiWrapper.cpp | 17 ++++++++-- src/NukiWrapper.h | 2 +- src/PreferencesKeys.h | 24 ++++++------- src/WebCfgServer.cpp | 34 +++++++++++++------ 10 files changed, 131 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 3cd3d14..1f25aff 100644 --- a/README.md +++ b/README.md @@ -456,6 +456,7 @@ Changing settings has to enabled first in the configuration portal. Check the se | autoLockEnabled | Whether auto lock is enabled. | 1 = enabled, 0 = disabled |`{ "autoLockEnabled": "1" }` | | immediateAutoLockEnabled | Whether auto lock should be performed immediately after the door has been closed. | 1 = enabled, 0 = disabled |`{ "immediateAutoLockEnabled": "1" }`| | autoUpdateEnabled | Whether automatic firmware updates should be enabled. | 1 = enabled, 0 = disabled |`{ "autoUpdateEnabled": "1" }` | +| rebootNuki | Reboot the Nuki device immediately | 1 = reboot nuki |`{ "rebootNuki": "1" }` | ### Nuki Opener Configuration @@ -495,6 +496,7 @@ Changing settings has to enabled first in the configuration portal. Check the se | doubleButtonPressAction | The desired action, if the button is pressed twice. | "No Action", "Toggle RTO", "Activate RTO", "Deactivate RTO", "Toggle CM", "Activate CM", "Deactivate CM", "Open" |`{ "doubleButtonPressAction": "No Action" }` | | batteryType | The type of the batteries present in the smart lock. | "Alkali", "Accumulators", "Lithium" |`{ "batteryType": "Accumulators" }` | | automaticBatteryTypeDetection | Whether the automatic detection of the battery type is enabled. | 1 = enabled, 0 = disabled |`{ "automaticBatteryTypeDetection": "1" }` | +| rebootNuki | Reboot the Nuki device immediately | 1 = reboot nuki |`{ "rebootNuki": "1" }` | Example usage for changing multiple settings at once:
- `{ "buttonEnabled": "1", "lockngoTimeout": "60", "automaticBatteryTypeDetection": "1" }` diff --git a/src/HomeAssistantDiscovery.cpp b/src/HomeAssistantDiscovery.cpp index 70fc1f5..c34579b 100644 --- a/src/HomeAssistantDiscovery.cpp +++ b/src/HomeAssistantDiscovery.cpp @@ -717,7 +717,7 @@ void HomeAssistantDiscovery::publishHASSConfigAdditionalLockEntities(char *devic _preferences->getBytes(preference_acl, &aclPrefs, sizeof(aclPrefs)); uint32_t basicLockConfigAclPrefs[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - uint32_t advancedLockConfigAclPrefs[22] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t advancedLockConfigAclPrefs[23] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; if(_preferences->getBool(preference_conf_info_enabled, true)) { @@ -1823,6 +1823,34 @@ void HomeAssistantDiscovery::publishHASSConfigAdditionalLockEntities(char *devic { removeHassTopic((char*)"switch", (char*)"auto_update_enabled", uidString); } + + if((int)advancedLockConfigAclPrefs[22] == 1) + { + // Reboot Nuki + publishHassTopic("button", + "reboot_nuki", + uidString, + "_reboot_nuki", + "Reboot Nuki", + name, + baseTopic, + "", + deviceType, + "", + "", + "diagnostic", + String("~") + mqtt_topic_config_action, + { + { (char*)"en", (char*)"true" }, + { (char*)"pl_on", (char*)"{ \"rebootNuki\": \"1\"}" }, + { (char*)"pl_off", (char*)"{ \"rebootNuki\": \"0\"}" }, + { (char*)"val_tpl", (char*)"{{value_json.rebootNuki}}" } + }); + } + else + { + removeHassTopic((char*)"button", (char*)"reboot_nuki", uidString); + } } void HomeAssistantDiscovery::publishHASSConfigDoorSensor(char *deviceType, const char *baseTopic, char *name, char *uidString) @@ -1852,7 +1880,7 @@ void HomeAssistantDiscovery::publishHASSConfigAdditionalOpenerEntities(char *dev uint32_t aclPrefs[17]; _preferences->getBytes(preference_acl, &aclPrefs, sizeof(aclPrefs)); uint32_t basicOpenerConfigAclPrefs[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - uint32_t advancedOpenerConfigAclPrefs[20] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t advancedOpenerConfigAclPrefs[21] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; if(_preferences->getBool(preference_conf_info_enabled, true)) { @@ -2743,6 +2771,34 @@ void HomeAssistantDiscovery::publishHASSConfigAdditionalOpenerEntities(char *dev { removeHassTopic((char*)"switch", (char*)"automatic_battery_type_detection", uidString); } + + if((int)advancedOpenerConfigAclPrefs[20] == 1) + { + // Reboot Nuki + publishHassTopic("button", + "reboot_nuki", + uidString, + "_reboot_nuki", + "Reboot Nuki", + name, + baseTopic, + "", + deviceType, + "", + "", + "diagnostic", + String("~") + mqtt_topic_config_action, + { + { (char*)"en", (char*)"true" }, + { (char*)"pl_on", (char*)"{ \"rebootNuki\": \"1\"}" }, + { (char*)"pl_off", (char*)"{ \"rebootNuki\": \"0\"}" }, + { (char*)"val_tpl", (char*)"{{value_json.rebootNuki}}" } + }); + } + else + { + removeHassTopic((char*)"button", (char*)"reboot_nuki", uidString); + } } void HomeAssistantDiscovery::publishHASSConfigAccessLog(char *deviceType, const char *baseTopic, char *name, char *uidString) @@ -2934,6 +2990,7 @@ void HomeAssistantDiscovery::removeHASSConfig(char* uidString) removeHassTopic((char*)"button", (char*)"query_commandresult", uidString); removeHassTopic((char*)"switch", (char*)"auto_lock", uidString); removeHassTopic((char*)"switch", (char*)"auto_unlock", uidString); + removeHassTopic((char*)"button", (char*)"reboot_nuki", uidString); removeHassTopic((char*)"switch", (char*)"double_lock", uidString); removeHassTopic((char*)"switch", (char*)"automatic_battery_type_detection", uidString); removeHassTopic((char*)"select", (char*)"battery_type", uidString); diff --git a/src/NukiNetworkLock.cpp b/src/NukiNetworkLock.cpp index 9169e3a..967b771 100644 --- a/src/NukiNetworkLock.cpp +++ b/src/NukiNetworkLock.cpp @@ -855,6 +855,7 @@ void NukiNetworkLock::publishAdvancedConfig(const NukiLock::AdvancedConfig &conf json["autoLockEnabled"] = config.autoLockEnabled; json["immediateAutoLockEnabled"] = config.immediateAutoLockEnabled; json["autoUpdateEnabled"] = config.autoUpdateEnabled; + json["rebootNuki"] = 0; serializeJson(json, _buffer, _bufferSize); publishString(mqtt_topic_config_advanced_json, _buffer, true); diff --git a/src/NukiNetworkOpener.cpp b/src/NukiNetworkOpener.cpp index 08f0e0a..d427811 100644 --- a/src/NukiNetworkOpener.cpp +++ b/src/NukiNetworkOpener.cpp @@ -834,6 +834,7 @@ void NukiNetworkOpener::publishAdvancedConfig(const NukiOpener::AdvancedConfig & _network->batteryTypeToString(config.batteryType, str); json["batteryType"] = str; json["automaticBatteryTypeDetection"] = config.automaticBatteryTypeDetection; + json["rebootNuki"] = 0; serializeJson(json, _buffer, _bufferSize); publishString(mqtt_topic_config_advanced_json, _buffer, true); diff --git a/src/NukiOpenerWrapper.cpp b/src/NukiOpenerWrapper.cpp index 7163034..1275e4f 100644 --- a/src/NukiOpenerWrapper.cpp +++ b/src/NukiOpenerWrapper.cpp @@ -1515,7 +1515,7 @@ void NukiOpenerWrapper::onConfigUpdateReceived(const char *value) Nuki::CmdResult cmdResult; const char *basicKeys[14] = {"name", "latitude", "longitude", "pairingEnabled", "buttonEnabled", "ledFlashEnabled", "timeZoneOffset", "dstMode", "fobAction1", "fobAction2", "fobAction3", "operatingMode", "advertisingMode", "timeZone"}; - const char *advancedKeys[20] = {"intercomID", "busModeSwitch", "shortCircuitDuration", "electricStrikeDelay", "randomElectricStrikeDelay", "electricStrikeDuration", "disableRtoAfterRing", "rtoTimeout", "doorbellSuppression", "doorbellSuppressionDuration", "soundRing", "soundOpen", "soundRto", "soundCm", "soundConfirmation", "soundLevel", "singleButtonPressAction", "doubleButtonPressAction", "batteryType", "automaticBatteryTypeDetection"}; + const char *advancedKeys[21] = {"intercomID", "busModeSwitch", "shortCircuitDuration", "electricStrikeDelay", "randomElectricStrikeDelay", "electricStrikeDuration", "disableRtoAfterRing", "rtoTimeout", "doorbellSuppression", "doorbellSuppressionDuration", "soundRing", "soundOpen", "soundRto", "soundCm", "soundConfirmation", "soundLevel", "singleButtonPressAction", "doubleButtonPressAction", "batteryType", "automaticBatteryTypeDetection", "rebootNuki"}; bool basicUpdated = false; bool advancedUpdated = false; @@ -1846,7 +1846,7 @@ void NukiOpenerWrapper::onConfigUpdateReceived(const char *value) } } - for(int j=0; j < 20; j++) + for(int j=0; j < 21; j++) { if(json[advancedKeys[j]]) { @@ -2265,6 +2265,19 @@ void NukiOpenerWrapper::onConfigUpdateReceived(const char *value) jsonResult[advancedKeys[j]] = "invalidValue"; } } + else if(strcmp(advancedKeys[j], "rebootNuki") == 0) + { + const uint8_t keyvalue = atoi(jsonchar); + + if(keyvalue == 1) + { + cmdResult = _nukiOpener.requestReboot(); + } + else + { + jsonResult[advancedKeys[j]] = "invalidValue"; + } + } if(cmdResult != Nuki::CmdResult::Success) { diff --git a/src/NukiOpenerWrapper.h b/src/NukiOpenerWrapper.h index eb8237a..0af838a 100644 --- a/src/NukiOpenerWrapper.h +++ b/src/NukiOpenerWrapper.h @@ -151,7 +151,7 @@ private: int64_t _lastRssi = 0; int64_t _disableBleWatchdogTs = 0; uint32_t _basicOpenerConfigAclPrefs[16]; - uint32_t _advancedOpenerConfigAclPrefs[20]; + uint32_t _advancedOpenerConfigAclPrefs[21]; std::string _firmwareVersion = ""; std::string _hardwareVersion = ""; NukiOpener::LockAction _nextLockAction = (NukiOpener::LockAction)0xff; diff --git a/src/NukiWrapper.cpp b/src/NukiWrapper.cpp index a417326..ef16a6f 100644 --- a/src/NukiWrapper.cpp +++ b/src/NukiWrapper.cpp @@ -1423,7 +1423,7 @@ void NukiWrapper::onConfigUpdateReceived(const char *value) Nuki::CmdResult cmdResult; const char *basicKeys[16] = {"name", "latitude", "longitude", "autoUnlatch", "pairingEnabled", "buttonEnabled", "ledEnabled", "ledBrightness", "timeZoneOffset", "dstMode", "fobAction1", "fobAction2", "fobAction3", "singleLock", "advertisingMode", "timeZone"}; - const char *advancedKeys[22] = {"unlockedPositionOffsetDegrees", "lockedPositionOffsetDegrees", "singleLockedPositionOffsetDegrees", "unlockedToLockedTransitionOffsetDegrees", "lockNgoTimeout", "singleButtonPressAction", "doubleButtonPressAction", "detachedCylinder", "batteryType", "automaticBatteryTypeDetection", "unlatchDuration", "autoLockTimeOut", "autoUnLockDisabled", "nightModeEnabled", "nightModeStartTime", "nightModeEndTime", "nightModeAutoLockEnabled", "nightModeAutoUnlockDisabled", "nightModeImmediateLockOnStart", "autoLockEnabled", "immediateAutoLockEnabled", "autoUpdateEnabled"}; + const char *advancedKeys[23] = {"unlockedPositionOffsetDegrees", "lockedPositionOffsetDegrees", "singleLockedPositionOffsetDegrees", "unlockedToLockedTransitionOffsetDegrees", "lockNgoTimeout", "singleButtonPressAction", "doubleButtonPressAction", "detachedCylinder", "batteryType", "automaticBatteryTypeDetection", "unlatchDuration", "autoLockTimeOut", "autoUnLockDisabled", "nightModeEnabled", "nightModeStartTime", "nightModeEndTime", "nightModeAutoLockEnabled", "nightModeAutoUnlockDisabled", "nightModeImmediateLockOnStart", "autoLockEnabled", "immediateAutoLockEnabled", "autoUpdateEnabled", "rebootNuki"}; bool basicUpdated = false; bool advancedUpdated = false; @@ -1794,7 +1794,7 @@ void NukiWrapper::onConfigUpdateReceived(const char *value) } } - for(int j=0; j < 22; j++) + for(int j=0; j < 23; j++) { if(json[advancedKeys[j]]) { @@ -2257,6 +2257,19 @@ void NukiWrapper::onConfigUpdateReceived(const char *value) jsonResult[advancedKeys[j]] = "invalidValue"; } } + else if(strcmp(advancedKeys[j], "rebootNuki") == 0) + { + const uint8_t keyvalue = atoi(jsonchar); + + if(keyvalue == 1) + { + cmdResult = _nukiLock.requestReboot(); + } + else + { + jsonResult[advancedKeys[j]] = "invalidValue"; + } + } if(cmdResult != Nuki::CmdResult::Success) { diff --git a/src/NukiWrapper.h b/src/NukiWrapper.h index c7f9888..1336f92 100644 --- a/src/NukiWrapper.h +++ b/src/NukiWrapper.h @@ -155,7 +155,7 @@ private: int64_t _lastRssi = 0; int64_t _disableBleWatchdogTs = 0; uint32_t _basicLockConfigaclPrefs[16]; - uint32_t _advancedLockConfigaclPrefs[22]; + uint32_t _advancedLockConfigaclPrefs[23]; std::string _firmwareVersion = ""; std::string _hardwareVersion = ""; volatile NukiLock::LockAction _nextLockAction = (NukiLock::LockAction)0xff; diff --git a/src/PreferencesKeys.h b/src/PreferencesKeys.h index 212c888..1e3190e 100644 --- a/src/PreferencesKeys.h +++ b/src/PreferencesKeys.h @@ -152,9 +152,9 @@ inline void initPreferences(Preferences* preferences) preferences->putBytes(preference_conf_lock_basic_acl, (byte*)(&basicLockConfigAclPrefs), sizeof(basicLockConfigAclPrefs)); uint32_t basicOpenerConfigAclPrefs[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; preferences->putBytes(preference_conf_opener_basic_acl, (byte*)(&basicOpenerConfigAclPrefs), sizeof(basicOpenerConfigAclPrefs)); - uint32_t advancedLockConfigAclPrefs[22] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t advancedLockConfigAclPrefs[23] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; preferences->putBytes(preference_conf_lock_advanced_acl, (byte*)(&advancedLockConfigAclPrefs), sizeof(advancedLockConfigAclPrefs)); - uint32_t advancedOpenerConfigAclPrefs[20] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t advancedOpenerConfigAclPrefs[21] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; preferences->putBytes(preference_conf_opener_advanced_acl, (byte*)(&advancedOpenerConfigAclPrefs), sizeof(advancedOpenerConfigAclPrefs)); #ifndef CONFIG_IDF_TARGET_ESP32H2 @@ -249,9 +249,9 @@ inline void initPreferences(Preferences* preferences) preferences->putBytes(preference_conf_lock_basic_acl, (byte*)(&basicLockConfigAclPrefs), sizeof(basicLockConfigAclPrefs)); uint32_t basicOpenerConfigAclPrefs[14] = {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}; preferences->putBytes(preference_conf_opener_basic_acl, (byte*)(&basicOpenerConfigAclPrefs), sizeof(basicOpenerConfigAclPrefs)); - uint32_t advancedLockConfigAclPrefs[22] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0}; + uint32_t advancedLockConfigAclPrefs[23] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0}; preferences->putBytes(preference_conf_lock_advanced_acl, (byte*)(&advancedLockConfigAclPrefs), sizeof(advancedLockConfigAclPrefs)); - uint32_t advancedOpenerConfigAclPrefs[20] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}; + uint32_t advancedOpenerConfigAclPrefs[21] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}; preferences->putBytes(preference_conf_opener_advanced_acl, (byte*)(&advancedOpenerConfigAclPrefs), sizeof(advancedOpenerConfigAclPrefs)); break; } @@ -264,9 +264,9 @@ inline void initPreferences(Preferences* preferences) preferences->putBytes(preference_conf_lock_basic_acl, (byte*)(&basicLockConfigAclPrefs), sizeof(basicLockConfigAclPrefs)); uint32_t basicOpenerConfigAclPrefs[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; preferences->putBytes(preference_conf_opener_basic_acl, (byte*)(&basicOpenerConfigAclPrefs), sizeof(basicOpenerConfigAclPrefs)); - uint32_t advancedLockConfigAclPrefs[22] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t advancedLockConfigAclPrefs[23] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; preferences->putBytes(preference_conf_lock_advanced_acl, (byte*)(&advancedLockConfigAclPrefs), sizeof(advancedLockConfigAclPrefs)); - uint32_t advancedOpenerConfigAclPrefs[20] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t advancedOpenerConfigAclPrefs[21] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; preferences->putBytes(preference_conf_opener_advanced_acl, (byte*)(&advancedOpenerConfigAclPrefs), sizeof(advancedOpenerConfigAclPrefs)); break; } @@ -279,9 +279,9 @@ inline void initPreferences(Preferences* preferences) preferences->putBytes(preference_conf_lock_basic_acl, (byte*)(&basicLockConfigAclPrefs), sizeof(basicLockConfigAclPrefs)); uint32_t basicOpenerConfigAclPrefs[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; preferences->putBytes(preference_conf_opener_basic_acl, (byte*)(&basicOpenerConfigAclPrefs), sizeof(basicOpenerConfigAclPrefs)); - uint32_t advancedLockConfigAclPrefs[22] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t advancedLockConfigAclPrefs[23] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; preferences->putBytes(preference_conf_lock_advanced_acl, (byte*)(&advancedLockConfigAclPrefs), sizeof(advancedLockConfigAclPrefs)); - uint32_t advancedOpenerConfigAclPrefs[20] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t advancedOpenerConfigAclPrefs[21] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; preferences->putBytes(preference_conf_opener_advanced_acl, (byte*)(&advancedOpenerConfigAclPrefs), sizeof(advancedOpenerConfigAclPrefs)); break; } @@ -294,9 +294,9 @@ inline void initPreferences(Preferences* preferences) preferences->putBytes(preference_conf_lock_basic_acl, (byte*)(&basicLockConfigAclPrefs), sizeof(basicLockConfigAclPrefs)); uint32_t basicOpenerConfigAclPrefs[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; preferences->putBytes(preference_conf_opener_basic_acl, (byte*)(&basicOpenerConfigAclPrefs), sizeof(basicOpenerConfigAclPrefs)); - uint32_t advancedLockConfigAclPrefs[22] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t advancedLockConfigAclPrefs[23] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; preferences->putBytes(preference_conf_lock_advanced_acl, (byte*)(&advancedLockConfigAclPrefs), sizeof(advancedLockConfigAclPrefs)); - uint32_t advancedOpenerConfigAclPrefs[20] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t advancedOpenerConfigAclPrefs[21] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; preferences->putBytes(preference_conf_opener_advanced_acl, (byte*)(&advancedOpenerConfigAclPrefs), sizeof(advancedOpenerConfigAclPrefs)); break; } @@ -309,9 +309,9 @@ inline void initPreferences(Preferences* preferences) preferences->putBytes(preference_conf_lock_basic_acl, (byte*)(&basicLockConfigAclPrefs), sizeof(basicLockConfigAclPrefs)); uint32_t basicOpenerConfigAclPrefs[14] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; preferences->putBytes(preference_conf_opener_basic_acl, (byte*)(&basicOpenerConfigAclPrefs), sizeof(basicOpenerConfigAclPrefs)); - uint32_t advancedLockConfigAclPrefs[22] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + uint32_t advancedLockConfigAclPrefs[23] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; preferences->putBytes(preference_conf_lock_advanced_acl, (byte*)(&advancedLockConfigAclPrefs), sizeof(advancedLockConfigAclPrefs)); - uint32_t advancedOpenerConfigAclPrefs[20] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + uint32_t advancedOpenerConfigAclPrefs[21] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; preferences->putBytes(preference_conf_opener_advanced_acl, (byte*)(&advancedOpenerConfigAclPrefs), sizeof(advancedOpenerConfigAclPrefs)); break; } diff --git a/src/WebCfgServer.cpp b/src/WebCfgServer.cpp index 9d26003..0ee333c 100644 --- a/src/WebCfgServer.cpp +++ b/src/WebCfgServer.cpp @@ -1465,8 +1465,8 @@ bool WebCfgServer::processArgs(PsychicRequest *request, String& message) uint32_t aclPrefs[17] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint32_t basicLockConfigAclPrefs[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint32_t basicOpenerConfigAclPrefs[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - uint32_t advancedLockConfigAclPrefs[22] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - uint32_t advancedOpenerConfigAclPrefs[20] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t advancedLockConfigAclPrefs[23] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t advancedOpenerConfigAclPrefs[21] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int params = request->params(); @@ -2567,6 +2567,10 @@ bool WebCfgServer::processArgs(PsychicRequest *request, String& message) { advancedLockConfigAclPrefs[21] = ((value == "1") ? 1 : 0); } + else if(key == "CONFLCKRBTNUKI") + { + advancedLockConfigAclPrefs[22] = ((value == "1") ? 1 : 0); + } else if(key == "CONFOPNNAME") { basicOpenerConfigAclPrefs[0] = ((value == "1") ? 1 : 0); @@ -2703,6 +2707,10 @@ bool WebCfgServer::processArgs(PsychicRequest *request, String& message) { advancedOpenerConfigAclPrefs[19] = ((value == "1") ? 1 : 0); } + else if(key == "CONFOPNRBTNUKI") + { + advancedOpenerConfigAclPrefs[20] = ((value == "1") ? 1 : 0); + } else if(key == "REGAPP") { if(_preferences->getBool(preference_register_as_app, false) != (value == "1")) @@ -2950,9 +2958,9 @@ bool WebCfgServer::processArgs(PsychicRequest *request, String& message) { uint32_t curAclPrefs[17] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint32_t curBasicLockConfigAclPrefs[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - uint32_t curAdvancedLockConfigAclPrefs[22] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t curAdvancedLockConfigAclPrefs[23] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint32_t curBasicOpenerConfigAclPrefs[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - uint32_t curAdvancedOpenerConfigAclPrefs[20] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t curAdvancedOpenerConfigAclPrefs[21] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; _preferences->getBytes(preference_acl, &curAclPrefs, sizeof(curAclPrefs)); _preferences->getBytes(preference_conf_lock_basic_acl, &curBasicLockConfigAclPrefs, sizeof(curBasicLockConfigAclPrefs)); _preferences->getBytes(preference_conf_lock_advanced_acl, &curAdvancedLockConfigAclPrefs, sizeof(curAdvancedLockConfigAclPrefs)); @@ -2981,7 +2989,7 @@ bool WebCfgServer::processArgs(PsychicRequest *request, String& message) break; } } - for(int i=0; i < 22; i++) + for(int i=0; i < 23; i++) { if(curAdvancedLockConfigAclPrefs[i] != advancedLockConfigAclPrefs[i]) { @@ -3004,7 +3012,7 @@ bool WebCfgServer::processArgs(PsychicRequest *request, String& message) break; } } - for(int i=0; i < 20; i++) + for(int i=0; i < 21; i++) { if(curAdvancedOpenerConfigAclPrefs[i] != advancedOpenerConfigAclPrefs[i]) { @@ -3789,7 +3797,7 @@ esp_err_t WebCfgServer::buildAccLvlHtml(PsychicRequest *request) { uint32_t basicLockConfigAclPrefs[16]; _preferences->getBytes(preference_conf_lock_basic_acl, &basicLockConfigAclPrefs, sizeof(basicLockConfigAclPrefs)); - uint32_t advancedLockConfigAclPrefs[22]; + uint32_t advancedLockConfigAclPrefs[23]; _preferences->getBytes(preference_conf_lock_advanced_acl, &advancedLockConfigAclPrefs, sizeof(advancedLockConfigAclPrefs)); response.print("

Nuki Lock Access Control

"); @@ -3856,6 +3864,7 @@ esp_err_t WebCfgServer::buildAccLvlHtml(PsychicRequest *request) printCheckBox(&response, "CONFLCKALENA", "Auto lock enabled", ((int)advancedLockConfigAclPrefs[19] == 1), "chk_config_lock"); printCheckBox(&response, "CONFLCKIALENA", "Immediate auto lock enabled", ((int)advancedLockConfigAclPrefs[20] == 1), "chk_config_lock"); printCheckBox(&response, "CONFLCKAUENA", "Auto update enabled", ((int)advancedLockConfigAclPrefs[21] == 1), "chk_config_lock"); + printCheckBox(&response, "CONFLCKRBTNUKI", "Reboot Nuki", ((int)advancedLockConfigAclPrefs[22] == 1), "chk_config_lock"); response.print("
"); response.print("
"); } @@ -3863,7 +3872,7 @@ esp_err_t WebCfgServer::buildAccLvlHtml(PsychicRequest *request) { uint32_t basicOpenerConfigAclPrefs[14]; _preferences->getBytes(preference_conf_opener_basic_acl, &basicOpenerConfigAclPrefs, sizeof(basicOpenerConfigAclPrefs)); - uint32_t advancedOpenerConfigAclPrefs[20]; + uint32_t advancedOpenerConfigAclPrefs[21]; _preferences->getBytes(preference_conf_opener_advanced_acl, &advancedOpenerConfigAclPrefs, sizeof(advancedOpenerConfigAclPrefs)); response.print("

Nuki Opener Access Control

"); @@ -3925,6 +3934,7 @@ esp_err_t WebCfgServer::buildAccLvlHtml(PsychicRequest *request) printCheckBox(&response, "CONFOPNDBPA", "Double button press action", ((int)advancedOpenerConfigAclPrefs[17] == 1), "chk_config_opener"); printCheckBox(&response, "CONFOPNBATT", "Battery type", ((int)advancedOpenerConfigAclPrefs[18] == 1), "chk_config_opener"); printCheckBox(&response, "CONFOPNABTD", "Automatic battery type detection", ((int)advancedOpenerConfigAclPrefs[19] == 1), "chk_config_opener"); + printCheckBox(&response, "CONFOPNRBTNUKI", "Reboot Nuki", ((int)advancedOpenerConfigAclPrefs[20] == 1), "chk_config_opener"); response.print("
"); response.print("
"); } @@ -4340,7 +4350,7 @@ esp_err_t WebCfgServer::buildInfoHtml(PsychicRequest *request) } uint32_t basicLockConfigAclPrefs[16]; _preferences->getBytes(preference_conf_lock_basic_acl, &basicLockConfigAclPrefs, sizeof(basicLockConfigAclPrefs)); - uint32_t advancedLockConfigAclPrefs[22]; + uint32_t advancedLockConfigAclPrefs[23]; _preferences->getBytes(preference_conf_lock_advanced_acl, &advancedLockConfigAclPrefs, sizeof(advancedLockConfigAclPrefs)); response.print("\n\n------------ NUKI LOCK ACL ------------"); response.print("\nLock: "); @@ -4438,6 +4448,8 @@ esp_err_t WebCfgServer::buildInfoHtml(PsychicRequest *request) response.print((int)advancedLockConfigAclPrefs[20] ? "Allowed" : "Disallowed"); response.print("\nAuto update enabled: "); response.print((int)advancedLockConfigAclPrefs[21] ? "Allowed" : "Disallowed"); + response.print("\nReboot Nuki: "); + response.print((int)advancedLockConfigAclPrefs[22] ? "Allowed" : "Disallowed"); if(_preferences->getBool(preference_show_secrets)) { @@ -4511,7 +4523,7 @@ esp_err_t WebCfgServer::buildInfoHtml(PsychicRequest *request) response.print(_preferences->getBool(preference_opener_continuous_mode, false) ? "Yes" : "No"); uint32_t basicOpenerConfigAclPrefs[14]; _preferences->getBytes(preference_conf_opener_basic_acl, &basicOpenerConfigAclPrefs, sizeof(basicOpenerConfigAclPrefs)); - uint32_t advancedOpenerConfigAclPrefs[20]; + uint32_t advancedOpenerConfigAclPrefs[21]; _preferences->getBytes(preference_conf_opener_advanced_acl, &advancedOpenerConfigAclPrefs, sizeof(advancedOpenerConfigAclPrefs)); response.print("\n\n------------ NUKI OPENER ACL ------------"); response.print("\nActivate Ring-to-Open: "); @@ -4599,6 +4611,8 @@ esp_err_t WebCfgServer::buildInfoHtml(PsychicRequest *request) response.print((int)advancedOpenerConfigAclPrefs[18] ? "Allowed" : "Disallowed"); response.print("\nAutomatic battery type detection: "); response.print((int)advancedOpenerConfigAclPrefs[19] ? "Allowed" : "Disallowed"); + response.print("\nReboot Nuki: "); + response.print((int)advancedOpenerConfigAclPrefs[20] ? "Allowed" : "Disallowed"); if(_preferences->getBool(preference_show_secrets)) { char tmp[16]; From 62b6d4c301e87904bac5d82397ccc02f304de183 Mon Sep 17 00:00:00 2001 From: iranl Date: Mon, 18 Nov 2024 21:03:19 +0100 Subject: [PATCH 2/3] Clear WiFi fix --- src/PreferencesKeys.h | 34 ++++++++----------------------- src/networkDevices/WifiDevice.cpp | 8 +------- 2 files changed, 10 insertions(+), 32 deletions(-) diff --git a/src/PreferencesKeys.h b/src/PreferencesKeys.h index 1e3190e..16b7c3e 100644 --- a/src/PreferencesKeys.h +++ b/src/PreferencesKeys.h @@ -3,7 +3,7 @@ #include #include "Config.h" #ifndef CONFIG_IDF_TARGET_ESP32H2 -#include "esp_wifi.h" +#include #endif //CHANGE REQUIRES REBOOT TO TAKE EFFECT @@ -143,7 +143,7 @@ inline void initPreferences(Preferences* preferences) if(firstStart) { Serial.println("First start, setting preference defaults"); - + preferences->putBool(preference_started_before, true); preferences->putBool(preference_lock_enabled, true); uint32_t aclPrefs[17] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; @@ -156,29 +156,8 @@ inline void initPreferences(Preferences* preferences) preferences->putBytes(preference_conf_lock_advanced_acl, (byte*)(&advancedLockConfigAclPrefs), sizeof(advancedLockConfigAclPrefs)); uint32_t advancedOpenerConfigAclPrefs[21] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; preferences->putBytes(preference_conf_opener_advanced_acl, (byte*)(&advancedOpenerConfigAclPrefs), sizeof(advancedOpenerConfigAclPrefs)); - -#ifndef CONFIG_IDF_TARGET_ESP32H2 - wifi_config_t wifi_cfg; - if(esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg) != ESP_OK) - { - Serial.println("Failed to get Wi-Fi configuration in RAM"); - } - - if (esp_wifi_set_storage(WIFI_STORAGE_FLASH) != ESP_OK) - { - Serial.println("Failed to set storage Wi-Fi"); - } - - memset(wifi_cfg.sta.ssid, 0, sizeof(wifi_cfg.sta.ssid)); - memset(wifi_cfg.sta.password, 0, sizeof(wifi_cfg.sta.password)); - - if (esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg) != ESP_OK) - { - Serial.println("Failed to clear NVS Wi-Fi configuration"); - } -#endif preferences->putString(preference_mqtt_lock_path, "nukihub"); - + preferences->putBool(preference_check_updates, true); preferences->putBool(preference_opener_continuous_mode, false); preferences->putBool(preference_official_hybrid_enabled, false); @@ -219,7 +198,12 @@ inline void initPreferences(Preferences* preferences) preferences->putInt(preference_query_interval_lockstate, 1800); preferences->putInt(preference_query_interval_configuration, 3600); preferences->putInt(preference_query_interval_battery, 1800); - preferences->putInt(preference_query_interval_keypad, 1800); + preferences->putInt(preference_query_interval_keypad, 1800); + +#ifndef CONFIG_IDF_TARGET_ESP32H2 + WiFi.begin(); + WiFi.disconnect(true, true); +#endif } else { diff --git a/src/networkDevices/WifiDevice.cpp b/src/networkDevices/WifiDevice.cpp index 3481645..58c76bc 100644 --- a/src/networkDevices/WifiDevice.cpp +++ b/src/networkDevices/WifiDevice.cpp @@ -111,13 +111,7 @@ void WifiDevice::initialize() } } - memset(wifi_cfg.sta.ssid, 0, sizeof(wifi_cfg.sta.ssid)); - memset(wifi_cfg.sta.password, 0, sizeof(wifi_cfg.sta.password)); - - if (esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg) != ESP_OK) - { - Log->println("Failed to clear NVS Wi-Fi configuration"); - } + WiFi.disconnect(true, true); if(found) { From 7a5f85f82d8e2a6a29892599b937bee1c4714ff2 Mon Sep 17 00:00:00 2001 From: iranl Date: Mon, 18 Nov 2024 23:13:14 +0100 Subject: [PATCH 3/3] Fix crash on valid JSON --- src/Config.h | 2 +- src/NukiOpenerWrapper.cpp | 50 +++++++++++++++++++++++++++++--- src/NukiWrapper.cpp | 60 ++++++++++++++++++++++++++++++++++----- 3 files changed, 100 insertions(+), 12 deletions(-) diff --git a/src/Config.h b/src/Config.h index 7beec7d..2f066f1 100644 --- a/src/Config.h +++ b/src/Config.h @@ -4,7 +4,7 @@ #define NUKI_HUB_VERSION "9.02" #define NUKI_HUB_BUILD "unknownbuildnr" -#define NUKI_HUB_DATE "2024-11-15" +#define NUKI_HUB_DATE "2024-11-18" #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/NukiOpenerWrapper.cpp b/src/NukiOpenerWrapper.cpp index 1275e4f..022d7ed 100644 --- a/src/NukiOpenerWrapper.cpp +++ b/src/NukiOpenerWrapper.cpp @@ -1521,9 +1521,30 @@ void NukiOpenerWrapper::onConfigUpdateReceived(const char *value) for(int i=0; i < 14; i++) { - if(json[basicKeys[i]]) + if(json[basicKeys[i]].is()) { - const char *jsonchar = json[basicKeys[i]].as(); + JsonVariantConst jsonKey = json[basicKeys[i]]; + char *jsonchar; + + if (jsonKey.is()) + { + itoa(jsonKey, jsonchar, 10); + } + else if (jsonKey.is()) + { + if (jsonKey) + { + itoa(1, jsonchar, 10); + } + else + { + itoa(0, jsonchar, 10); + } + } + else if (jsonKey.is()) + { + jsonchar = (char*)jsonKey.as(); + } if(strlen(jsonchar) == 0) { @@ -1848,9 +1869,30 @@ void NukiOpenerWrapper::onConfigUpdateReceived(const char *value) for(int j=0; j < 21; j++) { - if(json[advancedKeys[j]]) + if(json[advancedKeys[j]].is()) { - const char *jsonchar = json[advancedKeys[j]].as(); + JsonVariantConst jsonKey = json[advancedKeys[i]]; + char *jsonchar; + + if (jsonKey.is()) + { + itoa(jsonKey, jsonchar, 10); + } + else if (jsonKey.is()) + { + if (jsonKey) + { + itoa(1, jsonchar, 10); + } + else + { + itoa(0, jsonchar, 10); + } + } + else if (jsonKey.is()) + { + jsonchar = (char*)jsonKey.as(); + } if(strlen(jsonchar) == 0) { diff --git a/src/NukiWrapper.cpp b/src/NukiWrapper.cpp index ef16a6f..fd13ab6 100644 --- a/src/NukiWrapper.cpp +++ b/src/NukiWrapper.cpp @@ -116,7 +116,7 @@ void NukiWrapper::readSettings() _disableNonJSON = _preferences->getBool(preference_disable_non_json, false); _checkKeypadCodes = _preferences->getBool(preference_keypad_check_code_enabled, false); _pairedAsApp = _preferences->getBool(preference_register_as_app, false); - + _preferences->getBytes(preference_conf_lock_basic_acl, &_basicLockConfigaclPrefs, sizeof(_basicLockConfigaclPrefs)); _preferences->getBytes(preference_conf_lock_advanced_acl, &_advancedLockConfigaclPrefs, sizeof(_advancedLockConfigaclPrefs)); @@ -907,7 +907,7 @@ void NukiWrapper::updateAuth(bool retrieved) Log->println(F("No valid Nuki Lock PIN set")); return; } - + if(!_preferences->getBool(preference_auth_info_enabled)) { return; @@ -1421,6 +1421,10 @@ void NukiWrapper::onConfigUpdateReceived(const char *value) return; } + Log->println(value); + serializeJson(json, _resbuf, sizeof(_resbuf)); + Log->println(_resbuf); + Nuki::CmdResult cmdResult; const char *basicKeys[16] = {"name", "latitude", "longitude", "autoUnlatch", "pairingEnabled", "buttonEnabled", "ledEnabled", "ledBrightness", "timeZoneOffset", "dstMode", "fobAction1", "fobAction2", "fobAction3", "singleLock", "advertisingMode", "timeZone"}; const char *advancedKeys[23] = {"unlockedPositionOffsetDegrees", "lockedPositionOffsetDegrees", "singleLockedPositionOffsetDegrees", "unlockedToLockedTransitionOffsetDegrees", "lockNgoTimeout", "singleButtonPressAction", "doubleButtonPressAction", "detachedCylinder", "batteryType", "automaticBatteryTypeDetection", "unlatchDuration", "autoLockTimeOut", "autoUnLockDisabled", "nightModeEnabled", "nightModeStartTime", "nightModeEndTime", "nightModeAutoLockEnabled", "nightModeAutoUnlockDisabled", "nightModeImmediateLockOnStart", "autoLockEnabled", "immediateAutoLockEnabled", "autoUpdateEnabled", "rebootNuki"}; @@ -1429,9 +1433,30 @@ void NukiWrapper::onConfigUpdateReceived(const char *value) for(int i=0; i < 16; i++) { - if(json[basicKeys[i]]) + if(json[basicKeys[i]].is()) { - const char *jsonchar = json[basicKeys[i]].as(); + JsonVariantConst jsonKey = json[basicKeys[i]]; + char *jsonchar; + + if (jsonKey.is()) + { + itoa(jsonKey, jsonchar, 10); + } + else if (jsonKey.is()) + { + if (jsonKey) + { + itoa(1, jsonchar, 10); + } + else + { + itoa(0, jsonchar, 10); + } + } + else if (jsonKey.is()) + { + jsonchar = (char*)jsonKey.as(); + } if(strlen(jsonchar) == 0) { @@ -1796,9 +1821,30 @@ void NukiWrapper::onConfigUpdateReceived(const char *value) for(int j=0; j < 23; j++) { - if(json[advancedKeys[j]]) + if(json[advancedKeys[j]].is()) { - const char *jsonchar = json[advancedKeys[j]].as(); + JsonVariantConst jsonKey = json[advancedKeys[i]]; + char *jsonchar; + + if (jsonKey.is()) + { + itoa(jsonKey, jsonchar, 10); + } + else if (jsonKey.is()) + { + if (jsonKey) + { + itoa(1, jsonchar, 10); + } + else + { + itoa(0, jsonchar, 10); + } + } + else if (jsonKey.is()) + { + jsonchar = (char*)jsonKey.as(); + } if(strlen(jsonchar) == 0) { @@ -2663,7 +2709,7 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value) { idExists = std::find(_keypadCodeIds.begin(), _keypadCodeIds.end(), codeId) != _keypadCodeIds.end(); } - + if(strcmp(action, "check") == 0) { if(!_preferences->getBool(preference_keypad_check_code_enabled, false)) {