From b813faf771c5775edd438330e468b0d0f2462950 Mon Sep 17 00:00:00 2001 From: iranl Date: Sat, 2 Nov 2024 19:56:36 +0100 Subject: [PATCH] Fix --- README.md | 29 +++++++++++++++-------------- src/Config.h | 2 +- src/NukiNetwork.cpp | 10 +++++----- src/NukiOpenerWrapper.cpp | 29 ++++++++++++++++------------- src/NukiWrapper.cpp | 22 +++++++++++++--------- src/WebCfgServer.cpp | 10 +++++----- 6 files changed, 55 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index dedf3c8..e251f85 100644 --- a/README.md +++ b/README.md @@ -245,6 +245,7 @@ In a browser navigate to the IP address assigned to the ESP32. - Publish keypad entries information (Only available when a Keypad is detected): Enable to publish information about keypad codes through MQTT, see the "[Keypad control](#keypad-control-optional)" section of this README - Also publish keypad codes (Only available when a Keypad is detected): Enable to publish the actual keypad codes through MQTT, note that is could be considered a security risk - Add, modify and delete keypad codes (Only available when a Keypad is detected): Enable to allow configuration of keypad codes through MQTT, see the "[Keypad control](#keypad-control-optional)" section of this README +- Allow checking if keypad codes are valid (Only available when a Keypad is detected): Enable to allow checking if a given codeId and code combination is valid through MQTT, note that is could be considered a security risk - Publish timecontrol information: Enable to publish information about timecontrol entries through MQTT, see the "[Timecontrol](#timecontrol)" section of this README - Add, modify and delete timecontrol entries: Enable to allow configuration of timecontrol entries through MQTT, see the "[Timecontrol](#timecontrol)" section of this README - Publish authorization information: Enable to publish information about authorization entries through MQTT, see the "[Authorization](#authorization)" section of this README @@ -588,19 +589,19 @@ By default a maximum of 10 entries are published. To change Nuki Lock/Opener keypad settings set the `[lock/opener]/keypad/actionJson` topic to a JSON formatted value containing the following nodes. -| Node | Delete | Add | Update | Usage | Possible values | -|------------------|----------|----------|----------|------------------------------------------------------------------------------------------------------------------|----------------------------------------| -| action | Required | Required | Required | The action to execute | "delete", "add", "update" | -| codeId | Required | Not used | Required | The code ID of the existing code to delete or update | Integer | -| code | Not used | Required | Optional | The code to create or update | 6-digit Integer without zero's, can't start with "12"| -| enabled | Not used | Not used | Optional | Enable or disable the code, always enabled on add | 1 = enabled, 0 = disabled | -| name | Not used | Required | Optional | The name of the code to create or update | String, max 20 chars | -| timeLimited | Not used | Optional | Optional | If this authorization is restricted to access only at certain times, requires enabled = 1 | 1 = enabled, 0 = disabled | -| allowedFrom | Not used | Optional | Optional | The start timestamp from which access should be allowed (requires enabled = 1 and timeLimited = 1) | "YYYY-MM-DD HH:MM:SS" | -| allowedUntil | Not used | Optional | Optional | The end timestamp until access should be allowed (requires enabled = 1 and timeLimited = 1) | "YYYY-MM-DD HH:MM:SS" | -| allowedWeekdays | Not used | Optional | Optional | Weekdays on which access should be allowed (requires enabled = 1 and timeLimited = 1) | Array of days: "mon", "tue", "wed", "thu" , "fri" "sat", "sun"| -| allowedFromTime | Not used | Optional | Optional | The start time per day from which access should be allowed (requires enabled = 1 and timeLimited = 1) | "HH:MM" | -| allowedUntilTime | Not used | Optional | Optional | The end time per day until access should be allowed (requires enabled = 1 and timeLimited = 1) | "HH:MM" | +| Node | Delete | Add | Update | Check | Usage | Possible values | +|------------------|----------|----------|----------|----------|------------------------------------------------------------------------------------------------------------------|----------------------------------------| +| action | Required | Required | Required | Required | The action to execute | "delete", "add", "update", "check" | +| codeId | Required | Not used | Required | Required | The code ID of the existing code to delete or update | Integer | +| code | Not used | Required | Optional | Required | The code to create or update | 6-digit Integer without zero's, can't start with "12"| +| enabled | Not used | Not used | Optional | Not used | Enable or disable the code, always enabled on add | 1 = enabled, 0 = disabled | +| name | Not used | Required | Optional | Not used | The name of the code to create or update | String, max 20 chars | +| timeLimited | Not used | Optional | Optional | Not used | If this authorization is restricted to access only at certain times, requires enabled = 1 | 1 = enabled, 0 = disabled | +| allowedFrom | Not used | Optional | Optional | Not used | The start timestamp from which access should be allowed (requires enabled = 1 and timeLimited = 1) | "YYYY-MM-DD HH:MM:SS" | +| allowedUntil | Not used | Optional | Optional | Not used | The end timestamp until access should be allowed (requires enabled = 1 and timeLimited = 1) | "YYYY-MM-DD HH:MM:SS" | +| allowedWeekdays | Not used | Optional | Optional | Not used | Weekdays on which access should be allowed (requires enabled = 1 and timeLimited = 1) | Array of days: "mon", "tue", "wed", "thu" , "fri" "sat", "sun"| +| allowedFromTime | Not used | Optional | Optional | Not used | The start time per day from which access should be allowed (requires enabled = 1 and timeLimited = 1) | "HH:MM" | +| allowedUntilTime | Not used | Optional | Optional | Not used | The end time per day until access should be allowed (requires enabled = 1 and timeLimited = 1) | "HH:MM" | Examples: - Delete: `{ "action": "delete", "codeId": "1234" }` @@ -664,7 +665,7 @@ To change Nuki Lock/Opener timecontrol settings set the `[lock/opener]/timecontr | enabled | Not used | Not used | Optional | Enable or disable the entry, always enabled on add | 1 = enabled, 0 = disabled | | weekdays | Not used | Optional | Optional | Weekdays on which the chosen lock action should be exectued (requires enabled = 1) | Array of days: "mon", "tue", "wed", "thu" , "fri" "sat", "sun" | | time | Not used | Required | Optional | The time on which the chosen lock action should be executed (requires enabled = 1) | "HH:MM" | -| lockAction | Not used | Required | Optional | The lock action that should be executed on the chosen weekdays at the chosen time (requires enabled = 1) | For the Nuki lock: "Unlock", "Lock", "Unlatch", "LockNgo", "LockNgoUnlatch", "FullLock". For the Nuki Opener: "ActivateRTO", "DeactivateRTO", "ElectricStrikeActuation", "ActivateCM", "DeactivateCM | +| lockAction | Not used | Required | Optional | The lock action that should be executed on the chosen weekdays at the chosen time (requires enabled = 1) | For the Nuki lock: "Unlock", "Lock", "Unlatch", "LockNgo", "LockNgoUnlatch", "FullLock". For the Nuki Opener: "ActivateRTO", "DeactivateRTO", "ElectricStrikeActuation", "ActivateCM", "DeactivateCM | Examples: - Delete: `{ "action": "delete", "entryId": "1234" }` diff --git a/src/Config.h b/src/Config.h index 29bb237..b82a95b 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-01" +#define NUKI_HUB_DATE "2024-11-02" #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 a297e4f..9ae5d7a 100644 --- a/src/NukiNetwork.cpp +++ b/src/NukiNetwork.cpp @@ -607,12 +607,12 @@ bool NukiNetwork::reconnect() { _mqttConnectionState = 0; - while (!_device->mqttConnected() && (esp_timer_get_time() / 1000) > _nextReconnect) + while (!_device->mqttConnected() && espMillis() > _nextReconnect) { if(strcmp(_mqttBrokerAddr, "") == 0) { Log->println(F("MQTT Broker not configured, aborting connection attempt.")); - _nextReconnect = (esp_timer_get_time() / 1000) + 5000; + _nextReconnect = espMillis() + 5000; return false; } @@ -634,9 +634,9 @@ bool NukiNetwork::reconnect() _device->mqttSetServer(_mqttBrokerAddr, _mqttPort); _device->mqttConnect(); - int64_t timeout = (esp_timer_get_time() / 1000) + 60000; + int64_t timeout = espMillis() + 60000; - while(!_connectReplyReceived && (esp_timer_get_time() / 1000) < timeout) + while(!_connectReplyReceived && espMillis() < timeout) { delay(50); _device->update(); @@ -696,7 +696,7 @@ bool NukiNetwork::reconnect() Log->print(F("MQTT connect failed, rc=")); _device->printError(); _mqttConnectionState = 0; - _nextReconnect = (esp_timer_get_time() / 1000) + 5000; + _nextReconnect = espMillis() + 5000; //_device->mqttDisconnect(true); } } diff --git a/src/NukiOpenerWrapper.cpp b/src/NukiOpenerWrapper.cpp index 5ae4d50..4fa6762 100644 --- a/src/NukiOpenerWrapper.cpp +++ b/src/NukiOpenerWrapper.cpp @@ -278,8 +278,8 @@ void NukiOpenerWrapper::update() updateKeypad(false); } } - - if(_checkKeypadCodes && _invalidCount > 0 && ts - 120000 < _lastCodeCheck) + + if(_checkKeypadCodes && _invalidCount > 0 && (ts - (120000 * _invalidCount)) > _lastCodeCheck) { _invalidCount--; } @@ -893,8 +893,8 @@ void NukiOpenerWrapper::updateAuth(bool retrieved) { Log->println(F("No valid Nuki Lock PIN set")); return; - } - + } + if(!_preferences->getBool(preference_auth_info_enabled)) { return; @@ -2613,14 +2613,14 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value) return; } - if(pow(_invalidCount, 5) + _lastCodeCheck > (esp_timer_get_time() / 1000)) + if((pow(_invalidCount, 5) + _lastCodeCheck) > espMillis()) { _network->publishKeypadJsonCommandResult("checkingCodesBlockedTooManyInvalid"); - _lastCodeCheck = (esp_timer_get_time() / 1000); + _lastCodeCheck = espMillis(); return; } - _lastCodeCheck = (esp_timer_get_time() / 1000); + _lastCodeCheck = espMillis(); if(idExists) { @@ -2639,7 +2639,8 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value) { _invalidCount++; _network->publishKeypadJsonCommandResult("codeInvalid"); - Log->println("Invalid"); + Log->print("Invalid\nInvalid count: "); + Log->println(_invalidCount); return; } } @@ -2647,12 +2648,13 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value) { _invalidCount++; _network->publishKeypadJsonCommandResult("noExistingCodeIdSet"); + Log->print("Invalid count: "); + Log->println(_invalidCount); return; } } else { - Nuki::CmdResult result = (Nuki::CmdResult)-1; int retryCount = 0; @@ -2732,6 +2734,7 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value) } if(allowedUntil.length() > 0) + { if(allowedUntil.length() == 19) { allowedUntilAr[0] = (uint16_t)allowedUntil.substring(0, 4).toInt(); @@ -2869,7 +2872,7 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value) if(resultKp == Nuki::CmdResult::Success) { - delay(250); + delay(5000); std::list entries; _nukiOpener.getKeypadEntries(&entries); @@ -3213,7 +3216,7 @@ void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value) if(resultTc == Nuki::CmdResult::Success) { - delay(250); + delay(5000); std::list timeControlEntries; _nukiOpener.getTimeControlEntries(&timeControlEntries); @@ -3342,7 +3345,7 @@ void NukiOpenerWrapper::onAuthCommandReceived(const char *value) char oldName[33]; const char *action = json["action"].as(); - uint16_t authId = json["authId"].as(); + uint32_t authId = json["authId"].as(); //uint8_t idType = json["idType"].as(); //unsigned char secretKeyK[32] = {0x00}; uint8_t remoteAllowed; @@ -3669,7 +3672,7 @@ void NukiOpenerWrapper::onAuthCommandReceived(const char *value) if(resultAuth == Nuki::CmdResult::Success) { - delay(250); + delay(5000); std::list entries; _nukiOpener.getAuthorizationEntries(&entries); diff --git a/src/NukiWrapper.cpp b/src/NukiWrapper.cpp index aa419a4..799eb0c 100644 --- a/src/NukiWrapper.cpp +++ b/src/NukiWrapper.cpp @@ -431,7 +431,7 @@ void NukiWrapper::update() _network->clearAuthorizationInfo(); _clearAuthData = false; } - if(_checkKeypadCodes && _invalidCount > 0 && ts - 120000 < _lastCodeCheck) + if(_checkKeypadCodes && _invalidCount > 0 && (ts - (120000 * _invalidCount)) > _lastCodeCheck) { _invalidCount--; } @@ -2727,14 +2727,14 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value) return; } - if(pow(_invalidCount, 5) + _lastCodeCheck > (esp_timer_get_time() / 1000)) + if((pow(_invalidCount, 5) + _lastCodeCheck) > espMillis()) { _network->publishKeypadJsonCommandResult("checkingCodesBlockedTooManyInvalid"); - _lastCodeCheck = (esp_timer_get_time() / 1000); + _lastCodeCheck = espMillis(); return; } - _lastCodeCheck = (esp_timer_get_time() / 1000); + _lastCodeCheck = espMillis(); if(idExists) { @@ -2753,7 +2753,8 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value) { _invalidCount++; _network->publishKeypadJsonCommandResult("codeInvalid"); - Log->println("Invalid"); + Log->print("Invalid\nInvalid count: "); + Log->println(_invalidCount); return; } } @@ -2761,6 +2762,8 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value) { _invalidCount++; _network->publishKeypadJsonCommandResult("noExistingCodeIdSet"); + Log->print("Invalid count: "); + Log->println(_invalidCount); return; } } @@ -2846,6 +2849,7 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value) } if(allowedUntil.length() > 0) + { if(allowedUntil.length() == 19) { allowedUntilAr[0] = (uint16_t)allowedUntil.substring(0, 4).toInt(); @@ -2983,7 +2987,7 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value) if(resultKp == Nuki::CmdResult::Success) { - delay(250); + delay(5000); std::list entries; _nukiLock.getKeypadEntries(&entries); @@ -3328,7 +3332,7 @@ void NukiWrapper::onTimeControlCommandReceived(const char *value) if(resultTc == Nuki::CmdResult::Success) { - delay(250); + delay(5000); std::list timeControlEntries; _nukiLock.getTimeControlEntries(&timeControlEntries); @@ -3458,7 +3462,7 @@ void NukiWrapper::onAuthCommandReceived(const char *value) char oldName[33]; const char *action = json["action"].as(); - uint16_t authId = json["authId"].as(); + uint32_t authId = json["authId"].as(); //uint8_t idType = json["idType"].as(); //unsigned char secretKeyK[32] = {0x00}; uint8_t remoteAllowed; @@ -3783,11 +3787,11 @@ void NukiWrapper::onAuthCommandReceived(const char *value) } Nuki::CmdResult resultAuth = _nukiLock.retrieveAuthorizationEntries(0, _preferences->getInt(preference_auth_max_entries, MAX_AUTH)); - delay(250); bool foundExisting = false; if(resultAuth == Nuki::CmdResult::Success) { + delay(5000); std::list entries; _nukiLock.getAuthorizationEntries(&entries); diff --git a/src/WebCfgServer.cpp b/src/WebCfgServer.cpp index 02d44fd..7bbaa7f 100644 --- a/src/WebCfgServer.cpp +++ b/src/WebCfgServer.cpp @@ -3389,15 +3389,15 @@ esp_err_t WebCfgServer::buildCredHtml(PsychicRequest *request) PsychicStreamResponse response(request, "text/plain"); response.beginSend(); buildHtmlHeader(&response); - response.print("
"); + response.print(""); response.print("

Credentials

"); response.print(""); - printInputField(&response, "CREDUSER", "User (# to clear)", _preferences->getString(preference_cred_user).c_str(), 30, "", false, true); - printInputField(&response, "CREDPASS", "Password", "*", 30, "", true, true); - printInputField(&response, "CREDPASSRE", "Retype password", "*", 30, "", true); + printInputField(&response, "CREDUSER", "User (# to clear)", _preferences->getString(preference_cred_user).c_str(), 30, "id=\"inputuser\"", false, true); + printInputField(&response, "CREDPASS", "Password", "*", 30, "id=\"inputpass\"", true, true); + printInputField(&response, "CREDPASSRE", "Retype password", "*", 30, "id=\"inputpass2\"", true); response.print("
"); response.print("
"); - response.print("
"); + response.print(""); if(_nuki != nullptr) { response.print("

");