This commit is contained in:
iranl
2024-05-26 21:45:54 +02:00
parent 728bd5f818
commit 72289336ad
6 changed files with 181 additions and 175 deletions

View File

@@ -200,6 +200,7 @@ In a browser navigate to the IP address assigned to the ESP32.
- lock/trigger: The trigger of the last action: autoLock, automatic, button, manual, system. - 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/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.
- 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/completionStatus: Status of the last action as reported by Nuki Lock: success, motorBlocked, canceled, tooRecent, busy, lowMotorVoltage, clutchFailure, motorPowerFailure, incompleteFailure, invalidCode, otherError, unknown. - 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/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. - lock/authorizationName: If enabled in the web interface, this node returns the authorization name of the last lock action.

View File

@@ -12,6 +12,7 @@
#define mqtt_topic_lock_trigger "/lock/trigger" #define mqtt_topic_lock_trigger "/lock/trigger"
#define mqtt_topic_lock_last_lock_action "/lock/lastLockAction" #define mqtt_topic_lock_last_lock_action "/lock/lastLockAction"
#define mqtt_topic_lock_log "/lock/log" #define mqtt_topic_lock_log "/lock/log"
#define mqtt_topic_lock_log_latest "/lock/shortLog"
#define mqtt_topic_lock_auth_id "/lock/authorizationId" #define mqtt_topic_lock_auth_id "/lock/authorizationId"
#define mqtt_topic_lock_auth_name "/lock/authorizationName" #define mqtt_topic_lock_auth_name "/lock/authorizationName"
#define mqtt_topic_lock_completionStatus "/lock/completionStatus" #define mqtt_topic_lock_completionStatus "/lock/completionStatus"

View File

