diff --git a/src/MeshCore.h b/src/MeshCore.h index cfa33cf90b..9853420044 100644 --- a/src/MeshCore.h +++ b/src/MeshCore.h @@ -98,6 +98,8 @@ class RTCClock { */ virtual void tick() { /* no op */} + virtual const char* getSourceName() const { return "internal"; } + uint32_t getCurrentTimeUnique() { uint32_t t = getCurrentTime(); if (t <= last_unique) { diff --git a/src/helpers/AutoDiscoverRTCClock.cpp b/src/helpers/AutoDiscoverRTCClock.cpp index a310539bc7..d067b8d99b 100644 --- a/src/helpers/AutoDiscoverRTCClock.cpp +++ b/src/helpers/AutoDiscoverRTCClock.cpp @@ -26,6 +26,17 @@ bool AutoDiscoverRTCClock::i2c_probe(TwoWire& wire, uint8_t addr) { return (error == 0); } +void AutoDiscoverRTCClock::syncSystemClock() { + uint32_t hw_time = getCurrentTime(); + if (hw_time <= 1704067200UL) return; // DS3231 not set or lost power (before 2024-01-01) + + uint32_t sys_time = _fallback->getCurrentTime(); + int32_t drift = (int32_t)(hw_time - sys_time); + if (drift > 2 || drift < -2) { + _fallback->setCurrentTime(hw_time); + } +} + void AutoDiscoverRTCClock::begin(TwoWire& wire) { #if !defined(DISABLE_DS3231_PROBE) if (i2c_probe(wire, DS3231_ADDRESS)) { @@ -51,6 +62,17 @@ void AutoDiscoverRTCClock::begin(TwoWire& wire) { rtc_8130_success = true; MESH_DEBUG_PRINTLN("RX8130CE: Initialized"); } + + if (ds3231_success) _source_name = "DS3231"; + else if (rv3028_success) _source_name = "RV3028"; + else if (rtc_8563_success) _source_name = "PCF8563"; + else if (rtc_8130_success) _source_name = "RX8130CE"; + + _has_hw_rtc = ds3231_success || rv3028_success || rtc_8563_success || rtc_8130_success; + if (_has_hw_rtc) { + syncSystemClock(); + _last_sync_ms = millis(); + } } uint32_t AutoDiscoverRTCClock::getCurrentTime() { diff --git a/src/helpers/AutoDiscoverRTCClock.h b/src/helpers/AutoDiscoverRTCClock.h index 11364cd811..a52ac372db 100644 --- a/src/helpers/AutoDiscoverRTCClock.h +++ b/src/helpers/AutoDiscoverRTCClock.h @@ -4,12 +4,23 @@ #include #include +#ifndef RTC_RESYNC_INTERVAL_MS + #define RTC_RESYNC_INTERVAL_MS 3600000UL // re-sync system clock from hardware RTC once per hour +#endif + class AutoDiscoverRTCClock : public mesh::RTCClock { mesh::RTCClock* _fallback; + bool _has_hw_rtc; + unsigned long _last_sync_ms; + const char* _source_name; bool i2c_probe(TwoWire& wire, uint8_t addr); + void syncSystemClock(); public: - AutoDiscoverRTCClock(mesh::RTCClock& fallback) : _fallback(&fallback) { } + AutoDiscoverRTCClock(mesh::RTCClock& fallback) + : _fallback(&fallback), _has_hw_rtc(false), _last_sync_ms(0), _source_name("internal") { } + + const char* getSourceName() const override { return _source_name; } void begin(TwoWire& wire); uint32_t getCurrentTime() override; @@ -17,5 +28,12 @@ class AutoDiscoverRTCClock : public mesh::RTCClock { void tick() override { _fallback->tick(); // is typically VolatileRTCClock, which now needs tick() + if (_has_hw_rtc) { + unsigned long now = millis(); + if ((unsigned long)(now - _last_sync_ms) >= RTC_RESYNC_INTERVAL_MS) { + syncSystemClock(); + _last_sync_ms = now; + } + } } }; diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index b78ad6ebd6..397c9e222d 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -926,6 +926,13 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep #else strcpy(reply, "ERROR: Power management not supported"); #endif + } else if (memcmp(config, "rtcclock", 8) == 0) { + uint32_t now = getRTCClock()->getCurrentTime(); + DateTime dt = DateTime(now); + sprintf(reply, "> %s | %04d-%02d-%02d %02d:%02d:%02d UTC", + getRTCClock()->getSourceName(), + dt.year(), dt.month(), dt.day(), + dt.hour(), dt.minute(), dt.second()); } else { sprintf(reply, "??: %s", config); } diff --git a/variants/heltec_v3/platformio.ini b/variants/heltec_v3/platformio.ini index a70a93a508..a63009685e 100644 --- a/variants/heltec_v3/platformio.ini +++ b/variants/heltec_v3/platformio.ini @@ -47,8 +47,8 @@ build_flags = -D ADVERT_LON=0.0 -D ADMIN_PASSWORD='"password"' -D MAX_NEIGHBOURS=50 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 + -D MESH_PACKET_LOGGING=1 + -D MESH_DEBUG=1 build_src_filter = ${Heltec_lora32_v3.build_src_filter} + +<../examples/simple_repeater> @@ -167,8 +167,8 @@ build_flags = -D AUTO_SHUTDOWN_MILLIVOLTS=3400 -D BLE_DEBUG_LOGGING=1 -D OFFLINE_QUEUE_SIZE=256 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 + -D MESH_PACKET_LOGGING=1 + -D MESH_DEBUG=1 build_src_filter = ${Heltec_lora32_v3.build_src_filter} + + @@ -191,8 +191,8 @@ build_flags = -D WIFI_SSID='"myssid"' -D WIFI_PWD='"mypwd"' -D OFFLINE_QUEUE_SIZE=256 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 + -D MESH_PACKET_LOGGING=1 + -D MESH_DEBUG=1 build_src_filter = ${Heltec_lora32_v3.build_src_filter} + + diff --git a/variants/heltec_v4/platformio.ini b/variants/heltec_v4/platformio.ini index fabf38272d..1e2635f0c9 100644 --- a/variants/heltec_v4/platformio.ini +++ b/variants/heltec_v4/platformio.ini @@ -92,8 +92,8 @@ build_flags = -D ADVERT_LON=0.0 -D ADMIN_PASSWORD='"password"' -D MAX_NEIGHBOURS=50 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 + -D MESH_PACKET_LOGGING=1 + -D MESH_DEBUG=1 build_src_filter = ${heltec_v4_oled.build_src_filter} + +<../examples/simple_repeater> @@ -135,9 +135,9 @@ build_flags = -D ADMIN_PASSWORD='"password"' -D MAX_NEIGHBOURS=50 -D WITH_ESPNOW_BRIDGE=1 -; -D BRIDGE_DEBUG=1 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 + -D BRIDGE_DEBUG=1 + -D MESH_PACKET_LOGGING=1 + -D MESH_DEBUG=1 build_src_filter = ${heltec_v4_oled.build_src_filter} + + @@ -156,8 +156,8 @@ build_flags = -D ADVERT_LON=0.0 -D ADMIN_PASSWORD='"password"' -D ROOM_PASSWORD='"hello"' -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 + -D MESH_PACKET_LOGGING=1 + -D MESH_DEBUG=1 build_src_filter = ${heltec_v4_oled.build_src_filter} + +<../examples/simple_room_server> @@ -171,8 +171,8 @@ build_flags = ${heltec_v4_oled.build_flags} -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=1 -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 + -D MESH_PACKET_LOGGING=1 + -D MESH_DEBUG=1 build_src_filter = ${heltec_v4_oled.build_src_filter} +<../examples/simple_secure_chat/main.cpp> lib_deps = @@ -234,8 +234,8 @@ build_flags = -D WIFI_DEBUG_LOGGING=1 -D WIFI_SSID='"myssid"' -D WIFI_PWD='"mypwd"' -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 + -D MESH_PACKET_LOGGING=1 + -D MESH_DEBUG=1 build_src_filter = ${heltec_v4_oled.build_src_filter} + + @@ -320,8 +320,8 @@ build_flags = -D ADVERT_LON=0.0 -D ADMIN_PASSWORD='"password"' -D ROOM_PASSWORD='"hello"' -; -D MESH_PACKET_LOGGING=1 -; -D MESH_DEBUG=1 + -D MESH_PACKET_LOGGING=1 + -D MESH_DEBUG=1 build_src_filter = ${heltec_v4_tft.build_src_filter} + +<../examples/simple_room_server>