diff --git a/README.md b/README.md
index bd2103b..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" }`
@@ -609,7 +610,7 @@ Examples:
### Result of attempted keypad code changes
-The result of the last configuration change action will be published to the `[lock/opener]/configuration/commandResultJson` MQTT topic.
+The result of the last keypad change action will be published to the `[lock/opener]/configuration/commandResultJson` MQTT topic.
Possible values are "noValidPinSet", "keypadControlDisabled", "keypadNotAvailable", "keypadDisabled", "invalidConfig", "invalidJson", "noActionSet", "invalidAction", "noExistingCodeIdSet", "noNameSet", "noValidCodeSet", "noCodeSet", "invalidAllowedFrom", "invalidAllowedUntil", "invalidAllowedFromTime", "invalidAllowedUntilTime", "success", "failed", "timeOut", "working", "notPaired", "error" and "undefined".
## Keypad control (alternative, optional)
@@ -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/lib/nuki_ble b/lib/nuki_ble
index fcca247..0b4e590 160000
--- a/lib/nuki_ble
+++ b/lib/nuki_ble
@@ -1 +1 @@
-Subproject commit fcca24773874d43385fee33f0ea9510bd4c63c3e
+Subproject commit 0b4e5901c712a77417fda9a8a6ba54436e343e4a
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 9f31323..4fa6762 100644
--- a/src/NukiOpenerWrapper.cpp
+++ b/src/NukiOpenerWrapper.cpp
@@ -113,8 +113,9 @@ void NukiOpenerWrapper::readSettings()
_retryDelay = _preferences->getInt(preference_command_retry_delay);
_rssiPublishInterval = _preferences->getInt(preference_rssi_publish_interval) * 1000;
_disableNonJSON = _preferences->getBool(preference_disable_non_json, false);
+ _checkKeypadCodes = _preferences->getBool(preference_keypad_check_code_enabled, false);
_pairedAsApp = _preferences->getBool(preference_register_opener_as_app, false);
-
+
_preferences->getBytes(preference_conf_opener_basic_acl, &_basicOpenerConfigAclPrefs, sizeof(_basicOpenerConfigAclPrefs));
_preferences->getBytes(preference_conf_opener_advanced_acl, &_advancedOpenerConfigAclPrefs, sizeof(_advancedOpenerConfigAclPrefs));
@@ -278,6 +279,11 @@ void NukiOpenerWrapper::update()
}
}
+ if(_checkKeypadCodes && _invalidCount > 0 && (ts - (120000 * _invalidCount)) > _lastCodeCheck)
+ {
+ _invalidCount--;
+ }
+
if(_nextLockAction != (NukiOpener::LockAction)0xff)
{
int retryCount = 0;
@@ -791,10 +797,13 @@ void NukiOpenerWrapper::updateKeypad(bool retrieved)
_network->publishKeypad(entries, _maxKeypadCodeCount);
_keypadCodeIds.clear();
+ _keypadCodes.clear();
_keypadCodeIds.reserve(entries.size());
+ _keypadCodes.reserve(entries.size());
for(const auto& entry : entries)
{
_keypadCodeIds.push_back(entry.codeId);
+ _keypadCodes.push_back(entry.code);
}
}
@@ -884,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;
@@ -2597,416 +2606,423 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
idExists = std::find(_keypadCodeIds.begin(), _keypadCodeIds.end(), codeId) != _keypadCodeIds.end();
}
- Nuki::CmdResult result = (Nuki::CmdResult)-1;
- int retryCount = 0;
-
- while(retryCount < _nrOfRetries + 1)
- {
- if(strcmp(action, "delete") == 0)
+ if(strcmp(action, "check") == 0) {
+ if(!_preferences->getBool(preference_keypad_check_code_enabled, false))
{
- if(idExists)
+ _network->publishKeypadJsonCommandResult("checkingKeypadCodesDisabled");
+ return;
+ }
+
+ if((pow(_invalidCount, 5) + _lastCodeCheck) > espMillis())
+ {
+ _network->publishKeypadJsonCommandResult("checkingCodesBlockedTooManyInvalid");
+ _lastCodeCheck = espMillis();
+ return;
+ }
+
+ _lastCodeCheck = espMillis();
+
+ if(idExists)
+ {
+ auto it1 = std::find(_keypadCodeIds.begin(), _keypadCodeIds.end(), codeId);
+ int index = it1 - _keypadCodeIds.begin();
+ Log->print(F("Check keypad code: "));
+
+ if(code == _keypadCodes[index])
{
- result = _nukiOpener.deleteKeypadEntry(codeId);
- Log->print(F("Delete keypad code: "));
- Log->println((int)result);
+ _invalidCount = 0;
+ _network->publishKeypadJsonCommandResult("codeValid");
+ Log->println("Valid");
+ return;
}
else
{
- _network->publishKeypadJsonCommandResult("noExistingCodeIdSet");
+ _invalidCount++;
+ _network->publishKeypadJsonCommandResult("codeInvalid");
+ Log->print("Invalid\nInvalid count: ");
+ Log->println(_invalidCount);
return;
}
}
- else if(strcmp(action, "add") == 0 || strcmp(action, "update") == 0)
+ else
{
- if(name.length() < 1)
- {
- if (strcmp(action, "update") != 0)
+ _invalidCount++;
+ _network->publishKeypadJsonCommandResult("noExistingCodeIdSet");
+ Log->print("Invalid count: ");
+ Log->println(_invalidCount);
+ return;
+ }
+ }
+ else
+ {
+ Nuki::CmdResult result = (Nuki::CmdResult)-1;
+ int retryCount = 0;
+
+ while(retryCount < _nrOfRetries + 1)
+ {
+ if(strcmp(action, "delete") == 0) {
+ if(idExists)
{
- _network->publishKeypadJsonCommandResult("noNameSet");
+ result = _nukiOpener.deleteKeypadEntry(codeId);
+ Log->print(F("Delete keypad code: "));
+ Log->println((int)result);
+ }
+ else
+ {
+ _network->publishKeypadJsonCommandResult("noExistingCodeIdSet");
return;
}
}
-
- if(code != 12)
+ else if(strcmp(action, "add") == 0 || strcmp(action, "update") == 0)
{
- String codeStr = json["code"].as();
- bool codeValid = code > 100000 && code < 1000000 && (codeStr.indexOf('0') == -1);
-
- if (!codeValid)
+ if(name.length() < 1)
{
- _network->publishKeypadJsonCommandResult("noValidCodeSet");
- return;
- }
- }
- else if (strcmp(action, "update") != 0)
- {
- _network->publishKeypadJsonCommandResult("noCodeSet");
- return;
- }
-
- unsigned int allowedFromAr[6];
- unsigned int allowedUntilAr[6];
- unsigned int allowedFromTimeAr[2];
- unsigned int allowedUntilTimeAr[2];
- uint8_t allowedWeekdaysInt = 0;
-
- if(timeLimited == 1)
- {
- if(allowedFrom.length() > 0)
- {
- if(allowedFrom.length() == 19)
+ if (strcmp(action, "update") != 0)
{
- allowedFromAr[0] = (uint16_t)allowedFrom.substring(0, 4).toInt();
- allowedFromAr[1] = (uint8_t)allowedFrom.substring(5, 7).toInt();
- allowedFromAr[2] = (uint8_t)allowedFrom.substring(8, 10).toInt();
- allowedFromAr[3] = (uint8_t)allowedFrom.substring(11, 13).toInt();
- allowedFromAr[4] = (uint8_t)allowedFrom.substring(14, 16).toInt();
- allowedFromAr[5] = (uint8_t)allowedFrom.substring(17, 19).toInt();
+ _network->publishKeypadJsonCommandResult("noNameSet");
+ return;
+ }
+ }
- if(allowedFromAr[0] < 2000 || allowedFromAr[0] > 3000 || allowedFromAr[1] < 1 || allowedFromAr[1] > 12 || allowedFromAr[2] < 1 || allowedFromAr[2] > 31 || allowedFromAr[3] < 0 || allowedFromAr[3] > 23 || allowedFromAr[4] < 0 || allowedFromAr[4] > 59 || allowedFromAr[5] < 0 || allowedFromAr[5] > 59)
+ if(code != 12)
+ {
+ String codeStr = json["code"].as();
+ bool codeValid = code > 100000 && code < 1000000 && (codeStr.indexOf('0') == -1);
+
+ if (!codeValid)
+ {
+ _network->publishKeypadJsonCommandResult("noValidCodeSet");
+ return;
+ }
+ }
+ else if (strcmp(action, "update") != 0)
+ {
+ _network->publishKeypadJsonCommandResult("noCodeSet");
+ return;
+ }
+
+ unsigned int allowedFromAr[6];
+ unsigned int allowedUntilAr[6];
+ unsigned int allowedFromTimeAr[2];
+ unsigned int allowedUntilTimeAr[2];
+ uint8_t allowedWeekdaysInt = 0;
+
+ if(timeLimited == 1)
+ {
+ if(allowedFrom.length() > 0)
+ {
+ if(allowedFrom.length() == 19)
+ {
+ allowedFromAr[0] = (uint16_t)allowedFrom.substring(0, 4).toInt();
+ allowedFromAr[1] = (uint8_t)allowedFrom.substring(5, 7).toInt();
+ allowedFromAr[2] = (uint8_t)allowedFrom.substring(8, 10).toInt();
+ allowedFromAr[3] = (uint8_t)allowedFrom.substring(11, 13).toInt();
+ allowedFromAr[4] = (uint8_t)allowedFrom.substring(14, 16).toInt();
+ allowedFromAr[5] = (uint8_t)allowedFrom.substring(17, 19).toInt();
+
+ if(allowedFromAr[0] < 2000 || allowedFromAr[0] > 3000 || allowedFromAr[1] < 1 || allowedFromAr[1] > 12 || allowedFromAr[2] < 1 || allowedFromAr[2] > 31 || allowedFromAr[3] < 0 || allowedFromAr[3] > 23 || allowedFromAr[4] < 0 || allowedFromAr[4] > 59 || allowedFromAr[5] < 0 || allowedFromAr[5] > 59)
+ {
+ _network->publishKeypadJsonCommandResult("invalidAllowedFrom");
+ return;
+ }
+ }
+ else
{
_network->publishKeypadJsonCommandResult("invalidAllowedFrom");
return;
}
}
- else
- {
- _network->publishKeypadJsonCommandResult("invalidAllowedFrom");
- return;
- }
- }
- if(allowedUntil.length() > 0)
- {
- if(allowedUntil.length() == 19)
+ if(allowedUntil.length() > 0)
{
- allowedUntilAr[0] = (uint16_t)allowedUntil.substring(0, 4).toInt();
- allowedUntilAr[1] = (uint8_t)allowedUntil.substring(5, 7).toInt();
- allowedUntilAr[2] = (uint8_t)allowedUntil.substring(8, 10).toInt();
- allowedUntilAr[3] = (uint8_t)allowedUntil.substring(11, 13).toInt();
- allowedUntilAr[4] = (uint8_t)allowedUntil.substring(14, 16).toInt();
- allowedUntilAr[5] = (uint8_t)allowedUntil.substring(17, 19).toInt();
+ if(allowedUntil.length() == 19)
+ {
+ allowedUntilAr[0] = (uint16_t)allowedUntil.substring(0, 4).toInt();
+ allowedUntilAr[1] = (uint8_t)allowedUntil.substring(5, 7).toInt();
+ allowedUntilAr[2] = (uint8_t)allowedUntil.substring(8, 10).toInt();
+ allowedUntilAr[3] = (uint8_t)allowedUntil.substring(11, 13).toInt();
+ allowedUntilAr[4] = (uint8_t)allowedUntil.substring(14, 16).toInt();
+ allowedUntilAr[5] = (uint8_t)allowedUntil.substring(17, 19).toInt();
- if(allowedUntilAr[0] < 2000 || allowedUntilAr[0] > 3000 || allowedUntilAr[1] < 1 || allowedUntilAr[1] > 12 || allowedUntilAr[2] < 1 || allowedUntilAr[2] > 31 || allowedUntilAr[3] < 0 || allowedUntilAr[3] > 23 || allowedUntilAr[4] < 0 || allowedUntilAr[4] > 59 || allowedUntilAr[5] < 0 || allowedUntilAr[5] > 59)
+ if(allowedUntilAr[0] < 2000 || allowedUntilAr[0] > 3000 || allowedUntilAr[1] < 1 || allowedUntilAr[1] > 12 || allowedUntilAr[2] < 1 || allowedUntilAr[2] > 31 || allowedUntilAr[3] < 0 || allowedUntilAr[3] > 23 || allowedUntilAr[4] < 0 || allowedUntilAr[4] > 59 || allowedUntilAr[5] < 0 || allowedUntilAr[5] > 59)
+ {
+ _network->publishKeypadJsonCommandResult("invalidAllowedUntil");
+ return;
+ }
+ }
+ else
{
_network->publishKeypadJsonCommandResult("invalidAllowedUntil");
return;
}
}
- else
- {
- _network->publishKeypadJsonCommandResult("invalidAllowedUntil");
- return;
- }
- }
- if(allowedFromTime.length() > 0)
- {
- if(allowedFromTime.length() == 5)
+ if(allowedFromTime.length() > 0)
{
- allowedFromTimeAr[0] = (uint8_t)allowedFromTime.substring(0, 2).toInt();
- allowedFromTimeAr[1] = (uint8_t)allowedFromTime.substring(3, 5).toInt();
+ if(allowedFromTime.length() == 5)
+ {
+ allowedFromTimeAr[0] = (uint8_t)allowedFromTime.substring(0, 2).toInt();
+ allowedFromTimeAr[1] = (uint8_t)allowedFromTime.substring(3, 5).toInt();
- if(allowedFromTimeAr[0] < 0 || allowedFromTimeAr[0] > 23 || allowedFromTimeAr[1] < 0 || allowedFromTimeAr[1] > 59)
+ if(allowedFromTimeAr[0] < 0 || allowedFromTimeAr[0] > 23 || allowedFromTimeAr[1] < 0 || allowedFromTimeAr[1] > 59)
+ {
+ _network->publishKeypadJsonCommandResult("invalidAllowedFromTime");
+ return;
+ }
+ }
+ else
{
_network->publishKeypadJsonCommandResult("invalidAllowedFromTime");
return;
}
}
- else
- {
- _network->publishKeypadJsonCommandResult("invalidAllowedFromTime");
- return;
- }
- }
- if(allowedUntilTime.length() > 0)
- {
- if(allowedUntilTime.length() == 5)
+ if(allowedUntilTime.length() > 0)
{
- allowedUntilTimeAr[0] = (uint8_t)allowedUntilTime.substring(0, 2).toInt();
- allowedUntilTimeAr[1] = (uint8_t)allowedUntilTime.substring(3, 5).toInt();
+ if(allowedUntilTime.length() == 5)
+ {
+ allowedUntilTimeAr[0] = (uint8_t)allowedUntilTime.substring(0, 2).toInt();
+ allowedUntilTimeAr[1] = (uint8_t)allowedUntilTime.substring(3, 5).toInt();
- if(allowedUntilTimeAr[0] < 0 || allowedUntilTimeAr[0] > 23 || allowedUntilTimeAr[1] < 0 || allowedUntilTimeAr[1] > 59)
+ if(allowedUntilTimeAr[0] < 0 || allowedUntilTimeAr[0] > 23 || allowedUntilTimeAr[1] < 0 || allowedUntilTimeAr[1] > 59)
+ {
+ _network->publishKeypadJsonCommandResult("invalidAllowedUntilTime");
+ return;
+ }
+ }
+ else
{
_network->publishKeypadJsonCommandResult("invalidAllowedUntilTime");
return;
}
}
- else
+
+ if(allowedWeekdays.indexOf("mon") >= 0) allowedWeekdaysInt += 64;
+ if(allowedWeekdays.indexOf("tue") >= 0) allowedWeekdaysInt += 32;
+ if(allowedWeekdays.indexOf("wed") >= 0) allowedWeekdaysInt += 16;
+ if(allowedWeekdays.indexOf("thu") >= 0) allowedWeekdaysInt += 8;
+ if(allowedWeekdays.indexOf("fri") >= 0) allowedWeekdaysInt += 4;
+ if(allowedWeekdays.indexOf("sat") >= 0) allowedWeekdaysInt += 2;
+ if(allowedWeekdays.indexOf("sun") >= 0) allowedWeekdaysInt += 1;
+ }
+
+ if(strcmp(action, "add") == 0)
+ {
+ NukiOpener::NewKeypadEntry entry;
+ memset(&entry, 0, sizeof(entry));
+ size_t nameLen = name.length();
+ memcpy(&entry.name, name.c_str(), nameLen > 20 ? 20 : nameLen);
+ entry.code = code;
+ entry.timeLimited = timeLimited == 1 ? 1 : 0;
+
+ if(allowedFrom.length() > 0)
{
- _network->publishKeypadJsonCommandResult("invalidAllowedUntilTime");
+ entry.allowedFromYear = allowedFromAr[0];
+ entry.allowedFromMonth = allowedFromAr[1];
+ entry.allowedFromDay = allowedFromAr[2];
+ entry.allowedFromHour = allowedFromAr[3];
+ entry.allowedFromMin = allowedFromAr[4];
+ entry.allowedFromSec = allowedFromAr[5];
+ }
+
+ if(allowedUntil.length() > 0)
+ {
+ entry.allowedUntilYear = allowedUntilAr[0];
+ entry.allowedUntilMonth = allowedUntilAr[1];
+ entry.allowedUntilDay = allowedUntilAr[2];
+ entry.allowedUntilHour = allowedUntilAr[3];
+ entry.allowedUntilMin = allowedUntilAr[4];
+ entry.allowedUntilSec = allowedUntilAr[5];
+ }
+
+ entry.allowedWeekdays = allowedWeekdaysInt;
+
+ if(allowedFromTime.length() > 0)
+ {
+ entry.allowedFromTimeHour = allowedFromTimeAr[0];
+ entry.allowedFromTimeMin = allowedFromTimeAr[1];
+ }
+
+ if(allowedUntilTime.length() > 0)
+ {
+ entry.allowedUntilTimeHour = allowedUntilTimeAr[0];
+ entry.allowedUntilTimeMin = allowedUntilTimeAr[1];
+ }
+
+ result = _nukiOpener.addKeypadEntry(entry);
+ Log->print(F("Add keypad code: "));
+ Log->println((int)result);
+ }
+ else if (strcmp(action, "update") == 0)
+ {
+ if(!codeId)
+ {
+ _network->publishKeypadJsonCommandResult("noCodeIdSet");
return;
}
- }
- if(allowedWeekdays.indexOf("mon") >= 0)
- {
- allowedWeekdaysInt += 64;
- }
- if(allowedWeekdays.indexOf("tue") >= 0)
- {
- allowedWeekdaysInt += 32;
- }
- if(allowedWeekdays.indexOf("wed") >= 0)
- {
- allowedWeekdaysInt += 16;
- }
- if(allowedWeekdays.indexOf("thu") >= 0)
- {
- allowedWeekdaysInt += 8;
- }
- if(allowedWeekdays.indexOf("fri") >= 0)
- {
- allowedWeekdaysInt += 4;
- }
- if(allowedWeekdays.indexOf("sat") >= 0)
- {
- allowedWeekdaysInt += 2;
- }
- if(allowedWeekdays.indexOf("sun") >= 0)
- {
- allowedWeekdaysInt += 1;
- }
- }
-
- if(strcmp(action, "add") == 0)
- {
- NukiOpener::NewKeypadEntry entry;
- memset(&entry, 0, sizeof(entry));
- size_t nameLen = name.length();
- memcpy(&entry.name, name.c_str(), nameLen > 20 ? 20 : nameLen);
- entry.code = code;
- entry.timeLimited = timeLimited == 1 ? 1 : 0;
-
- if(allowedFrom.length() > 0)
- {
- entry.allowedFromYear = allowedFromAr[0];
- entry.allowedFromMonth = allowedFromAr[1];
- entry.allowedFromDay = allowedFromAr[2];
- entry.allowedFromHour = allowedFromAr[3];
- entry.allowedFromMin = allowedFromAr[4];
- entry.allowedFromSec = allowedFromAr[5];
- }
-
- if(allowedUntil.length() > 0)
- {
- entry.allowedUntilYear = allowedUntilAr[0];
- entry.allowedUntilMonth = allowedUntilAr[1];
- entry.allowedUntilDay = allowedUntilAr[2];
- entry.allowedUntilHour = allowedUntilAr[3];
- entry.allowedUntilMin = allowedUntilAr[4];
- entry.allowedUntilSec = allowedUntilAr[5];
- }
-
- entry.allowedWeekdays = allowedWeekdaysInt;
-
- if(allowedFromTime.length() > 0)
- {
- entry.allowedFromTimeHour = allowedFromTimeAr[0];
- entry.allowedFromTimeMin = allowedFromTimeAr[1];
- }
-
- if(allowedUntilTime.length() > 0)
- {
- entry.allowedUntilTimeHour = allowedUntilTimeAr[0];
- entry.allowedUntilTimeMin = allowedUntilTimeAr[1];
- }
-
- result = _nukiOpener.addKeypadEntry(entry);
- Log->print(F("Add keypad code: "));
- Log->println((int)result);
- }
- else if (strcmp(action, "update") == 0)
- {
- if(!codeId)
- {
- _network->publishKeypadJsonCommandResult("noCodeIdSet");
- return;
- }
-
- if(!idExists)
- {
- _network->publishKeypadJsonCommandResult("noExistingCodeIdSet");
- return;
- }
-
- Nuki::CmdResult resultKp = _nukiOpener.retrieveKeypadEntries(0, _preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD));
- bool foundExisting = false;
-
- if(resultKp == Nuki::CmdResult::Success)
- {
- delay(250);
- std::list entries;
- _nukiOpener.getKeypadEntries(&entries);
-
- for(const auto& entry : entries)
+ if(!idExists)
{
- if (codeId != entry.codeId)
- {
- continue;
- }
- else
- {
- foundExisting = true;
- }
-
- if(name.length() < 1)
- {
- memset(oldName, 0, sizeof(oldName));
- memcpy(oldName, entry.name, sizeof(entry.name));
- }
- if(code == 12)
- {
- code = entry.code;
- }
- if(enabled == 2)
- {
- enabled = entry.enabled;
- }
- if(timeLimited == 2)
- {
- timeLimited = entry.timeLimited;
- }
- if(allowedFrom.length() < 1)
- {
- allowedFrom = "old";
- allowedFromAr[0] = entry.allowedFromYear;
- allowedFromAr[1] = entry.allowedFromMonth;
- allowedFromAr[2] = entry.allowedFromDay;
- allowedFromAr[3] = entry.allowedFromHour;
- allowedFromAr[4] = entry.allowedFromMin;
- allowedFromAr[5] = entry.allowedFromSec;
- }
- if(allowedUntil.length() < 1)
- {
- allowedUntil = "old";
- allowedUntilAr[0] = entry.allowedUntilYear;
- allowedUntilAr[1] = entry.allowedUntilMonth;
- allowedUntilAr[2] = entry.allowedUntilDay;
- allowedUntilAr[3] = entry.allowedUntilHour;
- allowedUntilAr[4] = entry.allowedUntilMin;
- allowedUntilAr[5] = entry.allowedUntilSec;
- }
- if(allowedWeekdays.length() < 1)
- {
- allowedWeekdaysInt = entry.allowedWeekdays;
- }
- if(allowedFromTime.length() < 1)
- {
- allowedFromTime = "old";
- allowedFromTimeAr[0] = entry.allowedFromTimeHour;
- allowedFromTimeAr[1] = entry.allowedFromTimeMin;
- }
-
- if(allowedUntilTime.length() < 1)
- {
- allowedUntilTime = "old";
- allowedUntilTimeAr[0] = entry.allowedUntilTimeHour;
- allowedUntilTimeAr[1] = entry.allowedUntilTimeMin;
- }
+ _network->publishKeypadJsonCommandResult("noExistingCodeIdSet");
+ return;
}
- if(!foundExisting)
+ Nuki::CmdResult resultKp = _nukiOpener.retrieveKeypadEntries(0, _preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD));
+ bool foundExisting = false;
+
+ if(resultKp == Nuki::CmdResult::Success)
+ {
+ delay(5000);
+ std::list entries;
+ _nukiOpener.getKeypadEntries(&entries);
+
+ for(const auto& entry : entries)
+ {
+ if (codeId != entry.codeId) continue;
+ else foundExisting = true;
+
+ if(name.length() < 1)
+ {
+ memset(oldName, 0, sizeof(oldName));
+ memcpy(oldName, entry.name, sizeof(entry.name));
+ }
+ if(code == 12) code = entry.code;
+ if(enabled == 2) enabled = entry.enabled;
+ if(timeLimited == 2) timeLimited = entry.timeLimited;
+ if(allowedFrom.length() < 1)
+ {
+ allowedFrom = "old";
+ allowedFromAr[0] = entry.allowedFromYear;
+ allowedFromAr[1] = entry.allowedFromMonth;
+ allowedFromAr[2] = entry.allowedFromDay;
+ allowedFromAr[3] = entry.allowedFromHour;
+ allowedFromAr[4] = entry.allowedFromMin;
+ allowedFromAr[5] = entry.allowedFromSec;
+ }
+ if(allowedUntil.length() < 1)
+ {
+ allowedUntil = "old";
+ allowedUntilAr[0] = entry.allowedUntilYear;
+ allowedUntilAr[1] = entry.allowedUntilMonth;
+ allowedUntilAr[2] = entry.allowedUntilDay;
+ allowedUntilAr[3] = entry.allowedUntilHour;
+ allowedUntilAr[4] = entry.allowedUntilMin;
+ allowedUntilAr[5] = entry.allowedUntilSec;
+ }
+ if(allowedWeekdays.length() < 1) allowedWeekdaysInt = entry.allowedWeekdays;
+ if(allowedFromTime.length() < 1)
+ {
+ allowedFromTime = "old";
+ allowedFromTimeAr[0] = entry.allowedFromTimeHour;
+ allowedFromTimeAr[1] = entry.allowedFromTimeMin;
+ }
+
+ if(allowedUntilTime.length() < 1)
+ {
+ allowedUntilTime = "old";
+ allowedUntilTimeAr[0] = entry.allowedUntilTimeHour;
+ allowedUntilTimeAr[1] = entry.allowedUntilTimeMin;
+ }
+
+ }
+
+ if(!foundExisting)
+ {
+ _network->publishKeypadJsonCommandResult("failedToRetrieveExistingKeypadEntry");
+ return;
+ }
+ }
+ else
{
_network->publishKeypadJsonCommandResult("failedToRetrieveExistingKeypadEntry");
return;
}
- }
- else
- {
- _network->publishKeypadJsonCommandResult("failedToRetrieveExistingKeypadEntry");
- return;
- }
- NukiOpener::UpdatedKeypadEntry entry;
+ NukiOpener::UpdatedKeypadEntry entry;
- memset(&entry, 0, sizeof(entry));
- entry.codeId = codeId;
- entry.code = code;
+ memset(&entry, 0, sizeof(entry));
+ entry.codeId = codeId;
+ entry.code = code;
- if(name.length() < 1)
- {
- size_t nameLen = strlen(oldName);
- memcpy(&entry.name, oldName, nameLen > 20 ? 20 : nameLen);
- }
- else
- {
- size_t nameLen = name.length();
- memcpy(&entry.name, name.c_str(), nameLen > 20 ? 20 : nameLen);
- }
- entry.enabled = enabled;
- entry.timeLimited = timeLimited;
-
- if(enabled == 1)
- {
- if(timeLimited == 1)
+ if(name.length() < 1)
{
- if(allowedFrom.length() > 0)
- {
- entry.allowedFromYear = allowedFromAr[0];
- entry.allowedFromMonth = allowedFromAr[1];
- entry.allowedFromDay = allowedFromAr[2];
- entry.allowedFromHour = allowedFromAr[3];
- entry.allowedFromMin = allowedFromAr[4];
- entry.allowedFromSec = allowedFromAr[5];
- }
+ size_t nameLen = strlen(oldName);
+ memcpy(&entry.name, oldName, nameLen > 20 ? 20 : nameLen);
+ }
+ else
+ {
+ size_t nameLen = name.length();
+ memcpy(&entry.name, name.c_str(), nameLen > 20 ? 20 : nameLen);
+ }
+ entry.enabled = enabled;
+ entry.timeLimited = timeLimited;
- if(allowedUntil.length() > 0)
+ if(enabled == 1)
+ {
+ if(timeLimited == 1)
{
- entry.allowedUntilYear = allowedUntilAr[0];
- entry.allowedUntilMonth = allowedUntilAr[1];
- entry.allowedUntilDay = allowedUntilAr[2];
- entry.allowedUntilHour = allowedUntilAr[3];
- entry.allowedUntilMin = allowedUntilAr[4];
- entry.allowedUntilSec = allowedUntilAr[5];
- }
+ if(allowedFrom.length() > 0)
+ {
+ entry.allowedFromYear = allowedFromAr[0];
+ entry.allowedFromMonth = allowedFromAr[1];
+ entry.allowedFromDay = allowedFromAr[2];
+ entry.allowedFromHour = allowedFromAr[3];
+ entry.allowedFromMin = allowedFromAr[4];
+ entry.allowedFromSec = allowedFromAr[5];
+ }
- entry.allowedWeekdays = allowedWeekdaysInt;
+ if(allowedUntil.length() > 0)
+ {
+ entry.allowedUntilYear = allowedUntilAr[0];
+ entry.allowedUntilMonth = allowedUntilAr[1];
+ entry.allowedUntilDay = allowedUntilAr[2];
+ entry.allowedUntilHour = allowedUntilAr[3];
+ entry.allowedUntilMin = allowedUntilAr[4];
+ entry.allowedUntilSec = allowedUntilAr[5];
+ }
- if(allowedFromTime.length() > 0)
- {
- entry.allowedFromTimeHour = allowedFromTimeAr[0];
- entry.allowedFromTimeMin = allowedFromTimeAr[1];
- }
+ entry.allowedWeekdays = allowedWeekdaysInt;
- if(allowedUntilTime.length() > 0)
- {
- entry.allowedUntilTimeHour = allowedUntilTimeAr[0];
- entry.allowedUntilTimeMin = allowedUntilTimeAr[1];
+ if(allowedFromTime.length() > 0)
+ {
+ entry.allowedFromTimeHour = allowedFromTimeAr[0];
+ entry.allowedFromTimeMin = allowedFromTimeAr[1];
+ }
+
+ if(allowedUntilTime.length() > 0)
+ {
+ entry.allowedUntilTimeHour = allowedUntilTimeAr[0];
+ entry.allowedUntilTimeMin = allowedUntilTimeAr[1];
+ }
}
}
+
+ result = _nukiOpener.updateKeypadEntry(entry);
+ Log->print(F("Update keypad code: "));
+ Log->println((int)result);
}
-
- result = _nukiOpener.updateKeypadEntry(entry);
- Log->print(F("Update keypad code: "));
- Log->println((int)result);
}
- }
- else
- {
- _network->publishKeypadJsonCommandResult("invalidAction");
- return;
+ else
+ {
+ _network->publishKeypadJsonCommandResult("invalidAction");
+ return;
+ }
+
+ if(result != Nuki::CmdResult::Success) {
+ ++retryCount;
+ }
+ else break;
}
- if(result != Nuki::CmdResult::Success)
- {
- ++retryCount;
- }
- else
- {
- break;
- }
- }
+ updateKeypad(false);
- updateKeypad(false);
-
- if((int)result != -1)
- {
- char resultStr[15];
- memset(&resultStr, 0, sizeof(resultStr));
- NukiOpener::cmdResultToString(result, resultStr);
- _network->publishKeypadJsonCommandResult(resultStr);
+ if((int)result != -1)
+ {
+ char resultStr[15];
+ memset(&resultStr, 0, sizeof(resultStr));
+ NukiOpener::cmdResultToString(result, resultStr);
+ _network->publishKeypadJsonCommandResult(resultStr);
+ }
}
}
else
@@ -3200,7 +3216,7 @@ void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value)
if(resultTc == Nuki::CmdResult::Success)
{
- delay(250);
+ delay(5000);
std::list timeControlEntries;
_nukiOpener.getTimeControlEntries(&timeControlEntries);
@@ -3329,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;
@@ -3656,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/NukiOpenerWrapper.h b/src/NukiOpenerWrapper.h
index 3dee2ed..2dab4aa 100644
--- a/src/NukiOpenerWrapper.h
+++ b/src/NukiOpenerWrapper.h
@@ -106,13 +106,17 @@ private:
bool _publishAuthData = false;
bool _clearAuthData = false;
bool _disableNonJSON = false;
+ bool _checkKeypadCodes = false;
bool _pairedAsApp = false;
int _nrOfRetries = 0;
int _retryDelay = 0;
int _retryConfigCount = 0;
int _retryLockstateCount = 0;
int64_t _nextRetryTs = 0;
+ int64_t _invalidCount = 0;
+ int64_t _lastCodeCheck = 0;
std::vector _keypadCodeIds;
+ std::vector _keypadCodes;
std::vector _timeControlIds;
std::vector _authIds;
diff --git a/src/NukiWrapper.cpp b/src/NukiWrapper.cpp
index 2c71c48..799eb0c 100644
--- a/src/NukiWrapper.cpp
+++ b/src/NukiWrapper.cpp
@@ -185,8 +185,9 @@ void NukiWrapper::readSettings()
_retryDelay = _preferences->getInt(preference_command_retry_delay);
_rssiPublishInterval = _preferences->getInt(preference_rssi_publish_interval) * 1000;
_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));
@@ -430,6 +431,10 @@ void NukiWrapper::update()
_network->clearAuthorizationInfo();
_clearAuthData = false;
}
+ if(_checkKeypadCodes && _invalidCount > 0 && (ts - (120000 * _invalidCount)) > _lastCodeCheck)
+ {
+ _invalidCount--;
+ }
}
memcpy(&_lastKeyTurnerState, &_keyTurnerState, sizeof(NukiLock::KeyTurnerState));
@@ -875,10 +880,13 @@ void NukiWrapper::updateKeypad(bool retrieved)
_network->publishKeypad(entries, _maxKeypadCodeCount);
_keypadCodeIds.clear();
+ _keypadCodes.clear();
_keypadCodeIds.reserve(entries.size());
+ _keypadCodes.reserve(entries.size());
for(const auto& entry : entries)
{
_keypadCodeIds.push_back(entry.codeId);
+ _keypadCodes.push_back(entry.code);
}
}
@@ -2711,417 +2719,425 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value)
{
idExists = std::find(_keypadCodeIds.begin(), _keypadCodeIds.end(), codeId) != _keypadCodeIds.end();
}
-
- Nuki::CmdResult result = (Nuki::CmdResult)-1;
- int retryCount = 0;
-
- while(retryCount < _nrOfRetries + 1)
- {
- if(strcmp(action, "delete") == 0)
+
+ if(strcmp(action, "check") == 0) {
+ if(!_preferences->getBool(preference_keypad_check_code_enabled, false))
{
- if(idExists)
+ _network->publishKeypadJsonCommandResult("checkingKeypadCodesDisabled");
+ return;
+ }
+
+ if((pow(_invalidCount, 5) + _lastCodeCheck) > espMillis())
+ {
+ _network->publishKeypadJsonCommandResult("checkingCodesBlockedTooManyInvalid");
+ _lastCodeCheck = espMillis();
+ return;
+ }
+
+ _lastCodeCheck = espMillis();
+
+ if(idExists)
+ {
+ auto it1 = std::find(_keypadCodeIds.begin(), _keypadCodeIds.end(), codeId);
+ int index = it1 - _keypadCodeIds.begin();
+ Log->print(F("Check keypad code: "));
+
+ if(code == _keypadCodes[index])
{
- result = _nukiLock.deleteKeypadEntry(codeId);
- Log->print(F("Delete keypad code: "));
- Log->println((int)result);
+ _invalidCount = 0;
+ _network->publishKeypadJsonCommandResult("codeValid");
+ Log->println("Valid");
+ return;
}
else
{
- _network->publishKeypadJsonCommandResult("noExistingCodeIdSet");
+ _invalidCount++;
+ _network->publishKeypadJsonCommandResult("codeInvalid");
+ Log->print("Invalid\nInvalid count: ");
+ Log->println(_invalidCount);
return;
}
}
- else if(strcmp(action, "add") == 0 || strcmp(action, "update") == 0)
+ else
{
- if(name.length() < 1)
- {
- if (strcmp(action, "update") != 0)
+ _invalidCount++;
+ _network->publishKeypadJsonCommandResult("noExistingCodeIdSet");
+ Log->print("Invalid count: ");
+ Log->println(_invalidCount);
+ return;
+ }
+ }
+ else
+ {
+
+ Nuki::CmdResult result = (Nuki::CmdResult)-1;
+ int retryCount = 0;
+
+ while(retryCount < _nrOfRetries + 1)
+ {
+ if(strcmp(action, "delete") == 0) {
+ if(idExists)
{
- _network->publishKeypadJsonCommandResult("noNameSet");
+ result = _nukiLock.deleteKeypadEntry(codeId);
+ Log->print(F("Delete keypad code: "));
+ Log->println((int)result);
+ }
+ else
+ {
+ _network->publishKeypadJsonCommandResult("noExistingCodeIdSet");
return;
}
}
-
- if(code != 12)
+ else if(strcmp(action, "add") == 0 || strcmp(action, "update") == 0)
{
- String codeStr = json["code"].as();
- bool codeValid = code > 100000 && code < 1000000 && (codeStr.indexOf('0') == -1);
-
- if (!codeValid)
+ if(name.length() < 1)
{
- _network->publishKeypadJsonCommandResult("noValidCodeSet");
- return;
- }
- }
- else if (strcmp(action, "update") != 0)
- {
- _network->publishKeypadJsonCommandResult("noCodeSet");
- return;
- }
-
- unsigned int allowedFromAr[6];
- unsigned int allowedUntilAr[6];
- unsigned int allowedFromTimeAr[2];
- unsigned int allowedUntilTimeAr[2];
- uint8_t allowedWeekdaysInt = 0;
-
- if(timeLimited == 1)
- {
- if(allowedFrom.length() > 0)
- {
- if(allowedFrom.length() == 19)
+ if (strcmp(action, "update") != 0)
{
- allowedFromAr[0] = (uint16_t)allowedFrom.substring(0, 4).toInt();
- allowedFromAr[1] = (uint8_t)allowedFrom.substring(5, 7).toInt();
- allowedFromAr[2] = (uint8_t)allowedFrom.substring(8, 10).toInt();
- allowedFromAr[3] = (uint8_t)allowedFrom.substring(11, 13).toInt();
- allowedFromAr[4] = (uint8_t)allowedFrom.substring(14, 16).toInt();
- allowedFromAr[5] = (uint8_t)allowedFrom.substring(17, 19).toInt();
+ _network->publishKeypadJsonCommandResult("noNameSet");
+ return;
+ }
+ }
- if(allowedFromAr[0] < 2000 || allowedFromAr[0] > 3000 || allowedFromAr[1] < 1 || allowedFromAr[1] > 12 || allowedFromAr[2] < 1 || allowedFromAr[2] > 31 || allowedFromAr[3] < 0 || allowedFromAr[3] > 23 || allowedFromAr[4] < 0 || allowedFromAr[4] > 59 || allowedFromAr[5] < 0 || allowedFromAr[5] > 59)
+ if(code != 12)
+ {
+ String codeStr = json["code"].as();
+ bool codeValid = code > 100000 && code < 1000000 && (codeStr.indexOf('0') == -1);
+
+ if (!codeValid)
+ {
+ _network->publishKeypadJsonCommandResult("noValidCodeSet");
+ return;
+ }
+ }
+ else if (strcmp(action, "update") != 0)
+ {
+ _network->publishKeypadJsonCommandResult("noCodeSet");
+ return;
+ }
+
+ unsigned int allowedFromAr[6];
+ unsigned int allowedUntilAr[6];
+ unsigned int allowedFromTimeAr[2];
+ unsigned int allowedUntilTimeAr[2];
+ uint8_t allowedWeekdaysInt = 0;
+
+ if(timeLimited == 1)
+ {
+ if(allowedFrom.length() > 0)
+ {
+ if(allowedFrom.length() == 19)
+ {
+ allowedFromAr[0] = (uint16_t)allowedFrom.substring(0, 4).toInt();
+ allowedFromAr[1] = (uint8_t)allowedFrom.substring(5, 7).toInt();
+ allowedFromAr[2] = (uint8_t)allowedFrom.substring(8, 10).toInt();
+ allowedFromAr[3] = (uint8_t)allowedFrom.substring(11, 13).toInt();
+ allowedFromAr[4] = (uint8_t)allowedFrom.substring(14, 16).toInt();
+ allowedFromAr[5] = (uint8_t)allowedFrom.substring(17, 19).toInt();
+
+ if(allowedFromAr[0] < 2000 || allowedFromAr[0] > 3000 || allowedFromAr[1] < 1 || allowedFromAr[1] > 12 || allowedFromAr[2] < 1 || allowedFromAr[2] > 31 || allowedFromAr[3] < 0 || allowedFromAr[3] > 23 || allowedFromAr[4] < 0 || allowedFromAr[4] > 59 || allowedFromAr[5] < 0 || allowedFromAr[5] > 59)
+ {
+ _network->publishKeypadJsonCommandResult("invalidAllowedFrom");
+ return;
+ }
+ }
+ else
{
_network->publishKeypadJsonCommandResult("invalidAllowedFrom");
return;
}
}
- else
- {
- _network->publishKeypadJsonCommandResult("invalidAllowedFrom");
- return;
- }
- }
- if(allowedUntil.length() > 0)
- {
- if(allowedUntil.length() == 19)
+ if(allowedUntil.length() > 0)
{
- allowedUntilAr[0] = (uint16_t)allowedUntil.substring(0, 4).toInt();
- allowedUntilAr[1] = (uint8_t)allowedUntil.substring(5, 7).toInt();
- allowedUntilAr[2] = (uint8_t)allowedUntil.substring(8, 10).toInt();
- allowedUntilAr[3] = (uint8_t)allowedUntil.substring(11, 13).toInt();
- allowedUntilAr[4] = (uint8_t)allowedUntil.substring(14, 16).toInt();
- allowedUntilAr[5] = (uint8_t)allowedUntil.substring(17, 19).toInt();
+ if(allowedUntil.length() == 19)
+ {
+ allowedUntilAr[0] = (uint16_t)allowedUntil.substring(0, 4).toInt();
+ allowedUntilAr[1] = (uint8_t)allowedUntil.substring(5, 7).toInt();
+ allowedUntilAr[2] = (uint8_t)allowedUntil.substring(8, 10).toInt();
+ allowedUntilAr[3] = (uint8_t)allowedUntil.substring(11, 13).toInt();
+ allowedUntilAr[4] = (uint8_t)allowedUntil.substring(14, 16).toInt();
+ allowedUntilAr[5] = (uint8_t)allowedUntil.substring(17, 19).toInt();
- if(allowedUntilAr[0] < 2000 || allowedUntilAr[0] > 3000 || allowedUntilAr[1] < 1 || allowedUntilAr[1] > 12 || allowedUntilAr[2] < 1 || allowedUntilAr[2] > 31 || allowedUntilAr[3] < 0 || allowedUntilAr[3] > 23 || allowedUntilAr[4] < 0 || allowedUntilAr[4] > 59 || allowedUntilAr[5] < 0 || allowedUntilAr[5] > 59)
+ if(allowedUntilAr[0] < 2000 || allowedUntilAr[0] > 3000 || allowedUntilAr[1] < 1 || allowedUntilAr[1] > 12 || allowedUntilAr[2] < 1 || allowedUntilAr[2] > 31 || allowedUntilAr[3] < 0 || allowedUntilAr[3] > 23 || allowedUntilAr[4] < 0 || allowedUntilAr[4] > 59 || allowedUntilAr[5] < 0 || allowedUntilAr[5] > 59)
+ {
+ _network->publishKeypadJsonCommandResult("invalidAllowedUntil");
+ return;
+ }
+ }
+ else
{
_network->publishKeypadJsonCommandResult("invalidAllowedUntil");
return;
}
}
- else
- {
- _network->publishKeypadJsonCommandResult("invalidAllowedUntil");
- return;
- }
- }
- if(allowedFromTime.length() > 0)
- {
- if(allowedFromTime.length() == 5)
+ if(allowedFromTime.length() > 0)
{
- allowedFromTimeAr[0] = (uint8_t)allowedFromTime.substring(0, 2).toInt();
- allowedFromTimeAr[1] = (uint8_t)allowedFromTime.substring(3, 5).toInt();
+ if(allowedFromTime.length() == 5)
+ {
+ allowedFromTimeAr[0] = (uint8_t)allowedFromTime.substring(0, 2).toInt();
+ allowedFromTimeAr[1] = (uint8_t)allowedFromTime.substring(3, 5).toInt();
- if(allowedFromTimeAr[0] < 0 || allowedFromTimeAr[0] > 23 || allowedFromTimeAr[1] < 0 || allowedFromTimeAr[1] > 59)
+ if(allowedFromTimeAr[0] < 0 || allowedFromTimeAr[0] > 23 || allowedFromTimeAr[1] < 0 || allowedFromTimeAr[1] > 59)
+ {
+ _network->publishKeypadJsonCommandResult("invalidAllowedFromTime");
+ return;
+ }
+ }
+ else
{
_network->publishKeypadJsonCommandResult("invalidAllowedFromTime");
return;
}
}
- else
- {
- _network->publishKeypadJsonCommandResult("invalidAllowedFromTime");
- return;
- }
- }
- if(allowedUntilTime.length() > 0)
- {
- if(allowedUntilTime.length() == 5)
+ if(allowedUntilTime.length() > 0)
{
- allowedUntilTimeAr[0] = (uint8_t)allowedUntilTime.substring(0, 2).toInt();
- allowedUntilTimeAr[1] = (uint8_t)allowedUntilTime.substring(3, 5).toInt();
+ if(allowedUntilTime.length() == 5)
+ {
+ allowedUntilTimeAr[0] = (uint8_t)allowedUntilTime.substring(0, 2).toInt();
+ allowedUntilTimeAr[1] = (uint8_t)allowedUntilTime.substring(3, 5).toInt();
- if(allowedUntilTimeAr[0] < 0 || allowedUntilTimeAr[0] > 23 || allowedUntilTimeAr[1] < 0 || allowedUntilTimeAr[1] > 59)
+ if(allowedUntilTimeAr[0] < 0 || allowedUntilTimeAr[0] > 23 || allowedUntilTimeAr[1] < 0 || allowedUntilTimeAr[1] > 59)
+ {
+ _network->publishKeypadJsonCommandResult("invalidAllowedUntilTime");
+ return;
+ }
+ }
+ else
{
_network->publishKeypadJsonCommandResult("invalidAllowedUntilTime");
return;
}
}
- else
+
+ if(allowedWeekdays.indexOf("mon") >= 0) allowedWeekdaysInt += 64;
+ if(allowedWeekdays.indexOf("tue") >= 0) allowedWeekdaysInt += 32;
+ if(allowedWeekdays.indexOf("wed") >= 0) allowedWeekdaysInt += 16;
+ if(allowedWeekdays.indexOf("thu") >= 0) allowedWeekdaysInt += 8;
+ if(allowedWeekdays.indexOf("fri") >= 0) allowedWeekdaysInt += 4;
+ if(allowedWeekdays.indexOf("sat") >= 0) allowedWeekdaysInt += 2;
+ if(allowedWeekdays.indexOf("sun") >= 0) allowedWeekdaysInt += 1;
+ }
+
+ if(strcmp(action, "add") == 0)
+ {
+ NukiLock::NewKeypadEntry entry;
+ memset(&entry, 0, sizeof(entry));
+ size_t nameLen = name.length();
+ memcpy(&entry.name, name.c_str(), nameLen > 20 ? 20 : nameLen);
+ entry.code = code;
+ entry.timeLimited = timeLimited == 1 ? 1 : 0;
+
+ if(allowedFrom.length() > 0)
{
- _network->publishKeypadJsonCommandResult("invalidAllowedUntilTime");
+ entry.allowedFromYear = allowedFromAr[0];
+ entry.allowedFromMonth = allowedFromAr[1];
+ entry.allowedFromDay = allowedFromAr[2];
+ entry.allowedFromHour = allowedFromAr[3];
+ entry.allowedFromMin = allowedFromAr[4];
+ entry.allowedFromSec = allowedFromAr[5];
+ }
+
+ if(allowedUntil.length() > 0)
+ {
+ entry.allowedUntilYear = allowedUntilAr[0];
+ entry.allowedUntilMonth = allowedUntilAr[1];
+ entry.allowedUntilDay = allowedUntilAr[2];
+ entry.allowedUntilHour = allowedUntilAr[3];
+ entry.allowedUntilMin = allowedUntilAr[4];
+ entry.allowedUntilSec = allowedUntilAr[5];
+ }
+
+ entry.allowedWeekdays = allowedWeekdaysInt;
+
+ if(allowedFromTime.length() > 0)
+ {
+ entry.allowedFromTimeHour = allowedFromTimeAr[0];
+ entry.allowedFromTimeMin = allowedFromTimeAr[1];
+ }
+
+ if(allowedUntilTime.length() > 0)
+ {
+ entry.allowedUntilTimeHour = allowedUntilTimeAr[0];
+ entry.allowedUntilTimeMin = allowedUntilTimeAr[1];
+ }
+
+ result = _nukiLock.addKeypadEntry(entry);
+ Log->print(F("Add keypad code: "));
+ Log->println((int)result);
+ }
+ else if (strcmp(action, "update") == 0)
+ {
+ if(!codeId)
+ {
+ _network->publishKeypadJsonCommandResult("noCodeIdSet");
return;
}
- }
- if(allowedWeekdays.indexOf("mon") >= 0)
- {
- allowedWeekdaysInt += 64;
- }
- if(allowedWeekdays.indexOf("tue") >= 0)
- {
- allowedWeekdaysInt += 32;
- }
- if(allowedWeekdays.indexOf("wed") >= 0)
- {
- allowedWeekdaysInt += 16;
- }
- if(allowedWeekdays.indexOf("thu") >= 0)
- {
- allowedWeekdaysInt += 8;
- }
- if(allowedWeekdays.indexOf("fri") >= 0)
- {
- allowedWeekdaysInt += 4;
- }
- if(allowedWeekdays.indexOf("sat") >= 0)
- {
- allowedWeekdaysInt += 2;
- }
- if(allowedWeekdays.indexOf("sun") >= 0)
- {
- allowedWeekdaysInt += 1;
- }
- }
-
- if(strcmp(action, "add") == 0)
- {
- NukiLock::NewKeypadEntry entry;
- memset(&entry, 0, sizeof(entry));
- size_t nameLen = name.length();
- memcpy(&entry.name, name.c_str(), nameLen > 20 ? 20 : nameLen);
- entry.code = code;
- entry.timeLimited = timeLimited == 1 ? 1 : 0;
-
- if(allowedFrom.length() > 0)
- {
- entry.allowedFromYear = allowedFromAr[0];
- entry.allowedFromMonth = allowedFromAr[1];
- entry.allowedFromDay = allowedFromAr[2];
- entry.allowedFromHour = allowedFromAr[3];
- entry.allowedFromMin = allowedFromAr[4];
- entry.allowedFromSec = allowedFromAr[5];
- }
-
- if(allowedUntil.length() > 0)
- {
- entry.allowedUntilYear = allowedUntilAr[0];
- entry.allowedUntilMonth = allowedUntilAr[1];
- entry.allowedUntilDay = allowedUntilAr[2];
- entry.allowedUntilHour = allowedUntilAr[3];
- entry.allowedUntilMin = allowedUntilAr[4];
- entry.allowedUntilSec = allowedUntilAr[5];
- }
-
- entry.allowedWeekdays = allowedWeekdaysInt;
-
- if(allowedFromTime.length() > 0)
- {
- entry.allowedFromTimeHour = allowedFromTimeAr[0];
- entry.allowedFromTimeMin = allowedFromTimeAr[1];
- }
-
- if(allowedUntilTime.length() > 0)
- {
- entry.allowedUntilTimeHour = allowedUntilTimeAr[0];
- entry.allowedUntilTimeMin = allowedUntilTimeAr[1];
- }
-
- result = _nukiLock.addKeypadEntry(entry);
- Log->print(F("Add keypad code: "));
- Log->println((int)result);
- }
- else if (strcmp(action, "update") == 0)
- {
- if(!codeId)
- {
- _network->publishKeypadJsonCommandResult("noCodeIdSet");
- return;
- }
-
- if(!idExists)
- {
- _network->publishKeypadJsonCommandResult("noExistingCodeIdSet");
- return;
- }
-
- Nuki::CmdResult resultKp = _nukiLock.retrieveKeypadEntries(0, _preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD));
- bool foundExisting = false;
-
- if(resultKp == Nuki::CmdResult::Success)
- {
- delay(250);
- std::list entries;
- _nukiLock.getKeypadEntries(&entries);
-
- for(const auto& entry : entries)
+ if(!idExists)
{
- if (codeId != entry.codeId)
- {
- continue;
- }
- else
- {
- foundExisting = true;
- }
-
- if(name.length() < 1)
- {
- memset(oldName, 0, sizeof(oldName));
- memcpy(oldName, entry.name, sizeof(entry.name));
- }
- if(code == 12)
- {
- code = entry.code;
- }
- if(enabled == 2)
- {
- enabled = entry.enabled;
- }
- if(timeLimited == 2)
- {
- timeLimited = entry.timeLimited;
- }
- if(allowedFrom.length() < 1)
- {
- allowedFrom = "old";
- allowedFromAr[0] = entry.allowedFromYear;
- allowedFromAr[1] = entry.allowedFromMonth;
- allowedFromAr[2] = entry.allowedFromDay;
- allowedFromAr[3] = entry.allowedFromHour;
- allowedFromAr[4] = entry.allowedFromMin;
- allowedFromAr[5] = entry.allowedFromSec;
- }
- if(allowedUntil.length() < 1)
- {
- allowedUntil = "old";
- allowedUntilAr[0] = entry.allowedUntilYear;
- allowedUntilAr[1] = entry.allowedUntilMonth;
- allowedUntilAr[2] = entry.allowedUntilDay;
- allowedUntilAr[3] = entry.allowedUntilHour;
- allowedUntilAr[4] = entry.allowedUntilMin;
- allowedUntilAr[5] = entry.allowedUntilSec;
- }
- if(allowedWeekdays.length() < 1)
- {
- allowedWeekdaysInt = entry.allowedWeekdays;
- }
- if(allowedFromTime.length() < 1)
- {
- allowedFromTime = "old";
- allowedFromTimeAr[0] = entry.allowedFromTimeHour;
- allowedFromTimeAr[1] = entry.allowedFromTimeMin;
- }
-
- if(allowedUntilTime.length() < 1)
- {
- allowedUntilTime = "old";
- allowedUntilTimeAr[0] = entry.allowedUntilTimeHour;
- allowedUntilTimeAr[1] = entry.allowedUntilTimeMin;
- }
+ _network->publishKeypadJsonCommandResult("noExistingCodeIdSet");
+ return;
}
- if(!foundExisting)
+ Nuki::CmdResult resultKp = _nukiLock.retrieveKeypadEntries(0, _preferences->getInt(preference_keypad_max_entries, MAX_KEYPAD));
+ bool foundExisting = false;
+
+ if(resultKp == Nuki::CmdResult::Success)
+ {
+ delay(5000);
+ std::list entries;
+ _nukiLock.getKeypadEntries(&entries);
+
+ for(const auto& entry : entries)
+ {
+ if (codeId != entry.codeId) continue;
+ else foundExisting = true;
+
+ if(name.length() < 1)
+ {
+ memset(oldName, 0, sizeof(oldName));
+ memcpy(oldName, entry.name, sizeof(entry.name));
+ }
+ if(code == 12) code = entry.code;
+ if(enabled == 2) enabled = entry.enabled;
+ if(timeLimited == 2) timeLimited = entry.timeLimited;
+ if(allowedFrom.length() < 1)
+ {
+ allowedFrom = "old";
+ allowedFromAr[0] = entry.allowedFromYear;
+ allowedFromAr[1] = entry.allowedFromMonth;
+ allowedFromAr[2] = entry.allowedFromDay;
+ allowedFromAr[3] = entry.allowedFromHour;
+ allowedFromAr[4] = entry.allowedFromMin;
+ allowedFromAr[5] = entry.allowedFromSec;
+ }
+ if(allowedUntil.length() < 1)
+ {
+ allowedUntil = "old";
+ allowedUntilAr[0] = entry.allowedUntilYear;
+ allowedUntilAr[1] = entry.allowedUntilMonth;
+ allowedUntilAr[2] = entry.allowedUntilDay;
+ allowedUntilAr[3] = entry.allowedUntilHour;
+ allowedUntilAr[4] = entry.allowedUntilMin;
+ allowedUntilAr[5] = entry.allowedUntilSec;
+ }
+ if(allowedWeekdays.length() < 1) allowedWeekdaysInt = entry.allowedWeekdays;
+ if(allowedFromTime.length() < 1)
+ {
+ allowedFromTime = "old";
+ allowedFromTimeAr[0] = entry.allowedFromTimeHour;
+ allowedFromTimeAr[1] = entry.allowedFromTimeMin;
+ }
+
+ if(allowedUntilTime.length() < 1)
+ {
+ allowedUntilTime = "old";
+ allowedUntilTimeAr[0] = entry.allowedUntilTimeHour;
+ allowedUntilTimeAr[1] = entry.allowedUntilTimeMin;
+ }
+
+ }
+
+ if(!foundExisting)
+ {
+ _network->publishKeypadJsonCommandResult("failedToRetrieveExistingKeypadEntry");
+ return;
+ }
+ }
+ else
{
_network->publishKeypadJsonCommandResult("failedToRetrieveExistingKeypadEntry");
return;
}
- }
- else
- {
- _network->publishKeypadJsonCommandResult("failedToRetrieveExistingKeypadEntry");
- return;
- }
- NukiLock::UpdatedKeypadEntry entry;
+ NukiLock::UpdatedKeypadEntry entry;
- memset(&entry, 0, sizeof(entry));
- entry.codeId = codeId;
- entry.code = code;
+ memset(&entry, 0, sizeof(entry));
+ entry.codeId = codeId;
+ entry.code = code;
- if(name.length() < 1)
- {
- size_t nameLen = strlen(oldName);
- memcpy(&entry.name, oldName, nameLen > 20 ? 20 : nameLen);
- }
- else
- {
- size_t nameLen = name.length();
- memcpy(&entry.name, name.c_str(), nameLen > 20 ? 20 : nameLen);
- }
- entry.enabled = enabled;
- entry.timeLimited = timeLimited;
-
- if(enabled == 1)
- {
- if(timeLimited == 1)
+ if(name.length() < 1)
{
- if(allowedFrom.length() > 0)
- {
- entry.allowedFromYear = allowedFromAr[0];
- entry.allowedFromMonth = allowedFromAr[1];
- entry.allowedFromDay = allowedFromAr[2];
- entry.allowedFromHour = allowedFromAr[3];
- entry.allowedFromMin = allowedFromAr[4];
- entry.allowedFromSec = allowedFromAr[5];
- }
+ size_t nameLen = strlen(oldName);
+ memcpy(&entry.name, oldName, nameLen > 20 ? 20 : nameLen);
+ }
+ else
+ {
+ size_t nameLen = name.length();
+ memcpy(&entry.name, name.c_str(), nameLen > 20 ? 20 : nameLen);
+ }
+ entry.enabled = enabled;
+ entry.timeLimited = timeLimited;
- if(allowedUntil.length() > 0)
+ if(enabled == 1)
+ {
+ if(timeLimited == 1)
{
- entry.allowedUntilYear = allowedUntilAr[0];
- entry.allowedUntilMonth = allowedUntilAr[1];
- entry.allowedUntilDay = allowedUntilAr[2];
- entry.allowedUntilHour = allowedUntilAr[3];
- entry.allowedUntilMin = allowedUntilAr[4];
- entry.allowedUntilSec = allowedUntilAr[5];
- }
+ if(allowedFrom.length() > 0)
+ {
+ entry.allowedFromYear = allowedFromAr[0];
+ entry.allowedFromMonth = allowedFromAr[1];
+ entry.allowedFromDay = allowedFromAr[2];
+ entry.allowedFromHour = allowedFromAr[3];
+ entry.allowedFromMin = allowedFromAr[4];
+ entry.allowedFromSec = allowedFromAr[5];
+ }
- entry.allowedWeekdays = allowedWeekdaysInt;
+ if(allowedUntil.length() > 0)
+ {
+ entry.allowedUntilYear = allowedUntilAr[0];
+ entry.allowedUntilMonth = allowedUntilAr[1];
+ entry.allowedUntilDay = allowedUntilAr[2];
+ entry.allowedUntilHour = allowedUntilAr[3];
+ entry.allowedUntilMin = allowedUntilAr[4];
+ entry.allowedUntilSec = allowedUntilAr[5];
+ }
- if(allowedFromTime.length() > 0)
- {
- entry.allowedFromTimeHour = allowedFromTimeAr[0];
- entry.allowedFromTimeMin = allowedFromTimeAr[1];
- }
+ entry.allowedWeekdays = allowedWeekdaysInt;
- if(allowedUntilTime.length() > 0)
- {
- entry.allowedUntilTimeHour = allowedUntilTimeAr[0];
- entry.allowedUntilTimeMin = allowedUntilTimeAr[1];
+ if(allowedFromTime.length() > 0)
+ {
+ entry.allowedFromTimeHour = allowedFromTimeAr[0];
+ entry.allowedFromTimeMin = allowedFromTimeAr[1];
+ }
+
+ if(allowedUntilTime.length() > 0)
+ {
+ entry.allowedUntilTimeHour = allowedUntilTimeAr[0];
+ entry.allowedUntilTimeMin = allowedUntilTimeAr[1];
+ }
}
}
+
+ result = _nukiLock.updateKeypadEntry(entry);
+ Log->print(F("Update keypad code: "));
+ Log->println((int)result);
}
-
- result = _nukiLock.updateKeypadEntry(entry);
- Log->print(F("Update keypad code: "));
- Log->println((int)result);
}
- }
- else
- {
- _network->publishKeypadJsonCommandResult("invalidAction");
- return;
+ else
+ {
+ _network->publishKeypadJsonCommandResult("invalidAction");
+ return;
+ }
+
+ if(result != Nuki::CmdResult::Success) {
+ ++retryCount;
+ }
+ else break;
}
- if(result != Nuki::CmdResult::Success)
- {
- ++retryCount;
- }
- else
- {
- break;
- }
- }
+ updateKeypad(false);
- updateKeypad(false);
-
- if((int)result != -1)
- {
- char resultStr[15];
- memset(&resultStr, 0, sizeof(resultStr));
- NukiLock::cmdResultToString(result, resultStr);
- _network->publishKeypadJsonCommandResult(resultStr);
+ if((int)result != -1)
+ {
+ char resultStr[15];
+ memset(&resultStr, 0, sizeof(resultStr));
+ NukiLock::cmdResultToString(result, resultStr);
+ _network->publishKeypadJsonCommandResult(resultStr);
+ }
}
}
else
@@ -3316,7 +3332,7 @@ void NukiWrapper::onTimeControlCommandReceived(const char *value)
if(resultTc == Nuki::CmdResult::Success)
{
- delay(250);
+ delay(5000);
std::list timeControlEntries;
_nukiLock.getTimeControlEntries(&timeControlEntries);
@@ -3446,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;
@@ -3771,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/NukiWrapper.h b/src/NukiWrapper.h
index 72313b9..4cdb937 100644
--- a/src/NukiWrapper.h
+++ b/src/NukiWrapper.h
@@ -108,7 +108,11 @@ private:
int _restartBeaconTimeout = 0; // seconds
bool _publishAuthData = false;
bool _clearAuthData = false;
+ bool _checkKeypadCodes = false;
+ int64_t _invalidCount = 0;
+ int64_t _lastCodeCheck = 0;
std::vector _keypadCodeIds;
+ std::vector _keypadCodes;
std::vector _timeControlIds;
std::vector _authIds;
diff --git a/src/PreferencesKeys.h b/src/PreferencesKeys.h
index 1f5acf6..b01a959 100644
--- a/src/PreferencesKeys.h
+++ b/src/PreferencesKeys.h
@@ -97,6 +97,7 @@
#define preference_publish_debug_info (char*)"pubdbg"
#define preference_official_hybrid_actions (char*)"hybridAct"
#define preference_official_hybrid_retry (char*)"hybridRtry"
+#define preference_keypad_check_code_enabled (char*)"kpChkEna"
//NOT USER CHANGABLE
#define preference_updater_version (char*)"updVer"
@@ -292,7 +293,7 @@ private:
preference_network_custom_rst, preference_network_custom_cs, preference_network_custom_sck, preference_network_custom_miso, preference_network_custom_mosi,
preference_network_custom_pwr, preference_network_custom_mdio, preference_ntw_reconfigure, preference_lock_max_auth_entry_count, preference_opener_max_auth_entry_count,
preference_auth_control_enabled, preference_auth_topic_per_entry, preference_auth_info_enabled, preference_auth_max_entries, preference_wifi_ssid, preference_wifi_pass,
- preference_disable_network_not_connected
+ preference_keypad_check_code_enabled, preference_disable_network_not_connected
};
std::vector _redact =
{
@@ -308,7 +309,7 @@ private:
preference_publish_authdata, preference_publish_debug_info, preference_official_hybrid_enabled,
preference_official_hybrid_actions, preference_official_hybrid_retry, preference_conf_info_enabled, preference_disable_non_json, preference_update_from_mqtt,
preference_auth_control_enabled, preference_auth_topic_per_entry, preference_auth_info_enabled, preference_webserial_enabled,
- preference_ntw_reconfigure, preference_disable_network_not_connected
+ preference_ntw_reconfigure, preference_keypad_check_code_enabled, preference_disable_network_not_connected
};
std::vector _bytePrefs =
{
diff --git a/src/WebCfgServer.cpp b/src/WebCfgServer.cpp
index d681135..7bbaa7f 100644
--- a/src/WebCfgServer.cpp
+++ b/src/WebCfgServer.cpp
@@ -2200,6 +2200,16 @@ bool WebCfgServer::processArgs(PsychicRequest *request, String& message)
//configChanged = true;
}
}
+ else if(key == "KPCHECK")
+ {
+ if(_preferences->getBool(preference_keypad_check_code_enabled, false) != (value == "1"))
+ {
+ _preferences->putBool(preference_keypad_check_code_enabled, (value == "1"));
+ Log->print(F("Setting changed: "));
+ Log->println(key);
+ //configChanged = true;
+ }
+ }
else if(key == "KPENA")
{
if(_preferences->getBool(preference_keypad_control_enabled, false) != (value == "1"))
@@ -3379,15 +3389,15 @@ esp_err_t WebCfgServer::buildCredHtml(PsychicRequest *request)
PsychicStreamResponse response(request, "text/plain");
response.beginSend();
buildHtmlHeader(&response);
- response.print("");
+ response.print("");
if(_nuki != nullptr)
{
response.print("