@@ -429,83 +429,79 @@ void NetworkLock::publishAuthorizationInfo(const std::list<NukiLock::LogEntry>&
} }
} }
if(!latest) auto entry = json.add<JsonVariant>();
entry["index"] = log.index;
entry["authorizationId"] = log.authId;
entry["authorizationName"] = authName;
entry["timeYear"] = log.timeStampYear;
entry["timeMonth"] = log.timeStampMonth;
entry["timeDay"] = log.timeStampDay;
entry["timeHour"] = log.timeStampHour;
entry["timeMinute"] = log.timeStampMinute;
entry["timeSecond"] = log.timeStampSecond;
memset(str, 0, sizeof(str));
loggingTypeToString(log.loggingType, str);
entry["type"] = str;
switch(log.loggingType)
{ {
auto entry = json.add<JsonVariant>(); case NukiLock::LoggingType::LockAction:
memset(str, 0, sizeof(str));
NukiLock::lockactionToString((NukiLock::LockAction)log.data[0], str);
entry["action"] = str;
entry["index"] = log.index; memset(str, 0, sizeof(str));
entry["authorizationId"] = log.authId; NukiLock::triggerToString((NukiLock::Trigger)log.data[1], str);
entry["authorizationName"] = authName; entry["trigger"] = str;
entry["timeYear"] = log.timeStampYear;
entry["timeMonth"] = log.timeStampMonth;
entry["timeDay"] = log.timeStampDay;
entry["timeHour"] = log.timeStampHour;
entry["timeMinute"] = log.timeStampMinute;
entry["timeSecond"] = log.timeStampSecond;
memset(str, 0, sizeof(str)); memset(str, 0, sizeof(str));
loggingTypeToString(log.loggingType, str); NukiLock::completionStatusToString((NukiLock::CompletionStatus)log.data[3], str);
entry["type"] = str; entry["completionStatus"] = str;
entry["completionStatusVal"] = log.data[3];
break;
case NukiLock::LoggingType::KeypadAction:
memset(str, 0, sizeof(str));
NukiLock::lockactionToString((NukiLock::LockAction)log.data[0], str);
entry["action"] = str;
switch(log.loggingType) memset(str, 0, sizeof(str));
{ NukiLock::completionStatusToString((NukiLock::CompletionStatus)log.data[2], str);
case NukiLock::LoggingType::LockAction: entry["completionStatus"] = str;
memset(str, 0, sizeof(str)); entry["completionStatusVal"] = log.data[2];
NukiLock::lockactionToString((NukiLock::LockAction)log.data[0], str); break;
entry["action"] = str; case NukiLock::LoggingType::DoorSensor:
memset(str, 0, sizeof(str));
NukiLock::lockactionToString((NukiLock::LockAction)log.data[0], str);
memset(str, 0, sizeof(str)); switch(log.data[0])
NukiLock::triggerToString((NukiLock::Trigger)log.data[1], str); {
entry["trigger"] = str; case 0:
entry["action"] = "DoorOpened";
break;
case 1:
entry["action"] = "DoorClosed";
break;
case 2:
entry["action"] = "SensorJammed";
break;
default:
entry["action"] = "Unknown";
break;
}
memset(str, 0, sizeof(str)); memset(str, 0, sizeof(str));
NukiLock::completionStatusToString((NukiLock::CompletionStatus)log.data[3], str); NukiLock::completionStatusToString((NukiLock::CompletionStatus)log.data[2], str);
entry["completionStatus"] = str; entry["completionStatus"] = str;
entry["completionStatusVal"] = log.data[3]; break;
break;
case NukiLock::LoggingType::KeypadAction:
memset(str, 0, sizeof(str));
NukiLock::lockactionToString((NukiLock::LockAction)log.data[0], str);
entry["action"] = str;
memset(str, 0, sizeof(str));
NukiLock::completionStatusToString((NukiLock::CompletionStatus)log.data[2], str);
entry["completionStatus"] = str;
entry["completionStatusVal"] = log.data[2];
break;
case NukiLock::LoggingType::DoorSensor:
memset(str, 0, sizeof(str));
NukiLock::lockactionToString((NukiLock::LockAction)log.data[0], str);
switch(log.data[0])
{
case 0:
entry["action"] = "DoorOpened";
break;
case 1:
entry["action"] = "DoorClosed";
break;
case 2:
entry["action"] = "SensorJammed";
break;
default:
entry["action"] = "Unknown";
break;
}
memset(str, 0, sizeof(str));
NukiLock::completionStatusToString((NukiLock::CompletionStatus)log.data[2], str);
entry["completionStatus"] = str;
break;
}
} }
} }
if(!latest) serializeJson(json, _buffer, _bufferSize);
{
serializeJson(json, _buffer, _bufferSize); if(latest) publishString(mqtt_topic_lock_log_latest, _buffer);
publishString(mqtt_topic_lock_log, _buffer); else publishString(mqtt_topic_lock_log, _buffer);
}
if(authFound) if(authFound)
{ {

View File

@@ -398,106 +398,102 @@ void NetworkOpener::publishAuthorizationInfo(const std::list<NukiOpener::LogEntr
} }
} }
if(!latest) auto entry = json.add<JsonVariant>();
entry["index"] = log.index;
entry["authorizationId"] = log.authId;
entry["authorizationName"] = _authName;
entry["timeYear"] = log.timeStampYear;
entry["timeMonth"] = log.timeStampMonth;
entry["timeDay"] = log.timeStampDay;
entry["timeHour"] = log.timeStampHour;
entry["timeMinute"] = log.timeStampMinute;
entry["timeSecond"] = log.timeStampSecond;
memset(str, 0, sizeof(str));
loggingTypeToString(log.loggingType, str);
entry["type"] = str;
switch(log.loggingType)
{ {
auto entry = json.add<JsonVariant>(); case NukiOpener::LoggingType::LockAction:
memset(str, 0, sizeof(str));
NukiOpener::lockactionToString((NukiOpener::LockAction)log.data[0], str);
entry["action"] = str;
entry["index"] = log.index; memset(str, 0, sizeof(str));
entry["authorizationId"] = log.authId; NukiOpener::triggerToString((NukiOpener::Trigger)log.data[1], str);
entry["authorizationName"] = _authName; entry["trigger"] = str;
entry["timeYear"] = log.timeStampYear;
entry["timeMonth"] = log.timeStampMonth;
entry["timeDay"] = log.timeStampDay;
entry["timeHour"] = log.timeStampHour;
entry["timeMinute"] = log.timeStampMinute;
entry["timeSecond"] = log.timeStampSecond;
memset(str, 0, sizeof(str)); memset(str, 0, sizeof(str));
loggingTypeToString(log.loggingType, str); NukiOpener::completionStatusToString((NukiOpener::CompletionStatus)log.data[3], str);
entry["type"] = str; entry["completionStatus"] = str;
break;
case NukiOpener::LoggingType::KeypadAction:
memset(str, 0, sizeof(str));
NukiOpener::lockactionToString((NukiOpener::LockAction)log.data[0], str);
entry["action"] = str;
switch(log.loggingType) memset(str, 0, sizeof(str));
{ NukiOpener::completionStatusToString((NukiOpener::CompletionStatus)log.data[2], str);
case NukiOpener::LoggingType::LockAction: entry["completionStatus"] = str;
memset(str, 0, sizeof(str)); break;
NukiOpener::lockactionToString((NukiOpener::LockAction)log.data[0], str); case NukiOpener::LoggingType::DoorbellRecognition:
entry["action"] = str; switch(log.data[0] & 3)
{
case 0:
entry["mode"] = "None";
break;
case 1:
entry["mode"] = "RTO";
break;
case 2:
entry["mode"] = "CM";
break;
default:
entry["mode"] = "Unknown";
break;
}
memset(str, 0, sizeof(str)); switch(log.data[1])
NukiOpener::triggerToString((NukiOpener::Trigger)log.data[1], str); {
entry["trigger"] = str; case 0:
entry["source"] = "Doorbell";
break;
case 1:
entry["source"] = "Timecontrol";
break;
case 2:
entry["source"] = "App";
break;
case 3:
entry["source"] = "Button";
break;
case 4:
entry["source"] = "Fob";
break;
case 5:
entry["source"] = "Bridge";
break;
case 6:
entry["source"] = "Keypad";
break;
default:
entry["source"] = "Unknown";
break; }
memset(str, 0, sizeof(str)); entry["geofence"] = log.data[2] == 1 ? "active" : "inactive";
NukiOpener::completionStatusToString((NukiOpener::CompletionStatus)log.data[3], str); entry["doorbellSuppression"] = log.data[3] == 1 ? "active" : "inactive";
entry["completionStatus"] = str; entry["completionStatus"] = str;
break;
case NukiOpener::LoggingType::KeypadAction:
memset(str, 0, sizeof(str));
NukiOpener::lockactionToString((NukiOpener::LockAction)log.data[0], str);
entry["action"] = str;
memset(str, 0, sizeof(str)); break;
NukiOpener::completionStatusToString((NukiOpener::CompletionStatus)log.data[2], str);
entry["completionStatus"] = str;
break;
case NukiOpener::LoggingType::DoorbellRecognition:
switch(log.data[0] & 3)
{
case 0:
entry["mode"] = "None";
break;
case 1:
entry["mode"] = "RTO";
break;
case 2:
entry["mode"] = "CM";
break;
default:
entry["mode"] = "Unknown";
break;
}
switch(log.data[1])
{
case 0:
entry["source"] = "Doorbell";
break;
case 1:
entry["source"] = "Timecontrol";
break;
case 2:
entry["source"] = "App";
break;
case 3:
entry["source"] = "Button";
break;
case 4:
entry["source"] = "Fob";
break;
case 5:
entry["source"] = "Bridge";
break;
case 6:
entry["source"] = "Keypad";
break;
default:
entry["source"] = "Unknown";
break; }
entry["geofence"] = log.data[2] == 1 ? "active" : "inactive";
entry["doorbellSuppression"] = log.data[3] == 1 ? "active" : "inactive";
entry["completionStatus"] = str;
break;
}
} }
} }
if(!latest) serializeJson(json, _buffer, _bufferSize);
{
serializeJson(json, _buffer, _bufferSize); if(latest) publishString(mqtt_topic_lock_log_latest, _buffer);
publishString(mqtt_topic_lock_log, _buffer); else publishString(mqtt_topic_lock_log, _buffer);
}
if(authFound) if(authFound)
{ {

View File

@@ -499,22 +499,28 @@ void NukiOpenerWrapper::updateAuthData(bool retrieved)
if(!retrieved) if(!retrieved)
{ {
Nuki::CmdResult result = _nukiOpener.retrieveLogEntries(0, 3, 1, false); delay(250);
Nuki::CmdResult result = _nukiOpener.retrieveLogEntries(0, _preferences->getInt(preference_authlog_max_entries, MAX_AUTHLOG), 1, false);
Log->print(F("Retrieve log entries: ")); Log->print(F("Retrieve log entries: "));
Log->println(result); Log->println(result);
printCommandResult(result); printCommandResult(result);
if(result == Nuki::CmdResult::Success) if(result == Nuki::CmdResult::Success)
{ {
Nuki::CmdResult result = _nukiOpener.retrieveLogEntries(0, _preferences->getInt(preference_authlog_max_entries, MAX_AUTHLOG), 1, false); _waitAuthLogUpdateTs = millis() + 5000;
if(result == Nuki::CmdResult::Success) delay(100);
{
_waitAuthLogUpdateTs = millis() + 5000;
}
delay(150);
std::list<NukiOpener::LogEntry> log; std::list<NukiOpener::LogEntry> log;
_nukiOpener.getLogEntries(&log); _nukiOpener.getLogEntries(&log);
_network->publishAuthorizationInfo(log, true);
if(log.size() > _preferences->getInt(preference_authlog_max_entries, 3))
{
log.resize(_preferences->getInt(preference_authlog_max_entries, 3));
}
if(log.size() > 0)
{
_network->publishAuthorizationInfo(log, true);
}
} }
} }
else else
@@ -1734,7 +1740,7 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
_network->publishKeypadJsonCommandResult("noExistingCodeIdSet"); _network->publishKeypadJsonCommandResult("noExistingCodeIdSet");
return; return;
} }
NukiOpener::UpdatedKeypadEntry entry; NukiOpener::UpdatedKeypadEntry entry;
memset(&entry, 0, sizeof(entry)); memset(&entry, 0, sizeof(entry));
entry.codeId = codeId; entry.codeId = codeId;

