Publish keypad code and rolling log

This commit is contained in:
iranl
2024-05-30 19:36:23 +02:00
parent ff741f7989
commit 58ec4b345c
17 changed files with 213 additions and 131 deletions

View File

@@ -156,7 +156,8 @@ In a browser navigate to the IP address assigned to the ESP32.
### Access Level Configuration
#### 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
- 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
- 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
@@ -204,8 +205,9 @@ In a browser navigate to the IP address assigned to the ESP32.
- lock/binaryState: Reports the current lock state as a string, mostly for use by Home Assistant. Possible values are: locked, unlocked.
- lock/trigger: The trigger of the last action: autoLock, automatic, button, manual, system.
- lock/lastLockAction: Reports the last lock action as a string. Possible values are: Unlock, Lock, Unlatch, LockNgo, LockNgoUnlatch, FullLock, FobAction1, FobAction2, FobAction3, Unknown.
- lock/log: If "Publish auth data" is enabled in the web interface, this topic will be filled with the log of authorization data.
- lock/log: If "Publish auth data" is enabled in the web interface, this topic will be filled with the log of authorization data. By default a maximum of 5 logs are published at a time.
- lock/shortLog: If "Publish auth data" is enabled in the web interface, this topic will be filled with the 3 most recent entries in the log of authorization data, updates faster than lock/log.
- lock/rollingLog: If "Publish auth data" is enabled in the web interface, this topic will be filled with the last log entry from the authorization data. Logs are published in order.
- lock/completionStatus: Status of the last action as reported by Nuki Lock: success, motorBlocked, canceled, tooRecent, busy, lowMotorVoltage, clutchFailure, motorPowerFailure, incompleteFailure, invalidCode, otherError, unknown.
- lock/authorizationId: If enabled in the web interface, this node returns the authorization id of the last lock action.
- lock/authorizationName: If enabled in the web interface, this node returns the authorization name of the last lock action.
@@ -465,7 +467,8 @@ If a keypad is connected to the lock, keypad codes can be added, updated and rem
Information about current keypad codes is published as JSON data to the "keypad/json" MQTT topic.<br>
This needs to be enabled separately by checking "Publish keypad codes information" under "Access Level Configuration" and saving the configuration.
For security reasons, the code itself is not published.
For security reasons, the code itself is not published, unless this is explicitly enabled in the Nuki Hub settings.
By default a maximum of 10 entries are published.
To change Nuki Lock/Opener keypad settings set the `keypad/actionJson` topic to a JSON formatted value containing the following nodes.
@@ -499,8 +502,9 @@ If a keypad is connected to the lock, keypad codes can be added, updated and rem
This has to enabled first in the configuration portal. Check "Add, modify and delete keypad codes" under "Access Level Configuration" and save the configuration.
Information about codes is published under "keypad/code_x", x starting from 0 up the number of configured codes. This needs to be enabled separately by checking "Publish keypad codes information" under "Access Level Configuration" and saving the configuration.
By default a maximum of 10 entries are published.
For security reasons, the code itself is not published. To modify keypad codes, a command
For security reasons, the code itself is not published, unless this is explicitly enabled in the Nuki Hub settings. To modify keypad codes, a command
structure is setup under keypad/command:
- keypad/command/id: The id of an existing code, found under keypad_code_x
@@ -533,6 +537,7 @@ Time control entries can be added, updated and removed. This has to enabled firs
Information about current time control entries is published as JSON data to the "timecontrol/json" MQTT topic.<br>
This needs to be enabled separately by checking "Publish time control entries information" under "Access Level Configuration" and saving the configuration.
By default a maximum of 10 entries are published.
To change Nuki Lock/Opener time control settings set the `timecontrol/actionJson` topic to a JSON formatted value containing the following nodes.

View File

