add keypad control for opener

This commit is contained in:
technyon
2023-02-07 20:15:23 +01:00
parent ad648cc22d
commit 47c673fa08
11 changed files with 306 additions and 12 deletions

View File

@@ -25,6 +25,7 @@ NukiOpenerWrapper::NukiOpenerWrapper(const std::string& deviceName, uint32_t id,
network->setLockActionReceivedCallback(nukiOpenerInst->onLockActionReceivedCallback);
network->setConfigUpdateReceivedCallback(nukiOpenerInst->onConfigUpdateReceivedCallback);
network->setKeypadCommandReceivedCallback(nukiOpenerInst->onKeypadCommandReceivedCallback);
}
@@ -40,10 +41,12 @@ void NukiOpenerWrapper::initialize()
_nukiOpener.registerBleScanner(_bleScanner);
_intervalLockstate = _preferences->getInt(preference_query_interval_lockstate);
_intervalConfig = _preferences->getInt(preference_query_interval_battery);
_intervalBattery = _preferences->getInt(preference_query_interval_battery);
_intervalConfig = _preferences->getInt(preference_query_interval_configuration);
_intervalBattery = _preferences->getInt(preference_query_interval_battery);
_intervalKeypad = _preferences->getInt(preference_query_interval_keypad);
_keypadEnabled = _preferences->getBool(preference_keypad_control_enabled);
_publishAuthData = _preferences->getBool(preference_publish_authdata);
_maxKeypadCodeCount = _preferences->getUInt(preference_opener_max_keypad_code_count);
_restartBeaconTimeout = _preferences->getInt(preference_restart_ble_beacon_lost);
_hassEnabled = _preferences->getString(preference_mqtt_hass_discovery) != "";
_nrOfRetries = _preferences->getInt(preference_command_nr_of_retries);
@@ -71,6 +74,11 @@ void NukiOpenerWrapper::initialize()
_intervalBattery = 60 * 30;
_preferences->putInt(preference_query_interval_battery, _intervalBattery);
}
if(_intervalKeypad == 0)
{
_intervalKeypad = 60 * 30;
_preferences->putInt(preference_query_interval_keypad, _intervalKeypad);
}
/*
if(_intervalKeypad == 0)
{
@@ -172,6 +180,12 @@ void NukiOpenerWrapper::update()
}
}
if(_hasKeypad && _keypadEnabled && (_nextKeypadUpdateTs == 0 || ts > _nextKeypadUpdateTs))
{
_nextKeypadUpdateTs = ts + _intervalKeypad * 1000;
updateKeypad();
}
if(_nextLockAction != (NukiOpener::LockAction)0xff && ts > _nextRetryTs)
{
Nuki::CmdResult cmdResult = _nukiOpener.lockAction(_nextLockAction, 0, 0);
@@ -296,6 +310,8 @@ void NukiOpenerWrapper::updateConfig()
{
readConfig();
readAdvancedConfig();
_configRead = true;
_hasKeypad = _nukiConfig.hasKeypad > 0;
_network->publishConfig(_nukiConfig);
_network->publishAdvancedConfig(_nukiAdvancedConfig);
}
@@ -328,6 +344,35 @@ void NukiOpenerWrapper::updateAuthData()
postponeBleWatchdog();
}
void NukiOpenerWrapper::updateKeypad()
{
Nuki::CmdResult result = _nukiOpener.retrieveKeypadEntries(0, 0xffff);
if(result == 1)
{
std::list<NukiLock::KeypadEntry> entries;
_nukiOpener.getKeypadEntries(&entries);
entries.sort([](const NukiLock::KeypadEntry& a, const NukiLock::KeypadEntry& b) { return a.codeId < b.codeId; });
uint keypadCount = entries.size();
if(keypadCount > _maxKeypadCodeCount)
{
_maxKeypadCodeCount = keypadCount;
_preferences->putUInt(preference_opener_max_keypad_code_count, _maxKeypadCodeCount);
}
_network->publishKeypad(entries, _maxKeypadCodeCount);
_keypadCodeIds.clear();
_keypadCodeIds.reserve(entries.size());
for(const auto& entry : entries)
{
_keypadCodeIds.push_back(entry.codeId);
}
}
postponeBleWatchdog();
}
void NukiOpenerWrapper::postponeBleWatchdog()
{
_disableBleWatchdogTs = millis() + 15000;
@@ -358,6 +403,10 @@ void NukiOpenerWrapper::onConfigUpdateReceivedCallback(const char *topic, const
nukiOpenerInst->onConfigUpdateReceived(topic, value);
}
void NukiOpenerWrapper::onKeypadCommandReceivedCallback(const char *command, const uint &id, const String &name, const String &code, const int& enabled)
{
nukiOpenerInst->onKeypadCommandReceived(command, id, name, code, enabled);
}
void NukiOpenerWrapper::onConfigUpdateReceived(const char *topic, const char *value)
{
@@ -384,6 +433,117 @@ void NukiOpenerWrapper::onConfigUpdateReceived(const char *topic, const char *va
}
}
void NukiOpenerWrapper::onKeypadCommandReceived(const char *command, const uint &id, const String &name, const String &code, const int& enabled)
{
if(!_hasKeypad)
{
if(_configRead)
{
_network->publishKeypadCommandResult("KeypadNotAvailable");
}
return;
}
if(!_keypadEnabled)
{
return;
}
bool idExists = std::find(_keypadCodeIds.begin(), _keypadCodeIds.end(), id) != _keypadCodeIds.end();
int codeInt = code.toInt();
bool codeValid = codeInt > 100000 && codeInt < 1000000 && (code.indexOf('0') == -1);
NukiLock::CmdResult result = (NukiLock::CmdResult)-1;
if(strcmp(command, "add") == 0)
{
if(name == "" || name == "--")
{
_network->publishKeypadCommandResult("MissingParameterName");
return;
}
if(codeInt == 0)
{
_network->publishKeypadCommandResult("MissingParameterCode");
return;
}
if(!codeValid)
{
_network->publishKeypadCommandResult("CodeInvalid");
return;
}
NukiLock::NewKeypadEntry entry;
memset(&entry, 0, sizeof(entry));
size_t nameLen = name.length();
memcpy(&entry.name, name.c_str(), nameLen > 20 ? 20 : nameLen);
entry.code = codeInt;
result = _nukiOpener.addKeypadEntry(entry);
Log->print("Add keypad code: "); Log->println((int)result);
updateKeypad();
}
else if(strcmp(command, "delete") == 0)
{
if(!idExists)
{
_network->publishKeypadCommandResult("UnknownId");
return;
}
result = _nukiOpener.deleteKeypadEntry(id);
Log->print("Delete keypad code: "); Log->println((int)result);
updateKeypad();
}
else if(strcmp(command, "update") == 0)
{
if(name == "" || name == "--")
{
_network->publishKeypadCommandResult("MissingParameterName");
return;
}
if(codeInt == 0)
{
_network->publishKeypadCommandResult("MissingParameterCode");
return;
}
if(!codeValid)
{
_network->publishKeypadCommandResult("CodeInvalid");
return;
}
if(!idExists)
{
_network->publishKeypadCommandResult("UnknownId");
return;
}
NukiLock::UpdatedKeypadEntry entry;
memset(&entry, 0, sizeof(entry));
entry.codeId = id;
size_t nameLen = name.length();
memcpy(&entry.name, name.c_str(), nameLen > 20 ? 20 : nameLen);
entry.code = codeInt;
entry.enabled = enabled == 0 ? 0 : 1;
result = _nukiOpener.updateKeypadEntry(entry);
Log->print("Update keypad code: "); Log->println((int)result);
updateKeypad();
}
else if(command == "--")
{
return;
}
else
{
_network->publishKeypadCommandResult("UnknownCommand");
return;
}
if((int)result != -1)
{
char resultStr[15];
memset(&resultStr, 0, sizeof(resultStr));
NukiOpener::cmdResultToString(result, resultStr);
_network->publishKeypadCommandResult(resultStr);
}
}
const NukiOpener::OpenerState &NukiOpenerWrapper::keyTurnerState()
{
return _keyTurnerState;