Color overview gauges by active filament and show finish times.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'},
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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')
|
||||
|
||||
Reference in New Issue
Block a user