View File

@@ -480,22 +480,28 @@ void NukiWrapper::updateAuthData(bool retrieved)
if(!retrieved) if(!retrieved)
{ {
Nuki::CmdResult result = _nukiLock.retrieveLogEntries(0, 3, 1, false); delay(250);
Nuki::CmdResult result = _nukiLock.retrieveLogEntries(0, _preferences->getInt(preference_authlog_max_entries, MAX_AUTHLOG), 1, false);
Log->print(F("Retrieve log entries: ")); Log->print(F("Retrieve log entries: "));
Log->println(result); Log->println(result);
printCommandResult(result); printCommandResult(result);
if(result == Nuki::CmdResult::Success) if(result == Nuki::CmdResult::Success)
{ {
Nuki::CmdResult result = _nukiLock.retrieveLogEntries(0, _preferences->getInt(preference_authlog_max_entries, MAX_AUTHLOG), 1, false); _waitAuthLogUpdateTs = millis() + 5000;
if(result == Nuki::CmdResult::Success) delay(100);
{
_waitAuthLogUpdateTs = millis() + 5000;
}
delay(150);
std::list<NukiLock::LogEntry> log; std::list<NukiLock::LogEntry> log;
_nukiLock.getLogEntries(&log); _nukiLock.getLogEntries(&log);
_network->publishAuthorizationInfo(log, true);
if(log.size() > _preferences->getInt(preference_authlog_max_entries, 3))
{
log.resize(_preferences->getInt(preference_authlog_max_entries, 3));
}
if(log.size() > 0)
{
_network->publishAuthorizationInfo(log, true);
}
} }
} }
else else