@@ -1,39 +0,0 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the usual convention is to give header files names that end with `.h'.
It is most portable to use only letters, digits, dashes, and underscores in
header file names, and at most one dot.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html

View File

@@ -1,46 +0,0 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.
The source code of each library should be placed in a an own separate directory
("lib/your_library_name/[here are source files]").
For example, see a structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html

View File

@@ -1,6 +1,6 @@
{
"name": "BleScanner",
"version": "1.0.0",
"version": "1.1.0",
"description": "Generic BleScanner using NimBle listening to advertisements. Used by NukiBleEsp32 and EnOcean libraries",
"keywords": "ble esp32 scanner",
"authors": [
@@ -19,7 +19,7 @@
"dependencies": [
{
"name": "NimBLE-Arduino",
"version": "h2zero/NimBLE-Arduino @ ^1.3.8"
"version": "h2zero/NimBLE-Arduino @ ^1.4.0"
}
]
}

View File

@@ -4,4 +4,4 @@ board = esp32dev
framework = arduino
lib_deps =
h2zero/NimBLE-Arduino @ ^1.3.8
h2zero/NimBLE-Arduino @ ^1.4.0

View File

@@ -22,11 +22,14 @@ Scanner::Scanner(int reservedSubscribers) {
void Scanner::initialize(const std::string& deviceName, const bool wantDuplicates, const uint16_t interval, const uint16_t window) {
if (!BLEDevice::getInitialized()) {
if (wantDuplicates) {
// reduce memory footprint, cache is not used anyway
NimBLEDevice::setScanDuplicateCacheSize(10);
}
BLEDevice::init(deviceName);
}
bleScan = BLEDevice::getScan();
bleScan->setAdvertisedDeviceCallbacks(this, wantDuplicates);
bleScan->setActiveScan(true);
bleScan->setInterval(interval);
bleScan->setWindow(window);
}
@@ -36,15 +39,20 @@ void Scanner::update() {
return;
}
bleScan->clearResults();
if (scanDuration == 0) {
// Avoid unbridled growth of results vector
bleScan->setMaxResults(0);
} else {
log_w("Ble scanner max results not 0. Be aware of memory issue due to unbridled growth of results vector");
}
bool result = bleScan->start(scanDuration, nullptr, false);
if (!result) {
scanErrors++;
if (scanErrors % 100 == 0) {
log_w("BLE Scan error (100x)");
}
}
// if (!result) {
// scanErrors++;
// if (scanErrors % 100 == 0) {
// log_w("BLE Scan error (100x)");
// }
// }
}
void Scanner::enableScanning(bool enable) {

View File

@@ -16,6 +16,10 @@
#include <NimBLEDevice.h>
#include "BleInterfaces.h"
// Access to a globally available instance of BleScanner, created when first used
// Note that BLESCANNER.initialize() has to be called somewhere
#define BLESCANNER BleScanner::Scanner::instance()
namespace BleScanner {
class Scanner : public Publisher, BLEAdvertisedDeviceCallbacks {
@@ -23,6 +27,11 @@ class Scanner : public Publisher, BLEAdvertisedDeviceCallbacks {
Scanner(int reservedSubscribers = 10);
~Scanner() = default;
static Scanner& instance() {
static Scanner* scanner = new Scanner(); // only initialized once on first call
return *scanner;
}
/**
* @brief Initializes the BLE scanner
*
@@ -77,7 +86,7 @@ class Scanner : public Publisher, BLEAdvertisedDeviceCallbacks {
void onResult(NimBLEAdvertisedDevice* advertisedDevice) override;
private:
uint32_t scanDuration = 3;
uint32_t scanDuration = 0; //default indefinite scanning time
BLEScan* bleScan = nullptr;
std::vector<Subscriber*> subscribers;
uint16_t scanErrors = 0;

View File

@@ -13,6 +13,8 @@
#define mqtt_topic_lock_last_lock_action "/lock/lastLockAction"
#define mqtt_topic_lock_log "/lock/log"
#define mqtt_topic_lock_log_latest "/lock/shortLog"
#define mqtt_topic_lock_log_rolling "/lock/rollingLog"
#define mqtt_topic_lock_log_rolling_last "lock/lastRollingLog"
#define mqtt_topic_lock_auth_id "/lock/authorizationId"
#define mqtt_topic_lock_auth_name "/lock/authorizationName"
#define mqtt_topic_lock_completionStatus "/lock/completionStatus"

View File

@@ -3023,6 +3023,27 @@ void Network::publishHASSConfigAccessLog(char *deviceType, const char *baseTopic
"",
{ { (char*)"ic", (char*)"mdi:format-list-bulleted" },
{ (char*)"val_tpl", (char*)"{{ (value_json|selectattr('type', 'eq', 'LockAction')|selectattr('action', 'in', ['Lock', 'Unlock', 'Unlatch'])|first|default).authorizationName|default }}" }});
String rollingSate = "~";
rollingSate.concat(mqtt_topic_lock_log_rolling);
const char *rollingStateChr = rollingSate.c_str();
publishHassTopic("sensor",
"rolling_log",
uidString,
"_rolling_log",
"Rolling authorization log",
name,
baseTopic,
String("~") + mqtt_topic_lock_log_rolling,
deviceType,
"",
"",
"diagnostic",
"",
{ { (char*)"ic", (char*)"mdi:format-list-bulleted" },
{ (char*)"json_attr_t", (char*)rollingStateChr },
{ (char*)"val_tpl", (char*)"{{value_json.authorizationId}}" }});
}
void Network::publishHASSConfigKeypad(char *deviceType, const char *baseTopic, char *name, char *uidString)
@@ -3194,6 +3215,7 @@ void Network::removeHASSConfig(char* uidString)
removeHassTopic((char*)"sensor", (char*)"sound_level", uidString);
removeHassTopic((char*)"sensor", (char*)"last_action_authorization", uidString);
removeHassTopic((char*)"sensor", (char*)"keypad_status", uidString);
removeHassTopic((char*)"sensor", (char*)"rolling_log", uidString);
removeHassTopic((char*)"sensor", (char*)"wifi_signal_strength", uidString);
removeHassTopic((char*)"sensor", (char*)"bluetooth_signal_strength", uidString);
removeHassTopic((char*)"binary_sensor", (char*)"continuous_mode", uidString);

View File

@@ -116,6 +116,11 @@ void NetworkLock::initialize()
_network->initTopic(_mqttPath, mqtt_topic_timecontrol_action, "--");
}
if(_preferences->getBool(preference_publish_authdata, false))
{
_network->subscribe(_mqttPath, mqtt_topic_lock_log_rolling_last);
}
_network->addReconnectedCallback([&]()
{
_reconnected = true;
@@ -157,6 +162,13 @@ void NetworkLock::onMqttDataReceived(const char* topic, byte* payload, const uns
delay(200);
restartEsp(RestartReason::RequestedViaMqtt);
}
else if(comparePrefixedPath(topic, mqtt_topic_lock_log_rolling_last))
{
if(strcmp(value, "") == 0 ||
strcmp(value, "--") == 0) return;
if(atoi(value) > 0 && atoi(value) > _lastRollingLog) _lastRollingLog = atoi(value);
}
if(comparePrefixedPath(topic, mqtt_topic_lock_action))
{
@@ -439,7 +451,7 @@ void NetworkLock::publishAuthorizationInfo(const std::list<NukiLock::LogEntry>&
{
char str[50];
char authName[33];
bool authFound = false;
uint32_t authIndex = 0;
JsonDocument json;
@@ -454,9 +466,9 @@ void NetworkLock::publishAuthorizationInfo(const std::list<NukiLock::LogEntry>&
memcpy(authName, log.name, sizeName);
if(authName[sizeName - 1] != '\0') authName[sizeName] = '\0';
if(!authFound)
if(log.index > authIndex)
{
authFound = true;
authIndex = log.index;
_authFound = true;
_authId = log.authId;
memset(_authName, 0, sizeof(_authName));
@@ -531,6 +543,14 @@ void NetworkLock::publishAuthorizationInfo(const std::list<NukiLock::LogEntry>&
entry["completionStatus"] = str;
break;
}
if(log.index > _lastRollingLog)
{
_lastRollingLog = log.index;
serializeJson(entry, _buffer, _bufferSize);
publishString(mqtt_topic_lock_log_rolling, _buffer);
publishInt(mqtt_topic_lock_log_rolling_last, log.index);
}
}
serializeJson(json, _buffer, _bufferSize);
@@ -538,7 +558,7 @@ void NetworkLock::publishAuthorizationInfo(const std::list<NukiLock::LogEntry>&
if(latest) publishString(mqtt_topic_lock_log_latest, _buffer);
else publishString(mqtt_topic_lock_log, _buffer);
if(authFound)
if(authIndex > 0)
{
publishUInt(mqtt_topic_lock_auth_id, _authId);
publishString(mqtt_topic_lock_auth_name, _authName);
@@ -735,6 +755,12 @@ void NetworkLock::publishKeypad(const std::list<NukiLock::KeypadEntry>& entries,
auto jsonEntry = json.add<JsonVariant>();
jsonEntry["codeId"] = entry.codeId;
if(_preferences->getBool(preference_keypad_publish_code, false))
{
jsonEntry["code"] = entry.code;
}
jsonEntry["enabled"] = entry.enabled;
jsonEntry["name"] = entry.name;
char createdDT[20];
@@ -826,6 +852,19 @@ void NetworkLock::publishKeypad(const std::list<NukiLock::KeypadEntry>& entries,
++index;
}
if(!_preferences->getBool(preference_keypad_publish_code, false))
{
for(int i=0; i<maxKeypadCodeCount; i++)
{
String codeTopic = _mqttPath;
codeTopic.concat(mqtt_topic_keypad);
codeTopic.concat("/code_");
codeTopic.concat(std::to_string(i).c_str());
codeTopic.concat("/");
_network->removeTopic(codeTopic, "code");
}
}
}
else if (maxKeypadCodeCount > 0)
{
@@ -838,6 +877,7 @@ void NetworkLock::publishKeypad(const std::list<NukiLock::KeypadEntry>& entries,
codeTopic.concat("/");
_network->removeTopic(codeTopic, "id");
_network->removeTopic(codeTopic, "enabled");
_network->removeTopic(codeTopic, "code");
_network->removeTopic(codeTopic, "name");
_network->removeTopic(codeTopic, "createdYear");
_network->removeTopic(codeTopic, "createdMonth");
@@ -1028,6 +1068,7 @@ void NetworkLock::publishHASSConfig(char *deviceType, const char *baseTopic, cha
else
{
_network->removeHASSConfigTopic((char*)"sensor", (char*)"last_action_authorization", uidString);
_network->removeHASSConfigTopic((char*)"sensor", (char*)"rolling_log", uidString);
}
if(hasKeypad)
@@ -1098,6 +1139,12 @@ void NetworkLock::publishKeypadEntry(const String topic, NukiLock::KeypadEntry e
publishInt(concat(topic, "/id").c_str(), entry.codeId);
publishBool(concat(topic, "/enabled").c_str(), entry.enabled);
publishString(concat(topic, "/name").c_str(), codeName);
if(_preferences->getBool(preference_keypad_publish_code, false))
{
publishInt(concat(topic, "/code").c_str(), entry.code);
}
publishInt(concat(topic, "/createdYear").c_str(), entry.dateCreatedYear);
publishInt(concat(topic, "/createdMonth").c_str(), entry.dateCreatedMonth);
publishInt(concat(topic, "/createdDay").c_str(), entry.dateCreatedDay);

View File

@@ -92,6 +92,7 @@ private:
uint32_t _authId = 0;
char _authName[33];
bool _authFound = false;
uint32_t _lastRollingLog = 0;
char* _buffer;
size_t _bufferSize;

View File

@@ -97,6 +97,11 @@ void NetworkOpener::initialize()
_network->initTopic(_mqttPath, mqtt_topic_timecontrol_action, "--");
}
if(_preferences->getBool(preference_publish_authdata, false))
{
_network->subscribe(_mqttPath, mqtt_topic_lock_log_rolling_last);
}
_network->addReconnectedCallback([&]()
{
_reconnected = true;
@@ -116,6 +121,14 @@ void NetworkOpener::onMqttDataReceived(const char* topic, byte* payload, const u
{
char* value = (char*)payload;
if(comparePrefixedPath(topic, mqtt_topic_lock_log_rolling_last))
{
if(strcmp(value, "") == 0 ||
strcmp(value, "--") == 0) return;
if(atoi(value) > 0 && atoi(value) > _lastRollingLog) _lastRollingLog = atoi(value);
}
if(comparePrefixedPath(topic, mqtt_topic_lock_action))
{
if(strcmp(value, "") == 0 ||
@@ -406,7 +419,7 @@ void NetworkOpener::publishAuthorizationInfo(const std::list<NukiOpener::LogEntr
{
char str[50];
char authName[33];
bool authFound = false;
uint32_t authIndex = 0;
JsonDocument json;
@@ -421,9 +434,9 @@ void NetworkOpener::publishAuthorizationInfo(const std::list<NukiOpener::LogEntr
memcpy(authName, log.name, sizeName);
if(authName[sizeName - 1] != '\0') authName[sizeName] = '\0';
if(!authFound)
if(log.index > authIndex)
{
authFound = true;
authIndex = log.index;
_authFound = true;
_authId = log.authId;
memset(_authName, 0, sizeof(_authName));
@@ -521,6 +534,14 @@ void NetworkOpener::publishAuthorizationInfo(const std::list<NukiOpener::LogEntr
break;
}
if(log.index > _lastRollingLog)
{
_lastRollingLog = log.index;
serializeJson(entry, _buffer, _bufferSize);
publishString(mqtt_topic_lock_log_rolling, _buffer);
publishInt(mqtt_topic_lock_log_rolling_last, log.index);
}
}
serializeJson(json, _buffer, _bufferSize);
@@ -528,7 +549,7 @@ void NetworkOpener::publishAuthorizationInfo(const std::list<NukiOpener::LogEntr
if(latest) publishString(mqtt_topic_lock_log_latest, _buffer);
else publishString(mqtt_topic_lock_log, _buffer);
if(authFound)
if(authIndex > 0)
{
publishUInt(mqtt_topic_lock_auth_id, _authId);
publishString(mqtt_topic_lock_auth_name, _authName);
@@ -702,13 +723,23 @@ void NetworkOpener::publishBleAddress(const std::string &address)
publishString(mqtt_topic_lock_address, address);
}
void NetworkOpener::publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, char* lockAction, char* unlockAction, char* openAction)
void NetworkOpener::publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const bool& publishAuthData, char* lockAction, char* unlockAction, char* openAction)
{
String availabilityTopic = _preferences->getString("mqttpath");
availabilityTopic.concat("/maintenance/mqttConnectionState");
_network->publishHASSConfig(deviceType, baseTopic, name, uidString, availabilityTopic.c_str(), false, lockAction, unlockAction, openAction);
_network->publishHASSConfigAdditionalOpenerEntities(deviceType, baseTopic, name, uidString);
if(publishAuthData)
{
_network->publishHASSConfigAccessLog(deviceType, baseTopic, name, uidString);
}
else
{
_network->removeHASSConfigTopic((char*)"sensor", (char*)"last_action_authorization", uidString);
_network->removeHASSConfigTopic((char*)"sensor", (char*)"rolling_log", uidString);
}
}
void NetworkOpener::removeHASSConfig(char* uidString)
@@ -734,6 +765,12 @@ void NetworkOpener::publishKeypad(const std::list<NukiLock::KeypadEntry>& entrie
jsonEntry["codeId"] = entry.codeId;
jsonEntry["enabled"] = entry.enabled;
jsonEntry["name"] = entry.name;
if(_preferences->getBool(preference_keypad_publish_code, false))
{
jsonEntry["code"] = entry.code;
}
char createdDT[20];
sprintf(createdDT, "%04d-%02d-%02d %02d:%02d:%02d", entry.dateCreatedYear, entry.dateCreatedMonth, entry.dateCreatedDay, entry.dateCreatedHour, entry.dateCreatedMin, entry.dateCreatedSec);
jsonEntry["dateCreated"] = createdDT;
@@ -823,6 +860,19 @@ void NetworkOpener::publishKeypad(const std::list<NukiLock::KeypadEntry>& entrie
++index;
}
if(!_preferences->getBool(preference_keypad_publish_code, false))
{
for(int i=0; i<maxKeypadCodeCount; i++)
{
String codeTopic = _mqttPath;
codeTopic.concat(mqtt_topic_keypad);
codeTopic.concat("/code_");
codeTopic.concat(std::to_string(i).c_str());
codeTopic.concat("/");
_network->removeTopic(codeTopic, "code");
}
}
}
else if (maxKeypadCodeCount > 0)
{
@@ -835,6 +885,7 @@ void NetworkOpener::publishKeypad(const std::list<NukiLock::KeypadEntry>& entrie
codeTopic.concat("/");
_network->removeTopic(codeTopic, "id");
_network->removeTopic(codeTopic, "enabled");
_network->removeTopic(codeTopic, "code");
_network->removeTopic(codeTopic, "name");
_network->removeTopic(codeTopic, "createdYear");
_network->removeTopic(codeTopic, "createdMonth");
@@ -1025,6 +1076,12 @@ void NetworkOpener::publishKeypadEntry(const String topic, NukiLock::KeypadEntry
publishInt(concat(topic, "/id").c_str(), entry.codeId);
publishBool(concat(topic, "/enabled").c_str(), entry.enabled);
publishString(concat(topic, "/name").c_str(), codeName);
if(_preferences->getBool(preference_keypad_publish_code, false))
{
publishInt(concat(topic, "/code").c_str(), entry.code);
}
publishInt(concat(topic, "/createdYear").c_str(), entry.dateCreatedYear);
publishInt(concat(topic, "/createdMonth").c_str(), entry.dateCreatedMonth);
publishInt(concat(topic, "/createdDay").c_str(), entry.dateCreatedDay);

View File

@@ -31,7 +31,7 @@ public:
void publishRssi(const int& rssi);
void publishRetry(const std::string& message);
void publishBleAddress(const std::string& address);
void publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, char* lockAction, char* unlockAction, char* openAction);
void publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const bool& publishAuthData, char* lockAction, char* unlockAction, char* openAction);
void removeHASSConfig(char* uidString);
void publishKeypad(const std::list<NukiLock::KeypadEntry>& entries, uint maxKeypadCodeCount);
void publishTimeControl(const std::list<NukiOpener::TimeControlEntry>& timeControlEntries);
@@ -93,6 +93,7 @@ private:
uint32_t _authId = 0;
char _authName[33];
bool _authFound = false;
uint32_t _lastRollingLog = 0;
NukiOpener::LockState _currentLockState = NukiOpener::LockState::Undefined;

View File

@@ -521,6 +521,8 @@ void NukiOpenerWrapper::updateAuthData(bool retrieved)
log.resize(_preferences->getInt(preference_authlog_max_entries, 3));
}
log.sort([](const NukiOpener::LogEntry& a, const NukiOpener::LogEntry& b) { return a.index < b.index; });
if(log.size() > 0)
{
_network->publishAuthorizationInfo(log, true);
@@ -537,6 +539,8 @@ void NukiOpenerWrapper::updateAuthData(bool retrieved)
log.resize(_preferences->getInt(preference_authlog_max_entries, MAX_AUTHLOG));
}
log.sort([](const NukiOpener::LogEntry& a, const NukiOpener::LogEntry& b) { return a.index < b.index; });
Log->print(F("Log size: "));
Log->println(log.size());
@@ -2073,11 +2077,11 @@ void NukiOpenerWrapper::setupHASS()
if(_preferences->getBool(preference_opener_continuous_mode))
{
_network->publishHASSConfig((char*)"Opener", baseTopic.c_str(), (char*)_nukiConfig.name, uidString, (char*)"deactivateCM", (char*)"activateCM", (char*)"electricStrikeActuation");
_network->publishHASSConfig((char*)"Opener", baseTopic.c_str(), (char*)_nukiConfig.name, uidString, _publishAuthData, (char*)"deactivateCM", (char*)"activateCM", (char*)"electricStrikeActuation");
}
else
{
_network->publishHASSConfig((char*)"Opener", baseTopic.c_str(), (char*)_nukiConfig.name, uidString, (char*)"deactivateRTO", (char*)"activateRTO", (char*)"electricStrikeActuation");
_network->publishHASSConfig((char*)"Opener", baseTopic.c_str(), (char*)_nukiConfig.name, uidString, _publishAuthData, (char*)"deactivateRTO", (char*)"activateRTO", (char*)"electricStrikeActuation");
}
_hassSetupCompleted = true;

View File

@@ -502,6 +502,8 @@ void NukiWrapper::updateAuthData(bool retrieved)
log.resize(_preferences->getInt(preference_authlog_max_entries, 3));
}
log.sort([](const NukiLock::LogEntry& a, const NukiLock::LogEntry& b) { return a.index < b.index; });
if(log.size() > 0)
{
_network->publishAuthorizationInfo(log, true);
@@ -518,6 +520,8 @@ void NukiWrapper::updateAuthData(bool retrieved)
log.resize(_preferences->getInt(preference_authlog_max_entries, MAX_AUTHLOG));
}
log.sort([](const NukiLock::LogEntry& a, const NukiLock::LogEntry& b) { return a.index < b.index; });
Log->print(F("Log size: "));
Log->println(log.size());

View File

@@ -51,6 +51,7 @@
#define preference_access_level (char*)"accLvl"
#define preference_keypad_info_enabled (char*)"kpInfoEnabled"
#define preference_keypad_control_enabled (char*)"kpCntrlEnabled"
#define preference_keypad_publish_code (char*)"kpPubCode"
#define preference_timecontrol_control_enabled (char*)"tcCntrlEnabled"
#define preference_timecontrol_info_enabled (char*)"tcInfoEnabled"
#define preference_publish_authdata (char*)"pubAuth"
@@ -97,7 +98,7 @@ private:
preference_network_hardware, preference_network_wifi_fallback_disabled, preference_rssi_publish_interval, preference_hostname, preference_find_best_rssi,
preference_network_timeout, preference_restart_on_disconnect, preference_restart_ble_beacon_lost, preference_query_interval_lockstate,
preference_query_interval_configuration, preference_query_interval_battery, preference_query_interval_keypad, preference_keypad_control_enabled,
preference_keypad_info_enabled, preference_acl, preference_timecontrol_control_enabled, preference_timecontrol_info_enabled,
preference_keypad_info_enabled, preference_keypad_publish_code, preference_acl, preference_timecontrol_control_enabled, preference_timecontrol_info_enabled,
preference_conf_lock_basic_acl, preference_conf_lock_advanced_acl, preference_conf_opener_basic_acl, preference_conf_opener_advanced_acl,
preference_access_level, preference_register_as_app, preference_command_nr_of_retries, preference_command_retry_delay, preference_cred_user,
preference_cred_password, preference_publish_authdata, preference_publish_debug_info, preference_presence_detection_timeout, preference_disable_non_json,
@@ -115,8 +116,8 @@ private:
{
preference_started_before, preference_mqtt_log_enabled, preference_check_updates, preference_lock_enabled, preference_opener_enabled, preference_opener_continuous_mode,
preference_enable_bootloop_reset, preference_webserver_enabled, preference_find_best_rssi, preference_restart_on_disconnect, preference_keypad_control_enabled,
preference_keypad_info_enabled, preference_timecontrol_control_enabled, preference_timecontrol_info_enabled, preference_register_as_app, preference_ip_dhcp_enabled,
preference_publish_authdata, preference_has_mac_saved, preference_publish_debug_info, preference_network_wifi_fallback_disabled, preference_disable_non_json
preference_keypad_info_enabled, preference_keypad_publish_code, preference_timecontrol_control_enabled, preference_timecontrol_info_enabled, preference_register_as_app,
preference_ip_dhcp_enabled, preference_publish_authdata, preference_has_mac_saved, preference_publish_debug_info, preference_network_wifi_fallback_disabled, preference_disable_non_json
};
const bool isRedacted(const char* key) const

View File

@@ -561,6 +561,11 @@ bool WebCfgServer::processArgs(String& message)
_preferences->putBool(preference_keypad_info_enabled, (value == "1"));
configChanged = true;
}
else if(key == "KPCODE")
{
_preferences->putBool(preference_keypad_publish_code, (value == "1"));
configChanged = true;
}
else if(key == "KPENA")
{
_preferences->putBool(preference_keypad_control_enabled, (value == "1"));
@@ -1400,12 +1405,13 @@ void WebCfgServer::buildAccLvlHtml(String &response)
if((_nuki != nullptr && _nuki->hasKeypad()) || (_nukiOpener != nullptr && _nukiOpener->hasKeypad()))
{
printCheckBox(response, "KPPUB", "Publish keypad codes information", _preferences->getBool(preference_keypad_info_enabled), "");
printCheckBox(response, "KPPUB", "Publish keypad entries information", _preferences->getBool(preference_keypad_info_enabled), "");
printCheckBox(response, "KPCODE", "Also publish keypad codes (<span style=\"color: #ff0000\">Disadvised for security reasons</span>)", _preferences->getBool(preference_keypad_publish_code, false), "");
printCheckBox(response, "KPENA", "Add, modify and delete keypad codes", _preferences->getBool(preference_keypad_control_enabled), "");
}
printCheckBox(response, "TCPUB", "Publish time control entries information", _preferences->getBool(preference_timecontrol_info_enabled), "");
printCheckBox(response, "TCENA", "Add, modify and delete time control entries", _preferences->getBool(preference_timecontrol_control_enabled), "");
printCheckBox(response, "PUBAUTH", "Publish authorisation log (may reduce battery life)", _preferences->getBool(preference_publish_authdata), "");
printCheckBox(response, "PUBAUTH", "Publish authorization log (may reduce battery life)", _preferences->getBool(preference_publish_authdata), "");
response.concat("</table><br>");
if(_nuki != nullptr)
{