feat: add McpScreen phase 2 display tools
Main / Build (Brainfuck) (push) Has been cancelled
Main / Build (Breakout) (push) Has been cancelled
Main / Build (Calculator) (push) Has been cancelled
Main / Build (Diceware) (push) Has been cancelled
Main / Build (EpubReader) (push) Has been cancelled
Main / Build (GPIO) (push) Has been cancelled
Main / Build (GraphicsDemo) (push) Has been cancelled
Main / Build (HelloWorld) (push) Has been cancelled
Main / Build (M5UnitTest) (push) Has been cancelled
Main / Build (Magic8Ball) (push) Has been cancelled
Main / Build (MediaKeys) (push) Has been cancelled
Main / Build (MystifyDemo) (push) Has been cancelled
Main / Build (SerialConsole) (push) Has been cancelled
Main / Build (Snake) (push) Has been cancelled
Main / Build (TamaTac) (push) Has been cancelled
Main / Build (TodoList) (push) Has been cancelled
Main / Build (TwoEleven) (push) Has been cancelled
Main / Bundle (push) Has been cancelled

This commit is contained in:
Adolfo Reyna
2026-06-25 12:43:08 -04:00
parent ac9d6dc0d3
commit 0fb3c22f79
7 changed files with 928 additions and 83 deletions
+62 -16
View File
@@ -5,6 +5,7 @@
#include <string.h>
#include <esp_log.h>
#include <esp_heap_caps.h>
#include <tt_lvgl.h>
#include <tt_lvgl_toolbar.h>
#include <tt_wifi.h>
@@ -44,7 +45,7 @@ void mcp_ui_set_last_tool(McpScreenState* state, const char* tool) {
}
bool mcp_ui_clear(McpScreenState* state, int color) {
if (state == NULL || !state->visible) {
if (state == NULL || !state->visible || state->framebuffer == NULL) {
return false;
}
@@ -52,12 +53,12 @@ bool mcp_ui_clear(McpScreenState* state, int color) {
if (tt_lvgl_lock(pdMS_TO_TICKS(1500))) {
if (state->visible && state->draw_area != NULL && lv_obj_is_valid(state->draw_area)) {
lv_obj_clean(state->draw_area);
lv_obj_set_style_bg_color(
state->draw_area,
color == 1 ? lv_color_black() : lv_color_white(),
LV_PART_MAIN
);
lv_obj_set_style_bg_opa(state->draw_area, LV_OPA_COVER, LV_PART_MAIN);
uint16_t fill = color == 1 ? 0x0000 : 0xFFFF;
size_t pixel_count = (size_t)state->draw_width * state->draw_height;
for (size_t i = 0; i < pixel_count; ++i) {
state->framebuffer[i] = fill;
}
lv_obj_invalidate(state->draw_area);
state->draw_color = color;
state->override_active = true;
success = true;
@@ -127,15 +128,16 @@ static void* create_data(void) {
}
static void destroy_data(void* data) {
free(data);
McpScreenState* state = data;
if (state != NULL && state->framebuffer != NULL) {
heap_caps_free(state->framebuffer);
}
free(state);
}
static void on_create(AppHandle app, void* data) {
McpScreenState* state = data;
state->app = app;
if (!mcp_services_start(state)) {
ESP_LOGE(TAG, "One or more MCP services failed to start");
}
}
static void on_destroy(AppHandle app, void* data) {
@@ -145,6 +147,7 @@ static void on_destroy(AppHandle app, void* data) {
static void on_show(AppHandle app, void* data, lv_obj_t* parent) {
McpScreenState* state = data;
ESP_LOGI(TAG, "onShow: starting foreground UI and MCP service");
state->visible = true;
lv_obj_remove_flag(parent, LV_OBJ_FLAG_SCROLLABLE);
@@ -156,17 +159,27 @@ static void on_show(AppHandle app, void* data, lv_obj_t* parent) {
lv_obj_align(toolbar, LV_ALIGN_TOP_MID, 0, 0);
state->server_label = lv_label_create(toolbar);
lv_label_set_text(state->server_label, state->http_ready ? "MCP :80 ready" : "MCP starting");
lv_label_set_text(state->server_label, "MCP starting");
lv_obj_set_style_text_color(
state->server_label,
state->http_ready ? lv_palette_main(LV_PALETTE_GREEN) : lv_palette_main(LV_PALETTE_ORANGE),
lv_palette_main(LV_PALETTE_ORANGE),
LV_PART_MAIN
);
state->tool_label = lv_label_create(toolbar);
lv_label_set_text(state->tool_label, "Last: none");
state->draw_area = lv_obj_create(parent);
if (!mcp_services_start(state)) {
ESP_LOGE(TAG, "Failed to start foreground MCP service");
lv_label_set_text(state->server_label, "MCP start failed");
lv_obj_set_style_text_color(
state->server_label,
lv_palette_main(LV_PALETTE_RED),
LV_PART_MAIN
);
}
state->draw_area = lv_canvas_create(parent);
lv_obj_set_width(state->draw_area, LV_PCT(100));
lv_obj_set_flex_grow(state->draw_area, 1);
lv_obj_set_style_radius(state->draw_area, 0, LV_PART_MAIN);
@@ -182,9 +195,39 @@ static void on_show(AppHandle app, void* data, lv_obj_t* parent) {
state->draw_width = lv_obj_get_content_width(state->draw_area);
state->draw_height = lv_obj_get_content_height(state->draw_area);
size_t required_size = (size_t)state->draw_width * state->draw_height * sizeof(uint16_t);
if (state->framebuffer == NULL || state->framebuffer_size != required_size) {
if (state->framebuffer != NULL) {
heap_caps_free(state->framebuffer);
state->framebuffer = NULL;
}
state->framebuffer = heap_caps_malloc(required_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
if (state->framebuffer == NULL) {
state->framebuffer = heap_caps_malloc(required_size, MALLOC_CAP_8BIT);
}
state->framebuffer_size = state->framebuffer == NULL ? 0 : required_size;
}
if (state->framebuffer == NULL) {
ESP_LOGE(TAG, "Failed to allocate %u-byte framebuffer", (unsigned)required_size);
lv_obj_t* error = lv_label_create(state->draw_area);
lv_label_set_text(error, "Framebuffer allocation failed");
lv_obj_center(error);
return;
}
lv_canvas_set_buffer(
state->draw_area,
state->framebuffer,
state->draw_width,
state->draw_height,
LV_COLOR_FORMAT_RGB565
);
if (!state->override_active) {
lv_obj_set_style_bg_color(state->draw_area, lv_color_hex(0x101820), LV_PART_MAIN);
lv_obj_set_style_bg_opa(state->draw_area, LV_OPA_COVER, LV_PART_MAIN);
for (size_t i = 0; i < (size_t)state->draw_width * state->draw_height; ++i) {
state->framebuffer[i] = 0x10C3;
}
state->draw_color = 1;
lv_obj_t* title = lv_label_create(state->draw_area);
@@ -215,12 +258,15 @@ static void on_show(AppHandle app, void* data, lv_obj_t* parent) {
lv_obj_set_style_text_color(wifi, lv_color_white(), LV_PART_MAIN);
lv_obj_align(wifi, LV_ALIGN_CENTER, 0, 48);
}
}
static void on_hide(AppHandle app, void* data) {
(void)app;
McpScreenState* state = data;
ESP_LOGI(TAG, "onHide: stopping foreground MCP service");
state->visible = false;
mcp_services_hide(state);
state->draw_area = NULL;
state->server_label = NULL;
state->tool_label = NULL;