dashboard: add wifi client status view
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
#include <Arduino.h>
|
||||
#include <WiFi.h>
|
||||
#include <HTTPClient.h>
|
||||
#include <esp_display_panel.hpp>
|
||||
|
||||
#include <lvgl.h>
|
||||
@@ -7,8 +9,33 @@
|
||||
using namespace esp_panel::drivers;
|
||||
using namespace esp_panel::board;
|
||||
|
||||
static const char *DASHBOARD_VERSION = "0.0.2-wifi-status";
|
||||
|
||||
// Update these if your Cargo ESP AP credentials are different.
|
||||
static const char *CARGO_WIFI_SSID = "OverlandController";
|
||||
static const char *CARGO_WIFI_PASSWORD = "overland1234";
|
||||
|
||||
static const char *CARGO_API_STATUS_URL = "http://192.168.4.1/api/v1/status";
|
||||
|
||||
static lv_obj_t *wifi_label = nullptr;
|
||||
static lv_obj_t *api_label = nullptr;
|
||||
static lv_obj_t *status_label = nullptr;
|
||||
static lv_obj_t *touch_count_label = nullptr;
|
||||
|
||||
static uint32_t touch_count = 0;
|
||||
static unsigned long last_wifi_attempt_ms = 0;
|
||||
static unsigned long last_status_poll_ms = 0;
|
||||
|
||||
static void set_label_text(lv_obj_t *label, const String &text)
|
||||
{
|
||||
if (label == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
lvgl_port_lock(-1);
|
||||
lv_label_set_text(label, text.c_str());
|
||||
lvgl_port_unlock();
|
||||
}
|
||||
|
||||
static void touch_test_event_cb(lv_event_t *event)
|
||||
{
|
||||
@@ -19,14 +46,104 @@ static void touch_test_event_cb(lv_event_t *event)
|
||||
touch_count++;
|
||||
|
||||
if (touch_count_label != nullptr) {
|
||||
lvgl_port_lock(-1);
|
||||
lv_label_set_text_fmt(touch_count_label, "Touch test count: %lu", (unsigned long)touch_count);
|
||||
lvgl_port_unlock();
|
||||
}
|
||||
|
||||
Serial.print("Touch test count: ");
|
||||
Serial.println(touch_count);
|
||||
}
|
||||
|
||||
static void create_overland_boot_screen()
|
||||
static void connect_wifi_if_needed()
|
||||
{
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (millis() - last_wifi_attempt_ms < 10000) {
|
||||
return;
|
||||
}
|
||||
|
||||
last_wifi_attempt_ms = millis();
|
||||
|
||||
Serial.print("Connecting to Cargo ESP AP: ");
|
||||
Serial.println(CARGO_WIFI_SSID);
|
||||
|
||||
set_label_text(wifi_label, "WiFi: connecting...");
|
||||
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(CARGO_WIFI_SSID, CARGO_WIFI_PASSWORD);
|
||||
}
|
||||
|
||||
static void update_wifi_label()
|
||||
{
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
String text = "WiFi: connected\nIP: ";
|
||||
text += WiFi.localIP().toString();
|
||||
text += "\nRSSI: ";
|
||||
text += String(WiFi.RSSI());
|
||||
text += " dBm";
|
||||
set_label_text(wifi_label, text);
|
||||
} else {
|
||||
set_label_text(wifi_label, "WiFi: not connected\nSSID: " + String(CARGO_WIFI_SSID));
|
||||
}
|
||||
}
|
||||
|
||||
static void poll_status_api()
|
||||
{
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
set_label_text(api_label, "API: waiting for WiFi");
|
||||
set_label_text(status_label, "No API response yet.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (millis() - last_status_poll_ms < 5000) {
|
||||
return;
|
||||
}
|
||||
|
||||
last_status_poll_ms = millis();
|
||||
|
||||
Serial.print("GET ");
|
||||
Serial.println(CARGO_API_STATUS_URL);
|
||||
|
||||
set_label_text(api_label, "API: requesting /api/v1/status");
|
||||
|
||||
HTTPClient http;
|
||||
http.begin(CARGO_API_STATUS_URL);
|
||||
int code = http.GET();
|
||||
|
||||
if (code > 0) {
|
||||
String body = http.getString();
|
||||
|
||||
Serial.print("HTTP ");
|
||||
Serial.println(code);
|
||||
Serial.println(body);
|
||||
|
||||
String api_text = "API: HTTP ";
|
||||
api_text += String(code);
|
||||
api_text += "\nGET /api/v1/status";
|
||||
set_label_text(api_label, api_text);
|
||||
|
||||
if (body.length() > 900) {
|
||||
body = body.substring(0, 900);
|
||||
body += "\n...truncated...";
|
||||
}
|
||||
|
||||
set_label_text(status_label, body);
|
||||
} else {
|
||||
String error = "API request failed: ";
|
||||
error += http.errorToString(code);
|
||||
|
||||
Serial.println(error);
|
||||
set_label_text(api_label, error);
|
||||
set_label_text(status_label, "No valid response from Cargo ESP.");
|
||||
}
|
||||
|
||||
http.end();
|
||||
}
|
||||
|
||||
static void create_overland_status_screen()
|
||||
{
|
||||
lv_obj_t *screen = lv_scr_act();
|
||||
lv_obj_clean(screen);
|
||||
@@ -37,41 +154,61 @@ static void create_overland_boot_screen()
|
||||
lv_label_set_text(title, "Overland Controller");
|
||||
lv_obj_set_style_text_color(title, lv_color_hex(0xFFFFFF), 0);
|
||||
lv_obj_set_style_text_font(title, &lv_font_montserrat_30, 0);
|
||||
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 40);
|
||||
lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 24);
|
||||
|
||||
lv_obj_t *subtitle = lv_label_create(screen);
|
||||
lv_label_set_text(subtitle, "ESP32-S3 Dashboard Bring-Up");
|
||||
lv_label_set_text(subtitle, "ESP32-S3 Dashboard - WiFi/API Bring-Up");
|
||||
lv_obj_set_style_text_color(subtitle, lv_color_hex(0xB8C0C8), 0);
|
||||
lv_obj_set_width(subtitle, 760);
|
||||
lv_obj_set_width(subtitle, 920);
|
||||
lv_obj_set_style_text_align(subtitle, LV_TEXT_ALIGN_CENTER, 0);
|
||||
lv_obj_align_to(subtitle, title, LV_ALIGN_OUT_BOTTOM_MID, 0, 12);
|
||||
lv_obj_align_to(subtitle, title, LV_ALIGN_OUT_BOTTOM_MID, 0, 8);
|
||||
|
||||
lv_obj_t *card = lv_obj_create(screen);
|
||||
lv_obj_set_size(card, 760, 330);
|
||||
lv_obj_align(card, LV_ALIGN_CENTER, 0, 25);
|
||||
lv_obj_set_style_radius(card, 18, 0);
|
||||
lv_obj_set_style_bg_color(card, lv_color_hex(0x1F2933), 0);
|
||||
lv_obj_set_style_border_color(card, lv_color_hex(0x3A4652), 0);
|
||||
lv_obj_set_style_border_width(card, 2, 0);
|
||||
lv_obj_set_style_pad_all(card, 24, 0);
|
||||
lv_obj_t *left_card = lv_obj_create(screen);
|
||||
lv_obj_set_size(left_card, 430, 360);
|
||||
lv_obj_align(left_card, LV_ALIGN_LEFT_MID, 38, 20);
|
||||
lv_obj_set_style_radius(left_card, 16, 0);
|
||||
lv_obj_set_style_bg_color(left_card, lv_color_hex(0x1F2933), 0);
|
||||
lv_obj_set_style_border_color(left_card, lv_color_hex(0x3A4652), 0);
|
||||
lv_obj_set_style_border_width(left_card, 2, 0);
|
||||
lv_obj_set_style_pad_all(left_card, 18, 0);
|
||||
|
||||
lv_obj_t *status = lv_label_create(card);
|
||||
lv_obj_t *right_card = lv_obj_create(screen);
|
||||
lv_obj_set_size(right_card, 500, 360);
|
||||
lv_obj_align(right_card, LV_ALIGN_RIGHT_MID, -38, 20);
|
||||
lv_obj_set_style_radius(right_card, 16, 0);
|
||||
lv_obj_set_style_bg_color(right_card, lv_color_hex(0x1F2933), 0);
|
||||
lv_obj_set_style_border_color(right_card, lv_color_hex(0x3A4652), 0);
|
||||
lv_obj_set_style_border_width(right_card, 2, 0);
|
||||
lv_obj_set_style_pad_all(right_card, 18, 0);
|
||||
|
||||
lv_obj_t *hardware_label = lv_label_create(left_card);
|
||||
lv_label_set_text(
|
||||
status,
|
||||
"Hardware: Waveshare ESP32-S3 Touch LCD 5B\n"
|
||||
"Display: 1024 x 600\n"
|
||||
"Touch: Capacitive\n"
|
||||
"Cargo API Base: /api/v1\n"
|
||||
"WiFi: Not connected yet\n"
|
||||
"Mode: Local dashboard bring-up"
|
||||
hardware_label,
|
||||
"Hardware:\n"
|
||||
"Waveshare ESP32-S3 Touch LCD 5B\n\n"
|
||||
"Display:\n"
|
||||
"1024 x 600\n\n"
|
||||
"Cargo API Base:\n"
|
||||
"/api/v1"
|
||||
);
|
||||
lv_obj_set_style_text_color(status, lv_color_hex(0xFFFFFF), 0);
|
||||
lv_obj_set_style_text_line_space(status, 10, 0);
|
||||
lv_obj_set_width(status, 700);
|
||||
lv_obj_align(status, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
lv_obj_set_style_text_color(hardware_label, lv_color_hex(0xFFFFFF), 0);
|
||||
lv_obj_set_width(hardware_label, 380);
|
||||
lv_obj_align(hardware_label, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
|
||||
lv_obj_t *button = lv_btn_create(card);
|
||||
lv_obj_set_size(button, 260, 72);
|
||||
wifi_label = lv_label_create(left_card);
|
||||
lv_label_set_text(wifi_label, "WiFi: not connected");
|
||||
lv_obj_set_style_text_color(wifi_label, lv_color_hex(0xB8C0C8), 0);
|
||||
lv_obj_set_width(wifi_label, 380);
|
||||
lv_obj_align(wifi_label, LV_ALIGN_TOP_LEFT, 0, 175);
|
||||
|
||||
api_label = lv_label_create(left_card);
|
||||
lv_label_set_text(api_label, "API: waiting");
|
||||
lv_obj_set_style_text_color(api_label, lv_color_hex(0xB8C0C8), 0);
|
||||
lv_obj_set_width(api_label, 380);
|
||||
lv_obj_align(api_label, LV_ALIGN_TOP_LEFT, 0, 250);
|
||||
|
||||
lv_obj_t *button = lv_btn_create(left_card);
|
||||
lv_obj_set_size(button, 170, 54);
|
||||
lv_obj_align(button, LV_ALIGN_BOTTOM_LEFT, 0, 0);
|
||||
lv_obj_add_event_cb(button, touch_test_event_cb, LV_EVENT_CLICKED, nullptr);
|
||||
|
||||
@@ -79,17 +216,28 @@ static void create_overland_boot_screen()
|
||||
lv_label_set_text(button_label, "Touch Test");
|
||||
lv_obj_center(button_label);
|
||||
|
||||
touch_count_label = lv_label_create(card);
|
||||
touch_count_label = lv_label_create(left_card);
|
||||
lv_label_set_text(touch_count_label, "Touch test count: 0");
|
||||
lv_obj_set_style_text_color(touch_count_label, lv_color_hex(0xB8C0C8), 0);
|
||||
lv_obj_align(touch_count_label, LV_ALIGN_BOTTOM_LEFT, 300, -22);
|
||||
lv_obj_align(touch_count_label, LV_ALIGN_BOTTOM_LEFT, 190, -18);
|
||||
|
||||
lv_obj_t *status_title = lv_label_create(right_card);
|
||||
lv_label_set_text(status_title, "GET /api/v1/status");
|
||||
lv_obj_set_style_text_color(status_title, lv_color_hex(0xFFFFFF), 0);
|
||||
lv_obj_align(status_title, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
|
||||
status_label = lv_label_create(right_card);
|
||||
lv_label_set_text(status_label, "No API response yet.");
|
||||
lv_obj_set_style_text_color(status_label, lv_color_hex(0xDDE3EA), 0);
|
||||
lv_obj_set_width(status_label, 455);
|
||||
lv_obj_align(status_label, LV_ALIGN_TOP_LEFT, 0, 34);
|
||||
|
||||
lv_obj_t *footer = lv_label_create(screen);
|
||||
lv_label_set_text(footer, "Next: WiFi client -> GET /api/v1/status from Cargo ESP");
|
||||
lv_label_set_text(footer, "Current milestone: Dashboard WiFi client -> Cargo ESP /api/v1/status");
|
||||
lv_obj_set_style_text_color(footer, lv_color_hex(0x7D8996), 0);
|
||||
lv_obj_set_width(footer, 900);
|
||||
lv_obj_set_style_text_align(footer, LV_TEXT_ALIGN_CENTER, 0);
|
||||
lv_obj_align(footer, LV_ALIGN_BOTTOM_MID, 0, -28);
|
||||
lv_obj_align(footer, LV_ALIGN_BOTTOM_MID, 0, -18);
|
||||
}
|
||||
|
||||
void setup()
|
||||
@@ -101,6 +249,8 @@ void setup()
|
||||
Serial.println("================================");
|
||||
Serial.println("Overland Controller Dashboard");
|
||||
Serial.println("================================");
|
||||
Serial.print("Version: ");
|
||||
Serial.println(DASHBOARD_VERSION);
|
||||
Serial.println("Target: Waveshare ESP32-S3 Touch LCD 5B");
|
||||
Serial.println("Display: 1024x600");
|
||||
Serial.println("API Base: /api/v1");
|
||||
@@ -125,15 +275,19 @@ void setup()
|
||||
Serial.println("Initializing LVGL");
|
||||
lvgl_port_init(board->getLCD(), board->getTouch());
|
||||
|
||||
Serial.println("Creating Overland boot screen");
|
||||
Serial.println("Creating Overland WiFi/API screen");
|
||||
lvgl_port_lock(-1);
|
||||
create_overland_boot_screen();
|
||||
create_overland_status_screen();
|
||||
lvgl_port_unlock();
|
||||
|
||||
Serial.println("Dashboard boot screen ready");
|
||||
Serial.println("Dashboard WiFi/API screen ready");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
delay(1000);
|
||||
connect_wifi_if_needed();
|
||||
update_wifi_label();
|
||||
poll_status_api();
|
||||
|
||||
delay(500);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user