Time Control
This commit is contained in:
@@ -629,12 +629,12 @@ void NetworkLock::publishKeypad(const std::list<NukiLock::KeypadEntry>& entries,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkLock::publishTimeControl(const std::list<NukiLock::TimeControlEntry>& entries)
|
void NetworkLock::publishTimeControl(const std::list<NukiLock::TimeControlEntry>& timeControlEntries)
|
||||||
{
|
{
|
||||||
char str[50];
|
char str[50];
|
||||||
JsonDocument json;
|
JsonDocument json;
|
||||||
|
|
||||||
for(const auto& entry : entries)
|
for(const auto& entry : timeControlEntries)
|
||||||
{
|
{
|
||||||
auto jsonEntry = json.add();
|
auto jsonEntry = json.add();
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public:
|
|||||||
void publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const bool& hasDoorSensor, const bool& hasKeypad, const bool& publishAuthData, char* lockAction, char* unlockAction, char* openAction);
|
void publishHASSConfig(char* deviceType, const char* baseTopic, char* name, char* uidString, const bool& hasDoorSensor, const bool& hasKeypad, const bool& publishAuthData, char* lockAction, char* unlockAction, char* openAction);
|
||||||
void removeHASSConfig(char* uidString);
|
void removeHASSConfig(char* uidString);
|
||||||
void publishKeypad(const std::list<NukiLock::KeypadEntry>& entries, uint maxKeypadCodeCount);
|
void publishKeypad(const std::list<NukiLock::KeypadEntry>& entries, uint maxKeypadCodeCount);
|
||||||
void publishTimeControl(const std::list<NukiLock::TimeControlEntry>& entries);
|
void publishTimeControl(const std::list<NukiLock::TimeControlEntry>& timeControlEntries);
|
||||||
void publishKeypadCommandResult(const char* result);
|
void publishKeypadCommandResult(const char* result);
|
||||||
void publishKeypadJsonCommandResult(const char* result);
|
void publishKeypadJsonCommandResult(const char* result);
|
||||||
void publishTimeControlCommandResult(const char* result);
|
void publishTimeControlCommandResult(const char* result);
|
||||||
|
|||||||
@@ -398,24 +398,24 @@ void NetworkOpener::publishAuthorizationInfo(const std::list<NukiOpener::LogEntr
|
|||||||
{
|
{
|
||||||
case NukiOpener::LoggingType::LockAction:
|
case NukiOpener::LoggingType::LockAction:
|
||||||
memset(str, 0, sizeof(str));
|
memset(str, 0, sizeof(str));
|
||||||
NukiLock::lockactionToString((NukiLock::LockAction)log.data[0], str);
|
NukiOpener::lockactionToString((NukiOpener::LockAction)log.data[0], str);
|
||||||
entry["action"] = str;
|
entry["action"] = str;
|
||||||
|
|
||||||
memset(str, 0, sizeof(str));
|
memset(str, 0, sizeof(str));
|
||||||
NukiLock::triggerToString((NukiLock::Trigger)log.data[1], str);
|
NukiOpener::triggerToString((NukiOpener::Trigger)log.data[1], str);
|
||||||
entry["trigger"] = str;
|
entry["trigger"] = str;
|
||||||
|
|
||||||
memset(str, 0, sizeof(str));
|
memset(str, 0, sizeof(str));
|
||||||
NukiLock::completionStatusToString((NukiLock::CompletionStatus)log.data[3], str);
|
NukiOpener::completionStatusToString((NukiOpener::CompletionStatus)log.data[3], str);
|
||||||
entry["completionStatus"] = str;
|
entry["completionStatus"] = str;
|
||||||
break;
|
break;
|
||||||
case NukiOpener::LoggingType::KeypadAction:
|
case NukiOpener::LoggingType::KeypadAction:
|
||||||
memset(str, 0, sizeof(str));
|
memset(str, 0, sizeof(str));
|
||||||
NukiLock::lockactionToString((NukiLock::LockAction)log.data[0], str);
|
NukiOpener::lockactionToString((NukiOpener::LockAction)log.data[0], str);
|
||||||
entry["action"] = str;
|
entry["action"] = str;
|
||||||
|
|
||||||
memset(str, 0, sizeof(str));
|
memset(str, 0, sizeof(str));
|
||||||
NukiLock::completionStatusToString((NukiLock::CompletionStatus)log.data[2], str);
|
NukiOpener::completionStatusToString((NukiOpener::CompletionStatus)log.data[2], str);
|
||||||
entry["completionStatus"] = str;
|
entry["completionStatus"] = str;
|
||||||
break;
|
break;
|
||||||
case NukiOpener::LoggingType::DoorbellRecognition:
|
case NukiOpener::LoggingType::DoorbellRecognition:
|
||||||
@@ -685,12 +685,12 @@ void NetworkOpener::publishKeypad(const std::list<NukiLock::KeypadEntry>& entrie
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkOpener::publishTimeControl(const std::list<NukiLock::TimeControlEntry>& entries)
|
void NetworkOpener::publishTimeControl(const std::list<NukiOpener::TimeControlEntry>& timeControlEntries)
|
||||||
{
|
{
|
||||||
char str[50];
|
char str[50];
|
||||||
JsonDocument json;
|
JsonDocument json;
|
||||||
|
|
||||||
for(const auto& entry : entries)
|
for(const auto& entry : timeControlEntries)
|
||||||
{
|
{
|
||||||
auto jsonEntry = json.add();
|
auto jsonEntry = json.add();
|
||||||
|
|
||||||
@@ -749,7 +749,7 @@ void NetworkOpener::publishTimeControl(const std::list<NukiLock::TimeControlEntr
|
|||||||
jsonEntry["time"] = timeT;
|
jsonEntry["time"] = timeT;
|
||||||
|
|
||||||
memset(str, 0, sizeof(str));
|
memset(str, 0, sizeof(str));
|
||||||
NetworkOpener::lockactionToString(entry.lockAction, str);
|
NukiOpener::lockactionToString(entry.lockAction, str);
|
||||||
jsonEntry["lockAction"] = str;
|
jsonEntry["lockAction"] = str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public:
|
|||||||
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, char* lockAction, char* unlockAction, char* openAction);
|
||||||
void removeHASSConfig(char* uidString);
|
void removeHASSConfig(char* uidString);
|
||||||
void publishKeypad(const std::list<NukiLock::KeypadEntry>& entries, uint maxKeypadCodeCount);
|
void publishKeypad(const std::list<NukiLock::KeypadEntry>& entries, uint maxKeypadCodeCount);
|
||||||
void publishTimeControl(const std::list<NukiLock::TimeControlEntry>& entries);
|
void publishTimeControl(const std::list<NukiOpener::TimeControlEntry>& timeControlEntries);
|
||||||
void publishKeypadCommandResult(const char* result);
|
void publishKeypadCommandResult(const char* result);
|
||||||
void publishKeypadJsonCommandResult(const char* result);
|
void publishKeypadJsonCommandResult(const char* result);
|
||||||
void publishTimeControlCommandResult(const char* result);
|
void publishTimeControlCommandResult(const char* result);
|
||||||
|
|||||||
@@ -172,6 +172,11 @@ void NukiOpenerWrapper::update()
|
|||||||
setupHASS();
|
setupHASS();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(_nextTimeControlUpdateTs != 0 && ts > _nextTimeControlUpdateTs)
|
||||||
|
{
|
||||||
|
_nextTimeControlUpdateTs = 0;
|
||||||
|
updateTimeControl(true);
|
||||||
|
}
|
||||||
if(_hassEnabled && _configRead && _network->reconnected())
|
if(_hassEnabled && _configRead && _network->reconnected())
|
||||||
{
|
{
|
||||||
setupHASS();
|
setupHASS();
|
||||||
@@ -407,7 +412,7 @@ void NukiOpenerWrapper::updateConfig()
|
|||||||
_network->publishConfig(_nukiConfig);
|
_network->publishConfig(_nukiConfig);
|
||||||
_retryConfigCount = 0;
|
_retryConfigCount = 0;
|
||||||
|
|
||||||
if(_preferences->getBool(preference_timecontrol_info_enabled)) updateTimeControl();
|
if(_preferences->getBool(preference_timecontrol_info_enabled)) updateTimeControl(false);
|
||||||
|
|
||||||
const int pinStatus = _preferences->getInt(preference_opener_pin_status, 4);
|
const int pinStatus = _preferences->getInt(preference_opener_pin_status, 4);
|
||||||
|
|
||||||
@@ -504,6 +509,9 @@ void NukiOpenerWrapper::updateKeypad()
|
|||||||
std::list<NukiLock::KeypadEntry> entries;
|
std::list<NukiLock::KeypadEntry> entries;
|
||||||
_nukiOpener.getKeypadEntries(&entries);
|
_nukiOpener.getKeypadEntries(&entries);
|
||||||
|
|
||||||
|
Log->print(F("Opener keypad codes: "));
|
||||||
|
Log->println(entries.size());
|
||||||
|
|
||||||
entries.sort([](const NukiLock::KeypadEntry& a, const NukiLock::KeypadEntry& b) { return a.codeId < b.codeId; });
|
entries.sort([](const NukiLock::KeypadEntry& a, const NukiLock::KeypadEntry& b) { return a.codeId < b.codeId; });
|
||||||
|
|
||||||
uint keypadCount = entries.size();
|
uint keypadCount = entries.size();
|
||||||
@@ -526,23 +534,35 @@ void NukiOpenerWrapper::updateKeypad()
|
|||||||
postponeBleWatchdog();
|
postponeBleWatchdog();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NukiOpenerWrapper::updateTimeControl()
|
void NukiOpenerWrapper::updateTimeControl(bool retrieved)
|
||||||
{
|
{
|
||||||
if(!_preferences->getBool(preference_timecontrol_info_enabled)) return;
|
if(!_preferences->getBool(preference_timecontrol_info_enabled)) return;
|
||||||
|
|
||||||
Log->print(F("Querying lock time control: "));
|
if(!retrieved)
|
||||||
Nuki::CmdResult result = _nukiOpener.retrieveTimeControlEntries();
|
|
||||||
printCommandResult(result);
|
|
||||||
if(result == Nuki::CmdResult::Success)
|
|
||||||
{
|
{
|
||||||
std::list<NukiLock::TimeControlEntry> entries;
|
Log->print(F("Querying opener time control: "));
|
||||||
_nukiOpener.getTimeControlEntries(&entries);
|
Nuki::CmdResult result = _nukiOpener.retrieveTimeControlEntries();
|
||||||
|
printCommandResult(result);
|
||||||
|
if(result == Nuki::CmdResult::Success)
|
||||||
|
{
|
||||||
|
_nextTimeControlUpdateTs = millis() + 5000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::list<NukiOpener::TimeControlEntry> timeControlEntries;
|
||||||
|
_nukiOpener.getTimeControlEntries(&timeControlEntries);
|
||||||
|
|
||||||
entries.sort([](const NukiLock::TimeControlEntry& a, const NukiLock::TimeControlEntry& b) { return a.entryId < b.entryId; });
|
Log->print(F("Opener time control entries: "));
|
||||||
|
Log->println(timeControlEntries.size());
|
||||||
|
|
||||||
|
timeControlEntries.sort([](const NukiOpener::TimeControlEntry& a, const NukiOpener::TimeControlEntry& b) { return a.entryId < b.entryId; });
|
||||||
|
|
||||||
|
_network->publishTimeControl(timeControlEntries);
|
||||||
|
|
||||||
_timeControlIds.clear();
|
_timeControlIds.clear();
|
||||||
_timeControlIds.reserve(entries.size());
|
_timeControlIds.reserve(timeControlEntries.size());
|
||||||
for(const auto& entry : entries)
|
for(const auto& entry : timeControlEntries)
|
||||||
{
|
{
|
||||||
_timeControlIds.push_back(entry.entryId);
|
_timeControlIds.push_back(entry.entryId);
|
||||||
}
|
}
|
||||||
@@ -558,24 +578,31 @@ void NukiOpenerWrapper::postponeBleWatchdog()
|
|||||||
|
|
||||||
NukiOpener::LockAction NukiOpenerWrapper::lockActionToEnum(const char *str)
|
NukiOpener::LockAction NukiOpenerWrapper::lockActionToEnum(const char *str)
|
||||||
{
|
{
|
||||||
if(strcmp(str, "activateRTO") == 0) return NukiOpener::LockAction::ActivateRTO;
|
if(strcmp(str, "activateRTO") == 0 || strcmp(str, "ActivateRTO") == 0) return NukiOpener::LockAction::ActivateRTO;
|
||||||
else if(strcmp(str, "deactivateRTO") == 0) return NukiOpener::LockAction::DeactivateRTO;
|
else if(strcmp(str, "deactivateRTO") == 0 || strcmp(str, "DeactivateRTO") == 0) return NukiOpener::LockAction::DeactivateRTO;
|
||||||
else if(strcmp(str, "electricStrikeActuation") == 0) return NukiOpener::LockAction::ElectricStrikeActuation;
|
else if(strcmp(str, "electricStrikeActuation") == 0 || strcmp(str, "ElectricStrikeActuation") == 0) return NukiOpener::LockAction::ElectricStrikeActuation;
|
||||||
else if(strcmp(str, "activateCM") == 0) return NukiOpener::LockAction::ActivateCM;
|
else if(strcmp(str, "activateCM") == 0 || strcmp(str, "ActivateCM") == 0) return NukiOpener::LockAction::ActivateCM;
|
||||||
else if(strcmp(str, "deactivateCM") == 0) return NukiOpener::LockAction::DeactivateCM;
|
else if(strcmp(str, "deactivateCM") == 0 || strcmp(str, "DeactivateCM") == 0) return NukiOpener::LockAction::DeactivateCM;
|
||||||
else if(strcmp(str, "fobAction2") == 0) return NukiOpener::LockAction::FobAction2;
|
else if(strcmp(str, "fobAction2") == 0 || strcmp(str, "FobAction2") == 0) return NukiOpener::LockAction::FobAction2;
|
||||||
else if(strcmp(str, "fobAction1") == 0) return NukiOpener::LockAction::FobAction1;
|
else if(strcmp(str, "fobAction1") == 0 || strcmp(str, "FobAction1") == 0) return NukiOpener::LockAction::FobAction1;
|
||||||
else if(strcmp(str, "fobAction3") == 0) return NukiOpener::LockAction::FobAction3;
|
else if(strcmp(str, "fobAction3") == 0 || strcmp(str, "FobAction3") == 0) return NukiOpener::LockAction::FobAction3;
|
||||||
return (NukiOpener::LockAction)0xff;
|
return (NukiOpener::LockAction)0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
LockActionResult NukiOpenerWrapper::onLockActionReceivedCallback(const char *value)
|
LockActionResult NukiOpenerWrapper::onLockActionReceivedCallback(const char *value)
|
||||||
{
|
{
|
||||||
NukiOpener::LockAction action = nukiOpenerInst->lockActionToEnum(value);
|
NukiOpener::LockAction action;
|
||||||
if((int)action == 0xff)
|
|
||||||
|
if(strlen(value) > 0)
|
||||||
{
|
{
|
||||||
return LockActionResult::UnknownAction;
|
action = nukiOpenerInst->lockActionToEnum(value);
|
||||||
|
|
||||||
|
if((int)action == 0xff)
|
||||||
|
{
|
||||||
|
return LockActionResult::UnknownAction;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else return LockActionResult::UnknownAction;
|
||||||
|
|
||||||
nukiOpenerPreferences = new Preferences();
|
nukiOpenerPreferences = new Preferences();
|
||||||
nukiOpenerPreferences->begin("nukihub", true);
|
nukiOpenerPreferences->begin("nukihub", true);
|
||||||
@@ -822,7 +849,7 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicJsonDocument json(2048);
|
JsonDocument json;
|
||||||
DeserializationError jsonError = deserializeJson(json, value);
|
DeserializationError jsonError = deserializeJson(json, value);
|
||||||
|
|
||||||
if(jsonError)
|
if(jsonError)
|
||||||
@@ -1123,7 +1150,7 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value)
|
|||||||
|
|
||||||
void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value)
|
void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value)
|
||||||
{
|
{
|
||||||
if(_nukiLock.getSecurityPincode() == 0)
|
if(_nukiOpener.getSecurityPincode() == 0)
|
||||||
{
|
{
|
||||||
_network->publishTimeControlCommandResult("noPinSet");
|
_network->publishTimeControlCommandResult("noPinSet");
|
||||||
return;
|
return;
|
||||||
@@ -1151,9 +1178,21 @@ void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value)
|
|||||||
uint8_t enabled = json["enabled"].as<unsigned int>();
|
uint8_t enabled = json["enabled"].as<unsigned int>();
|
||||||
String weekdays = json["weekdays"].as<String>();
|
String weekdays = json["weekdays"].as<String>();
|
||||||
const char *time = json["time"].as<const char*>();
|
const char *time = json["time"].as<const char*>();
|
||||||
NukiOpener::LockAction timeControlLockAction = nukiOpenerInst->lockActionToEnum(json["lockAction"].as<const char*>());
|
const char *lockAct = json["lockAction"].as<const char*>();
|
||||||
|
NukiOpener::LockAction timeControlLockAction;
|
||||||
|
|
||||||
if((int)timeControlLockAction == 0xff)
|
if(strlen(lockAct) > 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
timeControlLockAction = nukiOpenerInst->lockActionToEnum(lockAct);
|
||||||
|
|
||||||
|
if((int)timeControlLockAction == 0xff)
|
||||||
|
{
|
||||||
|
_network->publishTimeControlCommandResult("invalidLockAction");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
_network->publishTimeControlCommandResult("invalidLockAction");
|
_network->publishTimeControlCommandResult("invalidLockAction");
|
||||||
return;
|
return;
|
||||||
@@ -1198,19 +1237,19 @@ void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value)
|
|||||||
|
|
||||||
if(timeAr[0] < 0 || timeAr[0] > 23 || timeAr[1] < 0 || timeAr[1] > 59)
|
if(timeAr[0] < 0 || timeAr[0] > 23 || timeAr[1] < 0 || timeAr[1] > 59)
|
||||||
{
|
{
|
||||||
_network->publishKeypadJsonCommandResult("invalidTime");
|
_network->publishTimeControlCommandResult("invalidTime");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_network->publishKeypadJsonCommandResult("invalidTime");
|
_network->publishTimeControlCommandResult("invalidTime");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_network->publishKeypadJsonCommandResult("invalidTime");
|
_network->publishTimeControlCommandResult("invalidTime");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1224,7 +1263,7 @@ void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value)
|
|||||||
|
|
||||||
if(strcmp(action, "add") == 0)
|
if(strcmp(action, "add") == 0)
|
||||||
{
|
{
|
||||||
NukiLock::NewTimeControlEntry entry;
|
NukiOpener::NewTimeControlEntry entry;
|
||||||
memset(&entry, 0, sizeof(entry));
|
memset(&entry, 0, sizeof(entry));
|
||||||
entry.weekdays = weekdaysInt;
|
entry.weekdays = weekdaysInt;
|
||||||
|
|
||||||
@@ -1236,13 +1275,13 @@ void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value)
|
|||||||
|
|
||||||
entry.lockAction = timeControlLockAction;
|
entry.lockAction = timeControlLockAction;
|
||||||
|
|
||||||
result = _nukiOpener.addKeypadEntry(entry);
|
result = _nukiOpener.addTimeControlEntry(entry);
|
||||||
Log->print("Add time control: ");
|
Log->print("Add time control: ");
|
||||||
Log->println((int)result);
|
Log->println((int)result);
|
||||||
}
|
}
|
||||||
else if (strcmp(action, "update") == 0)
|
else if (strcmp(action, "update") == 0)
|
||||||
{
|
{
|
||||||
NukiLock::TimeControlEntry entry;
|
NukiOpener::TimeControlEntry entry;
|
||||||
memset(&entry, 0, sizeof(entry));
|
memset(&entry, 0, sizeof(entry));
|
||||||
entry.entryId = entryId;
|
entry.entryId = entryId;
|
||||||
entry.enabled = enabled == 0 ? 0 : 1;
|
entry.enabled = enabled == 0 ? 0 : 1;
|
||||||
@@ -1271,7 +1310,7 @@ void NukiOpenerWrapper::onTimeControlCommandReceived(const char *value)
|
|||||||
{
|
{
|
||||||
char resultStr[15];
|
char resultStr[15];
|
||||||
memset(&resultStr, 0, sizeof(resultStr));
|
memset(&resultStr, 0, sizeof(resultStr));
|
||||||
NukiLock::cmdResultToString(result, resultStr);
|
NukiOpener::cmdResultToString(result, resultStr);
|
||||||
_network->publishTimeControlCommandResult(resultStr);
|
_network->publishTimeControlCommandResult(resultStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ private:
|
|||||||
void updateConfig();
|
void updateConfig();
|
||||||
void updateAuthData();
|
void updateAuthData();
|
||||||
void updateKeypad();
|
void updateKeypad();
|
||||||
void updateTimeControl();
|
void updateTimeControl(bool retrieved);
|
||||||
void postponeBleWatchdog();
|
void postponeBleWatchdog();
|
||||||
|
|
||||||
void updateGpioOutputs();
|
void updateGpioOutputs();
|
||||||
@@ -122,6 +122,7 @@ private:
|
|||||||
unsigned long _nextLockStateUpdateTs = 0;
|
unsigned long _nextLockStateUpdateTs = 0;
|
||||||
unsigned long _nextBatteryReportTs = 0;
|
unsigned long _nextBatteryReportTs = 0;
|
||||||
unsigned long _nextConfigUpdateTs = 0;
|
unsigned long _nextConfigUpdateTs = 0;
|
||||||
|
unsigned long _nextTimeControlUpdateTs = 0;
|
||||||
unsigned long _nextKeypadUpdateTs = 0;
|
unsigned long _nextKeypadUpdateTs = 0;
|
||||||
unsigned long _nextPairTs = 0;
|
unsigned long _nextPairTs = 0;
|
||||||
long _nextRssiTs = 0;
|
long _nextRssiTs = 0;
|
||||||
|
|||||||
@@ -184,6 +184,11 @@ void NukiWrapper::update()
|
|||||||
setupHASS();
|
setupHASS();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(_nextTimeControlUpdateTs != 0 && ts > _nextTimeControlUpdateTs)
|
||||||
|
{
|
||||||
|
_nextTimeControlUpdateTs = 0;
|
||||||
|
updateTimeControl(true);
|
||||||
|
}
|
||||||
if(_hassEnabled && _configRead && _network->reconnected())
|
if(_hassEnabled && _configRead && _network->reconnected())
|
||||||
{
|
{
|
||||||
setupHASS();
|
setupHASS();
|
||||||
@@ -381,7 +386,7 @@ void NukiWrapper::updateConfig()
|
|||||||
_network->publishConfig(_nukiConfig);
|
_network->publishConfig(_nukiConfig);
|
||||||
_retryConfigCount = 0;
|
_retryConfigCount = 0;
|
||||||
|
|
||||||
if(_preferences->getBool(preference_timecontrol_info_enabled)) updateTimeControl();
|
if(_preferences->getBool(preference_timecontrol_info_enabled)) updateTimeControl(false);
|
||||||
|
|
||||||
const int pinStatus = _preferences->getInt(preference_lock_pin_status, 4);
|
const int pinStatus = _preferences->getInt(preference_lock_pin_status, 4);
|
||||||
|
|
||||||
@@ -478,6 +483,9 @@ void NukiWrapper::updateKeypad()
|
|||||||
std::list<NukiLock::KeypadEntry> entries;
|
std::list<NukiLock::KeypadEntry> entries;
|
||||||
_nukiLock.getKeypadEntries(&entries);
|
_nukiLock.getKeypadEntries(&entries);
|
||||||
|
|
||||||
|
Log->print(F("Lock keypad codes: "));
|
||||||
|
Log->println(entries.size());
|
||||||
|
|
||||||
entries.sort([](const NukiLock::KeypadEntry& a, const NukiLock::KeypadEntry& b) { return a.codeId < b.codeId; });
|
entries.sort([](const NukiLock::KeypadEntry& a, const NukiLock::KeypadEntry& b) { return a.codeId < b.codeId; });
|
||||||
|
|
||||||
uint keypadCount = entries.size();
|
uint keypadCount = entries.size();
|
||||||
@@ -500,23 +508,35 @@ void NukiWrapper::updateKeypad()
|
|||||||
postponeBleWatchdog();
|
postponeBleWatchdog();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NukiWrapper::updateTimeControl()
|
void NukiWrapper::updateTimeControl(bool retrieved)
|
||||||
{
|
{
|
||||||
if(!_preferences->getBool(preference_timecontrol_info_enabled)) return;
|
if(!_preferences->getBool(preference_timecontrol_info_enabled)) return;
|
||||||
|
|
||||||
Log->print(F("Querying lock time control: "));
|
if(!retrieved)
|
||||||
Nuki::CmdResult result = _nukiLock.retrieveTimeControlEntries();
|
|
||||||
printCommandResult(result);
|
|
||||||
if(result == Nuki::CmdResult::Success)
|
|
||||||
{
|
{
|
||||||
std::list<NukiLock::TimeControlEntry> entries;
|
Log->print(F("Querying lock time control: "));
|
||||||
_nukiLock.getTimeControlEntries(&entries);
|
Nuki::CmdResult result = _nukiLock.retrieveTimeControlEntries();
|
||||||
|
printCommandResult(result);
|
||||||
|
if(result == Nuki::CmdResult::Success)
|
||||||
|
{
|
||||||
|
_nextTimeControlUpdateTs = millis() + 5000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::list<NukiLock::TimeControlEntry> timeControlEntries;
|
||||||
|
_nukiLock.getTimeControlEntries(&timeControlEntries);
|
||||||
|
|
||||||
entries.sort([](const NukiLock::TimeControlEntry& a, const NukiLock::TimeControlEntry& b) { return a.entryId < b.entryId; });
|
Log->print(F("Lock time control entries: "));
|
||||||
|
Log->println(timeControlEntries.size());
|
||||||
|
|
||||||
|
timeControlEntries.sort([](const NukiLock::TimeControlEntry& a, const NukiLock::TimeControlEntry& b) { return a.entryId < b.entryId; });
|
||||||
|
|
||||||
|
_network->publishTimeControl(timeControlEntries);
|
||||||
|
|
||||||
_timeControlIds.clear();
|
_timeControlIds.clear();
|
||||||
_timeControlIds.reserve(entries.size());
|
_timeControlIds.reserve(timeControlEntries.size());
|
||||||
for(const auto& entry : entries)
|
for(const auto& entry : timeControlEntries)
|
||||||
{
|
{
|
||||||
_timeControlIds.push_back(entry.entryId);
|
_timeControlIds.push_back(entry.entryId);
|
||||||
}
|
}
|
||||||
@@ -532,26 +552,32 @@ void NukiWrapper::postponeBleWatchdog()
|
|||||||
|
|
||||||
NukiLock::LockAction NukiWrapper::lockActionToEnum(const char *str)
|
NukiLock::LockAction NukiWrapper::lockActionToEnum(const char *str)
|
||||||
{
|
{
|
||||||
if(strcmp(str, "unlock") == 0) return NukiLock::LockAction::Unlock;
|
if(strcmp(str, "unlock") == 0 || strcmp(str, "Unlock") == 0) return NukiLock::LockAction::Unlock;
|
||||||
else if(strcmp(str, "lock") == 0) return NukiLock::LockAction::Lock;
|
else if(strcmp(str, "lock") == 0 || strcmp(str, "Lock") == 0) return NukiLock::LockAction::Lock;
|
||||||
else if(strcmp(str, "unlatch") == 0) return NukiLock::LockAction::Unlatch;
|
else if(strcmp(str, "unlatch") == 0 || strcmp(str, "Unlatch") == 0) return NukiLock::LockAction::Unlatch;
|
||||||
else if(strcmp(str, "lockNgo") == 0) return NukiLock::LockAction::LockNgo;
|
else if(strcmp(str, "lockNgo") == 0 || strcmp(str, "LockNgo") == 0) return NukiLock::LockAction::LockNgo;
|
||||||
else if(strcmp(str, "lockNgoUnlatch") == 0) return NukiLock::LockAction::LockNgoUnlatch;
|
else if(strcmp(str, "lockNgoUnlatch") == 0 || strcmp(str, "LockNgoUnlatch") == 0) return NukiLock::LockAction::LockNgoUnlatch;
|
||||||
else if(strcmp(str, "fullLock") == 0) return NukiLock::LockAction::FullLock;
|
else if(strcmp(str, "fullLock") == 0 || strcmp(str, "FullLock") == 0) return NukiLock::LockAction::FullLock;
|
||||||
else if(strcmp(str, "fobAction2") == 0) return NukiLock::LockAction::FobAction2;
|
else if(strcmp(str, "fobAction2") == 0 || strcmp(str, "FobAction2") == 0) return NukiLock::LockAction::FobAction2;
|
||||||
else if(strcmp(str, "fobAction1") == 0) return NukiLock::LockAction::FobAction1;
|
else if(strcmp(str, "fobAction1") == 0 || strcmp(str, "FobAction1") == 0) return NukiLock::LockAction::FobAction1;
|
||||||
else if(strcmp(str, "fobAction3") == 0) return NukiLock::LockAction::FobAction3;
|
else if(strcmp(str, "fobAction3") == 0 || strcmp(str, "FobAction3") == 0) return NukiLock::LockAction::FobAction3;
|
||||||
return (NukiLock::LockAction)0xff;
|
return (NukiLock::LockAction)0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
LockActionResult NukiWrapper::onLockActionReceivedCallback(const char *value)
|
LockActionResult NukiWrapper::onLockActionReceivedCallback(const char *value)
|
||||||
{
|
{
|
||||||
NukiLock::LockAction action = nukiInst->lockActionToEnum(value);
|
NukiLock::LockAction action;
|
||||||
|
|
||||||
if((int)action == 0xff)
|
if(strlen(value) > 0)
|
||||||
{
|
{
|
||||||
return LockActionResult::UnknownAction;
|
action = nukiInst->lockActionToEnum(value);
|
||||||
|
|
||||||
|
if((int)action == 0xff)
|
||||||
|
{
|
||||||
|
return LockActionResult::UnknownAction;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else return LockActionResult::UnknownAction;
|
||||||
|
|
||||||
nukiLockPreferences = new Preferences();
|
nukiLockPreferences = new Preferences();
|
||||||
nukiLockPreferences->begin("nukihub", true);
|
nukiLockPreferences->begin("nukihub", true);
|
||||||
@@ -821,7 +847,7 @@ void NukiWrapper::onKeypadJsonCommandReceived(const char *value)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicJsonDocument json(2048);
|
JsonDocument json;
|
||||||
DeserializationError jsonError = deserializeJson(json, value);
|
DeserializationError jsonError = deserializeJson(json, value);
|
||||||
|
|
||||||
if(jsonError)
|
if(jsonError)
|
||||||
@@ -1150,9 +1176,21 @@ void NukiWrapper::onTimeControlCommandReceived(const char *value)
|
|||||||
uint8_t enabled = json["enabled"].as<unsigned int>();
|
uint8_t enabled = json["enabled"].as<unsigned int>();
|
||||||
String weekdays = json["weekdays"].as<String>();
|
String weekdays = json["weekdays"].as<String>();
|
||||||
const char *time = json["time"].as<const char*>();
|
const char *time = json["time"].as<const char*>();
|
||||||
NukiLock::LockAction timeControlLockAction = nukiInst->lockActionToEnum(json["lockAction"].as<const char*>());
|
const char *lockAct = json["lockAction"].as<const char*>();
|
||||||
|
NukiLock::LockAction timeControlLockAction;
|
||||||
|
|
||||||
if((int)timeControlLockAction == 0xff)
|
if(strlen(lockAct) > 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
timeControlLockAction = nukiInst->lockActionToEnum(lockAct);
|
||||||
|
|
||||||
|
if((int)timeControlLockAction == 0xff)
|
||||||
|
{
|
||||||
|
_network->publishTimeControlCommandResult("invalidLockAction");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
_network->publishTimeControlCommandResult("invalidLockAction");
|
_network->publishTimeControlCommandResult("invalidLockAction");
|
||||||
return;
|
return;
|
||||||
@@ -1197,19 +1235,19 @@ void NukiWrapper::onTimeControlCommandReceived(const char *value)
|
|||||||
|
|
||||||
if(timeAr[0] < 0 || timeAr[0] > 23 || timeAr[1] < 0 || timeAr[1] > 59)
|
if(timeAr[0] < 0 || timeAr[0] > 23 || timeAr[1] < 0 || timeAr[1] > 59)
|
||||||
{
|
{
|
||||||
_network->publishKeypadJsonCommandResult("invalidTime");
|
_network->publishTimeControlCommandResult("invalidTime");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_network->publishKeypadJsonCommandResult("invalidTime");
|
_network->publishTimeControlCommandResult("invalidTime");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_network->publishKeypadJsonCommandResult("invalidTime");
|
_network->publishTimeControlCommandResult("invalidTime");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1235,7 +1273,7 @@ void NukiWrapper::onTimeControlCommandReceived(const char *value)
|
|||||||
|
|
||||||
entry.lockAction = timeControlLockAction;
|
entry.lockAction = timeControlLockAction;
|
||||||
|
|
||||||
result = _nukiLock.addKeypadEntry(entry);
|
result = _nukiLock.addTimeControlEntry(entry);
|
||||||
Log->print("Add time control: ");
|
Log->print("Add time control: ");
|
||||||
Log->println((int)result);
|
Log->println((int)result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ private:
|
|||||||
void updateConfig();
|
void updateConfig();
|
||||||
void updateAuthData();
|
void updateAuthData();
|
||||||
void updateKeypad();
|
void updateKeypad();
|
||||||
void updateTimeControl();
|
void updateTimeControl(bool retrieved);
|
||||||
void postponeBleWatchdog();
|
void postponeBleWatchdog();
|
||||||
|
|
||||||
void updateGpioOutputs();
|
void updateGpioOutputs();
|
||||||
@@ -121,6 +121,7 @@ private:
|
|||||||
unsigned long _nextLockStateUpdateTs = 0;
|
unsigned long _nextLockStateUpdateTs = 0;
|
||||||
unsigned long _nextBatteryReportTs = 0;
|
unsigned long _nextBatteryReportTs = 0;
|
||||||
unsigned long _nextConfigUpdateTs = 0;
|
unsigned long _nextConfigUpdateTs = 0;
|
||||||
|
unsigned long _nextTimeControlUpdateTs = 0;
|
||||||
unsigned long _nextKeypadUpdateTs = 0;
|
unsigned long _nextKeypadUpdateTs = 0;
|
||||||
unsigned long _nextRssiTs = 0;
|
unsigned long _nextRssiTs = 0;
|
||||||
unsigned long _lastRssi = 0;
|
unsigned long _lastRssi = 0;
|
||||||
|
|||||||
@@ -399,13 +399,13 @@ To change Nuki Lock/Opener time control settings set the `timecontrol/actionJson
|
|||||||
| enabled | Not used | Not used | Optional | Enable or disable the entry, enabled if not set | 1 = enabled, 0 = disabled |
|
| enabled | Not used | Not used | Optional | Enable or disable the entry, enabled if not set | 1 = enabled, 0 = disabled |
|
||||||
| weekdays | Not used | Optional | Optional | Weekdays on which the chosen lock action should be exectued | Array of days: "mon", "tue", "wed", "thu" , "fri" "sat", "sun" |
|
| weekdays | Not used | Optional | Optional | Weekdays on which the chosen lock action should be exectued | Array of days: "mon", "tue", "wed", "thu" , "fri" "sat", "sun" |
|
||||||
| time | Not used | Required | Required | The time on which the chosen lock action should be executed | "HH:MM" |
|
| time | Not used | Required | Required | The time on which the chosen lock action should be executed | "HH:MM" |
|
||||||
| lockaction | Not used | Required | Required | The lock action that should be executed on the chosen weekdays at the chosen time | For the Nuki lock: "Unlock", "Lock", "Unlatch", "LockNgo", "LockNgoUnlatch", "FullLock", "FobAction1", "FobAction2", "FobAction3. For the Nuki Opener: "ActivateRTO", "DeactivateRTO", "ElectricStrikeActuation", "ActivateCM", "DeactivateCM", "FobAction1", "FobAction2", "FobAction3" |
|
| lockAction | Not used | Required | Required | The lock action that should be executed on the chosen weekdays at the chosen time | For the Nuki lock: "Unlock", "Lock", "Unlatch", "LockNgo", "LockNgoUnlatch", "FullLock". For the Nuki Opener: "ActivateRTO", "DeactivateRTO", "ElectricStrikeActuation", "ActivateCM", "DeactivateCM" |
|
||||||
|
|
||||||
Example usage:<br>
|
Example usage:<br>
|
||||||
Examples:
|
Examples:
|
||||||
- Delete: `{ "action": "delete", "entryId": "1234" }`
|
- Delete: `{ "action": "delete", "entryId": "1234" }`
|
||||||
- Add: `{ "action": "add", "weekdays": [ "wed", "thu", "fri" ], "time": "08:00", "lockaction": "unlock" }`
|
- Add: `{ "action": "add", "weekdays": [ "wed", "thu", "fri" ], "time": "08:00", "lockAction": "Unlock" }`
|
||||||
- Update: `{ "action": "update", "entryId": "1234", "enabled": "1", "weekdays": [ "mon", "tue", "sat", "sun" ], "time": "08:00", "lockaction": "lock" }`
|
- Update: `{ "action": "update", "entryId": "1234", "enabled": "1", "weekdays": [ "mon", "tue", "sat", "sun" ], "time": "08:00", "lockAction": "Lock" }`
|
||||||
|
|
||||||
## GPIO lock control (optional)
|
## GPIO lock control (optional)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user