Color overview gauges by active filament and show finish times.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Joshua King
2026-10-20 19:22:04 -04:00
co-authored by Cursor
parent 360e86e46a
commit c5b7408b18
7 changed files with 380 additions and 235 deletions
+4 -6
View File
@@ -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.
+16 -7
View File
@@ -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) {
+36 -25
View File
@@ -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
+305 -190
View File
@@ -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
+6 -5
View File
@@ -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'},
+7
View File
@@ -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;
+6 -2
View File
@@ -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')