diff --git a/src/NetworkLock.cpp b/src/NetworkLock.cpp index 0d126db..9cc26aa 100644 --- a/src/NetworkLock.cpp +++ b/src/NetworkLock.cpp @@ -55,7 +55,7 @@ void NetworkLock::initialize() _network->subscribe(_mqttPath, mqtt_topic_webserver_action); _network->initTopic(_mqttPath, mqtt_topic_webserver_action, "--"); - _network->initTopic(_mqttPath, mqtt_topic_webserver_state, _preferences->getBool(preference_webserver_enabled, true) ? 1 : 0); + _network->initTopic(_mqttPath, mqtt_topic_webserver_state, (_preferences->getBool(preference_webserver_enabled, true) ? "1" : "0")); _network->initTopic(_mqttPath, mqtt_topic_query_config, "0"); _network->initTopic(_mqttPath, mqtt_topic_query_lockstate, "0"); @@ -111,22 +111,21 @@ void NetworkLock::onMqttDataReceived(const char* topic, byte* payload, const uns if(strcmp(value, "") == 0 || strcmp(value, "--") == 0) return; - publishString(mqtt_topic_webserver_action, "--"); - if(strcmp(value, "1") == 0) { - if(_preferences->getBool(preference_webserver_enabled)) return; + if(_preferences->getBool(preference_webserver_enabled, true)) return; Log->println(F("Webserver enabled, restarting.")); _preferences->putBool(preference_webserver_enabled, true); } else if (strcmp(value, "0") == 0) { - if(!_preferences->getBool(preference_webserver_enabled)) return; + if(!_preferences->getBool(preference_webserver_enabled, true)) return; Log->println(F("Webserver disabled, restarting.")); _preferences->putBool(preference_webserver_enabled, false); } + publishString(mqtt_topic_webserver_action, "--"); _network->clearWifiFallback(); delay(200); restartEsp(RestartReason::RequestedViaMqtt); @@ -410,15 +409,8 @@ void NetworkLock::publishAuthorizationInfo(const std::list& JsonDocument json; - int i = 5; for(const auto& log : logEntries) { - if(i <= 0) - { - break; - } - --i; - memset(authName, 0, sizeof(authName)); authName[0] = '\0'; @@ -468,6 +460,7 @@ void NetworkLock::publishAuthorizationInfo(const std::list& memset(str, 0, sizeof(str)); NukiLock::completionStatusToString((NukiLock::CompletionStatus)log.data[3], str); entry["completionStatus"] = str; + entry["completionStatusVal"] = log.data[3]; break; case NukiLock::LoggingType::KeypadAction: memset(str, 0, sizeof(str)); @@ -477,6 +470,7 @@ void NetworkLock::publishAuthorizationInfo(const std::list& 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)); diff --git a/src/NetworkOpener.cpp b/src/NetworkOpener.cpp index 574d646..3b5ad69 100644 --- a/src/NetworkOpener.cpp +++ b/src/NetworkOpener.cpp @@ -378,15 +378,8 @@ void NetworkOpener::publishAuthorizationInfo(const std::listgetInt(preference_authlog_max_entries, 5), 1, false); Log->print(F("Retrieve log entries: ")); Log->println(result); if(result != Nuki::CmdResult::Success) @@ -493,11 +493,16 @@ void NukiOpenerWrapper::updateAuthData() return; } - delay(100); + delay(_preferences->getInt(preference_authlog_max_entries, 5) * 30); std::list log; _nukiOpener.getLogEntries(&log); + if(log.size() > _preferences->getInt(preference_authlog_max_entries, 5)) + { + log.resize(_preferences->getInt(preference_authlog_max_entries, 5)); + } + Log->print(F("Log size: ")); Log->println(log.size()); @@ -513,7 +518,7 @@ void NukiOpenerWrapper::updateKeypad() if(!_preferences->getBool(preference_keypad_info_enabled)) return; Log->print(F("Querying opener keypad: ")); - Nuki::CmdResult result = _nukiOpener.retrieveKeypadEntries(0, 0xffff); + Nuki::CmdResult result = _nukiOpener.retrieveKeypadEntries(0, _preferences->getInt(preference_keypad_max_entries, 10)); printCommandResult(result); if(result == Nuki::CmdResult::Success) { @@ -525,6 +530,11 @@ void NukiOpenerWrapper::updateKeypad() entries.sort([](const NukiLock::KeypadEntry& a, const NukiLock::KeypadEntry& b) { return a.codeId < b.codeId; }); + if(entries.size() > _preferences->getInt(preference_keypad_max_entries, 10)) + { + entries.resize(_preferences->getInt(preference_keypad_max_entries, 10)); + } + uint keypadCount = entries.size(); if(keypadCount > _maxKeypadCodeCount) { @@ -572,6 +582,11 @@ void NukiOpenerWrapper::updateTimeControl(bool retrieved) timeControlEntries.sort([](const NukiOpener::TimeControlEntry& a, const NukiOpener::TimeControlEntry& b) { return a.entryId < b.entryId; }); + if(timeControlEntries.size() > _preferences->getInt(preference_timecontrol_max_entries, 10)) + { + timeControlEntries.resize(_preferences->getInt(preference_timecontrol_max_entries, 10)); + } + _network->publishTimeControl(timeControlEntries); _timeControlIds.clear(); @@ -1706,7 +1721,7 @@ void NukiOpenerWrapper::onKeypadJsonCommandReceived(const char *value) auto it = std::find(_keypadCodeIds.begin(), _keypadCodeIds.end(), codeId); entry.code = _keypadCodes[(it - _keypadCodeIds.begin())]; } - + entry.enabled = enabled == 0 ? 0 : 1; entry.timeLimited = timeLimited == 1 ? 1 : 0; diff --git a/src/NukiWrapper.cpp b/src/NukiWrapper.cpp index 65533db..14f739b 100644 --- a/src/NukiWrapper.cpp +++ b/src/NukiWrapper.cpp @@ -466,7 +466,7 @@ void NukiWrapper::updateAuthData() return; } - Nuki::CmdResult result = _nukiLock.retrieveLogEntries(0, 5, 1, false); + Nuki::CmdResult result = _nukiLock.retrieveLogEntries(0, _preferences->getInt(preference_authlog_max_entries, 5), 1, false); Log->print(F("Retrieve log entries: ")); Log->println(result); if(result != Nuki::CmdResult::Success) @@ -474,10 +474,15 @@ void NukiWrapper::updateAuthData() return; } - delay(100); + delay(_preferences->getInt(preference_authlog_max_entries, 5) * 30); std::list log; _nukiLock.getLogEntries(&log); + + if(log.size() > _preferences->getInt(preference_authlog_max_entries, 5)) + { + log.resize(_preferences->getInt(preference_authlog_max_entries, 5)); + } Log->print(F("Log size: ")); Log->println(log.size()); @@ -494,7 +499,7 @@ void NukiWrapper::updateKeypad() if(!_preferences->getBool(preference_keypad_info_enabled)) return; Log->print(F("Querying lock keypad: ")); - Nuki::CmdResult result = _nukiLock.retrieveKeypadEntries(0, 0xffff); + Nuki::CmdResult result = _nukiLock.retrieveKeypadEntries(0, _preferences->getInt(preference_keypad_max_entries, 10)); printCommandResult(result); if(result == Nuki::CmdResult::Success) { @@ -505,6 +510,11 @@ void NukiWrapper::updateKeypad() Log->println(entries.size()); entries.sort([](const NukiLock::KeypadEntry& a, const NukiLock::KeypadEntry& b) { return a.codeId < b.codeId; }); + + if(entries.size() > _preferences->getInt(preference_keypad_max_entries, 10)) + { + entries.resize(_preferences->getInt(preference_keypad_max_entries, 10)); + } uint keypadCount = entries.size(); if(keypadCount > _maxKeypadCodeCount) @@ -552,7 +562,12 @@ void NukiWrapper::updateTimeControl(bool retrieved) Log->println(timeControlEntries.size()); timeControlEntries.sort([](const NukiLock::TimeControlEntry& a, const NukiLock::TimeControlEntry& b) { return a.entryId < b.entryId; }); - + + if(timeControlEntries.size() > _preferences->getInt(preference_timecontrol_max_entries, 10)) + { + timeControlEntries.resize(_preferences->getInt(preference_timecontrol_max_entries, 10)); + } + _network->publishTimeControl(timeControlEntries); _timeControlIds.clear(); diff --git a/src/PreferencesKeys.h b/src/PreferencesKeys.h index 8ad13be..cea02b4 100644 --- a/src/PreferencesKeys.h +++ b/src/PreferencesKeys.h @@ -72,6 +72,12 @@ #define preference_has_mac_byte_1 (char*)"macb1" #define preference_has_mac_byte_2 (char*)"macb2" #define preference_latest_version (char*)"latest" +#define preference_task_size_network (char*)"tsksznetw" +#define preference_task_size_nuki (char*)"tsksznuki" +#define preference_task_size_pd (char*)"tskszpd" +#define preference_authlog_max_entries (char*)"authmaxentry" +#define preference_keypad_max_entries (char*)"kpmaxentry" +#define preference_timecontrol_max_entries (char*)"tcmaxentry" class DebugPreferences { @@ -83,17 +89,15 @@ private: preference_opener_continuous_mode, preference_mqtt_opener_path, preference_lock_max_keypad_code_count, preference_opener_max_keypad_code_count, preference_mqtt_ca, preference_mqtt_crt, preference_mqtt_key, preference_mqtt_hass_discovery, preference_mqtt_hass_cu_url, preference_ip_dhcp_enabled, preference_ip_address, preference_ip_subnet, preference_ip_gateway, preference_ip_dns_server, - preference_network_hardware, preference_network_wifi_fallback_disabled, preference_rssi_publish_interval, - preference_hostname, 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_network_hardware, preference_network_wifi_fallback_disabled, preference_rssi_publish_interval, preference_hostname, + 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_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_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_has_mac_saved, preference_has_mac_byte_0, preference_has_mac_byte_1, preference_has_mac_byte_2, preference_latest_version, + preference_task_size_network, preference_task_size_nuki, preference_task_size_pd, preference_authlog_max_entries, preference_keypad_max_entries, preference_timecontrol_max_entries }; std::vector _redact = { diff --git a/src/WebCfgServer.cpp b/src/WebCfgServer.cpp index dcfd1c4..90a0499 100644 --- a/src/WebCfgServer.cpp +++ b/src/WebCfgServer.cpp @@ -78,6 +78,14 @@ void WebCfgServer::initialize() buildAccLvlHtml(response); _server.send(200, "text/html", response); }); + _server.on("/advanced", [&]() { + if (_hasCredentials && !_server.authenticate(_credUser, _credPassword)) { + return _server.requestAuthentication(); + } + String response = ""; + buildAdvancedConfigHtml(response); + _server.send(200, "text/html", response); + }); _server.on("/cred", [&]() { if (_hasCredentials && !_server.authenticate(_credUser, _credPassword)) { return _server.requestAuthentication(); @@ -465,6 +473,36 @@ bool WebCfgServer::processArgs(String& message) _preferences->putInt(preference_restart_ble_beacon_lost, value.toInt()); configChanged = true; } + else if(key == "TSKNTWK") + { + _preferences->putInt(preference_task_size_network, value.toInt()); + configChanged = true; + } + else if(key == "TSKNUKI") + { + _preferences->putInt(preference_task_size_nuki, value.toInt()); + configChanged = true; + } + else if(key == "TSKPD") + { + _preferences->putInt(preference_task_size_pd, value.toInt()); + configChanged = true; + } + else if(key == "ALMAX") + { + _preferences->putInt(preference_authlog_max_entries, value.toInt()); + configChanged = true; + } + else if(key == "KPMAX") + { + _preferences->putInt(preference_keypad_max_entries, value.toInt()); + configChanged = true; + } + else if(key == "TCMAX") + { + _preferences->putInt(preference_timecontrol_max_entries, value.toInt()); + configChanged = true; + } else if(key == "ACLLVLCHANGED") { aclLvlChanged = true; @@ -488,7 +526,7 @@ bool WebCfgServer::processArgs(String& message) { _preferences->putBool(preference_timecontrol_control_enabled, (value == "1")); configChanged = true; - } + } else if(key == "PUBAUTH") { _preferences->putBool(preference_publish_authdata, (value == "1")); @@ -1071,23 +1109,25 @@ void WebCfgServer::buildHtml(String& response) if(_preferences->getBool(preference_check_updates)) printParameter(response, "Latest Firmware", _preferences->getString(preference_latest_version).c_str(), "/ota"); response.concat("
"); - response.concat(""); if(_allowRestartToPortal) { - response.concat(""); } @@ -1257,6 +1297,26 @@ void WebCfgServer::buildMqttConfigHtml(String &response) response.concat(""); } +void WebCfgServer::buildAdvancedConfigHtml(String &response) +{ + buildHtmlHeader(response); + response.concat(""); + response.concat("

Advanced Configuration

"); + response.concat("

Warning: Changing these settings can lead to bootloops that might require you to erase the ESP32 and reflash nukihub using USB/serial

"); + response.concat("

MQTT and Network Configuration

"); + response.concat("
MQTT and Network Configuration
"); buildNavigationButton(response, "Edit", "/mqttconfig", _brokerConfigured ? "" : "(!) Please configure MQTT broker"); - response.concat("

Nuki Configuration

"); + response.concat("
Nuki Configuration
"); buildNavigationButton(response, "Edit", "/nukicfg"); - response.concat("

Access Level Configuration

"); + response.concat("
Access Level Configuration
"); buildNavigationButton(response, "Edit", "/acclvl"); - response.concat("

Credentials

"); + response.concat("
Credentials
"); buildNavigationButton(response, "Edit", "/cred", _pinsConfigured ? "" : "(!) Please configure PIN"); - response.concat("

GPIO Configuration

"); + response.concat("
GPIO Configuration
"); buildNavigationButton(response, "Edit", "/gpiocfg"); - response.concat("

Firmware update

"); + response.concat("
Firmware update
"); buildNavigationButton(response, "Open", "/ota"); + response.concat("
Advanced Configuration
"); + buildNavigationButton(response, "Edit", "/advanced"); response.concat("

Wi-Fi

"); + response.concat("
Wi-Fi
"); buildNavigationButton(response, "Restart and configure Wi-Fi", "/wifi"); response.concat("
"); + printInputField(response, "TSKNTWK", "Task size Network", _preferences->getInt(preference_task_size_network, 12288), 6); + printInputField(response, "TSKNUKI", "Task size Nuki", _preferences->getInt(preference_task_size_nuki, 8192), 6); + printInputField(response, "TSKPD", "Task size Presence Detection", _preferences->getInt(preference_task_size_pd, 1024), 6); + printInputField(response, "ALMAX", "Max auth log entries", _preferences->getInt(preference_authlog_max_entries, 5), 3); + printInputField(response, "KPMAX", "Max keypad entries", _preferences->getInt(preference_keypad_max_entries, 10), 3); + printInputField(response, "TCMAX", "Max timecontrol entries", _preferences->getInt(preference_timecontrol_max_entries, 10), 3); + response.concat("
"); + + response.concat("
"); + response.concat(""); + response.concat(""); +} + void WebCfgServer::buildAccLvlHtml(String &response) { buildHtmlHeader(response); @@ -1765,7 +1825,7 @@ void WebCfgServer::buildInfoHtml(String &response) response.concat(uxTaskGetStackHighWaterMark(networkTaskHandle)); response.concat(", nuki: "); response.concat(uxTaskGetStackHighWaterMark(nukiTaskHandle)); - + if(_preferences->getInt(preference_presence_detection_timeout) >= 0) { response.concat(", pd: "); diff --git a/src/WebCfgServer.h b/src/WebCfgServer.h index 48a16e8..6d3deac 100644 --- a/src/WebCfgServer.h +++ b/src/WebCfgServer.h @@ -42,6 +42,7 @@ private: void buildOtaHtml(String& response, bool errored); void buildOtaCompletedHtml(String& response); void buildMqttConfigHtml(String& response); + void buildAdvancedConfigHtml(String& response); void buildNukiConfigHtml(String& response); void buildGpioConfigHtml(String& response); void buildConfirmHtml(String& response, const String &message, uint32_t redirectDelay = 5); diff --git a/src/main.cpp b/src/main.cpp index 87e3ddd..c35785d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -52,7 +52,11 @@ void networkTask(void *pvParameters) { networkOpener->update(); } - webCfgServer->update(); + + if(preferences->getBool(preference_webserver_enabled, true)) + { + webCfgServer->update(); + } // millis() is about to overflow. Restart device to prevent problems with overflow if(millis() > restartTs) @@ -112,12 +116,12 @@ void setupTasks() { // configMAX_PRIORITIES is 25 - xTaskCreatePinnedToCore(networkTask, "ntw", 12288, NULL, 3, &networkTaskHandle, 1); - xTaskCreatePinnedToCore(nukiTask, "nuki", 8192, NULL, 2, &nukiTaskHandle, 1); - + xTaskCreatePinnedToCore(networkTask, "ntw", preferences->getInt(preference_task_size_network, 12288), NULL, 3, &networkTaskHandle, 1); + xTaskCreatePinnedToCore(nukiTask, "nuki", preferences->getInt(preference_task_size_nuki, 8192), NULL, 2, &nukiTaskHandle, 1); + if(preferences->getInt(preference_presence_detection_timeout) >= 0) { - xTaskCreatePinnedToCore(presenceDetectionTask, "prdet", 1024, NULL, 5, &presenceDetectionTaskHandle, 1); + xTaskCreatePinnedToCore(presenceDetectionTask, "prdet", preferences->getInt(preference_task_size_pd, 1024), NULL, 5, &presenceDetectionTaskHandle, 1); } } @@ -325,13 +329,13 @@ void setup() webCfgServer = new WebCfgServer(nuki, nukiOpener, network, gpio, ethServer, preferences, network->networkDeviceType() == NetworkDeviceType::WiFi); webCfgServer->initialize(); } - + if(preferences->getInt(preference_presence_detection_timeout) >= 0) { presenceDetection = new PresenceDetection(preferences, bleScanner, network, CharBuffer::get(), CHAR_BUFFER_SIZE); presenceDetection->initialize(); } - + setupTasks(); }