diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index a2729d84..90eb15cc 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -498,6 +498,25 @@ extern "C" EMSCRIPTEN_KEEPALIVE int sim_test_disable_screen_timeout() { return 1; } +// Re-anchors this instance's RTC to the host's real wall clock. SimRTCClock +// (variants/sim/SimRTCClock.h) already starts out reading time(NULL), so a +// freshly booted instance needs no help -- but the clock is a shared, live +// thing the real mesh code legitimately writes to at runtime: a received +// packet or a contact-list bootstrap carrying a timestamp ahead of ours +// pushes it forward (BaseChatMesh::bootstrapRTCfromContacts(), +// MyMesh's own timestamp handling), which is correct behaviour on a real +// node with no better time source, and means one peer with a badly skewed +// clock can drag every node that hears it. Calling this on every (re)boot +// makes "reset the device" mean "the demo's clock matches the visitor's own +// computer again", the same guarantee the timezone hook above gives. +// Seconds since the Unix epoch, as a double because a JS Date.now()/1000 +// value has no exact int32 representation to pass through ccall. +extern "C" EMSCRIPTEN_KEEPALIVE int sim_test_sync_time(double epoch_secs) { + if (epoch_secs < 1000000000.0) return 0; // obvious nonsense (pre-2001) -- leave the clock alone + rtc_clock.setCurrentTime((uint32_t)epoch_secs); + return 1; +} + #ifdef DISPLAY_CLASS // Jumps the on-device UI straight to the DM thread with the first known // ADV_TYPE_CHAT contact (UITask::openContactDM() -- the exact same real diff --git a/src/helpers/BaseChatMesh.cpp b/src/helpers/BaseChatMesh.cpp index c91a2d02..b1cfaeec 100644 --- a/src/helpers/BaseChatMesh.cpp +++ b/src/helpers/BaseChatMesh.cpp @@ -62,7 +62,14 @@ void BaseChatMesh::bootstrapRTCfromContacts() { latest = contacts[i].lastmod; } } - if (latest != 0) { + // A bootstrap is a *floor*, not an assignment: the newest contact we know + // of proves the clock must be at least that late, it says nothing about it + // being any earlier. Setting it unconditionally drags a clock that already + // knows better (a board with a real RTC, or the sim's host wall clock -- + // see variants/sim/SimRTCClock.h) *backwards* to whatever timestamp + // happened to be persisted with the contact list, which then reads as a + // stopped/lagging clock on the Home screen after every reboot. + if (latest != 0 && latest + 1 > getRTCClock()->getCurrentTime()) { getRTCClock()->setCurrentTime(latest + 1); } }