Add Authorization entries (#456)

* Add and remove libs and components for Arduino Core 3

* Arduino Core 3

* Add back Solo1

* Change ESP32-S3 to 4MB build

* Add Authorization info and control

* Use esp_crt_bundle for HTTPS requests

* Remove Solo1 support

* Improve Nuki device config read functions

* Webserial

* OTA Improvements

* Authorization Entries

* Authorization entries

* Authorization
This commit is contained in:
iranl
2024-08-17 05:21:22 +02:00
committed by GitHub
parent 00a9b30a39
commit b298d410eb
20 changed files with 1728 additions and 155 deletions

View File

@@ -69,7 +69,7 @@ void NukiNetworkOpener::initialize()
_network->removeTopic(_mqttPath, mqtt_topic_battery_keypad_critical);
//_network->removeTopic(_mqttPath, mqtt_topic_presence);
}
if(!_preferences->getBool(preference_conf_info_enabled, true))
{
_network->removeTopic(_mqttPath, mqtt_topic_config_basic_json);
@@ -110,6 +110,12 @@ void NukiNetworkOpener::initialize()
_network->initTopic(_mqttPath, mqtt_topic_timecontrol_action, "--");
}
if(_preferences->getBool(preference_auth_control_enabled))
{
_network->subscribe(_mqttPath, mqtt_topic_auth_action);
_network->initTopic(_mqttPath, mqtt_topic_auth_action, "--");
}
if(_preferences->getBool(preference_publish_authdata, false))
{
_network->subscribe(_mqttPath, mqtt_topic_lock_log_rolling_last);
@@ -281,6 +287,18 @@ void NukiNetworkOpener::onMqttDataReceived(const char* topic, byte* payload, con
publishString(mqtt_topic_timecontrol_action, "--", true);
}
if(comparePrefixedPath(topic, mqtt_topic_auth_action))
{
if(strcmp(value, "") == 0 || strcmp(value, "--") == 0) return;
if(_authCommandReceivedReceivedCallback != NULL)
{
_authCommandReceivedReceivedCallback(value);
}
publishString(mqtt_topic_auth_action, "--", true);
}
}
void NukiNetworkOpener::publishKeyTurnerState(const NukiOpener::OpenerState& keyTurnerState, const NukiOpener::OpenerState& lastKeyTurnerState)
@@ -501,7 +519,7 @@ void NukiNetworkOpener::publishAuthorizationInfo(const std::list<NukiOpener::Log
memset(str, 0, sizeof(str));
NukiOpener::lockactionToString((NukiOpener::LockAction)log.data[0], str);
entry["action"] = str;
switch(log.data[1])
{
case 0:
@@ -527,7 +545,7 @@ void NukiNetworkOpener::publishAuthorizationInfo(const std::list<NukiOpener::Log
NukiOpener::completionStatusToString((NukiOpener::CompletionStatus)log.data[2], str);
entry["completionStatus"] = str;
}
entry["codeId"] = 256U*log.data[4]+log.data[3];
break;
case NukiOpener::LoggingType::DoorbellRecognition:
@@ -583,7 +601,7 @@ void NukiNetworkOpener::publishAuthorizationInfo(const std::list<NukiOpener::Log
entry["codeId"] = 256U*log.data[7]+log.data[6];
break;
}
if(log.index > _lastRollingLog)
{
_lastRollingLog = log.index;
@@ -654,7 +672,7 @@ void NukiNetworkOpener::publishConfig(const NukiOpener::Config &config)
itoa(config.nukiId, uidString, 16);
JsonDocument json;
memset(_nukiName, 0, sizeof(_nukiName));
memcpy(_nukiName, config.name, sizeof(config.name));
@@ -1000,7 +1018,7 @@ void NukiNetworkOpener::publishKeypad(const std::list<NukiLock::KeypadEntry>& en
_network->removeTopic(codeTopic, "createdSec");
_network->removeTopic(codeTopic, "lockCount");
}
for(int j=entries.size(); j<maxKeypadCodeCount; j++)
{
String codesTopic = _mqttPath;
@@ -1084,7 +1102,7 @@ void NukiNetworkOpener::publishTimeControl(const std::list<NukiOpener::TimeContr
memset(str, 0, sizeof(str));
NukiOpener::lockactionToString(entry.lockAction, str);
jsonEntry["lockAction"] = str;
if(topicPerEntry)
{
String basePath = mqtt_topic_timecontrol;
@@ -1093,7 +1111,6 @@ void NukiNetworkOpener::publishTimeControl(const std::list<NukiOpener::TimeContr
jsonEntry["index"] = index;
serializeJson(jsonEntry, _buffer, _bufferSize);
publishString(basePath.c_str(), _buffer, true);
String basePathPrefix = "~";
basePathPrefix.concat(basePath);
const char *basePathPrefixChr = basePathPrefix.c_str();
@@ -1103,7 +1120,7 @@ void NukiNetworkOpener::publishTimeControl(const std::list<NukiOpener::TimeContr
std::string mqttDeviceName = std::string("timecontrol_") + std::to_string(index);
std::string uidStringPostfix = std::string("_") + mqttDeviceName;
std::string displayName = std::string("Timecontrol - ") + std::to_string(entry.entryId);
_network->publishHassTopic("switch",
mqttDeviceName.c_str(),
uidString,
@@ -1124,13 +1141,13 @@ void NukiNetworkOpener::publishTimeControl(const std::list<NukiOpener::TimeContr
{ (char*)"stat_on", (char*)"1" },
{ (char*)"stat_off", (char*)"0" }});
}
++index;
}
serializeJson(json, _buffer, _bufferSize);
publishString(mqtt_topic_timecontrol_json, _buffer, true);
for(int j=timeControlEntries.size(); j<maxTimeControlEntryCount; j++)
{
String entriesTopic = _mqttPath;
@@ -1142,6 +1159,152 @@ void NukiNetworkOpener::publishTimeControl(const std::list<NukiOpener::TimeContr
}
}
void NukiNetworkOpener::publishAuth(const std::list<NukiOpener::AuthorizationEntry>& authEntries, uint maxAuthEntryCount)
{
uint index = 0;
char str[50];
char uidString[20];
itoa(_preferences->getUInt(preference_nuki_id_opener, 0), uidString, 16);
String baseTopic = _preferences->getString(preference_mqtt_opener_path);
JsonDocument json;
for(const auto& entry : authEntries)
{
auto jsonEntry = json.add<JsonVariant>();
jsonEntry["authId"] = entry.authId;
jsonEntry["idType"] = entry.idType; //CONSIDER INT TO STRING
jsonEntry["enabled"] = entry.enabled;
jsonEntry["name"] = entry.name;
jsonEntry["remoteAllowed"] = entry.remoteAllowed;
char createdDT[20];
sprintf(createdDT, "%04d-%02d-%02d %02d:%02d:%02d", entry.createdYear, entry.createdMonth, entry.createdDay, entry.createdHour, entry.createdMinute, entry.createdSecond);
jsonEntry["dateCreated"] = createdDT;
jsonEntry["lockCount"] = entry.lockCount;
char lastActiveDT[20];
sprintf(lastActiveDT, "%04d-%02d-%02d %02d:%02d:%02d", entry.lastActYear, entry.lastActMonth, entry.lastActDay, entry.lastActHour, entry.lastActMinute, entry.lastActSecond);
jsonEntry["dateLastActive"] = lastActiveDT;
jsonEntry["timeLimited"] = entry.timeLimited;
char allowedFromDT[20];
sprintf(allowedFromDT, "%04d-%02d-%02d %02d:%02d:%02d", entry.allowedFromYear, entry.allowedFromMonth, entry.allowedFromDay, entry.allowedFromHour, entry.allowedFromMinute, entry.allowedFromSecond);
jsonEntry["allowedFrom"] = allowedFromDT;
char allowedUntilDT[20];
sprintf(allowedUntilDT, "%04d-%02d-%02d %02d:%02d:%02d", entry.allowedUntilYear, entry.allowedUntilMonth, entry.allowedUntilDay, entry.allowedUntilHour, entry.allowedUntilMinute, entry.allowedUntilSecond);
jsonEntry["allowedUntil"] = allowedUntilDT;
uint8_t allowedWeekdaysInt = entry.allowedWeekdays;
JsonArray weekdays = jsonEntry["allowedWeekdays"].to<JsonArray>();
while(allowedWeekdaysInt > 0) {
if(allowedWeekdaysInt >= 64)
{
weekdays.add("mon");
allowedWeekdaysInt -= 64;
continue;
}
if(allowedWeekdaysInt >= 32)
{
weekdays.add("tue");
allowedWeekdaysInt -= 32;
continue;
}
if(allowedWeekdaysInt >= 16)
{
weekdays.add("wed");
allowedWeekdaysInt -= 16;
continue;
}
if(allowedWeekdaysInt >= 8)
{
weekdays.add("thu");
allowedWeekdaysInt -= 8;
continue;
}
if(allowedWeekdaysInt >= 4)
{
weekdays.add("fri");
allowedWeekdaysInt -= 4;
continue;
}
if(allowedWeekdaysInt >= 2)
{
weekdays.add("sat");
allowedWeekdaysInt -= 2;
continue;
}
if(allowedWeekdaysInt >= 1)
{
weekdays.add("sun");
allowedWeekdaysInt -= 1;
continue;
}
}
char allowedFromTimeT[5];
sprintf(allowedFromTimeT, "%02d:%02d", entry.allowedFromTimeHour, entry.allowedFromTimeMin);
jsonEntry["allowedFromTime"] = allowedFromTimeT;
char allowedUntilTimeT[5];
sprintf(allowedUntilTimeT, "%02d:%02d", entry.allowedUntilTimeHour, entry.allowedUntilTimeMin);
jsonEntry["allowedUntilTime"] = allowedUntilTimeT;
if(_preferences->getBool(preference_auth_topic_per_entry, false))
{
String basePath = mqtt_topic_auth;
basePath.concat("/entries/");
basePath.concat(std::to_string(index).c_str());
jsonEntry["index"] = index;
serializeJson(jsonEntry, _buffer, _bufferSize);
publishString(basePath.c_str(), _buffer, true);
String basePathPrefix = "~";
basePathPrefix.concat(basePath);
const char *basePathPrefixChr = basePathPrefix.c_str();
std::string baseCommand = std::string("{ \"action\": \"update\", \"authId\": \"") + std::to_string(entry.authId);
std::string enaCommand = baseCommand + (char*)"\", \"enabled\": \"1\" }";
std::string disCommand = baseCommand + (char*)"\", \"enabled\": \"0\" }";
std::string mqttDeviceName = std::string("auth_") + std::to_string(index);
std::string uidStringPostfix = std::string("_") + mqttDeviceName;
std::string displayName = std::string("Authorization - ") + std::to_string(entry.authId);
_network->publishHassTopic("switch",
mqttDeviceName.c_str(),
uidString,
uidStringPostfix.c_str(),
displayName.c_str(),
_nukiName,
baseTopic.c_str(),
String("~") + basePath.c_str(),
(char*)"Opener",
"",
"",
"diagnostic",
String("~") + mqtt_topic_auth_action,
{ { (char*)"json_attr_t", (char*)basePathPrefixChr },
{ (char*)"pl_on", (char*)enaCommand.c_str() },
{ (char*)"pl_off", (char*)disCommand.c_str() },
{ (char*)"val_tpl", (char*)"{{value_json.enabled}}" },
{ (char*)"stat_on", (char*)"1" },
{ (char*)"stat_off", (char*)"0" }});
}
++index;
}
serializeJson(json, _buffer, _bufferSize);
publishString(mqtt_topic_auth_json, _buffer, true);
for(int j=authEntries.size(); j<maxAuthEntryCount; j++)
{
String entriesTopic = _mqttPath;
entriesTopic.concat(mqtt_topic_auth_entries);
entriesTopic.concat("/");
_network->removeTopic(entriesTopic, (char*)std::to_string(j).c_str());
std::string mqttDeviceName = std::string("auth_") + std::to_string(j);
_network->removeHassTopic((char*)"switch", (char*)mqttDeviceName.c_str(), uidString);
}
}
void NukiNetworkOpener::publishConfigCommandResult(const char* result)
{
publishString(mqtt_topic_config_action_command_result, result, true);
@@ -1163,6 +1326,11 @@ void NukiNetworkOpener::publishTimeControlCommandResult(const char* result)
publishString(mqtt_topic_timecontrol_command_result, result, true);
}
void NukiNetworkOpener::publishAuthCommandResult(const char* result)
{
publishString(mqtt_topic_auth_command_result, result, true);
}
void NukiNetworkOpener::publishStatusUpdated(const bool statusUpdated)
{
publishBool(mqtt_topic_lock_status_updated, statusUpdated, true);
@@ -1194,6 +1362,11 @@ void NukiNetworkOpener::setTimeControlCommandReceivedCallback(void (*timeControl
_timeControlCommandReceivedReceivedCallback = timeControlCommandReceivedReceivedCallback;
}
void NukiNetworkOpener::setAuthCommandReceivedCallback(void (*authCommandReceivedReceivedCallback)(const char *))
{
_authCommandReceivedReceivedCallback = authCommandReceivedReceivedCallback;
}
void NukiNetworkOpener::publishFloat(const char *topic, const float value, bool retain, const uint8_t precision)
{
_network->publishFloat(_mqttPath, topic, value, retain, precision);