diff --git a/esphome/bambu-display/README.md b/esphome/bambu-display/README.md index 0a6c1bf..e87e67c 100644 --- a/esphome/bambu-display/README.md +++ b/esphome/bambu-display/README.md @@ -17,12 +17,10 @@ Home Assistant must be running and its printer integrations must have current pr The configured swipe order is: -1. Fleet — one steam gauge per printer, matching the progress arcs on the - printer pages. The needle is print progress, and the arc color follows - status: green while printing, amber while paused, red for an error. The - center is the percent complete and the caption is the status. A line under - the gauges counts printers that need attention, are printing, paused, idle, - offline or still syncing. Tap a gauge to open that printer. +1. Print Status Overview — one steam gauge per printer. Each ring uses the + color of that printer's active filament. The center shows the percent + complete in white, with the printer name and estimated finish time underneath. + The local time is in the top-right corner. Tap a gauge to open that printer. 2. PrintsCharming — P1S, Office, both four-slot AMS units. 3. Polly-Pocket — A1 mini, Office, external spool. 4. Ds-Turd-Flinger — A1, Upstairs, four-slot AMS. diff --git a/esphome/bambu-display/dashboard.h b/esphome/bambu-display/dashboard.h index e8eb895..8a64bbc 100644 --- a/esphome/bambu-display/dashboard.h +++ b/esphome/bambu-display/dashboard.h @@ -226,6 +226,15 @@ struct Snapshot { return progress_text + " " + finish_time + " " + time_line; return progress_text + " " + time_line; } + // Active tray is the spool the printer loaded most recently. Without one, keep green. + uint32_t active_filament_color() const { + for (const auto &tray : trays) + if (is_on(tray.active)) { + const uint32_t color = filament_color(tray.color); + if (color != TRACK) return color; + } + return GREEN; + } uint32_t status_color() const { if (!live()) return MUTED; const auto state = lower(status); @@ -290,7 +299,7 @@ struct Widgets { lv_obj_t *elapsed = nullptr; }; struct OverviewWidgets { - lv_obj_t *arc, *value, *detail; + lv_obj_t *arc, *value, *finish; }; inline void set_text(lv_obj_t *label, const std::string &text) { @@ -361,15 +370,15 @@ inline void render(const Snapshot &data, const Widgets &widgets) { inline void render_overview(const Snapshot &data, const OverviewWidgets &widgets) { const bool live = data.live(); - const uint32_t color = data.status_color(); + const uint32_t filament = data.active_filament_color(); const float shown = live && std::isfinite(data.progress) ? std::clamp(data.progress, 0.0f, 100.0f) : NAN; - lv_arc_set_value(widgets.arc, live ? gauge_value(data.progress, 100) : 0); - lv_obj_set_style_arc_color(widgets.arc, lv_color_hex(color), LV_PART_INDICATOR); + lv_obj_set_style_arc_color(widgets.arc, lv_color_hex(filament), LV_PART_MAIN); + lv_obj_set_style_arc_color(widgets.arc, lv_color_hex(filament), LV_PART_INDICATOR); + lv_arc_set_value(widgets.arc, 100); set_text(widgets.value, number(shown)); - lv_obj_set_style_text_color(widgets.value, lv_color_hex(live ? color : MUTED), 0); - set_text(widgets.detail, data.status_text()); - lv_obj_set_style_text_color(widgets.detail, lv_color_hex(color), 0); + lv_obj_set_style_text_color(widgets.value, lv_color_hex(0xFFFFFF), 0); + set_text(widgets.finish, live && !data.finish_time.empty() ? data.finish_time : "--"); } inline void render_fleet_summary(lv_obj_t *label, const FleetCounts &counts) { diff --git a/esphome/bambu-display/generate.py b/esphome/bambu-display/generate.py index 717cbd8..8205214 100644 --- a/esphome/bambu-display/generate.py +++ b/esphome/bambu-display/generate.py @@ -246,13 +246,13 @@ def snapshot_lines(printer, expressions, trays): def overview_slots(count): - """Place one steam gauge per printer. Full-size arcs match the printer pages.""" + """Place one steam gauge per printer under the page title.""" columns = 4 if count > 4 else max(count, 1) rows = (count + columns - 1) // columns - top, bottom = 8, 400 - arc = min(154, (800 // columns) - 20, (bottom - top) // rows - 36) - col_w = 800 // columns + top, bottom = 46, 432 row_h = (bottom - top) // rows + arc = min(154, (800 // columns) - 24, row_h - 48) + col_w = 800 // columns slots = [] for index in range(count): row, col = divmod(index, columns) @@ -267,34 +267,36 @@ def overview_slots(count): def overview_gauge(printer, x, y, arc): pid = printer['id'] scale = arc / 154 - value_font = 32 if arc >= 140 else 18 - detail_font = 14 if arc >= 140 else 12 - name_font = 14 if arc >= 140 else 12 + value_font = 32 if arc >= 130 else 18 open_page = [{'lvgl.page.show': f'{pid}_page'}] - inner = max(8, int(round(13 * scale))) + inner = max(10, int(round(13 * scale))) + inner_x = x + int(round(8 * scale)) + number_y = y + int(round(arc * 0.30)) return [ - {'arc': {'id': f'{pid}_overview_arc', 'x': x + int(round(8 * scale)), 'y': y, - 'width': arc, 'height': arc, 'min_value': 0, 'max_value': 100, 'value': 0, - 'start_angle': 135, 'end_angle': 45, 'arc_width': inner, 'arc_color': TRACK, + {'arc': {'id': f'{pid}_overview_arc', 'x': inner_x, 'y': y, + 'width': arc, 'height': arc, 'min_value': 0, 'max_value': 100, 'value': 100, + 'start_angle': 135, 'end_angle': 45, 'arc_width': inner, 'arc_color': GREEN, 'indicator': {'arc_color': GREEN, 'arc_width': inner}, 'adjustable': False, 'gesture_bubble': True, 'clickable': True, 'on_click': open_page}}, - label('--', x + int(round(14 * scale)), y + int(round(47 * scale)), int(round(142 * scale)), - value_font, id=f'{pid}_overview_value', text_align='CENTER', + label('--', inner_x, number_y, arc, value_font, id=f'{pid}_overview_value', + text_align='CENTER', text_color=0xFFFFFF, clickable=True, on_click=open_page), + label('%', inner_x, number_y + (34 if value_font >= 28 else 20), arc, 16, + id=f'{pid}_overview_percent', text_align='CENTER', text_color=0xFFFFFF, clickable=True, on_click=open_page), - label('SYNCING', x + int(round(14 * scale)), y + int(round(86 * scale)), - int(round(142 * scale)), detail_font, id=f'{pid}_overview_detail', - text_align='CENTER', text_color=MUTED, clickable=True, on_click=open_page), - label(printer['name'], x, y + int(round(137 * scale)), arc + 16, name_font, - text_align='CENTER', text_color=GREEN, clickable=True, on_click=open_page), + label(printer['name'], x, y + arc + 2, arc + 16, 14, text_align='CENTER', + text_color=TEXT_COLOR, clickable=True, on_click=open_page), + label('--', x, y + arc + 22, arc + 16, 14, id=f'{pid}_overview_finish', + text_align='CENTER', text_color=TEXT_COLOR, clickable=True, on_click=open_page), ] def overview_page(printers): - widgets = [] + widgets = [ + label('Print Status Overview', 16, 10, 520, 22, text_color=GREEN), + label('--:--', 548, 12, 236, 18, id='fleet_clock', text_align='RIGHT', text_color=TEXT_COLOR), + ] for printer, (x, y, arc) in zip(printers, overview_slots(len(printers))): widgets += overview_gauge(printer, x, y, arc) - widgets.append(label('SYNCING', 90, 404, 620, 14, id='fleet_summary', - text_align='CENTER', text_color=MUTED)) for direction, x, text in (('previous', 16, '<'), ('next', 720, '>')): widgets.append({'button': {'x': x, 'y': 446, 'width': 64, 'height': 30, 'bg_color': TRACK, 'radius': 8, 'border_width': 0, @@ -316,16 +318,25 @@ def overview_page(printers): def fleet_refresh_lines(snapshots): - lines = ['bambu_display::FleetCounts counts;'] + lines = [] for pid, snapshot in snapshots: lines.append('{') lines.extend(snapshot) - lines.append('bambu_display::tally(counts, data);') lines.append('bambu_display::render_overview(data, {' + ', '.join([ f'id({pid}_overview_arc)', f'id({pid}_overview_value)', - f'id({pid}_overview_detail)']) + '});') + f'id({pid}_overview_finish)']) + '});') lines.append('}') - lines.append('bambu_display::render_fleet_summary(id(fleet_summary), counts);') + lines += [ + '{', + 'const auto clock = id(ha_time).now();', + 'std::string clock_text = "--:--";', + 'if (clock.is_valid()) {', + ' clock_text = clock.strftime("%I:%M %p");', + ' if (!clock_text.empty() && clock_text[0] == \'0\') clock_text.erase(0, 1);', + '}', + 'bambu_display::set_text(id(fleet_clock), clock_text);', + '}', + ] return lines diff --git a/esphome/bambu-display/generated.yaml b/esphome/bambu-display/generated.yaml index 2046f40..34368b8 100644 --- a/esphome/bambu-display/generated.yaml +++ b/esphome/bambu-display/generated.yaml @@ -1490,7 +1490,6 @@ script: - id: fleet_refresh then: - lambda: !lambda |- - bambu_display::FleetCounts counts; { bambu_display::Snapshot data; data.connected = id(ha_api).is_connected_with_state_subscription(); @@ -1532,8 +1531,7 @@ script: data.trays.push_back({"B2", id(prints_charming_tray_5_type).state, id(prints_charming_tray_5_color).state, id(prints_charming_tray_5_active).state}); data.trays.push_back({"B3", id(prints_charming_tray_6_type).state, id(prints_charming_tray_6_color).state, id(prints_charming_tray_6_active).state}); data.trays.push_back({"B4", id(prints_charming_tray_7_type).state, id(prints_charming_tray_7_color).state, id(prints_charming_tray_7_active).state}); - bambu_display::tally(counts, data); - bambu_display::render_overview(data, {id(prints_charming_overview_arc), id(prints_charming_overview_value), id(prints_charming_overview_detail)}); + bambu_display::render_overview(data, {id(prints_charming_overview_arc), id(prints_charming_overview_value), id(prints_charming_overview_finish)}); } { bambu_display::Snapshot data; @@ -1567,8 +1565,7 @@ script: if (clock.is_valid() && seconds_left >= 0) data.finish_time = esphome::ESPTime::from_epoch_local(clock.timestamp + seconds_left).strftime("%H:%M"); data.trays.push_back({"EXT", id(polly_pocket_tray_0_type).state, id(polly_pocket_tray_0_color).state, id(polly_pocket_tray_0_active).state}); - bambu_display::tally(counts, data); - bambu_display::render_overview(data, {id(polly_pocket_overview_arc), id(polly_pocket_overview_value), id(polly_pocket_overview_detail)}); + bambu_display::render_overview(data, {id(polly_pocket_overview_arc), id(polly_pocket_overview_value), id(polly_pocket_overview_finish)}); } { bambu_display::Snapshot data; @@ -1605,8 +1602,7 @@ script: data.trays.push_back({"A2", id(ds_turd_flinger_tray_1_type).state, id(ds_turd_flinger_tray_1_color).state, id(ds_turd_flinger_tray_1_active).state}); data.trays.push_back({"A3", id(ds_turd_flinger_tray_2_type).state, id(ds_turd_flinger_tray_2_color).state, id(ds_turd_flinger_tray_2_active).state}); data.trays.push_back({"A4", id(ds_turd_flinger_tray_3_type).state, id(ds_turd_flinger_tray_3_color).state, id(ds_turd_flinger_tray_3_active).state}); - bambu_display::tally(counts, data); - bambu_display::render_overview(data, {id(ds_turd_flinger_overview_arc), id(ds_turd_flinger_overview_value), id(ds_turd_flinger_overview_detail)}); + bambu_display::render_overview(data, {id(ds_turd_flinger_overview_arc), id(ds_turd_flinger_overview_value), id(ds_turd_flinger_overview_finish)}); } { bambu_display::Snapshot data; @@ -1643,8 +1639,7 @@ script: data.trays.push_back({"A2", id(jordyns_layer_slayer_tray_1_type).state, id(jordyns_layer_slayer_tray_1_color).state, id(jordyns_layer_slayer_tray_1_active).state}); data.trays.push_back({"A3", id(jordyns_layer_slayer_tray_2_type).state, id(jordyns_layer_slayer_tray_2_color).state, id(jordyns_layer_slayer_tray_2_active).state}); data.trays.push_back({"A4", id(jordyns_layer_slayer_tray_3_type).state, id(jordyns_layer_slayer_tray_3_color).state, id(jordyns_layer_slayer_tray_3_active).state}); - bambu_display::tally(counts, data); - bambu_display::render_overview(data, {id(jordyns_layer_slayer_overview_arc), id(jordyns_layer_slayer_overview_value), id(jordyns_layer_slayer_overview_detail)}); + bambu_display::render_overview(data, {id(jordyns_layer_slayer_overview_arc), id(jordyns_layer_slayer_overview_value), id(jordyns_layer_slayer_overview_finish)}); } { bambu_display::Snapshot data; @@ -1691,8 +1686,7 @@ script: data.trays.push_back({"B2", id(constipation_orion_tray_5_type).state, id(constipation_orion_tray_5_color).state, id(constipation_orion_tray_5_active).state}); data.trays.push_back({"B3", id(constipation_orion_tray_6_type).state, id(constipation_orion_tray_6_color).state, id(constipation_orion_tray_6_active).state}); data.trays.push_back({"B4", id(constipation_orion_tray_7_type).state, id(constipation_orion_tray_7_color).state, id(constipation_orion_tray_7_active).state}); - bambu_display::tally(counts, data); - bambu_display::render_overview(data, {id(constipation_orion_overview_arc), id(constipation_orion_overview_value), id(constipation_orion_overview_detail)}); + bambu_display::render_overview(data, {id(constipation_orion_overview_arc), id(constipation_orion_overview_value), id(constipation_orion_overview_finish)}); } { bambu_display::Snapshot data; @@ -1722,8 +1716,7 @@ script: const auto clock = id(ha_time).now(); if (clock.is_valid() && seconds_left >= 0) data.finish_time = esphome::ESPTime::from_epoch_local(clock.timestamp + seconds_left).strftime("%H:%M"); - bambu_display::tally(counts, data); - bambu_display::render_overview(data, {id(centauri_carbon_overview_arc), id(centauri_carbon_overview_value), id(centauri_carbon_overview_detail)}); + bambu_display::render_overview(data, {id(centauri_carbon_overview_arc), id(centauri_carbon_overview_value), id(centauri_carbon_overview_finish)}); } { bambu_display::Snapshot data; @@ -1749,10 +1742,17 @@ script: const auto clock = id(ha_time).now(); if (clock.is_valid() && seconds_left >= 0) data.finish_time = esphome::ESPTime::from_epoch_local(clock.timestamp + seconds_left).strftime("%H:%M"); - bambu_display::tally(counts, data); - bambu_display::render_overview(data, {id(saturn_overview_arc), id(saturn_overview_value), id(saturn_overview_detail)}); + bambu_display::render_overview(data, {id(saturn_overview_arc), id(saturn_overview_value), id(saturn_overview_finish)}); + } + { + const auto clock = id(ha_time).now(); + std::string clock_text = "--:--"; + if (clock.is_valid()) { + clock_text = clock.strftime("%I:%M %p"); + if (!clock_text.empty() && clock_text[0] == '0') clock_text.erase(0, 1); + } + bambu_display::set_text(id(fleet_clock), clock_text); } - bambu_display::render_fleet_summary(id(fleet_summary), counts); interval: - interval: 1s then: @@ -1819,22 +1819,44 @@ lvgl: on_load: - script.execute: fleet_refresh widgets: + - label: + text: Print Status Overview + x: 16 + y: 10 + width: 520 + height: 30 + text_color: 65280 + text_font: montserrat_22 + long_mode: DOT + gesture_bubble: true + - label: + text: --:-- + x: 548 + y: 12 + width: 236 + height: 26 + text_color: 15658734 + text_font: montserrat_18 + long_mode: DOT + gesture_bubble: true + id: fleet_clock + text_align: RIGHT - arc: id: prints_charming_overview_arc - x: 23 - y: 8 - width: 154 - height: 154 + x: 27 + y: 46 + width: 145 + height: 145 min_value: 0 max_value: 100 - value: 0 + value: 100 start_angle: 135 end_angle: 45 - arc_width: 13 - arc_color: 1647403 + arc_width: 12 + arc_color: 65280 indicator: arc_color: 65280 - arc_width: 13 + arc_width: 12 adjustable: false gesture_bubble: true clickable: true @@ -1842,11 +1864,11 @@ lvgl: - lvgl.page.show: prints_charming_page - label: text: -- - x: 29 - y: 55 - width: 142 + x: 27 + y: 90 + width: 145 height: 40 - text_color: 15658734 + text_color: 16777215 text_font: montserrat_32 long_mode: DOT gesture_bubble: true @@ -1856,27 +1878,27 @@ lvgl: on_click: - lvgl.page.show: prints_charming_page - label: - text: SYNCING - x: 29 - y: 94 - width: 142 - height: 22 - text_color: 11449271 - text_font: montserrat_14 + text: '%' + x: 27 + y: 124 + width: 145 + height: 24 + text_color: 16777215 + text_font: montserrat_16 long_mode: DOT gesture_bubble: true - id: prints_charming_overview_detail + id: prints_charming_overview_percent text_align: CENTER clickable: true on_click: - lvgl.page.show: prints_charming_page - label: text: PrintsCharming - x: 15 - y: 145 - width: 170 + x: 19 + y: 193 + width: 161 height: 22 - text_color: 65280 + text_color: 15658734 text_font: montserrat_14 long_mode: DOT gesture_bubble: true @@ -1884,22 +1906,37 @@ lvgl: clickable: true on_click: - lvgl.page.show: prints_charming_page + - label: + text: -- + x: 19 + y: 213 + width: 161 + height: 22 + text_color: 15658734 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + id: prints_charming_overview_finish + text_align: CENTER + clickable: true + on_click: + - lvgl.page.show: prints_charming_page - arc: id: polly_pocket_overview_arc - x: 223 - y: 8 - width: 154 - height: 154 + x: 227 + y: 46 + width: 145 + height: 145 min_value: 0 max_value: 100 - value: 0 + value: 100 start_angle: 135 end_angle: 45 - arc_width: 13 - arc_color: 1647403 + arc_width: 12 + arc_color: 65280 indicator: arc_color: 65280 - arc_width: 13 + arc_width: 12 adjustable: false gesture_bubble: true clickable: true @@ -1907,11 +1944,11 @@ lvgl: - lvgl.page.show: polly_pocket_page - label: text: -- - x: 229 - y: 55 - width: 142 + x: 227 + y: 90 + width: 145 height: 40 - text_color: 15658734 + text_color: 16777215 text_font: montserrat_32 long_mode: DOT gesture_bubble: true @@ -1921,27 +1958,27 @@ lvgl: on_click: - lvgl.page.show: polly_pocket_page - label: - text: SYNCING - x: 229 - y: 94 - width: 142 - height: 22 - text_color: 11449271 - text_font: montserrat_14 + text: '%' + x: 227 + y: 124 + width: 145 + height: 24 + text_color: 16777215 + text_font: montserrat_16 long_mode: DOT gesture_bubble: true - id: polly_pocket_overview_detail + id: polly_pocket_overview_percent text_align: CENTER clickable: true on_click: - lvgl.page.show: polly_pocket_page - label: text: Polly-Pocket - x: 215 - y: 145 - width: 170 + x: 219 + y: 193 + width: 161 height: 22 - text_color: 65280 + text_color: 15658734 text_font: montserrat_14 long_mode: DOT gesture_bubble: true @@ -1949,22 +1986,37 @@ lvgl: clickable: true on_click: - lvgl.page.show: polly_pocket_page + - label: + text: -- + x: 219 + y: 213 + width: 161 + height: 22 + text_color: 15658734 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + id: polly_pocket_overview_finish + text_align: CENTER + clickable: true + on_click: + - lvgl.page.show: polly_pocket_page - arc: id: ds_turd_flinger_overview_arc - x: 423 - y: 8 - width: 154 - height: 154 + x: 427 + y: 46 + width: 145 + height: 145 min_value: 0 max_value: 100 - value: 0 + value: 100 start_angle: 135 end_angle: 45 - arc_width: 13 - arc_color: 1647403 + arc_width: 12 + arc_color: 65280 indicator: arc_color: 65280 - arc_width: 13 + arc_width: 12 adjustable: false gesture_bubble: true clickable: true @@ -1972,11 +2024,11 @@ lvgl: - lvgl.page.show: ds_turd_flinger_page - label: text: -- - x: 429 - y: 55 - width: 142 + x: 427 + y: 90 + width: 145 height: 40 - text_color: 15658734 + text_color: 16777215 text_font: montserrat_32 long_mode: DOT gesture_bubble: true @@ -1986,27 +2038,27 @@ lvgl: on_click: - lvgl.page.show: ds_turd_flinger_page - label: - text: SYNCING - x: 429 - y: 94 - width: 142 - height: 22 - text_color: 11449271 - text_font: montserrat_14 + text: '%' + x: 427 + y: 124 + width: 145 + height: 24 + text_color: 16777215 + text_font: montserrat_16 long_mode: DOT gesture_bubble: true - id: ds_turd_flinger_overview_detail + id: ds_turd_flinger_overview_percent text_align: CENTER clickable: true on_click: - lvgl.page.show: ds_turd_flinger_page - label: text: Ds-Turd-Flinger - x: 415 - y: 145 - width: 170 + x: 419 + y: 193 + width: 161 height: 22 - text_color: 65280 + text_color: 15658734 text_font: montserrat_14 long_mode: DOT gesture_bubble: true @@ -2014,22 +2066,37 @@ lvgl: clickable: true on_click: - lvgl.page.show: ds_turd_flinger_page + - label: + text: -- + x: 419 + y: 213 + width: 161 + height: 22 + text_color: 15658734 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + id: ds_turd_flinger_overview_finish + text_align: CENTER + clickable: true + on_click: + - lvgl.page.show: ds_turd_flinger_page - arc: id: jordyns_layer_slayer_overview_arc - x: 623 - y: 8 - width: 154 - height: 154 + x: 627 + y: 46 + width: 145 + height: 145 min_value: 0 max_value: 100 - value: 0 + value: 100 start_angle: 135 end_angle: 45 - arc_width: 13 - arc_color: 1647403 + arc_width: 12 + arc_color: 65280 indicator: arc_color: 65280 - arc_width: 13 + arc_width: 12 adjustable: false gesture_bubble: true clickable: true @@ -2037,11 +2104,11 @@ lvgl: - lvgl.page.show: jordyns_layer_slayer_page - label: text: -- - x: 629 - y: 55 - width: 142 + x: 627 + y: 90 + width: 145 height: 40 - text_color: 15658734 + text_color: 16777215 text_font: montserrat_32 long_mode: DOT gesture_bubble: true @@ -2051,27 +2118,27 @@ lvgl: on_click: - lvgl.page.show: jordyns_layer_slayer_page - label: - text: SYNCING - x: 629 - y: 94 - width: 142 - height: 22 - text_color: 11449271 - text_font: montserrat_14 + text: '%' + x: 627 + y: 124 + width: 145 + height: 24 + text_color: 16777215 + text_font: montserrat_16 long_mode: DOT gesture_bubble: true - id: jordyns_layer_slayer_overview_detail + id: jordyns_layer_slayer_overview_percent text_align: CENTER clickable: true on_click: - lvgl.page.show: jordyns_layer_slayer_page - label: text: Jordyns-Layer-Slayer - x: 615 - y: 145 - width: 170 + x: 619 + y: 193 + width: 161 height: 22 - text_color: 65280 + text_color: 15658734 text_font: montserrat_14 long_mode: DOT gesture_bubble: true @@ -2079,22 +2146,37 @@ lvgl: clickable: true on_click: - lvgl.page.show: jordyns_layer_slayer_page + - label: + text: -- + x: 619 + y: 213 + width: 161 + height: 22 + text_color: 15658734 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + id: jordyns_layer_slayer_overview_finish + text_align: CENTER + clickable: true + on_click: + - lvgl.page.show: jordyns_layer_slayer_page - arc: id: constipation_orion_overview_arc - x: 123 - y: 204 - width: 154 - height: 154 + x: 127 + y: 239 + width: 145 + height: 145 min_value: 0 max_value: 100 - value: 0 + value: 100 start_angle: 135 end_angle: 45 - arc_width: 13 - arc_color: 1647403 + arc_width: 12 + arc_color: 65280 indicator: arc_color: 65280 - arc_width: 13 + arc_width: 12 adjustable: false gesture_bubble: true clickable: true @@ -2102,11 +2184,11 @@ lvgl: - lvgl.page.show: constipation_orion_page - label: text: -- - x: 129 - y: 251 - width: 142 + x: 127 + y: 283 + width: 145 height: 40 - text_color: 15658734 + text_color: 16777215 text_font: montserrat_32 long_mode: DOT gesture_bubble: true @@ -2116,27 +2198,27 @@ lvgl: on_click: - lvgl.page.show: constipation_orion_page - label: - text: SYNCING - x: 129 - y: 290 - width: 142 - height: 22 - text_color: 11449271 - text_font: montserrat_14 + text: '%' + x: 127 + y: 317 + width: 145 + height: 24 + text_color: 16777215 + text_font: montserrat_16 long_mode: DOT gesture_bubble: true - id: constipation_orion_overview_detail + id: constipation_orion_overview_percent text_align: CENTER clickable: true on_click: - lvgl.page.show: constipation_orion_page - label: text: Constipation-Orion - x: 115 - y: 341 - width: 170 + x: 119 + y: 386 + width: 161 height: 22 - text_color: 65280 + text_color: 15658734 text_font: montserrat_14 long_mode: DOT gesture_bubble: true @@ -2144,22 +2226,37 @@ lvgl: clickable: true on_click: - lvgl.page.show: constipation_orion_page + - label: + text: -- + x: 119 + y: 406 + width: 161 + height: 22 + text_color: 15658734 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + id: constipation_orion_overview_finish + text_align: CENTER + clickable: true + on_click: + - lvgl.page.show: constipation_orion_page - arc: id: centauri_carbon_overview_arc - x: 323 - y: 204 - width: 154 - height: 154 + x: 327 + y: 239 + width: 145 + height: 145 min_value: 0 max_value: 100 - value: 0 + value: 100 start_angle: 135 end_angle: 45 - arc_width: 13 - arc_color: 1647403 + arc_width: 12 + arc_color: 65280 indicator: arc_color: 65280 - arc_width: 13 + arc_width: 12 adjustable: false gesture_bubble: true clickable: true @@ -2167,11 +2264,11 @@ lvgl: - lvgl.page.show: centauri_carbon_page - label: text: -- - x: 329 - y: 251 - width: 142 + x: 327 + y: 283 + width: 145 height: 40 - text_color: 15658734 + text_color: 16777215 text_font: montserrat_32 long_mode: DOT gesture_bubble: true @@ -2181,27 +2278,27 @@ lvgl: on_click: - lvgl.page.show: centauri_carbon_page - label: - text: SYNCING - x: 329 - y: 290 - width: 142 - height: 22 - text_color: 11449271 - text_font: montserrat_14 + text: '%' + x: 327 + y: 317 + width: 145 + height: 24 + text_color: 16777215 + text_font: montserrat_16 long_mode: DOT gesture_bubble: true - id: centauri_carbon_overview_detail + id: centauri_carbon_overview_percent text_align: CENTER clickable: true on_click: - lvgl.page.show: centauri_carbon_page - label: text: Centauri Carbon - x: 315 - y: 341 - width: 170 + x: 319 + y: 386 + width: 161 height: 22 - text_color: 65280 + text_color: 15658734 text_font: montserrat_14 long_mode: DOT gesture_bubble: true @@ -2209,22 +2306,37 @@ lvgl: clickable: true on_click: - lvgl.page.show: centauri_carbon_page + - label: + text: -- + x: 319 + y: 406 + width: 161 + height: 22 + text_color: 15658734 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + id: centauri_carbon_overview_finish + text_align: CENTER + clickable: true + on_click: + - lvgl.page.show: centauri_carbon_page - arc: id: saturn_overview_arc - x: 523 - y: 204 - width: 154 - height: 154 + x: 527 + y: 239 + width: 145 + height: 145 min_value: 0 max_value: 100 - value: 0 + value: 100 start_angle: 135 end_angle: 45 - arc_width: 13 - arc_color: 1647403 + arc_width: 12 + arc_color: 65280 indicator: arc_color: 65280 - arc_width: 13 + arc_width: 12 adjustable: false gesture_bubble: true clickable: true @@ -2232,11 +2344,11 @@ lvgl: - lvgl.page.show: saturn_page - label: text: -- - x: 529 - y: 251 - width: 142 + x: 527 + y: 283 + width: 145 height: 40 - text_color: 15658734 + text_color: 16777215 text_font: montserrat_32 long_mode: DOT gesture_bubble: true @@ -2246,27 +2358,27 @@ lvgl: on_click: - lvgl.page.show: saturn_page - label: - text: SYNCING - x: 529 - y: 290 - width: 142 - height: 22 - text_color: 11449271 - text_font: montserrat_14 + text: '%' + x: 527 + y: 317 + width: 145 + height: 24 + text_color: 16777215 + text_font: montserrat_16 long_mode: DOT gesture_bubble: true - id: saturn_overview_detail + id: saturn_overview_percent text_align: CENTER clickable: true on_click: - lvgl.page.show: saturn_page - label: text: Saturn - x: 515 - y: 341 - width: 170 + x: 519 + y: 386 + width: 161 height: 22 - text_color: 65280 + text_color: 15658734 text_font: montserrat_14 long_mode: DOT gesture_bubble: true @@ -2275,17 +2387,20 @@ lvgl: on_click: - lvgl.page.show: saturn_page - label: - text: SYNCING - x: 90 - y: 404 - width: 620 + text: -- + x: 519 + y: 406 + width: 161 height: 22 - text_color: 11449271 + text_color: 15658734 text_font: montserrat_14 long_mode: DOT gesture_bubble: true - id: fleet_summary + id: saturn_overview_finish text_align: CENTER + clickable: true + on_click: + - lvgl.page.show: saturn_page - button: x: 16 y: 446 diff --git a/esphome/bambu-display/preview.py b/esphome/bambu-display/preview.py index 72a417d..0e5dfe1 100644 --- a/esphome/bambu-display/preview.py +++ b/esphome/bambu-display/preview.py @@ -92,14 +92,15 @@ inline void setup() { {'script.execute': 'fleet_refresh'}, {'delay': '300ms'}, {'snapshot.take': {'id': 'panel_display', 'filename': 'fleet.bmp'}}, {'lambda': Lambda( - 'if (std::string(lv_label_get_text(id(fleet_summary))) != ' - + json.dumps(f'{len(printers)} printing') - + ') { ESP_LOGE("preview", "Fleet summary render failed"); exit(7); }')}] + 'if (std::string(lv_label_get_text(id(fleet_clock))) == "--:--") ' + '{ ESP_LOGE("preview", "Fleet clock render failed"); exit(7); }')}] for printer in printers: pid = printer['id'] steps.append({'lambda': Lambda( - f'if (std::string(lv_label_get_text(id({pid}_overview_detail))) != "PRINTING") ' - f'{{ ESP_LOGE("preview", "Fleet row render failed: {pid}"); exit(7); }}')}) + f'if (std::string(lv_label_get_text(id({pid}_overview_value))) != "67" || ' + f'std::string(lv_label_get_text(id({pid}_overview_percent))) != "%" || ' + f'std::string(lv_label_get_text(id({pid}_overview_finish))) == "--") ' + f'{{ ESP_LOGE("preview", "Fleet gauge render failed: {pid}"); exit(7); }}')}) for printer in printers: steps += [{'lvgl.page.show': printer['id'] + '_page'}, {'script.execute': printer['id'] + '_refresh'}, {'delay': '300ms'}, diff --git a/esphome/bambu-display/test_dashboard.cpp b/esphome/bambu-display/test_dashboard.cpp index 6d17d1e..de9adb0 100644 --- a/esphome/bambu-display/test_dashboard.cpp +++ b/esphome/bambu-display/test_dashboard.cpp @@ -123,6 +123,13 @@ int main() { data.connected = false; assert(data.overview_task() == "Waiting for Home Assistant"); assert(data.overview_meta() == "--"); + data.trays = {{"A1", "PLA", "#FF8800FF", "off"}, {"A2", "PETG", "00FF00", "on"}}; + assert(data.active_filament_color() == GREEN); + data.trays[1].active = "off"; + data.trays[0].active = "on"; + assert(data.active_filament_color() == 0xFF8800); + data.trays.clear(); + assert(data.active_filament_color() == GREEN); FleetCounts counts; data.connected = true; diff --git a/esphome/bambu-display/test_generate.py b/esphome/bambu-display/test_generate.py index 60dbd65..a1270d0 100644 --- a/esphome/bambu-display/test_generate.py +++ b/esphome/bambu-display/test_generate.py @@ -157,14 +157,18 @@ class FleetTests(unittest.TestCase): [printer['id'] for printer in self.printers]) for arc, printer in zip(arcs, self.printers): self.assertEqual(arc['on_click'], [{'lvgl.page.show': printer['id'] + '_page'}]) - self.assertEqual(arc['width'], 154) + self.assertGreaterEqual(arc['width'], 120) + self.assertLessEqual(arc['width'], 154) self.assertEqual(arc['start_angle'], 135) self.assertLessEqual(arc['x'] + arc['width'], 800) self.assertLessEqual(arc['y'] + arc['height'], 480) code = next(script['then'][0]['lambda'] for script in package['script'] if script['id'] == 'fleet_refresh') for printer in self.printers: self.assertIn(f'id({printer["id"]}_overview_arc)', code) - self.assertIn(f'id({printer["id"]}_overview_detail)', code) + self.assertIn(f'id({printer["id"]}_overview_finish)', code) + titles = [next(iter(widget.values())).get('text') for widget in page['widgets']] + self.assertIn('Print Status Overview', titles) + self.assertNotIn('fleet_summary', {next(iter(widget.values())).get('id') for widget in page['widgets']}) shown = [step['if']['condition']['lvgl.page.is_showing'] for step in package['interval'][0]['then']] self.assertIn('fleet_page', shown) charming = next(item for item in package['lvgl']['pages'] if item['id'] == 'prints_charming_page')