From eb84b1a2b3ede43e6b9c21d31251484dbf82a0a4 Mon Sep 17 00:00:00 2001 From: liquidraver <504870+liquidraver@users.noreply.github.com> Date: Thu, 21 May 2026 09:55:26 +0200 Subject: [PATCH] joystick UI: add Time Sync admin menu item New 6th item in the repeater admin submenu (admin only). Sends "clock sync" as a CLI command; the repeater reads sender_timestamp from the packet metadata and sets its RTC to our companion epoch if ours is ahead. Response lands in the existing admin history list. --- .../helpers/ui-joystick/screens/contacts.cpp | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/zephcore/helpers/ui-joystick/screens/contacts.cpp b/zephcore/helpers/ui-joystick/screens/contacts.cpp index 0d7aa01..4f798c8 100644 --- a/zephcore/helpers/ui-joystick/screens/contacts.cpp +++ b/zephcore/helpers/ui-joystick/screens/contacts.cpp @@ -1201,8 +1201,8 @@ int RepeaterAdminScreen::render(JoystickDisplay &display) display.setColor(_permissions != 0 ? JoystickDisplay::YELLOW : JoystickDisplay::LIGHT); display.drawTextCentered(display.width() / 2, kHeaderSepY + 2, _permissions != 0 ? "Admin" : "Guest"); - static const char * const kItems[] = { "Neighbours", "Stats", "Telemetry", "Info", "Commands" }; - int count = (_permissions != 0) ? 5 : 4; + static const char * const kItems[] = { "Neighbours", "Stats", "Telemetry", "Info", "Commands", "Time Sync" }; + int count = (_permissions != 0) ? 6 : 4; int max_vis = (display.height() - kAdminContentY) / kMenuLineH; if (max_vis < 1) max_vis = 1; int start = computeListStart(_submenu_sel, count, max_vis); @@ -1401,7 +1401,7 @@ bool RepeaterAdminScreen::handleInput(char c) case STATE_SUBMENU: { bool is_admin = (_permissions != 0); - int count = is_admin ? 5 : 4; + int count = is_admin ? 6 : 4; if (handleCommonListNavigation(c, _submenu_sel, count)) return true; if (c == KEY_ENTER) { if (_submenu_sel == 4 && is_admin) { @@ -1416,6 +1416,30 @@ bool RepeaterAdminScreen::handleInput(char c) return true; } + if (_submenu_sel == 5 && is_admin) { + /* Time Sync: send "clock sync" CLI. The repeater reads the + * packet's sender_timestamp (set by sendCommandData() to our + * current epoch) and updates its own RTC if our time is ahead. */ + int idx; + if (_hist_count < ADMIN_HIST_MAX) { + idx = (_hist_head + _hist_count) % ADMIN_HIST_MAX; + _hist_count++; + } else { + idx = _hist_head; + _hist_head = (_hist_head + 1) % ADMIN_HIST_MAX; + } + strncpy(_hist[idx].cmd, "Time Sync", ADMIN_CMD_MAX - 1); + _hist[idx].cmd[ADMIN_CMD_MAX - 1] = '\0'; + _hist[idx].resp[0] = '\0'; + _hist[idx].has_resp = false; + if (sendCLI("clock sync")) { + _pending = PENDING_CMD; + _state = STATE_MAIN; + _hist_scroll = 0; + } + return true; + } + /* Items 0 through 3: Neighbours, Stats, Telemetry, Info */ struct { const char *label;