dashboard: use status field filtering
This commit is contained in:
@@ -65,3 +65,13 @@ Current dashboard firmware files:
|
|||||||
- `esp_panel_board_custom_conf.h` - Waveshare board/display configuration
|
- `esp_panel_board_custom_conf.h` - Waveshare board/display configuration
|
||||||
|
|
||||||
This refactor keeps behavior unchanged while preparing for later `api` and `ui` file splits.
|
This refactor keeps behavior unchanged while preparing for later `api` and `ui` file splits.
|
||||||
|
|
||||||
|
|
||||||
|
## Status Field Filtering
|
||||||
|
|
||||||
|
The dashboard uses field-filtered `/api/v1/status` calls:
|
||||||
|
|
||||||
|
- Fast poll: `/api/v1/status?fields=battery,temps,relays`
|
||||||
|
- Slow poll: `/api/v1/status?fields=network,system,config`
|
||||||
|
|
||||||
|
This keeps the endpoint model simple while reducing payload size, JSON parsing, and UI churn.
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
static const char *DASHBOARD_VERSION = "0.0.8-refactor-config-model";
|
static const char *DASHBOARD_VERSION = "0.0.9-status-fields";
|
||||||
|
|
||||||
// Update these if your Cargo ESP AP credentials are different.
|
// Update these if your Cargo ESP AP credentials are different.
|
||||||
static const char *CARGO_WIFI_SSID = "OverlandController";
|
static const char *CARGO_WIFI_SSID = "OverlandController";
|
||||||
static const char *CARGO_WIFI_PASSWORD = "overland1234";
|
static const char *CARGO_WIFI_PASSWORD = "overland1234";
|
||||||
|
|
||||||
static const char *CARGO_API_STATUS_URL = "http://192.168.4.1/api/v1/status";
|
static const char *CARGO_API_STATUS_URL = "http://192.168.4.1/api/v1/status";
|
||||||
|
static const char *CARGO_API_FAST_STATUS_URL = "http://192.168.4.1/api/v1/status?fields=battery,temps,relays";
|
||||||
|
static const char *CARGO_API_SLOW_STATUS_URL = "http://192.168.4.1/api/v1/status?fields=network,system,config";
|
||||||
static const char *CARGO_API_RELAY_SET_URL = "http://192.168.4.1/api/v1/relay/set";
|
static const char *CARGO_API_RELAY_SET_URL = "http://192.168.4.1/api/v1/relay/set";
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ static uint32_t touch_count = 0;
|
|||||||
static unsigned long last_wifi_attempt_ms = 0;
|
static unsigned long last_wifi_attempt_ms = 0;
|
||||||
static unsigned long last_wifi_label_update_ms = 0;
|
static unsigned long last_wifi_label_update_ms = 0;
|
||||||
static unsigned long last_status_poll_ms = 0;
|
static unsigned long last_status_poll_ms = 0;
|
||||||
|
static unsigned long last_metadata_poll_ms = 0;
|
||||||
|
|
||||||
static String last_battery_text;
|
static String last_battery_text;
|
||||||
static String last_temps_text;
|
static String last_temps_text;
|
||||||
@@ -264,28 +265,37 @@ static void parse_status_json(const String &body)
|
|||||||
status_model.api_ok = true;
|
status_model.api_ok = true;
|
||||||
status_model.http_code = 200;
|
status_model.http_code = 200;
|
||||||
|
|
||||||
|
if (doc["battery"].is<JsonObject>()) {
|
||||||
JsonObject battery = doc["battery"];
|
JsonObject battery = doc["battery"];
|
||||||
status_model.bms_connected = battery["connected"] | false;
|
status_model.bms_connected = battery["connected"] | status_model.bms_connected;
|
||||||
status_model.soc = battery["soc"] | -1;
|
status_model.soc = battery["soc"] | status_model.soc;
|
||||||
status_model.voltage = battery["voltage"] | 0.0;
|
status_model.voltage = battery["voltage"] | status_model.voltage;
|
||||||
status_model.current = battery["current"] | 0.0;
|
status_model.current = battery["current"] | status_model.current;
|
||||||
status_model.battery_temp_f = battery["temperature_f"] | 0.0;
|
status_model.battery_temp_f = battery["temperature_f"] | status_model.battery_temp_f;
|
||||||
status_model.remaining_ah = battery["remaining_ah"] | 0.0;
|
status_model.remaining_ah = battery["remaining_ah"] | status_model.remaining_ah;
|
||||||
status_model.capacity_ah = battery["capacity_ah"] | 0.0;
|
status_model.capacity_ah = battery["capacity_ah"] | status_model.capacity_ah;
|
||||||
status_model.cell_delta_mv = battery["cell_delta_mv"] | -1;
|
status_model.cell_delta_mv = battery["cell_delta_mv"] | status_model.cell_delta_mv;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doc["config"].is<JsonObject>()) {
|
||||||
JsonObject config = doc["config"];
|
JsonObject config = doc["config"];
|
||||||
status_model.hardware_profile = String((const char *)(config["hardware_profile"] | "unknown"));
|
status_model.hardware_profile = String((const char *)(config["hardware_profile"] | status_model.hardware_profile.c_str()));
|
||||||
status_model.output_count = config["output_count"] | 0;
|
status_model.output_count = config["output_count"] | status_model.output_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doc["system"].is<JsonObject>()) {
|
||||||
JsonObject system = doc["system"];
|
JsonObject system = doc["system"];
|
||||||
status_model.firmware_version = String((const char *)(system["firmware_version"] | "unknown"));
|
status_model.firmware_version = String((const char *)(system["firmware_version"] | status_model.firmware_version.c_str()));
|
||||||
status_model.uptime_seconds = system["uptime_seconds"] | 0;
|
status_model.uptime_seconds = system["uptime_seconds"] | status_model.uptime_seconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doc["network"].is<JsonObject>()) {
|
||||||
JsonObject network = doc["network"];
|
JsonObject network = doc["network"];
|
||||||
status_model.cargo_ap_ssid = String((const char *)(network["ap_ssid"] | "unknown"));
|
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"] | "n/a"));
|
status_model.cargo_sta_ip = String((const char *)(network["sta_ip"] | status_model.cargo_sta_ip.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doc["temps"].is<JsonArray>()) {
|
||||||
String temps = "";
|
String temps = "";
|
||||||
JsonArray temp_array = doc["temps"];
|
JsonArray temp_array = doc["temps"];
|
||||||
int shown_temps = 0;
|
int shown_temps = 0;
|
||||||
@@ -327,6 +337,10 @@ static void parse_status_json(const String &body)
|
|||||||
temps = "No temp sensors reported";
|
temps = "No temp sensors reported";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_model.temps_text = temps;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doc["relays"].is<JsonArray>()) {
|
||||||
String outputs = "";
|
String outputs = "";
|
||||||
JsonArray relay_array = doc["relays"];
|
JsonArray relay_array = doc["relays"];
|
||||||
|
|
||||||
@@ -367,10 +381,9 @@ static void parse_status_json(const String &body)
|
|||||||
outputs = "No outputs reported";
|
outputs = "No outputs reported";
|
||||||
}
|
}
|
||||||
|
|
||||||
status_model.temps_text = temps;
|
|
||||||
status_model.outputs_text = outputs;
|
status_model.outputs_text = outputs;
|
||||||
|
|
||||||
update_relay_buttons();
|
update_relay_buttons();
|
||||||
|
}
|
||||||
|
|
||||||
Serial.println("Parsed status summary:");
|
Serial.println("Parsed status summary:");
|
||||||
Serial.print(" SOC: ");
|
Serial.print(" SOC: ");
|
||||||
@@ -448,57 +461,45 @@ static void update_wifi_label()
|
|||||||
set_label_text_if_changed(wifi_label, last_wifi_text, text);
|
set_label_text_if_changed(wifi_label, last_wifi_text, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void poll_status_api()
|
static bool fetch_status_fields(const char *url, const char *label)
|
||||||
{
|
{
|
||||||
if (WiFi.status() != WL_CONNECTED) {
|
if (WiFi.status() != WL_CONNECTED) {
|
||||||
set_label_text_if_changed(system_label, last_system_text, "API: waiting for WiFi");
|
set_label_text_if_changed(system_label, last_system_text, "API: waiting for WiFi");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (millis() - last_status_poll_ms < 5000) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
last_status_poll_ms = millis();
|
|
||||||
|
|
||||||
String requesting;
|
|
||||||
requesting += "API: requesting\n";
|
|
||||||
requesting += "/api/v1/status\n";
|
|
||||||
requesting += "Dashboard IP:\n";
|
|
||||||
requesting += WiFi.localIP().toString();
|
|
||||||
set_label_text_if_changed(system_label, last_system_text, requesting);
|
|
||||||
|
|
||||||
Serial.print("GET ");
|
Serial.print("GET ");
|
||||||
Serial.println(CARGO_API_STATUS_URL);
|
Serial.println(url);
|
||||||
|
|
||||||
HTTPClient http;
|
HTTPClient http;
|
||||||
http.setTimeout(5000);
|
http.setTimeout(5000);
|
||||||
http.begin(CARGO_API_STATUS_URL);
|
http.begin(url);
|
||||||
int code = http.GET();
|
int code = http.GET();
|
||||||
|
|
||||||
status_model.http_code = code;
|
status_model.http_code = code;
|
||||||
|
|
||||||
|
Serial.print(label);
|
||||||
Serial.print(" HTTP code: ");
|
Serial.print(" HTTP code: ");
|
||||||
Serial.println(code);
|
Serial.println(code);
|
||||||
|
|
||||||
if (code == 200) {
|
if (code == 200) {
|
||||||
String body = http.getString();
|
String body = http.getString();
|
||||||
|
|
||||||
Serial.print("Body length: ");
|
Serial.print(label);
|
||||||
|
Serial.print(" body length: ");
|
||||||
Serial.println(body.length());
|
Serial.println(body.length());
|
||||||
Serial.println(body);
|
|
||||||
|
|
||||||
String received;
|
|
||||||
received += "API: received\nHTTP: 200\nBytes: ";
|
|
||||||
received += String(body.length());
|
|
||||||
set_label_text_if_changed(system_label, last_system_text, received);
|
|
||||||
|
|
||||||
parse_status_json(body);
|
parse_status_json(body);
|
||||||
} else {
|
http.end();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
status_model.api_ok = false;
|
status_model.api_ok = false;
|
||||||
|
|
||||||
String system;
|
String system;
|
||||||
system += "API: error\nHTTP: ";
|
system += "API: error\n";
|
||||||
|
system += label;
|
||||||
|
system += "\nHTTP: ";
|
||||||
system += String(code);
|
system += String(code);
|
||||||
if (code <= 0) {
|
if (code <= 0) {
|
||||||
system += "\n";
|
system += "\n";
|
||||||
@@ -507,9 +508,27 @@ static void poll_status_api()
|
|||||||
|
|
||||||
Serial.println(system);
|
Serial.println(system);
|
||||||
set_label_text_if_changed(system_label, last_system_text, system);
|
set_label_text_if_changed(system_label, last_system_text, system);
|
||||||
}
|
|
||||||
|
|
||||||
http.end();
|
http.end();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void poll_status_api()
|
||||||
|
{
|
||||||
|
if (WiFi.status() != WL_CONNECTED) {
|
||||||
|
set_label_text_if_changed(system_label, last_system_text, "API: waiting for WiFi");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (millis() - last_status_poll_ms >= 2000) {
|
||||||
|
last_status_poll_ms = millis();
|
||||||
|
fetch_status_fields(CARGO_API_FAST_STATUS_URL, "fast status");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (millis() - last_metadata_poll_ms >= 30000) {
|
||||||
|
last_metadata_poll_ms = millis();
|
||||||
|
fetch_status_fields(CARGO_API_SLOW_STATUS_URL, "slow status");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static lv_obj_t *create_card(lv_obj_t *parent, const char *title, int width, int height, lv_align_t align, int x, int y)
|
static lv_obj_t *create_card(lv_obj_t *parent, const char *title, int width, int height, lv_align_t align, int x, int y)
|
||||||
@@ -624,7 +643,7 @@ static void create_overland_status_screen()
|
|||||||
lv_obj_align(touch_count_label, LV_ALIGN_TOP_LEFT, 0, 142);
|
lv_obj_align(touch_count_label, LV_ALIGN_TOP_LEFT, 0, 142);
|
||||||
|
|
||||||
lv_obj_t *footer = lv_label_create(screen);
|
lv_obj_t *footer = lv_label_create(screen);
|
||||||
lv_label_set_text(footer, "Polling Cargo ESP /api/v1/status every 5 seconds");
|
lv_label_set_text(footer, "Fast: battery/temps/relays every 2s | Slow: system/config/network every 30s");
|
||||||
lv_obj_set_style_text_color(footer, lv_color_hex(0x7D8996), 0);
|
lv_obj_set_style_text_color(footer, lv_color_hex(0x7D8996), 0);
|
||||||
lv_obj_set_width(footer, 900);
|
lv_obj_set_width(footer, 900);
|
||||||
lv_obj_set_style_text_align(footer, LV_TEXT_ALIGN_CENTER, 0);
|
lv_obj_set_style_text_align(footer, LV_TEXT_ALIGN_CENTER, 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user