diff --git a/lib/nuki_ble b/lib/nuki_ble index a7673b4..341c956 160000 --- a/lib/nuki_ble +++ b/lib/nuki_ble @@ -1 +1 @@ -Subproject commit a7673b41f2889c673985ccd710835744f336ce5a +Subproject commit 341c956cc993349a7ec62986d672e714e4e913fd diff --git a/src/Config.h b/src/Config.h index 222fd01..77c8192 100644 --- a/src/Config.h +++ b/src/Config.h @@ -5,7 +5,7 @@ #define NUKI_HUB_VERSION "9.07" #define NUKI_HUB_VERSION_INT (uint32_t)907 #define NUKI_HUB_BUILD "unknownbuildnr" -#define NUKI_HUB_DATE "2025-01-06" +#define NUKI_HUB_DATE "2025-01-07" #define GITHUB_LATEST_RELEASE_URL (char*)"https://github.com/technyon/nuki_hub/releases/latest" #define GITHUB_OTA_MANIFEST_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/manifest.json" diff --git a/src/HomeAssistantDiscovery.cpp b/src/HomeAssistantDiscovery.cpp index 63da986..a27f530 100644 --- a/src/HomeAssistantDiscovery.cpp +++ b/src/HomeAssistantDiscovery.cpp @@ -3,6 +3,7 @@ #include "Logger.h" #include "PreferencesKeys.h" #include "MqttTopics.h" +#include "esp_mac.h" HomeAssistantDiscovery::HomeAssistantDiscovery(NetworkDevice* device, Preferences *preferences, char* buffer, size_t bufferSize) : _device(device), @@ -16,12 +17,15 @@ HomeAssistantDiscovery::HomeAssistantDiscovery(NetworkDevice* device, Preference _checkUpdates = _preferences->getBool(preference_check_updates, false); _updateFromMQTT = _preferences->getBool(preference_update_from_mqtt, false); _hostname = _preferences->getString(preference_hostname, ""); - uint32_t savedDevId = _preferences->getUInt(preference_nukihub_id, 0); - uint32_t curDevId = ESP.getEfuseMac() & 0xFFFFFFFF; + uint64_t savedDevId = _preferences->getULong64(preference_nukihub_id, 0); + uint8_t mac[8]; + esp_efuse_mac_get_default(mac); + uint64_t curDevId; + memcpy(&curDevId, &mac, 8); if (savedDevId == 0) { - _preferences->putUInt(preference_nukihub_id, curDevId); + _preferences->putULong64(preference_nukihub_id, curDevId); char uidString[20]; itoa(_preferences->getUInt(preference_device_id_lock, 0), uidString, 10); removeHASSConfig(uidString); @@ -29,7 +33,7 @@ HomeAssistantDiscovery::HomeAssistantDiscovery(NetworkDevice* device, Preference } else if(savedDevId != curDevId) { - _preferences->putUInt(preference_nukihub_id, curDevId); + _preferences->putULong64(preference_nukihub_id, curDevId); Log->print("Efuse ID: "); Log->println(curDevId); Log->print("Saved ID: "); diff --git a/src/NukiNetworkLock.cpp b/src/NukiNetworkLock.cpp index 3e2e9ae..45e2005 100644 --- a/src/NukiNetworkLock.cpp +++ b/src/NukiNetworkLock.cpp @@ -160,7 +160,7 @@ void NukiNetworkLock::initialize() bool NukiNetworkLock::update() { bool ret = false; - + if(_nukiOfficial->hasOffStateToPublish()) { publishState(_nukiOfficial->getOffStateToPublish()); @@ -182,7 +182,7 @@ bool NukiNetworkLock::update() _offConnected = _nukiOfficial->getOffConnected(); } - + return ret; } @@ -420,7 +420,7 @@ void NukiNetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyT json["lock_state"] = str; } - json["lockngo_state"] = (keyTurnerState.lockNgoTimer == 0 ? 0 : 1); + json["lockngo_state"] = keyTurnerState.lockNgoTimer != 255 ? keyTurnerState.lockNgoTimer : 0; memset(&str, 0, sizeof(str)); @@ -445,7 +445,7 @@ void NukiNetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyT sprintf(curTime, "%04d-%02d-%02d %02d:%02d:%02d", keyTurnerState.currentTimeYear, keyTurnerState.currentTimeMonth, keyTurnerState.currentTimeDay, keyTurnerState.currentTimeHour, keyTurnerState.currentTimeMinute, keyTurnerState.currentTimeSecond); json["currentTime"] = curTime; json["timeZoneOffset"] = keyTurnerState.timeZoneOffset; - json["nightModeActive"] = keyTurnerState.nightModeActive; + json["nightModeActive"] = keyTurnerState.nightModeActive != 255 ? keyTurnerState.nightModeActive : 0; memset(&str, 0, sizeof(str)); @@ -492,10 +492,10 @@ void NukiNetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyT json["door_sensor_state"] = str; - bool critical = (keyTurnerState.criticalBatteryState & 0b00000001) > 0; - bool charging = (keyTurnerState.criticalBatteryState & 0b00000010) > 0; - uint8_t level = (keyTurnerState.criticalBatteryState & 0b11111100) >> 1; - bool keypadCritical = (keyTurnerState.accessoryBatteryState & (1 << 7)) != 0 ? (keyTurnerState.accessoryBatteryState & (1 << 6)) != 0 : false; + bool critical = (keyTurnerState.criticalBatteryState & 1) == 1; + bool charging = (keyTurnerState.criticalBatteryState & 2) == 2; + uint8_t level = ((keyTurnerState.criticalBatteryState & 0b11111100) >> 1); + bool keypadCritical = keyTurnerState.accessoryBatteryState != 255 ? ((keyTurnerState.accessoryBatteryState & 1) == 1 ? (keyTurnerState.accessoryBatteryState & 3) == 3 : false) : false; jsonBattery["critical"] = critical ? "1" : "0"; jsonBattery["charging"] = charging ? "1" : "0"; @@ -514,6 +514,15 @@ void NukiNetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyT _nukiPublisher->publishBool(mqtt_topic_battery_keypad_critical, keypadCritical, true); } + bool doorSensorCritical = keyTurnerState.accessoryBatteryState != 255 ? ((keyTurnerState.accessoryBatteryState & 4) == 4 ? (keyTurnerState.accessoryBatteryState & 12) == 12 : false) : false; + + jsonBattery["doorSensorCritical"] = doorSensorCritical ? "1" : "0"; + + if((_firstTunerStatePublish || keyTurnerState.accessoryBatteryState != lastKeyTurnerState.accessoryBatteryState) && !_disableNonJSON) + { + _nukiPublisher->publishBool(mqtt_topic_battery_doorsensor_critical, doorSensorCritical, true); + } + serializeJson(jsonBattery, _buffer, _bufferSize); _nukiPublisher->publishString(mqtt_topic_battery_basic_json, _buffer, true); } @@ -523,6 +532,43 @@ void NukiNetworkLock::publishKeyTurnerState(const NukiLock::KeyTurnerState& keyT json["door_sensor_state"] = str; } + if (keyTurnerState.network != 255) + { + json["remoteAccessEnabled"] = ((keyTurnerState.network & 1) == 1) ? 1 : 0; + json["bridgePaired"] = (((keyTurnerState.network >> 1) & 1) == 1) ? 1 : 0; + json["sseConnectedViaWifi"] = (((keyTurnerState.network >> 2) & 1) == 1) ? 1 : 0; + json["sseConnectionEstablished"] = (((keyTurnerState.network >> 3) & 1) == 1) ? 1 : 0; + json["isSseConnectedViaThread"] = (((keyTurnerState.network >> 4) & 1) == 1) ? 1 : 0; + json["threadSseUplinkEnabledByUser"] = (((keyTurnerState.network >> 5) & 1) == 1) ? 1 : 0; + json["nat64AvailableViaThread"] = (((keyTurnerState.network >> 6) & 1) == 1) ? 1 : 0; + } + if (keyTurnerState.bleConnectionStrength != 255) + { + json["bleConnectionStrength"] = keyTurnerState.bleConnectionStrength; + } + if (keyTurnerState.wifiConnectionStrength != 255) + { + json["wifiConnectionStrength"] = keyTurnerState.wifiConnectionStrength; + } + if (keyTurnerState.wifi != 255) + { + json["wifiStatus"] = (keyTurnerState.wifi & 3); + json["sseStatus"] = ((keyTurnerState.wifi >> 2) & 3); + json["wifiQuality"] = ((keyTurnerState.wifi >> 4) & 15); + } + if (keyTurnerState.mqtt != 255) + { + json["mqttStatus"] = (keyTurnerState.mqtt & 3); + json["mqttConnectionChannel"] = ((keyTurnerState.mqtt >> 2) & 1); + } + if (keyTurnerState.thread != 255) + { + json["threadConnectionStatus"] = (keyTurnerState.thread & 3); + json["threadSseStatus"] = ((keyTurnerState.thread >> 2) & 3); + json["isCommissioningModeActive"] = (keyTurnerState.thread & 16) != 0 ? 1 : 0; + json["isWifiDisabledBecauseOfThread"] = (keyTurnerState.thread & 32) != 0 ? 1 : 0; + } + json["auth_id"] = getAuthId(); json["auth_name"] = getAuthName(); @@ -820,7 +866,7 @@ void NukiNetworkLock::publishConfig(const NukiLock::Config &config) _network->advertisingModeToString(config.advertisingMode, str); json["advertisingMode"] = str; json["hasKeypad"] = config.hasKeypad; - json["hasKeypadV2"] = config.hasKeypadV2; + json["hasKeypadV2"] = (config.hasKeypadV2 == 255 ? 0 : config.hasKeypadV2); json["firmwareVersion"] = std::to_string(config.firmwareVersion[0]) + "." + std::to_string(config.firmwareVersion[1]) + "." + std::to_string(config.firmwareVersion[2]); json["hardwareRevision"] = std::to_string(config.hardwareRevision[0]) + "." + std::to_string(config.hardwareRevision[1]); memset(str, 0, sizeof(str)); @@ -829,12 +875,12 @@ void NukiNetworkLock::publishConfig(const NukiLock::Config &config) memset(str, 0, sizeof(str)); _network->timeZoneIdToString(config.timeZoneId, str); json["timeZone"] = str; - json["deviceType"] = config.deviceType; - json["channel"] = config.network; - json["wifiCapable"] = config.network & 1; - json["threadCapable"] = (((unsigned int)config.network & 2) != 0 ? 1 : 0); - json["matterStatus"] = config.matterStatus; - json["productVariant"] = config.productVariant; + json["deviceType"] = (config.deviceType == 255 ? 0 : config.deviceType); + json["channel"] = (config.network == 255 ? 0 : config.network); + json["wifiCapable"] = (config.network == 255 ? 0 : config.network & 1); + json["threadCapable"] = (config.network == 255 ? 0 : ((config.network & 2) != 0 ? 1 : 0)); + json["matterStatus"] = (config.matterStatus == 255 ? 0 : config.matterStatus); + json["productVariant"] = (config.productVariant == 255 ? 0 : config.productVariant); serializeJson(json, _buffer, _bufferSize); _nukiPublisher->publishString(mqtt_topic_config_basic_json, _buffer, true); diff --git a/src/NukiNetworkOpener.cpp b/src/NukiNetworkOpener.cpp index e22272b..f647db4 100644 --- a/src/NukiNetworkOpener.cpp +++ b/src/NukiNetworkOpener.cpp @@ -48,7 +48,7 @@ void NukiNetworkOpener::initialize() _network->subscribe(_mqttPath, mqtt_topic_query_config); _network->subscribe(_mqttPath, mqtt_topic_query_lockstate); _network->subscribe(_mqttPath, mqtt_topic_query_battery); - + _network->initTopic(_mqttPath, mqtt_topic_keypad_json_action, "--"); _network->initTopic(_mqttPath, mqtt_topic_timecontrol_action, "--"); _network->initTopic(_mqttPath, mqtt_topic_auth_action, "--"); @@ -371,7 +371,7 @@ void NukiNetworkOpener::publishKeyTurnerState(const NukiOpener::OpenerState& key json["trigger"] = str; - json["ringToOpenTimer"] = keyTurnerState.ringToOpenTimer; + json["ringToOpenTimer"] = keyTurnerState.ringToOpenTimer != 255 ? keyTurnerState.ringToOpenTimer : 0; char curTime[20]; sprintf(curTime, "%04d-%02d-%02d %02d:%02d:%02d", keyTurnerState.currentTimeYear, keyTurnerState.currentTimeMonth, keyTurnerState.currentTimeDay, keyTurnerState.currentTimeHour, keyTurnerState.currentTimeMinute, keyTurnerState.currentTimeSecond); json["currentTime"] = curTime; @@ -400,17 +400,7 @@ void NukiNetworkOpener::publishKeyTurnerState(const NukiOpener::OpenerState& key json["lock_completion_status"] = str; - memset(&str, 0, sizeof(str)); - NukiOpener::doorSensorStateToString(keyTurnerState.doorSensorState, str); - - if(_firstTunerStatePublish || keyTurnerState.doorSensorState != lastKeyTurnerState.doorSensorState) - { - _nukiPublisher->publishString(mqtt_topic_lock_door_sensor_state, str, true); - } - - json["door_sensor_state"] = str; - - bool critical = (keyTurnerState.criticalBatteryState & 0b00000001) > 0; + bool critical = (keyTurnerState.criticalBatteryState & 1); jsonBattery["critical"] = critical ? "1" : "0"; if((_firstTunerStatePublish || keyTurnerState.criticalBatteryState != lastKeyTurnerState.criticalBatteryState) && !_disableNonJSON) @@ -418,6 +408,14 @@ void NukiNetworkOpener::publishKeyTurnerState(const NukiOpener::OpenerState& key _nukiPublisher->publishBool(mqtt_topic_battery_critical, critical, true); } + bool keypadCritical = keyTurnerState.accessoryBatteryState != 255 ? ((keyTurnerState.accessoryBatteryState & 1) == 1 ? (keyTurnerState.accessoryBatteryState & 3) == 3 : false) : false; + jsonBattery["keypadCritical"] = keypadCritical ? "1" : "0"; + + if((_firstTunerStatePublish || keyTurnerState.accessoryBatteryState != lastKeyTurnerState.accessoryBatteryState) && !_disableNonJSON) + { + _nukiPublisher->publishBool(mqtt_topic_battery_keypad_critical, keypadCritical, true); + } + json["auth_id"] = _authId; json["auth_name"] = _authName; @@ -775,7 +773,7 @@ void NukiNetworkOpener::publishConfig(const NukiOpener::Config &config) _network->advertisingModeToString(config.advertisingMode, str); json["advertisingMode"] = str; json["hasKeypad"] = config.hasKeypad; - json["hasKeypadV2"] = config.hasKeypadV2; + json["hasKeypadV2"] = (config.hasKeypadV2 == 255 ? 0 : config.hasKeypadV2); json["firmwareVersion"] = std::to_string(config.firmwareVersion[0]) + "." + std::to_string(config.firmwareVersion[1]) + "." + std::to_string(config.firmwareVersion[2]); json["hardwareRevision"] = std::to_string(config.hardwareRevision[0]) + "." + std::to_string(config.hardwareRevision[1]); memset(str, 0, sizeof(str)); diff --git a/src/NukiOpenerWrapper.cpp b/src/NukiOpenerWrapper.cpp index 37840a8..a7d37b1 100644 --- a/src/NukiOpenerWrapper.cpp +++ b/src/NukiOpenerWrapper.cpp @@ -589,7 +589,7 @@ void NukiOpenerWrapper::updateConfig() if(_preferences->getUInt(preference_nuki_id_opener, 0) == _nukiConfig.nukiId) { - _hasKeypad = _nukiConfig.hasKeypad == 1 || (_nukiConfig.hasKeypadV2 > 0 && _nukiConfig.hasKeypadV2 != 252); + _hasKeypad = _nukiConfig.hasKeypad == 1 || _nukiConfig.hasKeypadV2 == 1; _firmwareVersion = std::to_string(_nukiConfig.firmwareVersion[0]) + "." + std::to_string(_nukiConfig.firmwareVersion[1]) + "." + std::to_string(_nukiConfig.firmwareVersion[2]); _hardwareVersion = std::to_string(_nukiConfig.hardwareRevision[0]) + "." + std::to_string(_nukiConfig.hardwareRevision[1]); if(_preferences->getBool(preference_conf_info_enabled, true)) diff --git a/src/NukiWrapper.cpp b/src/NukiWrapper.cpp index cf8f193..80bcbcf 100644 --- a/src/NukiWrapper.cpp +++ b/src/NukiWrapper.cpp @@ -589,7 +589,7 @@ void NukiWrapper::updateConfig() if(_preferences->getUInt(preference_nuki_id_lock, 0) == _nukiConfig.nukiId) { - _hasKeypad = _nukiConfig.hasKeypad == 1 || (_nukiConfig.hasKeypadV2 > 0 && _nukiConfig.hasKeypadV2 != 252); + _hasKeypad = _nukiConfig.hasKeypad == 1 || _nukiConfig.hasKeypadV2 == 1; _firmwareVersion = std::to_string(_nukiConfig.firmwareVersion[0]) + "." + std::to_string(_nukiConfig.firmwareVersion[1]) + "." + std::to_string(_nukiConfig.firmwareVersion[2]); _hardwareVersion = std::to_string(_nukiConfig.hardwareRevision[0]) + "." + std::to_string(_nukiConfig.hardwareRevision[1]); if(_preferences->getBool(preference_conf_info_enabled, true)) diff --git a/src/PreferencesKeys.h b/src/PreferencesKeys.h index decc236..7277beb 100644 --- a/src/PreferencesKeys.h +++ b/src/PreferencesKeys.h @@ -367,22 +367,22 @@ inline void initPreferences(Preferences* preferences) if (lastConfigVer < 907) { Log->println("Migration 9.07"); - + char ca[2200] = {0}; char cert[2200] = {0}; char key[2200] = {0}; - + size_t caLength = preferences->getString(preference_mqtt_ca, ca, 2200); size_t crtLength = preferences->getString(preference_mqtt_crt, cert, 2200); size_t keyLength = preferences->getString(preference_mqtt_key, key, 2200); - + if (caLength > 1) { if (!SPIFFS.begin(true)) { Log->println("SPIFFS Mount Failed"); } else - { + { File file = SPIFFS.open("/mqtt_ssl.ca", FILE_WRITE); if (!file) { Log->println("Failed to open /mqtt_ssl.ca for writing"); @@ -396,9 +396,9 @@ inline void initPreferences(Preferences* preferences) file.close(); } } - + rebootOnMigrate = true; - preferences->putBool(preference_mqtt_ssl_enabled, true); + preferences->putBool(preference_mqtt_ssl_enabled, true); preferences->putString(preference_mqtt_ca, ""); } @@ -408,7 +408,7 @@ inline void initPreferences(Preferences* preferences) Log->println("SPIFFS Mount Failed"); } else - { + { File file = SPIFFS.open("/mqtt_ssl.crt", FILE_WRITE); if (!file) { Log->println("Failed to open /mqtt_ssl.crt for writing"); @@ -422,18 +422,18 @@ inline void initPreferences(Preferences* preferences) file.close(); } } - + rebootOnMigrate = true; preferences->putString(preference_mqtt_crt, ""); } - + if (keyLength > 1) { if (!SPIFFS.begin(true)) { Log->println("SPIFFS Mount Failed"); } else - { + { File file = SPIFFS.open("/mqtt_ssl.key", FILE_WRITE); if (!file) { Log->println("Failed to open /mqtt_ssl.key for writing"); @@ -447,13 +447,13 @@ inline void initPreferences(Preferences* preferences) file.close(); } } - + rebootOnMigrate = true; preferences->putString(preference_mqtt_key, ""); } } preferences->putInt(preference_config_version, NUKI_HUB_VERSION_INT); - + if (rebootOnMigrate) { restartEsp(RestartReason::OTACompleted); @@ -493,8 +493,7 @@ private: }; std::vector _redact = { - preference_mqtt_user, preference_mqtt_password, preference_mqtt_ca, preference_mqtt_crt, preference_mqtt_key, preference_cred_user, preference_cred_password, - preference_nuki_id_lock, preference_nuki_id_opener, preference_wifi_pass + preference_mqtt_user, preference_mqtt_password, preference_cred_user, preference_cred_password, preference_nuki_id_lock, preference_nuki_id_opener, preference_wifi_pass }; std::vector _boolPrefs = { @@ -517,17 +516,24 @@ private: }; std::vector _intPrefs = { - preference_config_version, preference_device_id_lock, preference_device_id_opener, preference_nuki_id_lock, preference_nuki_id_opener, preference_mqtt_broker_port, + preference_config_version, preference_mqtt_broker_port, preference_command_retry_delay, preference_query_interval_hybrid_lockstate, preference_lock_pin_status, preference_opener_pin_status, preference_lock_max_keypad_code_count, preference_opener_max_keypad_code_count, preference_lock_max_timecontrol_entry_count, preference_opener_max_timecontrol_entry_count, preference_buffer_size, preference_network_hardware, preference_rssi_publish_interval, preference_network_timeout, preference_restart_ble_beacon_lost, preference_query_interval_lockstate, preference_query_interval_configuration, preference_query_interval_battery, preference_query_interval_keypad, preference_command_nr_of_retries, - preference_command_retry_delay, preference_query_interval_hybrid_lockstate, preference_task_size_network, preference_task_size_nuki, preference_authlog_max_entries, preference_keypad_max_entries, preference_timecontrol_max_entries, preference_ble_tx_power, preference_network_custom_mdc, preference_network_custom_clk, preference_network_custom_phy, preference_network_custom_addr, preference_network_custom_irq, preference_network_custom_rst, preference_network_custom_cs, preference_network_custom_sck, preference_network_custom_miso, preference_network_custom_mosi, preference_network_custom_pwr, preference_network_custom_mdio }; + std::vector _uintPrefs = + { + preference_device_id_lock, preference_device_id_opener, preference_nuki_id_lock, preference_nuki_id_opener + }; + std::vector _uint64Prefs = + { + preference_nukihub_id + }; public: const std::vector getPreferencesKeys() { @@ -549,4 +555,12 @@ public: { return _intPrefs; } + const std::vector getPreferencesUIntKeys() + { + return _uintPrefs; + } + const std::vector getPreferencesUInt64Keys() + { + return _uint64Prefs; + } }; \ No newline at end of file diff --git a/src/WebCfgServer.cpp b/src/WebCfgServer.cpp index fc5c778..92087dd 100644 --- a/src/WebCfgServer.cpp +++ b/src/WebCfgServer.cpp @@ -3512,6 +3512,8 @@ bool WebCfgServer::processImport(PsychicRequest *request, PsychicResponse* resp, const std::vector boolPrefs = debugPreferences.getPreferencesBoolKeys(); const std::vector bytePrefs = debugPreferences.getPreferencesByteKeys(); const std::vector intPrefs = debugPreferences.getPreferencesIntKeys(); + const std::vector uintPrefs = debugPreferences.getPreferencesUIntKeys(); + const std::vector uint64Prefs = debugPreferences.getPreferencesUInt64Keys(); for(const auto& key : keysPrefs) { @@ -3527,14 +3529,6 @@ bool WebCfgServer::processImport(PsychicRequest *request, PsychicResponse* resp, { continue; } - if(strcmp(key, preference_device_id_lock) == 0) - { - continue; - } - if(strcmp(key, preference_device_id_opener) == 0) - { - continue; - } if(std::find(boolPrefs.begin(), boolPrefs.end(), key) != boolPrefs.end()) { if (doc[key].as().length() > 0) @@ -3559,7 +3553,30 @@ bool WebCfgServer::processImport(PsychicRequest *request, PsychicResponse* resp, } continue; } - + if(std::find(uintPrefs.begin(), uintPrefs.end(), key) != uintPrefs.end()) + { + if (doc[key].as().length() > 0) + { + _preferences->putUInt(key, doc[key].as()); + } + else + { + _preferences->remove(key); + } + continue; + } + if(std::find(uint64Prefs.begin(), uint64Prefs.end(), key) != uint64Prefs.end()) + { + if (doc[key].as().length() > 0) + { + _preferences->putULong64(key, doc[key].as()); + } + else + { + _preferences->remove(key); + } + continue; + } if (doc[key].as().length() > 0) { _preferences->putString(key, doc[key].as()); @@ -5057,7 +5074,7 @@ esp_err_t WebCfgServer::buildInfoHtml(PsychicRequest *request, PsychicResponse* response.print("\nNuki Hub configuration URL for HA: "); response.print(_preferences->getString(preference_mqtt_hass_cu_url, "").length() > 0 ? _preferences->getString(preference_mqtt_hass_cu_url, "") : "http://" + _network->localIP()); response.print("\nNuki Hub ID: "); - response.print(_preferences->getUInt(preference_nukihub_id, 0)); + response.print(_preferences->getULong64(preference_nukihub_id, 0)); } else {