dashboard: add hidden diagnostics overlay
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
static const char *DASHBOARD_VERSION = "0.1.74-relay-latest-state-queue";
|
||||
static const char *DASHBOARD_VERSION = "0.1.75-hidden-diagnostics";
|
||||
|
||||
// Update these if your Cargo ESP AP credentials are different.
|
||||
static const char *CARGO_WIFI_SSID = "OverlandController";
|
||||
|
||||
@@ -24,4 +24,10 @@ struct DashboardStatus {
|
||||
unsigned long uptime_seconds = 0;
|
||||
String cargo_ap_ssid = "unknown";
|
||||
String cargo_sta_ip = "unknown";
|
||||
int cargo_ap_clients = 0;
|
||||
int cargo_sta_rssi_dbm = 0;
|
||||
unsigned long cargo_free_heap = 0;
|
||||
unsigned long cargo_min_free_heap = 0;
|
||||
String cargo_chip_model = "unknown";
|
||||
int cargo_cpu_mhz = 0;
|
||||
};
|
||||
|
||||
@@ -40,6 +40,13 @@ static lv_obj_t *vehicle_fuel_value_label = nullptr;
|
||||
static lv_obj_t *relay_buttons[6] = {nullptr};
|
||||
static lv_obj_t *relay_button_labels[6] = {nullptr};
|
||||
|
||||
static lv_obj_t *diagnostics_overlay = nullptr;
|
||||
static lv_obj_t *diagnostics_label = nullptr;
|
||||
static unsigned long diagnostics_last_update_ms = 0;
|
||||
static unsigned long diagnostics_last_tap_ms = 0;
|
||||
static unsigned long system_card_last_tap_ms = 0;
|
||||
static int system_card_tap_count = 0;
|
||||
|
||||
static String relay_ids[6];
|
||||
static String relay_names[6];
|
||||
static bool relay_states[6] = {false};
|
||||
@@ -353,8 +360,200 @@ static void request_fast_status_refresh()
|
||||
fast_status_refresh_requested = false;
|
||||
}
|
||||
|
||||
|
||||
static String format_diag_uptime(unsigned long seconds)
|
||||
{
|
||||
unsigned long days = seconds / 86400;
|
||||
seconds %= 86400;
|
||||
unsigned long hours = seconds / 3600;
|
||||
seconds %= 3600;
|
||||
unsigned long minutes = seconds / 60;
|
||||
|
||||
String out;
|
||||
if (days > 0) {
|
||||
out += String(days);
|
||||
out += "d ";
|
||||
}
|
||||
out += String(hours);
|
||||
out += "h ";
|
||||
out += String(minutes);
|
||||
out += "m";
|
||||
return out;
|
||||
}
|
||||
|
||||
static void update_diagnostics_overlay()
|
||||
{
|
||||
if (diagnostics_overlay == nullptr || diagnostics_label == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (millis() - diagnostics_last_update_ms < 500) {
|
||||
return;
|
||||
}
|
||||
|
||||
diagnostics_last_update_ms = millis();
|
||||
|
||||
String text;
|
||||
text += "DIAGNOSTICS\n\n";
|
||||
|
||||
text += "Dashboard ESP32-S3\n";
|
||||
text += " Version: ";
|
||||
text += DASHBOARD_VERSION;
|
||||
text += "\n Uptime: ";
|
||||
text += format_diag_uptime(millis() / 1000);
|
||||
text += "\n Free heap: ";
|
||||
text += String(ESP.getFreeHeap());
|
||||
text += "\n Min heap: ";
|
||||
text += String(ESP.getMinFreeHeap());
|
||||
text += "\n WiFi: ";
|
||||
text += WiFi.status() == WL_CONNECTED ? "connected" : "offline";
|
||||
text += "\n RSSI: ";
|
||||
text += WiFi.status() == WL_CONNECTED ? String(WiFi.RSSI()) : String("--");
|
||||
text += " dBm\n IP: ";
|
||||
text += WiFi.status() == WL_CONNECTED ? WiFi.localIP().toString() : String("--");
|
||||
text += "\n Last HTTP: ";
|
||||
text += String(status_model.http_code);
|
||||
text += "\n Cargo API: ";
|
||||
text += status_model.api_ok ? "OK" : "FAIL";
|
||||
|
||||
text += "\n\nCargo ESP\n";
|
||||
text += " Version: ";
|
||||
text += status_model.firmware_version;
|
||||
text += "\n Uptime: ";
|
||||
text += format_diag_uptime(status_model.uptime_seconds);
|
||||
text += "\n Chip: ";
|
||||
text += status_model.cargo_chip_model;
|
||||
text += "\n CPU: ";
|
||||
text += String(status_model.cargo_cpu_mhz);
|
||||
text += " MHz";
|
||||
text += "\n Free heap: ";
|
||||
text += String(status_model.cargo_free_heap);
|
||||
text += "\n Min heap: ";
|
||||
text += String(status_model.cargo_min_free_heap);
|
||||
|
||||
text += "\n\nCargo Network\n";
|
||||
text += " AP SSID: ";
|
||||
text += status_model.cargo_ap_ssid;
|
||||
text += "\n AP clients: ";
|
||||
text += String(status_model.cargo_ap_clients);
|
||||
text += "\n STA IP: ";
|
||||
text += status_model.cargo_sta_ip.length() ? status_model.cargo_sta_ip : String("--");
|
||||
text += "\n STA RSSI: ";
|
||||
text += status_model.cargo_sta_rssi_dbm == 0 ? String("--") : String(status_model.cargo_sta_rssi_dbm);
|
||||
text += " dBm";
|
||||
|
||||
text += "\n\nPower / Sensors\n";
|
||||
text += " BMS: ";
|
||||
text += status_model.bms_connected ? "connected" : "offline";
|
||||
text += "\n SOC: ";
|
||||
text += status_model.soc >= 0 ? String(status_model.soc) + "%" : String("--");
|
||||
text += "\n Current: ";
|
||||
text += String(status_model.current, 2);
|
||||
text += " A";
|
||||
text += "\n Cell delta: ";
|
||||
text += String(status_model.cell_delta_mv);
|
||||
text += " mV";
|
||||
|
||||
text += "\n\nControls\n";
|
||||
text += " Relays visible: ";
|
||||
text += String(relay_count);
|
||||
text += "\n API busy: ";
|
||||
text += api_request_in_progress ? "yes" : "no";
|
||||
|
||||
text += "\n\nDouble tap anywhere to return.";
|
||||
|
||||
lvgl_port_lock(-1);
|
||||
lv_label_set_text(diagnostics_label, text.c_str());
|
||||
lvgl_port_unlock();
|
||||
}
|
||||
|
||||
static void close_diagnostics_overlay()
|
||||
{
|
||||
if (diagnostics_overlay == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
lvgl_port_lock(-1);
|
||||
lv_obj_del(diagnostics_overlay);
|
||||
diagnostics_overlay = nullptr;
|
||||
diagnostics_label = nullptr;
|
||||
lvgl_port_unlock();
|
||||
}
|
||||
|
||||
static void diagnostics_overlay_event_cb(lv_event_t *event)
|
||||
{
|
||||
if (lv_event_get_code(event) != LV_EVENT_CLICKED) {
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned long now = millis();
|
||||
if (now - diagnostics_last_tap_ms < 650) {
|
||||
close_diagnostics_overlay();
|
||||
diagnostics_last_tap_ms = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
diagnostics_last_tap_ms = now;
|
||||
}
|
||||
|
||||
static void show_diagnostics_overlay()
|
||||
{
|
||||
if (diagnostics_overlay != nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
lvgl_port_lock(-1);
|
||||
|
||||
diagnostics_overlay = lv_obj_create(lv_scr_act());
|
||||
lv_obj_set_size(diagnostics_overlay, 1024, 600);
|
||||
lv_obj_align(diagnostics_overlay, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_style_bg_color(diagnostics_overlay, lv_color_hex(0x101418), 0);
|
||||
lv_obj_set_style_bg_opa(diagnostics_overlay, LV_OPA_COVER, 0);
|
||||
lv_obj_set_style_border_width(diagnostics_overlay, 0, 0);
|
||||
lv_obj_set_style_pad_all(diagnostics_overlay, 22, 0);
|
||||
lv_obj_add_flag(diagnostics_overlay, LV_OBJ_FLAG_CLICKABLE);
|
||||
lv_obj_add_event_cb(diagnostics_overlay, diagnostics_overlay_event_cb, LV_EVENT_CLICKED, nullptr);
|
||||
|
||||
diagnostics_label = lv_label_create(diagnostics_overlay);
|
||||
lv_label_set_text(diagnostics_label, "DIAGNOSTICS\nLoading...");
|
||||
lv_obj_set_style_text_color(diagnostics_label, lv_color_hex(0xDDE3EA), 0);
|
||||
lv_obj_set_style_text_font(diagnostics_label, &lv_font_montserrat_26, 0);
|
||||
lv_obj_set_width(diagnostics_label, 960);
|
||||
lv_label_set_long_mode(diagnostics_label, LV_LABEL_LONG_WRAP);
|
||||
lv_obj_align(diagnostics_label, LV_ALIGN_TOP_LEFT, 8, 8);
|
||||
|
||||
lvgl_port_unlock();
|
||||
|
||||
diagnostics_last_update_ms = 0;
|
||||
update_diagnostics_overlay();
|
||||
}
|
||||
|
||||
static void system_card_event_cb(lv_event_t *event)
|
||||
{
|
||||
if (lv_event_get_code(event) != LV_EVENT_CLICKED) {
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned long now = millis();
|
||||
if (now - system_card_last_tap_ms > 3000) {
|
||||
system_card_tap_count = 0;
|
||||
}
|
||||
|
||||
system_card_last_tap_ms = now;
|
||||
system_card_tap_count++;
|
||||
|
||||
if (system_card_tap_count >= 5) {
|
||||
system_card_tap_count = 0;
|
||||
show_diagnostics_overlay();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void create_overland_overview_screen();
|
||||
static void show_boot_screen();
|
||||
static void show_diagnostics_overlay();
|
||||
static void close_diagnostics_overlay();
|
||||
static void update_diagnostics_overlay();
|
||||
|
||||
static void layout_relay_buttons()
|
||||
{
|
||||
@@ -903,12 +1102,18 @@ static void parse_status_json(const String &body)
|
||||
JsonObject system = doc["system"];
|
||||
status_model.firmware_version = String((const char *)(system["firmware_version"] | status_model.firmware_version.c_str()));
|
||||
status_model.uptime_seconds = system["uptime_seconds"] | status_model.uptime_seconds;
|
||||
status_model.cargo_free_heap = system["free_heap"] | status_model.cargo_free_heap;
|
||||
status_model.cargo_min_free_heap = system["min_free_heap"] | status_model.cargo_min_free_heap;
|
||||
status_model.cargo_chip_model = String((const char *)(system["chip_model"] | status_model.cargo_chip_model.c_str()));
|
||||
status_model.cargo_cpu_mhz = system["cpu_mhz"] | status_model.cargo_cpu_mhz;
|
||||
}
|
||||
|
||||
if (doc["network"].is<JsonObject>()) {
|
||||
JsonObject network = doc["network"];
|
||||
status_model.cargo_ap_ssid = String((const char *)(network["ap_ssid"] | status_model.cargo_ap_ssid.c_str()));
|
||||
status_model.cargo_sta_ip = String((const char *)(network["sta_ip"] | status_model.cargo_sta_ip.c_str()));
|
||||
status_model.cargo_ap_clients = network["ap_clients"] | status_model.cargo_ap_clients;
|
||||
status_model.cargo_sta_rssi_dbm = network["sta_rssi_dbm"] | status_model.cargo_sta_rssi_dbm;
|
||||
}
|
||||
|
||||
if (doc["temps"].is<JsonArray>()) {
|
||||
@@ -1188,6 +1393,8 @@ static void create_overland_overview_screen()
|
||||
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_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);
|
||||
battery_card_obj = battery_card;
|
||||
lv_obj_t *temp_card = create_card(screen, "", 260, 310, LV_ALIGN_TOP_LEFT, 426, 68);
|
||||
|
||||
Reference in New Issue
Block a user