From a14cd00387945d8a72dc3c96fad2507facfdc37c Mon Sep 17 00:00:00 2001 From: nick Date: Thu, 18 Jun 2026 22:49:40 -0600 Subject: [PATCH] dashboard: clean up and enable swipe page navigation --- docs/CHANGELOG.md | 7 ++ docs/dashboard-esp32s3.md | 7 ++ .../esp32-s3-dashboard/dashboard_config.h | 2 +- .../esp32-s3-dashboard/esp32-s3-dashboard.ino | 83 ++++--------------- 4 files changed, 33 insertions(+), 66 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 371dd99..fe044f7 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -2,6 +2,13 @@ ## Unreleased +### Changed +- Reworked ESP32-S3 dashboard page navigation to use screen-wide LVGL swipe gestures. +- Removed failed temporary double-tap and transparent hitbox navigation experiments. +- Kept the temporary Cargo ESP WiFi boot-screen bypass for Battery Detail testing. + +## Unreleased + ### Added - ESP32-S3 dashboard Battery Detail screen to the left of the main dashboard. - Swipe navigation between Battery Detail and Main Dashboard pages. diff --git a/docs/dashboard-esp32s3.md b/docs/dashboard-esp32s3.md index cc1ab86..b8eb4fe 100644 --- a/docs/dashboard-esp32s3.md +++ b/docs/dashboard-esp32s3.md @@ -304,3 +304,10 @@ The dashboard enclosure will include an M9N GPS module connected to the ESP32-S3 The dashboard has a hidden diagnostics overlay. Tap the top status card five times within roughly three seconds to open it. Double-tap the diagnostics overlay to return to the main dashboard. The diagnostics overlay shows dashboard version, uptime, heap, WiFi RSSI/IP, Cargo API status, Cargo firmware version, Cargo uptime, Cargo heap, Cargo AP client count, BMS status, relay count, and basic control-loop state. + + +## Dashboard Page Navigation +- Main Dashboard remains the default startup page. +- Swipe right from the main dashboard to open Battery Detail. +- Swipe left from Battery Detail to return to the main dashboard. +- Diagnostics remains hidden behind the multi-tap system-card gesture. diff --git a/firmware/esp32-s3-dashboard/dashboard_config.h b/firmware/esp32-s3-dashboard/dashboard_config.h index 943ceb7..d88273d 100644 --- a/firmware/esp32-s3-dashboard/dashboard_config.h +++ b/firmware/esp32-s3-dashboard/dashboard_config.h @@ -1,6 +1,6 @@ #pragma once -static const char *DASHBOARD_VERSION = "0.1.87-temp-wifi-screen-bypass"; +static const char *DASHBOARD_VERSION = "0.1.88-clean-swipe-nav"; // Update these if your Cargo ESP AP credentials are different. static const char *CARGO_WIFI_SSID = "OverlandController"; diff --git a/firmware/esp32-s3-dashboard/esp32-s3-dashboard.ino b/firmware/esp32-s3-dashboard/esp32-s3-dashboard.ino index 6eb0021..2be7606 100644 --- a/firmware/esp32-s3-dashboard/esp32-s3-dashboard.ino +++ b/firmware/esp32-s3-dashboard/esp32-s3-dashboard.ino @@ -555,46 +555,8 @@ static String signed_float_text(float value, int decimals, const char *suffix) return text; } -static void battery_nav_doubletap_cb(lv_event_t *event) -{ - if (lv_event_get_code(event) != LV_EVENT_PRESSED) return; - static uint32_t last_press_ms = 0; - static DashboardScreen last_target = SCREEN_OVERVIEW; - DashboardScreen target = (DashboardScreen)(intptr_t)lv_event_get_user_data(event); - uint32_t now_ms = millis(); - - if (target == last_target && now_ms - last_press_ms <= 700) { - last_press_ms = 0; - show_dashboard_screen(target); - return; - } - - last_target = target; - last_press_ms = now_ms; -} - -static void add_doubletap_nav_target(lv_obj_t *obj, DashboardScreen target) -{ - if (obj == nullptr) return; - lv_obj_add_flag(obj, LV_OBJ_FLAG_CLICKABLE); - lv_obj_add_event_cb(obj, battery_nav_doubletap_cb, LV_EVENT_RELEASED, (void *)target); - lv_obj_add_event_cb(obj, battery_nav_doubletap_cb, LV_EVENT_SHORT_CLICKED, (void *)target); -} - -static void add_doubletap_overlay(lv_obj_t *parent, int width, int height, DashboardScreen target) -{ - lv_obj_t *overlay = lv_obj_create(parent); - lv_obj_set_size(overlay, width, height); - lv_obj_center(overlay); - lv_obj_set_style_bg_opa(overlay, LV_OPA_TRANSP, 0); - lv_obj_set_style_border_opa(overlay, LV_OPA_TRANSP, 0); - lv_obj_set_style_pad_all(overlay, 0, 0); - lv_obj_clear_flag(overlay, LV_OBJ_FLAG_SCROLLABLE); - lv_obj_add_flag(overlay, LV_OBJ_FLAG_CLICKABLE); - lv_obj_add_event_cb(overlay, battery_nav_doubletap_cb, LV_EVENT_RELEASED, (void *)target); -} static void dashboard_root_event_cb(lv_event_t *event) { @@ -610,6 +572,18 @@ static void dashboard_root_event_cb(lv_event_t *event) } } +static void enable_dashboard_swipe_nav(lv_obj_t *obj) +{ + if (obj == nullptr) return; + + lv_obj_add_event_cb(obj, dashboard_root_event_cb, LV_EVENT_GESTURE, nullptr); + + uint32_t child_count = lv_obj_get_child_cnt(obj); + for (uint32_t i = 0; i < child_count; i++) { + enable_dashboard_swipe_nav(lv_obj_get_child(obj, i)); + } +} + static void make_detail_label(lv_obj_t *parent, lv_obj_t **label, const char *text, const lv_font_t *font, lv_color_t color, int width, lv_align_t align, int x, int y, lv_text_align_t text_align = LV_TEXT_ALIGN_LEFT) { *label = lv_label_create(parent); @@ -679,19 +653,6 @@ static lv_obj_t *create_battery_metric_tile(lv_obj_t *parent, const char *title, } -static void add_screen_doubletap_hitbox(lv_obj_t *screen, int x, int y, int width, int height, DashboardScreen target) -{ - lv_obj_t *hitbox = lv_obj_create(screen); - lv_obj_set_size(hitbox, width, height); - lv_obj_align(hitbox, LV_ALIGN_TOP_LEFT, x, y); - lv_obj_set_style_bg_opa(hitbox, LV_OPA_TRANSP, 0); - lv_obj_set_style_border_opa(hitbox, LV_OPA_TRANSP, 0); - lv_obj_set_style_pad_all(hitbox, 0, 0); - lv_obj_clear_flag(hitbox, LV_OBJ_FLAG_SCROLLABLE); - lv_obj_add_flag(hitbox, LV_OBJ_FLAG_CLICKABLE); - lv_obj_add_event_cb(hitbox, battery_nav_doubletap_cb, LV_EVENT_PRESSED, (void *)target); - lv_obj_move_foreground(hitbox); -} static void create_battery_detail_screen() { @@ -717,16 +678,10 @@ static void create_battery_detail_screen() lv_obj_align(page_dots, LV_ALIGN_RIGHT_MID, -10, 0); lv_obj_t *hero_card = create_card(screen, "", 300, 500, LV_ALIGN_TOP_LEFT, 32, 78); - add_doubletap_nav_target(hero_card, SCREEN_OVERVIEW); make_detail_label(hero_card, &battery_detail_status_label, "BMS --", &lv_font_montserrat_26, lv_color_hex(0xB8C0C8), 260, LV_ALIGN_TOP_MID, 0, 30, LV_TEXT_ALIGN_CENTER); make_detail_label(hero_card, &battery_detail_soc_label, "--%", &lv_font_montserrat_48, lv_color_hex(0xFFFFFF), 260, LV_ALIGN_TOP_MID, 0, 126, LV_TEXT_ALIGN_CENTER); make_detail_label(hero_card, &battery_detail_estimate_label, "--", &lv_font_montserrat_30, lv_color_hex(0xDDE3EA), 260, LV_ALIGN_TOP_MID, 0, 236, LV_TEXT_ALIGN_CENTER); - add_doubletap_nav_target(battery_detail_status_label, SCREEN_OVERVIEW); - add_doubletap_nav_target(battery_detail_soc_label, SCREEN_OVERVIEW); - add_doubletap_nav_target(battery_detail_estimate_label, SCREEN_OVERVIEW); - add_doubletap_overlay(hero_card, 300, 500, SCREEN_OVERVIEW); - lv_obj_t *hint_label = nullptr; make_detail_label(hero_card, &hint_label, "Double tap to return", &lv_font_montserrat_26, lv_color_hex(0x7D8996), 260, LV_ALIGN_BOTTOM_MID, 0, -28, LV_TEXT_ALIGN_CENTER); @@ -743,19 +698,18 @@ static void create_battery_detail_screen() make_detail_label(delta_card, &battery_detail_delta_label, "-- mV", &lv_font_montserrat_30, lv_color_hex(0xFFFFFF), 220, LV_ALIGN_RIGHT_MID, -20, 0, LV_TEXT_ALIGN_RIGHT); update_battery_detail_widgets(); - - add_screen_doubletap_hitbox(screen, 32, 78, 300, 500, SCREEN_OVERVIEW); + enable_dashboard_swipe_nav(screen); } static void show_dashboard_screen(DashboardScreen screen) { - lvgl_port_lock(-1); + if (screen == current_dashboard_screen) return; + if (screen == SCREEN_BATTERY_DETAIL) { create_battery_detail_screen(); } else { create_overland_overview_screen(); } - lvgl_port_unlock(); } @@ -1598,7 +1552,9 @@ static void create_overland_overview_screen() current_dashboard_screen = SCREEN_OVERVIEW; lv_obj_set_style_bg_color(screen, lv_color_hex(0x101418), 0); - lv_obj_t *system_card = create_card(screen, "", 960, 48, LV_ALIGN_TOP_MID, 0, 12); + + lv_obj_add_event_cb(screen, dashboard_root_event_cb, LV_EVENT_GESTURE, nullptr); +lv_obj_t *system_card = create_card(screen, "", 960, 48, LV_ALIGN_TOP_MID, 0, 12); lv_obj_add_flag(system_card, LV_OBJ_FLAG_CLICKABLE); lv_obj_add_event_cb(system_card, system_card_event_cb, LV_EVENT_CLICKED, nullptr); lv_obj_t *battery_card = create_card(screen, "", 380, 310, LV_ALIGN_TOP_LEFT, 32, 68); @@ -1651,7 +1607,6 @@ static void create_overland_overview_screen() lv_label_set_text(battery_soc_label, "--%"); lv_obj_set_style_text_color(battery_soc_label, lv_color_hex(0xFFFFFF), 0); lv_obj_set_style_text_font(battery_soc_label, &lv_font_montserrat_48, 0); - lv_obj_set_style_text_font(battery_soc_label, &lv_font_montserrat_48, 0); lv_obj_set_width(battery_soc_label, 280); lv_obj_set_style_text_align(battery_soc_label, LV_TEXT_ALIGN_CENTER, 0); lv_obj_align(battery_soc_label, LV_ALIGN_TOP_MID, 0, 90); @@ -1868,9 +1823,7 @@ void setup() lvgl_port_lock(-1); // TEMP DEBUG: bypass blocking Cargo ESP WiFi screen while troubleshooting pages. - lvgl_port_lock(-1); create_overland_overview_screen(); - lvgl_port_unlock(); overview_screen_created = true; lvgl_port_unlock();