Merge branch 'technyon:master' into update-wifimanager
This commit is contained in:
41
README.md
41
README.md
@@ -10,7 +10,7 @@ It exposes the lock state (and much more) through MQTT and allows executing comm
|
||||
|
||||
***Nuki Hub does not integrate with the Nuki mobile app, it can't register itself as a bridge in the official Nuki mobile app.***
|
||||
|
||||
Feel free to join us on Discord: https://discord.gg/feB9FnMY
|
||||
Feel free to join us on Discord: https://discord.gg/24HxpGBJ
|
||||
|
||||
## Supported devices
|
||||
|
||||
@@ -157,16 +157,16 @@ In a browser navigate to the IP address assigned to the ESP32.
|
||||
#### Nuki General Access Control
|
||||
- Publish keypad codes 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
|
||||
- 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
|
||||
- Publish time control information: Enable to publish information about time control entries through MQTT, see the "Time control" section of this README
|
||||
- Add, modify and delete time control entries: Enable to allow configuration of time control entries through MQTT, see the "Time control" section of this README
|
||||
- Publish auth data: Enable to publish authorization data to the MQTT topic lock/log. Requires the Nuki security code / PIN to be set, see "Nuki Lock PIN / Nuki Opener PIN" below.
|
||||
- Publish time control information: Enable to publish information about time control entries through MQTT, see the "[Time Control](#time-control)" section of this README
|
||||
- Add, modify and delete time control entries: Enable to allow configuration of time control entries through MQTT, see the "[Time Control](#time-control)" section of this README
|
||||
- Publish auth data: Enable to publish authorization data to the MQTT topic lock/log. Requires the Nuki security code / PIN to be set, see "[Nuki Lock PIN / Nuki Opener PIN](#nuki-lock-pin--nuki-opener-pin)" below.
|
||||
|
||||
#### Nuki Lock/Opener Access Control
|
||||
- Enable or disable executing each available lock action for the Nuki Lock and Nuki Opener through MQTT. Note: GPIO control is not restricted through this setting.
|
||||
|
||||
#### Nuki Lock/Opener Config Control
|
||||
- Enable or disable changing each available configuration setting for the Nuki Lock and Nuki Opener through MQTT.
|
||||
- NOTE: Changing configuration settings requires the Nuki security code / PIN to be set, see "Nuki Lock PIN / Nuki Opener PIN" below.
|
||||
- NOTE: Changing configuration settings requires the Nuki security code / PIN to be set, see "[Nuki Lock PIN / Nuki Opener PIN](#nuki-lock-pin--nuki-opener-pin)" below.
|
||||
|
||||
### Credentials
|
||||
|
||||
@@ -185,7 +185,7 @@ In a browser navigate to the IP address assigned to the ESP32.
|
||||
|
||||
### GPIO Configuration
|
||||
|
||||
- Gpio [2-33]: See the "GPIO lock control" section of this README.
|
||||
- Gpio [2-33]: See the "[GPIO lock control](#gpio-lock-control-optional)" section of this README.
|
||||
|
||||
## Exposed MQTT Topics
|
||||
|
||||
@@ -269,7 +269,7 @@ In a browser navigate to the IP address assigned to the ESP32.
|
||||
|
||||
### Time Control
|
||||
|
||||
- See the "Time control" section of this README.
|
||||
- See the "[Time Control](#time-control)" section of this README.
|
||||
|
||||
### Info
|
||||
|
||||
@@ -391,7 +391,7 @@ Example usage for changing multiple settings at once:<br>
|
||||
The result of the last configuration change action will be published to the `configuration/commandResult` MQTT topic as JSON data.<br>
|
||||
<br>
|
||||
The JSON data will include a node called "general" and a node for every setting that Nuki Hub detected in the action.<br>
|
||||
Possible values for the "general" node are "noPinSet", "invalidJson", "invalidConfig", "success" and "noChange".<br>
|
||||
Possible values for the "general" node are "noValidPinSet", "invalidJson", "invalidConfig", "success" and "noChange".<br>
|
||||
Possible values for the node per setting are "unchanged", "noValueSet", "invalidValue", "valueTooLong", "accessDenied", "success", "failed", "timeOut", "working", "notPaired", "error" and "undefined"<br>
|
||||
<br>
|
||||
Example:
|
||||
@@ -416,8 +416,25 @@ To enable SSL encryption, supply the necessary information in the MQTT Configura
|
||||
The following configurations are supported:<br>
|
||||
CA, CERT and KEY are empty -> No encryption<br>
|
||||
CA is filled but CERT and KEY are empty -> Encrypted MQTT<br>
|
||||
CA, CERT and KEY are filled -> Encrypted MQTT with client vaildation
|
||||
CA, CERT and KEY are filled -> Encrypted MQTT with client vaildation<br>
|
||||
<br>
|
||||
Example certificate creation for your MQTT server:
|
||||
```console
|
||||
# make a ca key
|
||||
openssl genpkey -algorithm RSA -out ca.key
|
||||
|
||||
# make a CA cert
|
||||
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt -subj "/C=US/ST=YourState/L=YourCity/O=YourOrganization/OU=YourUnit/CN=YourCAName"
|
||||
|
||||
# make a server key
|
||||
openssl genpkey -algorithm RSA -out server.key
|
||||
|
||||
# Make a sign request, MAKE SURE THE CN MATCHES YOUR MQTT SERVERNAME
|
||||
openssl req -new -key server.key -out server.csr -subj "/C=US/ST=YourState/L=YourCity/O=YourOrganization/OU=YourUnit/CN=homeserver.local"
|
||||
|
||||
# sign it
|
||||
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 3650
|
||||
```
|
||||
## Home Assistant Discovery (optional)
|
||||
|
||||
This software supports [MQTT Discovery](https://www.home-assistant.io/docs/mqtt/discovery/) for integrating Nuki Hub with Home Assistant.<br>
|
||||
@@ -448,7 +465,7 @@ To change Nuki Lock/Opener keypad settings set the `keypad/actionJson` topic to
|
||||
|------------------|----------|----------|----------|------------------------------------------------------------------------------------------------------------------|----------------------------------------|
|
||||
| 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 | Required | The code to create or update | 6-digit Integer without zero's, can't start with "12"|
|
||||
| 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, disabled if not set on update | 1 = enabled, 0 = disabled |
|
||||
| name | Not used | Required | Required | 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, disabled if not set (requires enabled = 1) | 1 = enabled, 0 = disabled |
|
||||
@@ -461,12 +478,12 @@ To change Nuki Lock/Opener keypad settings set the `keypad/actionJson` topic to
|
||||
Examples:
|
||||
- Delete: `{ "action": "delete", "codeId": "1234" }`
|
||||
- Add: `{ "action": "add", "code": "589472", "name": "Test", "timeLimited": "1", "allowedFrom": "2024-04-12 10:00:00", "allowedUntil": "2034-04-12 10:00:00", "allowedWeekdays": [ "wed", "thu", "fri" ], "allowedFromTime": "08:00", "allowedUntilTime": "16:00" }`
|
||||
- Update: `{ "action": "update", "codeId": "1234", "code": "589472", "enabled": "1", "name": "Test", "timeLimited": "1", "allowedFrom": "2024-04-12 10:00:00", "allowedUntil": "2034-04-12 10:00:00", "allowedWeekdays": [ "mon", "tue", "sat", "sun" ], "allowedFromTime": "08:00", "allowedUntilTime": "16:00" }`
|
||||
- Update: `{ "action": "update", "codeId": "1234", "enabled": "1", "name": "Test", "timeLimited": "1", "allowedFrom": "2024-04-12 10:00:00", "allowedUntil": "2034-04-12 10:00:00", "allowedWeekdays": [ "mon", "tue", "sat", "sun" ], "allowedFromTime": "08:00", "allowedUntilTime": "16:00" }`
|
||||
|
||||
### Result of attempted keypad code changes
|
||||
|
||||
The result of the last configuration change action will be published to the `configuration/commandResultJson` MQTT topic.<br>
|
||||
Possible values are "noPinSet", "keypadControlDisabled", "keypadNotAvailable", "keypadDisabled", "invalidConfig", "invalidJson", "noActionSet", "invalidAction", "noExistingCodeIdSet", "noNameSet", "noValidCodeSet", "noCodeSet", "invalidAllowedFrom", "invalidAllowedUntil", "invalidAllowedFromTime", "invalidAllowedUntilTime", "success", "failed", "timeOut", "working", "notPaired", "error" and "undefined".<br>
|
||||
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".<br>
|
||||
|
||||
## Keypad control (alternative, optional)
|
||||
|
||||
|
||||
@@ -24,14 +24,6 @@ build_flags =
|
||||
-DESP_PLATFORM
|
||||
-DESP32
|
||||
-DARDUINO_ARCH_ESP32
|
||||
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_NONE
|
||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=0
|
||||
; -DDEBUG_SENSE_NUKI
|
||||
; -DDEBUG_NUKI_COMMAND
|
||||
; -DDEBUG_NUKI_CONNECT
|
||||
; -DDEBUG_NUKI_COMMUNICATION
|
||||
; -DDEBUG_NUKI_HEX_DATA
|
||||
; -DDEBUG_NUKI_READABLE_DATA
|
||||
lib_deps =
|
||||
|
||||
monitor_speed = 115200
|
||||
@@ -41,9 +33,17 @@ monitor_filters =
|
||||
|
||||
[env:esp32dev]
|
||||
board = esp32dev
|
||||
build_flags =
|
||||
${env.build_flags}
|
||||
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_NONE
|
||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=0
|
||||
|
||||
[env:esp32-c3]
|
||||
board = esp32-c3-devkitc-02
|
||||
build_flags =
|
||||
${env.build_flags}
|
||||
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_NONE
|
||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=0
|
||||
|
||||
[env:esp32solo1]
|
||||
platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.10.03/platform-espressif32-2023.10.03.zip
|
||||
@@ -51,51 +51,70 @@ board = esp32-solo1
|
||||
build_flags =
|
||||
${env.build_flags}
|
||||
-DFRAMEWORK_ARDUINO_SOLO1
|
||||
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_NONE
|
||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=0
|
||||
|
||||
[env:esp32-s3]
|
||||
board = esp32-s3-devkitc-1
|
||||
|
||||
[env:esp32dev_dbg]
|
||||
extends = env:esp32dev
|
||||
build_flags =
|
||||
${env.build_flags}
|
||||
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_NONE
|
||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=0
|
||||
|
||||
[env:esp32dev_dbg]
|
||||
board = esp32dev
|
||||
build_flags =
|
||||
${env.build_flags}
|
||||
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=4
|
||||
-DDEBUG_NUKIHUB
|
||||
-DDEBUG_SENSE_NUKI
|
||||
-DDEBUG_NUKI_COMMAND
|
||||
-DDEBUG_NUKI_CONNECT
|
||||
-DDEBUG_NUKI_COMMUNICATION
|
||||
-DDEBUG_NUKI_HEX_DATA
|
||||
;-DDEBUG_NUKI_HEX_DATA
|
||||
-DDEBUG_NUKI_READABLE_DATA
|
||||
|
||||
[env:esp32-s3_dbg]
|
||||
extends = env:esp32-s3
|
||||
board = esp32-s3-devkitc-1
|
||||
build_flags =
|
||||
${env.build_flags}
|
||||
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=4
|
||||
-DDEBUG_NUKIHUB
|
||||
-DDEBUG_SENSE_NUKI
|
||||
-DDEBUG_NUKI_COMMAND
|
||||
-DDEBUG_NUKI_CONNECT
|
||||
-DDEBUG_NUKI_COMMUNICATION
|
||||
-DDEBUG_NUKI_HEX_DATA
|
||||
;-DDEBUG_NUKI_HEX_DATA
|
||||
-DDEBUG_NUKI_READABLE_DATA
|
||||
|
||||
[env:esp32-c3_dbg]
|
||||
extends = env:esp32-c3
|
||||
board = esp32-c3-devkitc-02
|
||||
build_flags =
|
||||
${env.build_flags}
|
||||
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=4
|
||||
-DDEBUG_NUKIHUB
|
||||
-DDEBUG_SENSE_NUKI
|
||||
-DDEBUG_NUKI_COMMAND
|
||||
-DDEBUG_NUKI_CONNECT
|
||||
-DDEBUG_NUKI_COMMUNICATION
|
||||
-DDEBUG_NUKI_HEX_DATA
|
||||
;-DDEBUG_NUKI_HEX_DATA
|
||||
-DDEBUG_NUKI_READABLE_DATA
|
||||
|
||||
[env:esp32solo1_dbg]
|
||||
extends = env:esp32solo1
|
||||
platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.10.03/platform-espressif32-2023.10.03.zip
|
||||
board = esp32-solo1
|
||||
build_flags =
|
||||
${env.build_flags}
|
||||
-DFRAMEWORK_ARDUINO_SOLO1
|
||||
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=4
|
||||
-DDEBUG_NUKIHUB
|
||||
-DDEBUG_SENSE_NUKI
|
||||
-DDEBUG_NUKI_COMMAND
|
||||
-DDEBUG_NUKI_CONNECT
|
||||
-DDEBUG_NUKI_COMMUNICATION
|
||||
-DDEBUG_NUKI_HEX_DATA
|
||||
;-DDEBUG_NUKI_HEX_DATA
|
||||
-DDEBUG_NUKI_READABLE_DATA
|
||||
@@ -198,7 +198,7 @@ void NetworkLock::onMqttDataReceived(const char* topic, byte* payload, const uns
|
||||
if(comparePrefixedPath(topic, mqtt_topic_config_action))
|
||||
{
|
||||
if(strcmp(value, "") == 0 || strcmp(value, "--") == 0) return;
|
||||
|
||||
|
||||
if(_configUpdateReceivedCallback != NULL)
|
||||
{
|
||||
_configUpdateReceivedCallback(value);
|
||||
@@ -264,7 +264,7 @@ void NetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyTurne
|
||||
}
|
||||
|
||||
json["trigger"] = str;
|
||||
|
||||
|
||||
char curTime[20];
|
||||
sprintf(curTime, "%04d-%02d-%02d %02d:%02d:%02d", keyTurnerState.currentTimeYear, keyTurnerState.currentTimeMonth, keyTurnerState.currentTimeDay, keyTurnerState.currentTimeHour, keyTurnerState.currentTimeMinute, keyTurnerState.currentTimeSecond);
|
||||
json["currentTime"] = curTime;
|
||||
@@ -374,11 +374,8 @@ void NetworkLock::publishState(NukiLock::LockState lockState)
|
||||
void NetworkLock::publishAuthorizationInfo(const std::list<NukiLock::LogEntry>& logEntries)
|
||||
{
|
||||
char str[50];
|
||||
|
||||
_authId = 0;
|
||||
memset(_authName, 0, sizeof(_authName));
|
||||
_authName[0] = '\0';
|
||||
_authFound = false;
|
||||
char authName[33];
|
||||
bool authFound = false;
|
||||
|
||||
JsonDocument json;
|
||||
|
||||
@@ -390,20 +387,31 @@ void NetworkLock::publishAuthorizationInfo(const std::list<NukiLock::LogEntry>&
|
||||
break;
|
||||
}
|
||||
--i;
|
||||
if((log.loggingType == NukiLock::LoggingType::LockAction || log.loggingType == NukiLock::LoggingType::KeypadAction) && ! _authFound)
|
||||
|
||||
memset(authName, 0, sizeof(authName));
|
||||
authName[0] = '\0';
|
||||
|
||||
if((log.loggingType == NukiLock::LoggingType::LockAction || log.loggingType == NukiLock::LoggingType::KeypadAction))
|
||||
{
|
||||
_authFound = true;
|
||||
_authId = log.authId;
|
||||
int sizeName = sizeof(log.name);
|
||||
memcpy(_authName, log.name, sizeName);
|
||||
if(_authName[sizeName - 1] != '\0') _authName[sizeName] = '\0';
|
||||
memcpy(authName, log.name, sizeName);
|
||||
if(authName[sizeName - 1] != '\0') authName[sizeName] = '\0';
|
||||
|
||||
if(!authFound)
|
||||
{
|
||||
authFound = true;
|
||||
_authFound = true;
|
||||
_authId = log.authId;
|
||||
memset(_authName, 0, sizeof(_authName));
|
||||
memcpy(_authName, authName, sizeof(authName));
|
||||
}
|
||||
}
|
||||
|
||||
auto entry = json.add<JsonVariant>();
|
||||
|
||||
entry["index"] = log.index;
|
||||
entry["authorizationId"] = log.authId;
|
||||
entry["authorizationName"] = _authName;
|
||||
entry["authorizationName"] = authName;
|
||||
entry["timeYear"] = log.timeStampYear;
|
||||
entry["timeMonth"] = log.timeStampMonth;
|
||||
entry["timeDay"] = log.timeStampDay;
|
||||
@@ -469,7 +477,7 @@ void NetworkLock::publishAuthorizationInfo(const std::list<NukiLock::LogEntry>&
|
||||
serializeJson(json, _buffer, _bufferSize);
|
||||
publishString(mqtt_topic_lock_log, _buffer);
|
||||
|
||||
if(_authFound)
|
||||
if(authFound)
|
||||
{
|
||||
publishUInt(mqtt_topic_lock_auth_id, _authId);
|
||||
publishString(mqtt_topic_lock_auth_name, _authName);
|
||||
|
||||
@@ -265,7 +265,7 @@ void NetworkOpener::publishKeyTurnerState(const NukiOpener::OpenerState& keyTurn
|
||||
}
|
||||
|
||||
json["trigger"] = str;
|
||||
|
||||
|
||||
json["ringToOpenTimer"] = keyTurnerState.ringToOpenTimer;
|
||||
char curTime[20];
|
||||
sprintf(curTime, "%04d-%02d-%02d %02d:%02d:%02d", keyTurnerState.currentTimeYear, keyTurnerState.currentTimeMonth, keyTurnerState.currentTimeDay, keyTurnerState.currentTimeHour, keyTurnerState.currentTimeMinute, keyTurnerState.currentTimeSecond);
|
||||
@@ -372,11 +372,8 @@ void NetworkOpener::publishState(NukiOpener::OpenerState lockState)
|
||||
void NetworkOpener::publishAuthorizationInfo(const std::list<NukiOpener::LogEntry>& logEntries)
|
||||
{
|
||||
char str[50];
|
||||
|
||||
_authId = 0;
|
||||
memset(_authName, 0, sizeof(_authName));
|
||||
_authName[0] = '\0';
|
||||
_authFound = false;
|
||||
char authName[33];
|
||||
bool authFound = false;
|
||||
|
||||
JsonDocument json;
|
||||
|
||||
@@ -389,13 +386,23 @@ void NetworkOpener::publishAuthorizationInfo(const std::list<NukiOpener::LogEntr
|
||||
}
|
||||
--i;
|
||||
|
||||
if((log.loggingType == NukiOpener::LoggingType::LockAction || log.loggingType == NukiOpener::LoggingType::KeypadAction) && ! _authFound)
|
||||
memset(authName, 0, sizeof(authName));
|
||||
authName[0] = '\0';
|
||||
|
||||
if((log.loggingType == NukiOpener::LoggingType::LockAction || log.loggingType == NukiOpener::LoggingType::KeypadAction))
|
||||
{
|
||||
_authFound = true;
|
||||
_authId = log.authId;
|
||||
int sizeName = sizeof(log.name);
|
||||
memcpy(_authName, log.name, sizeName);
|
||||
if(_authName[sizeName - 1] != '\0') _authName[sizeName] = '\0';
|
||||
memcpy(authName, log.name, sizeName);
|
||||
if(authName[sizeName - 1] != '\0') authName[sizeName] = '\0';
|
||||
|
||||
if(!authFound)
|
||||
{
|
||||
authFound = true;
|
||||
_authFound = true;
|
||||
_authId = log.authId;
|
||||
memset(_authName, 0, sizeof(_authName));
|
||||
memcpy(_authName, authName, sizeof(authName));
|
||||
}
|
||||
}
|
||||
|
||||
auto entry = json.add<JsonVariant>();
|
||||
@@ -493,7 +500,7 @@ void NetworkOpener::publishAuthorizationInfo(const std::list<NukiOpener::LogEntr
|
||||
serializeJson(json, _buffer, _bufferSize);
|
||||
publishString(mqtt_topic_lock_log, _buffer);
|
||||
|
||||
if(_authFound)
|
||||
if(authFound)
|
||||
{
|
||||
publishUInt(mqtt_topic_lock_auth_id, _authId);
|
||||
publishString(mqtt_topic_lock_auth_name, _authName);
|
||||
@@ -888,7 +895,7 @@ void NetworkOpener::publishStatusUpdated(const bool statusUpdated)
|
||||
{
|
||||
publishBool(mqtt_topic_lock_status_updated, statusUpdated);
|
||||
}
|
||||
|
||||
|
||||
void NetworkOpener::setLockActionReceivedCallback(LockActionResult (*lockActionReceivedCallback)(const char *))
|
||||
{
|
||||
_lockActionReceivedCallback = lockActionReceivedCallback;
|
||||
|
||||
@@ -306,6 +306,11 @@ bool NukiOpenerWrapper::isPinSet()
|
||||
return _nukiOpener.getSecurityPincode() != 0;
|
||||
}
|
||||
|
||||
bool NukiOpenerWrapper::isPinValid()
|
||||
{
|
||||
return _preferences->getInt(preference_opener_pin_status, 4) == 1;
|
||||
}
|
||||
|
||||
void NukiOpenerWrapper::setPin(const uint16_t pin)
|
||||
{
|
||||
_nukiOpener.saveSecurityPincode(pin);
|
||||
@@ -374,15 +379,18 @@ void NukiOpenerWrapper::updateKeyTurnerState()
|
||||
|
||||
if(_publishAuthData)
|
||||
{
|
||||
Log->println(F("Publishing auth data"));
|
||||
updateAuthData();
|
||||
Log->println(F("Done publishing auth data"));
|
||||
}
|
||||
|
||||
postponeBleWatchdog();
|
||||
Log->println(F("Done querying lock state"));
|
||||
}
|
||||
|
||||
void NukiOpenerWrapper::updateBatteryState()
|
||||
{
|
||||
Log->print("Querying opener battery state: ");
|
||||
Log->print(F("Querying opener battery state: "));
|
||||
Nuki::CmdResult result = _nukiOpener.requestBatteryReport(&_batteryReport);
|
||||
printCommandResult(result);
|
||||
if(result == Nuki::CmdResult::Success)
|
||||
@@ -390,6 +398,7 @@ void NukiOpenerWrapper::updateBatteryState()
|
||||
_network->publishBatteryReport(_batteryReport);
|
||||
}
|
||||
postponeBleWatchdog();
|
||||
Log->println(F("Done querying lock battery state"));
|
||||
}
|
||||
|
||||
void NukiOpenerWrapper::updateConfig()
|
||||
@@ -471,27 +480,28 @@ void NukiOpenerWrapper::updateConfig()
|
||||
|
||||
void NukiOpenerWrapper::updateAuthData()
|
||||
{
|
||||
if(!isPinSet()) return;
|
||||
if(!isPinValid())
|
||||
{
|
||||
Log->println(F("No valid PIN set"));
|
||||
return;
|
||||
}
|
||||
|
||||
Nuki::CmdResult result = _nukiOpener.retrieveLogEntries(0, 0, 0, true);
|
||||
Nuki::CmdResult result = _nukiOpener.retrieveLogEntries(0, 5, 1, false);
|
||||
Log->print(F("Retrieve log entries: "));
|
||||
Log->println(result);
|
||||
if(result != Nuki::CmdResult::Success)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
delay(100);
|
||||
|
||||
uint16_t count = _nukiOpener.getLogEntryCount();
|
||||
|
||||
result = _nukiOpener.retrieveLogEntries(0, count < 5 ? count : 5, 1, false);
|
||||
if(result != Nuki::CmdResult::Success)
|
||||
{
|
||||
return;
|
||||
}
|
||||
delay(1000);
|
||||
|
||||
std::list<NukiOpener::LogEntry> log;
|
||||
_nukiOpener.getLogEntries(&log);
|
||||
|
||||
Log->print(F("Log size: "));
|
||||
Log->println(log.size());
|
||||
|
||||
if(log.size() > 0)
|
||||
{
|
||||
_network->publishAuthorizationInfo(log);
|
||||
@@ -527,9 +537,12 @@ void NukiOpenerWrapper::updateKeypad()
|
||||
|
||||
_keypadCodeIds.clear();
|
||||
_keypadCodeIds.reserve(entries.size());
|
||||
_keypadCodes.clear();
|
||||
_keypadCodes.reserve(entries.size());
|
||||
for(const auto& entry : entries)
|
||||
{
|
||||
_keypadCodeIds.push_back(entry.codeId);
|
||||
_keypadCodes.push_back(entry.code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -781,9 +794,9 @@ void NukiOpenerWrapper::onConfigUpdateReceived(const char *value)
|
||||
return;
|
||||
}
|
||||
|
||||
if(!isPinSet())
|
||||
if(!isPinValid())
|
||||
{
|
||||
jsonResult["general"] = "noPinSet";
|
||||
jsonResult["general"] = "noValidPinSet";
|
||||
serializeJson(jsonResult, _resbuf, sizeof(_resbuf));
|
||||
_network->publishConfigCommandResult(_resbuf);
|
||||
return;
|
||||
@@ -1413,9 +1426,9 @@ void NukiOpenerWrapper::onKeypadCommandReceived(const char *command, const uint
|
||||
|
||||
void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
{
|
||||
if(!isPinSet())
|
||||
if(!isPinValid())
|
||||
{
|
||||
_network->publishKeypadJsonCommandResult("noPinSet");
|
||||
_network->publishKeypadJsonCommandResult("noValidPinSet");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1480,7 +1493,7 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
if(idExists)
|
||||
{
|
||||
result = _nukiOpener.deleteKeypadEntry(codeId);
|
||||
Log->print("Delete keypad code: ");
|
||||
Log->print(F("Delete keypad code: "));
|
||||
Log->println((int)result);
|
||||
}
|
||||
else
|
||||
@@ -1507,7 +1520,7 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (strcmp(action, "update") != 0)
|
||||
{
|
||||
_network->publishKeypadJsonCommandResult("noCodeSet");
|
||||
return;
|
||||
@@ -1666,7 +1679,7 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
}
|
||||
|
||||
result = _nukiOpener.addKeypadEntry(entry);
|
||||
Log->print("Add keypad code: ");
|
||||
Log->print(F("Add keypad code: "));
|
||||
Log->println((int)result);
|
||||
}
|
||||
else if (strcmp(action, "update") == 0)
|
||||
@@ -1688,7 +1701,14 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
entry.codeId = codeId;
|
||||
size_t nameLen = strlen(name);
|
||||
memcpy(&entry.name, name, nameLen > 20 ? 20 : nameLen);
|
||||
entry.code = code;
|
||||
|
||||
if(code) entry.code = code;
|
||||
else
|
||||
{
|
||||
auto it = std::find(_keypadCodeIds.begin(), _keypadCodeIds.end(), codeId);
|
||||
entry.code = _keypadCodes[(it - _keypadCodeIds.begin())];
|
||||
}
|
||||
|
||||
entry.enabled = enabled == 0 ? 0 : 1;
|
||||
entry.timeLimited = timeLimited == 1 ? 1 : 0;
|
||||
|
||||
@@ -1727,7 +1747,7 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
}
|
||||
|
||||
result = _nukiOpener.updateKeypadEntry(entry);
|
||||
Log->print("Update keypad code: ");
|
||||
Log->print(F("Update keypad code: "));
|
||||
Log->println((int)result);
|
||||
}
|
||||
}
|
||||
@@ -1762,9 +1782,9 @@ void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value)
|
||||
return;
|
||||
}
|
||||
|
||||
if(!isPinSet())
|
||||
if(!isPinValid())
|
||||
{
|
||||
_network->publishTimeControlCommandResult("noPinSet");
|
||||
_network->publishTimeControlCommandResult("noValidPinSet");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1817,7 +1837,7 @@ void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value)
|
||||
if(idExists)
|
||||
{
|
||||
result = _nukiOpener.removeTimeControlEntry(entryId);
|
||||
Log->print("Delete time control ");
|
||||
Log->print(F("Delete time control "));
|
||||
Log->println((int)result);
|
||||
}
|
||||
else
|
||||
@@ -1882,7 +1902,7 @@ void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value)
|
||||
entry.lockAction = timeControlLockAction;
|
||||
|
||||
result = _nukiOpener.addTimeControlEntry(entry);
|
||||
Log->print("Add time control: ");
|
||||
Log->print(F("Add time control: "));
|
||||
Log->println((int)result);
|
||||
}
|
||||
else if (strcmp(action, "update") == 0)
|
||||
@@ -1908,7 +1928,7 @@ void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value)
|
||||
entry.lockAction = timeControlLockAction;
|
||||
|
||||
result = _nukiOpener.updateTimeControlEntry(entry);
|
||||
Log->print("Update time control: ");
|
||||
Log->print(F("Update time control: "));
|
||||
Log->println((int)result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ public:
|
||||
void deactivateCM();
|
||||
|
||||
bool isPinSet();
|
||||
bool isPinValid();
|
||||
void setPin(const uint16_t pin);
|
||||
|
||||
void unpair();
|
||||
@@ -106,6 +107,7 @@ private:
|
||||
int _retryLockstateCount = 0;
|
||||
unsigned long _nextRetryTs = 0;
|
||||
std::vector<uint16_t> _keypadCodeIds;
|
||||
std::vector<uint32_t> _keypadCodes;
|
||||
std::vector<uint8_t> _timeControlIds;
|
||||
|
||||
NukiOpener::OpenerState _lastKeyTurnerState;
|
||||
|
||||
@@ -310,6 +310,11 @@ bool NukiWrapper::isPinSet()
|
||||
return _nukiLock.getSecurityPincode() != 0;
|
||||
}
|
||||
|
||||
bool NukiWrapper::isPinValid()
|
||||
{
|
||||
return _preferences->getInt(preference_lock_pin_status, 4) == 1;
|
||||
}
|
||||
|
||||
void NukiWrapper::setPin(const uint16_t pin)
|
||||
{
|
||||
_nukiLock.saveSecurityPincode(pin);
|
||||
@@ -348,7 +353,9 @@ void NukiWrapper::updateKeyTurnerState()
|
||||
|
||||
if(_publishAuthData)
|
||||
{
|
||||
Log->println(F("Publishing auth data"));
|
||||
updateAuthData();
|
||||
Log->println(F("Done publishing auth data"));
|
||||
}
|
||||
|
||||
_network->publishKeyTurnerState(_keyTurnerState, _lastKeyTurnerState);
|
||||
@@ -359,11 +366,12 @@ void NukiWrapper::updateKeyTurnerState()
|
||||
Log->println(lockStateStr);
|
||||
|
||||
postponeBleWatchdog();
|
||||
Log->println(F("Done querying lock state"));
|
||||
}
|
||||
|
||||
void NukiWrapper::updateBatteryState()
|
||||
{
|
||||
Log->print("Querying lock battery state: ");
|
||||
Log->print(F("Querying lock battery state: "));
|
||||
Nuki::CmdResult result = _nukiLock.requestBatteryReport(&_batteryReport);
|
||||
printCommandResult(result);
|
||||
if(result == Nuki::CmdResult::Success)
|
||||
@@ -371,6 +379,7 @@ void NukiWrapper::updateBatteryState()
|
||||
_network->publishBatteryReport(_batteryReport);
|
||||
}
|
||||
postponeBleWatchdog();
|
||||
Log->println(F("Done querying lock battery state"));
|
||||
}
|
||||
|
||||
void NukiWrapper::updateConfig()
|
||||
@@ -452,27 +461,28 @@ void NukiWrapper::updateConfig()
|
||||
|
||||
void NukiWrapper::updateAuthData()
|
||||
{
|
||||
if(!isPinSet()) return;
|
||||
if(!isPinValid())
|
||||
{
|
||||
Log->println(F("No valid PIN set"));
|
||||
return;
|
||||
}
|
||||
|
||||
Nuki::CmdResult result = _nukiLock.retrieveLogEntries(0, 0, 0, true);
|
||||
Nuki::CmdResult result = _nukiLock.retrieveLogEntries(0, 5, 1, false);
|
||||
Log->print(F("Retrieve log entries: "));
|
||||
Log->println(result);
|
||||
if(result != Nuki::CmdResult::Success)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
delay(100);
|
||||
|
||||
uint16_t count = _nukiLock.getLogEntryCount();
|
||||
|
||||
result = _nukiLock.retrieveLogEntries(0, count < 5 ? count : 5, 1, false);
|
||||
if(result != Nuki::CmdResult::Success)
|
||||
{
|
||||
return;
|
||||
}
|
||||
delay(1000);
|
||||
|
||||
std::list<NukiLock::LogEntry> log;
|
||||
_nukiLock.getLogEntries(&log);
|
||||
|
||||
Log->print(F("Log size: "));
|
||||
Log->println(log.size());
|
||||
|
||||
if(log.size() > 0)
|
||||
{
|
||||
_network->publishAuthorizationInfo(log);
|
||||
@@ -508,9 +518,12 @@ void NukiWrapper::updateKeypad()
|
||||
|
||||
_keypadCodeIds.clear();
|
||||
_keypadCodeIds.reserve(entries.size());
|
||||
_keypadCodes.clear();
|
||||
_keypadCodes.reserve(entries.size());
|
||||
for(const auto& entry : entries)
|
||||
{
|
||||
_keypadCodeIds.push_back(entry.codeId);
|
||||
_keypadCodes.push_back(entry.code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -717,9 +730,9 @@ void NukiWrapper::onConfigUpdateReceived(const char *value)
|
||||
return;
|
||||
}
|
||||
|
||||
if(!isPinSet())
|
||||
if(!isPinValid())
|
||||
{
|
||||
jsonResult["general"] = "noPinSet";
|
||||
jsonResult["general"] = "noValidPinSet";
|
||||
serializeJson(jsonResult, _resbuf, sizeof(_resbuf));
|
||||
_network->publishConfigCommandResult(_resbuf);
|
||||
return;
|
||||
@@ -1399,9 +1412,9 @@ void NukiWrapper::onKeypadCommandReceived(const char *command, const uint &id, c
|
||||
|
||||
void NukiWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
{
|
||||
if(!isPinSet())
|
||||
if(!isPinValid())
|
||||
{
|
||||
_network->publishKeypadJsonCommandResult("noPinSet");
|
||||
_network->publishKeypadJsonCommandResult("noValidPinSet");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1466,7 +1479,7 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
if(idExists)
|
||||
{
|
||||
result = _nukiLock.deleteKeypadEntry(codeId);
|
||||
Log->print("Delete keypad code: ");
|
||||
Log->print(F("Delete keypad code: "));
|
||||
Log->println((int)result);
|
||||
}
|
||||
else
|
||||
@@ -1493,7 +1506,7 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (strcmp(action, "update") != 0)
|
||||
{
|
||||
_network->publishKeypadJsonCommandResult("noCodeSet");
|
||||
return;
|
||||
@@ -1652,7 +1665,7 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
}
|
||||
|
||||
result = _nukiLock.addKeypadEntry(entry);
|
||||
Log->print("Add keypad code: ");
|
||||
Log->print(F("Add keypad code: "));
|
||||
Log->println((int)result);
|
||||
}
|
||||
else if (strcmp(action, "update") == 0)
|
||||
@@ -1674,7 +1687,14 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
entry.codeId = codeId;
|
||||
size_t nameLen = strlen(name);
|
||||
memcpy(&entry.name, name, nameLen > 20 ? 20 : nameLen);
|
||||
entry.code = code;
|
||||
|
||||
if(code) entry.code = code;
|
||||
else
|
||||
{
|
||||
auto it = std::find(_keypadCodeIds.begin(), _keypadCodeIds.end(), codeId);
|
||||
entry.code = _keypadCodes[(it - _keypadCodeIds.begin())];
|
||||
}
|
||||
|
||||
entry.enabled = enabled == 0 ? 0 : 1;
|
||||
entry.timeLimited = timeLimited == 1 ? 1 : 0;
|
||||
|
||||
@@ -1713,7 +1733,7 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value)
|
||||
}
|
||||
|
||||
result = _nukiLock.updateKeypadEntry(entry);
|
||||
Log->print("Update keypad code: ");
|
||||
Log->print(F("Update keypad code: "));
|
||||
Log->println((int)result);
|
||||
}
|
||||
}
|
||||
@@ -1748,9 +1768,9 @@ void NukiWrapper::onTimeControlCommandReceived(const char *value)
|
||||
return;
|
||||
}
|
||||
|
||||
if(!isPinSet())
|
||||
if(!isPinValid())
|
||||
{
|
||||
_network->publishTimeControlCommandResult("noPinSet");
|
||||
_network->publishTimeControlCommandResult("noValidPinSet");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1803,7 +1823,7 @@ void NukiWrapper::onTimeControlCommandReceived(const char *value)
|
||||
if(idExists)
|
||||
{
|
||||
result = _nukiLock.removeTimeControlEntry(entryId);
|
||||
Log->print("Delete time control ");
|
||||
Log->print(F("Delete time control: "));
|
||||
Log->println((int)result);
|
||||
}
|
||||
else
|
||||
@@ -1868,7 +1888,7 @@ void NukiWrapper::onTimeControlCommandReceived(const char *value)
|
||||
entry.lockAction = timeControlLockAction;
|
||||
|
||||
result = _nukiLock.addTimeControlEntry(entry);
|
||||
Log->print("Add time control: ");
|
||||
Log->print(F("Add time control: "));
|
||||
Log->println((int)result);
|
||||
}
|
||||
else if (strcmp(action, "update") == 0)
|
||||
@@ -1894,7 +1914,7 @@ void NukiWrapper::onTimeControlCommandReceived(const char *value)
|
||||
entry.lockAction = timeControlLockAction;
|
||||
|
||||
result = _nukiLock.updateTimeControlEntry(entry);
|
||||
Log->print("Update time control: ");
|
||||
Log->print(F("Update time control: "));
|
||||
Log->println((int)result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ public:
|
||||
void lockngounlatch();
|
||||
|
||||
bool isPinSet();
|
||||
bool isPinValid();
|
||||
void setPin(const uint16_t pin);
|
||||
void unpair();
|
||||
|
||||
@@ -94,6 +95,7 @@ private:
|
||||
bool _publishAuthData = false;
|
||||
bool _clearAuthData = false;
|
||||
std::vector<uint16_t> _keypadCodeIds;
|
||||
std::vector<uint32_t> _keypadCodes;
|
||||
std::vector<uint8_t> _timeControlIds;
|
||||
|
||||
NukiLock::KeyTurnerState _lastKeyTurnerState;
|
||||
|
||||
@@ -1555,8 +1555,8 @@ void WebCfgServer::buildInfoHtml(String &response)
|
||||
response.concat(_nuki->hardwareVersion().c_str());
|
||||
response.concat("\nLock paired: ");
|
||||
response.concat(_nuki->isPaired() ? "Yes\n" : "No\n");
|
||||
response.concat("Lock PIN set: ");
|
||||
response.concat(_nuki->isPaired() ? _nuki->isPinSet() ? "Yes\n" : "No\n" : "-\n");
|
||||
response.concat("Lock valid PIN set: ");
|
||||
response.concat(_nuki->isPaired() ? _nuki->isPinValid() ? "Yes\n" : "No\n" : "-\n");
|
||||
response.concat("Lock has door sensor: ");
|
||||
response.concat(_nuki->hasDoorSensor() ? "Yes\n" : "No\n");
|
||||
response.concat("Lock has keypad: ");
|
||||
@@ -1668,8 +1668,8 @@ void WebCfgServer::buildInfoHtml(String &response)
|
||||
response.concat("\nOpener hardware version: ");
|
||||
response.concat(_nukiOpener->hardwareVersion().c_str()); response.concat("\nOpener paired: ");
|
||||
response.concat(_nukiOpener->isPaired() ? "Yes\n" : "No\n");
|
||||
response.concat("Opener PIN set: ");
|
||||
response.concat(_nukiOpener->isPaired() ? _nukiOpener->isPinSet() ? "Yes\n" : "No\n" : "-\n");
|
||||
response.concat("Opener valid PIN set: ");
|
||||
response.concat(_nukiOpener->isPaired() ? _nukiOpener->isPinValid() ? "Yes\n" : "No\n" : "-\n");
|
||||
response.concat("Opener has keypad: ");
|
||||
response.concat(_nukiOpener->hasKeypad() ? "Yes\n" : "No\n");
|
||||
response.concat("Opener ACL (Activate Ring-to-Open): ");
|
||||
|
||||
Reference in New Issue
Block a user