Merge pull request #589 from iranl/ntp

Update NukiHub and Nuki device time using NTP
This commit is contained in:
iranl
2025-01-02 12:04:54 +01:00
committed by GitHub
8 changed files with 120 additions and 7 deletions

View File

@@ -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 "2024-12-31"
#define NUKI_HUB_DATE "2025-01-02"
#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"

View File

@@ -6,6 +6,8 @@
#include <NukiOpenerUtils.h>
#include "Config.h"
#include "hal/wdt_hal.h"
#include <time.h>
#include "esp_sntp.h"
NukiOpenerWrapper* nukiOpenerInst;
Preferences* nukiOpenerPreferences = nullptr;
@@ -55,7 +57,7 @@ void NukiOpenerWrapper::initialize()
_nukiOpener.setDebugHexData(_preferences->getBool(preference_debug_hex_data, false));
_nukiOpener.setDebugCommand(_preferences->getBool(preference_debug_command, false));
_nukiOpener.registerLogger(Log);
_nukiOpener.initialize(_preferences->getBool(preference_connect_mode, true));
_nukiOpener.registerBleScanner(_bleScanner);
_nukiOpener.setEventHandler(this);
@@ -317,6 +319,11 @@ void NukiOpenerWrapper::update()
_waitKeypadUpdateTs = 0;
updateKeypad(true);
}
if(_preferences->getBool(preference_update_time, false) && ts > (120 * 1000) && ts > _nextTimeUpdateTs)
{
_nextTimeUpdateTs = ts + (12 * 60 * 60 * 1000);
updateTime();
}
if(_waitTimeControlUpdateTs != 0 && ts > _waitTimeControlUpdateTs)
{
_waitTimeControlUpdateTs = 0;
@@ -4154,3 +4161,39 @@ void NukiOpenerWrapper::updateGpioOutputs()
}
}
}
void NukiOpenerWrapper::updateTime()
{
if(!isPinValid())
{
Log->println(F("No valid PIN set"));
return;
}
time_t now;
tm tm;
time(&now);
localtime_r(&now, &tm);
if (int(tm.tm_year + 1900) < int(2025))
{
Log->println(F("NTP Time not valid, not updating Nuki device"));
return;
}
Nuki::TimeValue nukiTime;
nukiTime.year = tm.tm_year + 1900;
nukiTime.month = tm.tm_mon + 1;
nukiTime.day = tm.tm_mday;
nukiTime.hour = tm.tm_hour;
nukiTime.minute = tm.tm_min;
nukiTime.second = tm.tm_sec;
Nuki::CmdResult cmdResult = _nukiOpener.updateTime(nukiTime);
char resultStr[15] = {0};
NukiOpener::cmdResultToString(cmdResult, resultStr);
Log->print(F("Opener time update result: "));
Log->println(resultStr);
}

View File

@@ -68,6 +68,7 @@ private:
void updateTimeControl(bool retrieved);
void updateAuth(bool retrieved);
void postponeBleWatchdog();
void updateTime();
void updateGpioOutputs();
@@ -147,6 +148,7 @@ private:
int64_t _waitKeypadUpdateTs = 0;
int64_t _waitTimeControlUpdateTs = 0;
int64_t _waitAuthUpdateTs = 0;
int64_t _nextTimeUpdateTs = 0;
int64_t _nextKeypadUpdateTs = 0;
int64_t _nextPairTs = 0;
int64_t _nextRssiTs = 0;

View File

@@ -6,6 +6,8 @@
#include <NukiLockUtils.h>
#include "Config.h"
#include "hal/wdt_hal.h"
#include <time.h>
#include "esp_sntp.h"
NukiWrapper* nukiInst = nullptr;
@@ -19,6 +21,7 @@ NukiWrapper::NukiWrapper(const std::string& deviceName, NukiDeviceId* deviceId,
_gpio(gpio),
_preferences(preferences)
{
Log->print("Device id lock: ");
Log->println(_deviceId->get());
@@ -368,6 +371,11 @@ void NukiWrapper::update()
_nextKeypadUpdateTs = ts + _intervalKeypad * 1000;
updateKeypad(false);
}
if(_preferences->getBool(preference_update_time, false) && ts > (120 * 1000) && ts > _nextTimeUpdateTs)
{
_nextTimeUpdateTs = ts + (12 * 60 * 60 * 1000);
updateTime();
}
}
if(_clearAuthData)
{
@@ -4195,3 +4203,39 @@ void NukiWrapper::updateGpioOutputs()
}
}
}
void NukiWrapper::updateTime()
{
if(!isPinValid())
{
Log->println(F("No valid PIN set"));
return;
}
time_t now;
tm tm;
time(&now);
localtime_r(&now, &tm);
if (int(tm.tm_year + 1900) < int(2025))
{
Log->println(F("NTP Time not valid, not updating Nuki device"));
return;
}
Nuki::TimeValue nukiTime;
nukiTime.year = tm.tm_year + 1900;
nukiTime.month = tm.tm_mon + 1;
nukiTime.day = tm.tm_mday;
nukiTime.hour = tm.tm_hour;
nukiTime.minute = tm.tm_min;
nukiTime.second = tm.tm_sec;
Nuki::CmdResult cmdResult = _nukiLock.updateTime(nukiTime);
char resultStr[15] = {0};
NukiLock::cmdResultToString(cmdResult, resultStr);
Log->print(F("Lock time update result: "));
Log->println(resultStr);
}

View File

@@ -73,6 +73,7 @@ private:
void updateTimeControl(bool retrieved);
void updateAuth(bool retrieved);
void postponeBleWatchdog();
void updateTime();
void updateGpioOutputs();
@@ -153,6 +154,7 @@ private:
int64_t _waitKeypadUpdateTs = 0;
int64_t _waitTimeControlUpdateTs = 0;
int64_t _waitAuthUpdateTs = 0;
int64_t _nextTimeUpdateTs = 0;
int64_t _nextKeypadUpdateTs = 0;
int64_t _nextRssiTs = 0;
int64_t _lastRssi = 0;

View File

@@ -68,6 +68,7 @@
#define preference_debug_command (char*)"dbgCommand"
#define preference_connect_mode (char*)"nukiConnMode"
#define preference_http_auth_type (char*)"httpdAuthType"
#define preference_update_time (char*)"updateTime"
// CHANGE DOES NOT REQUIRE REBOOT TO TAKE EFFECT
#define preference_find_best_rssi (char*)"nwbestrssi"
@@ -369,7 +370,7 @@ private:
preference_started_before, preference_config_version, preference_device_id_lock, preference_device_id_opener, preference_nuki_id_lock, preference_nuki_id_opener,
preference_mqtt_broker, preference_mqtt_broker_port, preference_mqtt_user, preference_mqtt_password, preference_mqtt_log_enabled, preference_check_updates,
preference_webserver_enabled, preference_lock_enabled, preference_lock_pin_status, preference_mqtt_lock_path, preference_opener_enabled, preference_opener_pin_status,
preference_opener_continuous_mode, preference_lock_max_keypad_code_count, preference_opener_max_keypad_code_count,
preference_opener_continuous_mode, preference_lock_max_keypad_code_count, preference_opener_max_keypad_code_count, preference_update_time,
preference_lock_max_timecontrol_entry_count, preference_opener_max_timecontrol_entry_count, preference_enable_bootloop_reset, preference_mqtt_ca, preference_mqtt_crt,
preference_mqtt_key, preference_mqtt_hass_discovery, preference_mqtt_hass_cu_url, preference_buffer_size, preference_ip_dhcp_enabled, preference_ip_address,
preference_ip_subnet, preference_ip_gateway, preference_ip_dns_server, preference_network_hardware, preference_http_auth_type,
@@ -398,7 +399,7 @@ private:
std::vector<char*> _boolPrefs =
{
preference_started_before, preference_mqtt_log_enabled, preference_check_updates, preference_lock_enabled, preference_opener_enabled, preference_opener_continuous_mode,
preference_timecontrol_topic_per_entry, preference_keypad_topic_per_entry, preference_enable_bootloop_reset, preference_webserver_enabled,
preference_timecontrol_topic_per_entry, preference_keypad_topic_per_entry, preference_enable_bootloop_reset, preference_webserver_enabled, preference_update_time,
preference_restart_on_disconnect, preference_keypad_control_enabled, preference_keypad_info_enabled, preference_keypad_publish_code, preference_show_secrets,
preference_timecontrol_control_enabled, preference_timecontrol_info_enabled, preference_register_as_app, preference_register_opener_as_app, preference_ip_dhcp_enabled,
preference_publish_authdata, preference_publish_debug_info, preference_official_hybrid_enabled, preference_mqtt_hass_enabled, preference_retain_gpio,

View File

@@ -1676,6 +1676,16 @@ bool WebCfgServer::processArgs(PsychicRequest *request, PsychicResponse* resp, S
}
}
#endif
else if(key == "UPTIME")
{
if(_preferences->getBool(preference_update_time, false) != (value == "1"))
{
_preferences->putBool(preference_update_time, (value == "1"));
Log->print(F("Setting changed: "));
Log->println(key);
configChanged = true;
}
}
else if(key == "NWHW")
{
if(_preferences->getInt(preference_network_hardware, 0) != value.toInt())
@@ -4360,7 +4370,7 @@ esp_err_t WebCfgServer::buildNukiConfigHtml(PsychicRequest *request, PsychicResp
}
printInputField(&response, "RSBC", "Restart if bluetooth beacons not received (seconds; -1 to disable)", _preferences->getInt(preference_restart_ble_beacon_lost), 10, "");
printInputField(&response, "TXPWR", "BLE transmit power in dB (minimum -12, maximum 9)", _preferences->getInt(preference_ble_tx_power, 9), 10, "");
printCheckBox(&response, "UPTIME", "Update Nuki Hub and Lock/Opener time using NTP", _preferences->getBool(preference_update_time, false), "");
response.print("</table>");
response.print("<br><input type=\"submit\" name=\"submit\" value=\"Save\">");
response.print("</form>");

View File

@@ -29,6 +29,8 @@
#include "RestartReason.h"
#include "EspMillis.h"
#include "NimBLEDevice.h"
#include <time.h>
#include "esp_sntp.h"
/*
#ifdef DEBUG_NUKIHUB
@@ -249,7 +251,6 @@ void nukiTask(void *pvParameters)
{
int64_t nukiLoopTs = 0;
bool whiteListed = false;
while(true)
{
if(disableNetwork || wifiConnected)
@@ -437,7 +438,6 @@ void otaTask(void *pvParameter)
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
Log->println("Firmware upgrade failed, restarting");
esp_ota_set_boot_partition(esp_ota_get_next_update_partition(NULL));
restartEsp(RestartReason::OTAAborted);
@@ -480,6 +480,10 @@ void setupTasks(bool ota)
}
}
void cbSyncTime(struct timeval *tv) {
Log->println(F("NTP time synched"));
}
void setup()
{
//Set Log level to error for all TAGS
@@ -804,6 +808,13 @@ void setup()
#endif
*/
}
if(preferences->getBool(preference_update_time, false))
{
sntp_set_sync_interval(12 * 60 * 60 * 1000UL);
sntp_set_time_sync_notification_cb(cbSyncTime);
configTime(0, 0, "pool.ntp.org");
}
#endif
if(doOta)