Show a grey ring behind black filament gauges so they stay visible.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -18,7 +18,8 @@ Home Assistant must be running and its printer integrations must have current pr
|
||||
The configured swipe order is:
|
||||
|
||||
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
|
||||
color of that printer's active filament. Black filament keeps a grey ring
|
||||
behind the gauge so it stays visible on the black page. 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.
|
||||
|
||||
@@ -17,6 +17,7 @@ constexpr uint32_t MUTED = 0xAEB3B7;
|
||||
constexpr uint32_t RED = 0xFF737B;
|
||||
constexpr uint32_t AMBER = 0xF2C572;
|
||||
constexpr uint32_t TRACK = 0x19232B;
|
||||
constexpr uint32_t RING_BACKING = 0x6E767E;
|
||||
|
||||
inline std::string lower(std::string text) {
|
||||
for (char &c : text) c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
|
||||
@@ -104,6 +105,11 @@ inline uint32_t filament_color(std::string value) {
|
||||
return rgb;
|
||||
}
|
||||
|
||||
// A black ring disappears on the black page. Anything this dark needs a grey arc behind it.
|
||||
inline bool filament_is_black(uint32_t color) {
|
||||
return ((color >> 16) & 0xFF) <= 0x28 && ((color >> 8) & 0xFF) <= 0x28 && (color & 0xFF) <= 0x28;
|
||||
}
|
||||
|
||||
struct Tray {
|
||||
std::string label, type, color, active;
|
||||
};
|
||||
@@ -299,7 +305,7 @@ struct Widgets {
|
||||
lv_obj_t *elapsed = nullptr;
|
||||
};
|
||||
struct OverviewWidgets {
|
||||
lv_obj_t *arc, *value, *finish;
|
||||
lv_obj_t *arc, *value, *finish, *backing;
|
||||
};
|
||||
|
||||
inline void set_text(lv_obj_t *label, const std::string &text) {
|
||||
@@ -376,6 +382,13 @@ inline void render_overview(const Snapshot &data, const OverviewWidgets &widgets
|
||||
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);
|
||||
if (filament_is_black(filament)) {
|
||||
lv_obj_set_style_arc_color(widgets.backing, lv_color_hex(RING_BACKING), LV_PART_MAIN);
|
||||
lv_obj_set_style_arc_color(widgets.backing, lv_color_hex(RING_BACKING), LV_PART_INDICATOR);
|
||||
lv_obj_clear_flag(widgets.backing, LV_OBJ_FLAG_HIDDEN);
|
||||
} else {
|
||||
lv_obj_add_flag(widgets.backing, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
set_text(widgets.value, number(shown));
|
||||
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 : "--");
|
||||
|
||||
@@ -32,6 +32,7 @@ ELEGOO_FDM = {'nozzle': 'nozzle_temperature', 'bed': 'bed_temperature',
|
||||
ELEGOO_RESIN = {'uv': 'uv_led_temp', 'elapsed': 'current_print_time'}
|
||||
BG, CARD, TRACK, TEXT_COLOR, MUTED, GREEN = (
|
||||
0x000000, 0x000000, 0x19232B, 0xEEEEEE, 0xAEB3B7, 0x00FF00)
|
||||
RING_BACKING = 0x6E767E
|
||||
ORANGE, CYAN = 0xFFAA00, 0x00E5E5
|
||||
|
||||
|
||||
@@ -272,7 +273,15 @@ def overview_gauge(printer, x, y, arc):
|
||||
inner = max(10, int(round(13 * scale)))
|
||||
inner_x = x + int(round(8 * scale))
|
||||
number_y = y + int(round(arc * 0.30))
|
||||
pad = 8
|
||||
return [
|
||||
{'arc': {'id': f'{pid}_overview_ring', 'x': inner_x - pad // 2, 'y': y - pad // 2,
|
||||
'width': arc + pad, 'height': arc + pad, 'min_value': 0, 'max_value': 100,
|
||||
'value': 100, 'start_angle': 135, 'end_angle': 45,
|
||||
'arc_width': inner + pad, 'arc_color': RING_BACKING,
|
||||
'indicator': {'arc_color': RING_BACKING, 'arc_width': inner + pad},
|
||||
'adjustable': False, 'hidden': True, 'gesture_bubble': True, 'clickable': True,
|
||||
'on_click': open_page}},
|
||||
{'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,
|
||||
@@ -324,7 +333,7 @@ def fleet_refresh_lines(snapshots):
|
||||
lines.extend(snapshot)
|
||||
lines.append('bambu_display::render_overview(data, {' + ', '.join([
|
||||
f'id({pid}_overview_arc)', f'id({pid}_overview_value)',
|
||||
f'id({pid}_overview_finish)']) + '});')
|
||||
f'id({pid}_overview_finish)', f'id({pid}_overview_ring)']) + '});')
|
||||
lines.append('}')
|
||||
lines += [
|
||||
'{',
|
||||
|
||||
@@ -1531,7 +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::render_overview(data, {id(prints_charming_overview_arc), id(prints_charming_overview_value), id(prints_charming_overview_finish)});
|
||||
bambu_display::render_overview(data, {id(prints_charming_overview_arc), id(prints_charming_overview_value), id(prints_charming_overview_finish), id(prints_charming_overview_ring)});
|
||||
}
|
||||
{
|
||||
bambu_display::Snapshot data;
|
||||
@@ -1565,7 +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::render_overview(data, {id(polly_pocket_overview_arc), id(polly_pocket_overview_value), id(polly_pocket_overview_finish)});
|
||||
bambu_display::render_overview(data, {id(polly_pocket_overview_arc), id(polly_pocket_overview_value), id(polly_pocket_overview_finish), id(polly_pocket_overview_ring)});
|
||||
}
|
||||
{
|
||||
bambu_display::Snapshot data;
|
||||
@@ -1602,7 +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::render_overview(data, {id(ds_turd_flinger_overview_arc), id(ds_turd_flinger_overview_value), id(ds_turd_flinger_overview_finish)});
|
||||
bambu_display::render_overview(data, {id(ds_turd_flinger_overview_arc), id(ds_turd_flinger_overview_value), id(ds_turd_flinger_overview_finish), id(ds_turd_flinger_overview_ring)});
|
||||
}
|
||||
{
|
||||
bambu_display::Snapshot data;
|
||||
@@ -1639,7 +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::render_overview(data, {id(jordyns_layer_slayer_overview_arc), id(jordyns_layer_slayer_overview_value), id(jordyns_layer_slayer_overview_finish)});
|
||||
bambu_display::render_overview(data, {id(jordyns_layer_slayer_overview_arc), id(jordyns_layer_slayer_overview_value), id(jordyns_layer_slayer_overview_finish), id(jordyns_layer_slayer_overview_ring)});
|
||||
}
|
||||
{
|
||||
bambu_display::Snapshot data;
|
||||
@@ -1686,7 +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::render_overview(data, {id(constipation_orion_overview_arc), id(constipation_orion_overview_value), id(constipation_orion_overview_finish)});
|
||||
bambu_display::render_overview(data, {id(constipation_orion_overview_arc), id(constipation_orion_overview_value), id(constipation_orion_overview_finish), id(constipation_orion_overview_ring)});
|
||||
}
|
||||
{
|
||||
bambu_display::Snapshot data;
|
||||
@@ -1716,7 +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::render_overview(data, {id(centauri_carbon_overview_arc), id(centauri_carbon_overview_value), id(centauri_carbon_overview_finish)});
|
||||
bambu_display::render_overview(data, {id(centauri_carbon_overview_arc), id(centauri_carbon_overview_value), id(centauri_carbon_overview_finish), id(centauri_carbon_overview_ring)});
|
||||
}
|
||||
{
|
||||
bambu_display::Snapshot data;
|
||||
@@ -1742,7 +1742,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::render_overview(data, {id(saturn_overview_arc), id(saturn_overview_value), id(saturn_overview_finish)});
|
||||
bambu_display::render_overview(data, {id(saturn_overview_arc), id(saturn_overview_value), id(saturn_overview_finish), id(saturn_overview_ring)});
|
||||
}
|
||||
{
|
||||
const auto clock = id(ha_time).now();
|
||||
@@ -1841,6 +1841,28 @@ lvgl:
|
||||
gesture_bubble: true
|
||||
id: fleet_clock
|
||||
text_align: RIGHT
|
||||
- arc:
|
||||
id: prints_charming_overview_ring
|
||||
x: 23
|
||||
y: 42
|
||||
width: 153
|
||||
height: 153
|
||||
min_value: 0
|
||||
max_value: 100
|
||||
value: 100
|
||||
start_angle: 135
|
||||
end_angle: 45
|
||||
arc_width: 20
|
||||
arc_color: 7239294
|
||||
indicator:
|
||||
arc_color: 7239294
|
||||
arc_width: 20
|
||||
adjustable: false
|
||||
hidden: true
|
||||
gesture_bubble: true
|
||||
clickable: true
|
||||
on_click:
|
||||
- lvgl.page.show: prints_charming_page
|
||||
- arc:
|
||||
id: prints_charming_overview_arc
|
||||
x: 27
|
||||
@@ -1921,6 +1943,28 @@ lvgl:
|
||||
clickable: true
|
||||
on_click:
|
||||
- lvgl.page.show: prints_charming_page
|
||||
- arc:
|
||||
id: polly_pocket_overview_ring
|
||||
x: 223
|
||||
y: 42
|
||||
width: 153
|
||||
height: 153
|
||||
min_value: 0
|
||||
max_value: 100
|
||||
value: 100
|
||||
start_angle: 135
|
||||
end_angle: 45
|
||||
arc_width: 20
|
||||
arc_color: 7239294
|
||||
indicator:
|
||||
arc_color: 7239294
|
||||
arc_width: 20
|
||||
adjustable: false
|
||||
hidden: true
|
||||
gesture_bubble: true
|
||||
clickable: true
|
||||
on_click:
|
||||
- lvgl.page.show: polly_pocket_page
|
||||
- arc:
|
||||
id: polly_pocket_overview_arc
|
||||
x: 227
|
||||
@@ -2001,6 +2045,28 @@ lvgl:
|
||||
clickable: true
|
||||
on_click:
|
||||
- lvgl.page.show: polly_pocket_page
|
||||
- arc:
|
||||
id: ds_turd_flinger_overview_ring
|
||||
x: 423
|
||||
y: 42
|
||||
width: 153
|
||||
height: 153
|
||||
min_value: 0
|
||||
max_value: 100
|
||||
value: 100
|
||||
start_angle: 135
|
||||
end_angle: 45
|
||||
arc_width: 20
|
||||
arc_color: 7239294
|
||||
indicator:
|
||||
arc_color: 7239294
|
||||
arc_width: 20
|
||||
adjustable: false
|
||||
hidden: true
|
||||
gesture_bubble: true
|
||||
clickable: true
|
||||
on_click:
|
||||
- lvgl.page.show: ds_turd_flinger_page
|
||||
- arc:
|
||||
id: ds_turd_flinger_overview_arc
|
||||
x: 427
|
||||
@@ -2081,6 +2147,28 @@ lvgl:
|
||||
clickable: true
|
||||
on_click:
|
||||
- lvgl.page.show: ds_turd_flinger_page
|
||||
- arc:
|
||||
id: jordyns_layer_slayer_overview_ring
|
||||
x: 623
|
||||
y: 42
|
||||
width: 153
|
||||
height: 153
|
||||
min_value: 0
|
||||
max_value: 100
|
||||
value: 100
|
||||
start_angle: 135
|
||||
end_angle: 45
|
||||
arc_width: 20
|
||||
arc_color: 7239294
|
||||
indicator:
|
||||
arc_color: 7239294
|
||||
arc_width: 20
|
||||
adjustable: false
|
||||
hidden: true
|
||||
gesture_bubble: true
|
||||
clickable: true
|
||||
on_click:
|
||||
- lvgl.page.show: jordyns_layer_slayer_page
|
||||
- arc:
|
||||
id: jordyns_layer_slayer_overview_arc
|
||||
x: 627
|
||||
@@ -2161,6 +2249,28 @@ lvgl:
|
||||
clickable: true
|
||||
on_click:
|
||||
- lvgl.page.show: jordyns_layer_slayer_page
|
||||
- arc:
|
||||
id: constipation_orion_overview_ring
|
||||
x: 123
|
||||
y: 235
|
||||
width: 153
|
||||
height: 153
|
||||
min_value: 0
|
||||
max_value: 100
|
||||
value: 100
|
||||
start_angle: 135
|
||||
end_angle: 45
|
||||
arc_width: 20
|
||||
arc_color: 7239294
|
||||
indicator:
|
||||
arc_color: 7239294
|
||||
arc_width: 20
|
||||
adjustable: false
|
||||
hidden: true
|
||||
gesture_bubble: true
|
||||
clickable: true
|
||||
on_click:
|
||||
- lvgl.page.show: constipation_orion_page
|
||||
- arc:
|
||||
id: constipation_orion_overview_arc
|
||||
x: 127
|
||||
@@ -2241,6 +2351,28 @@ lvgl:
|
||||
clickable: true
|
||||
on_click:
|
||||
- lvgl.page.show: constipation_orion_page
|
||||
- arc:
|
||||
id: centauri_carbon_overview_ring
|
||||
x: 323
|
||||
y: 235
|
||||
width: 153
|
||||
height: 153
|
||||
min_value: 0
|
||||
max_value: 100
|
||||
value: 100
|
||||
start_angle: 135
|
||||
end_angle: 45
|
||||
arc_width: 20
|
||||
arc_color: 7239294
|
||||
indicator:
|
||||
arc_color: 7239294
|
||||
arc_width: 20
|
||||
adjustable: false
|
||||
hidden: true
|
||||
gesture_bubble: true
|
||||
clickable: true
|
||||
on_click:
|
||||
- lvgl.page.show: centauri_carbon_page
|
||||
- arc:
|
||||
id: centauri_carbon_overview_arc
|
||||
x: 327
|
||||
@@ -2321,6 +2453,28 @@ lvgl:
|
||||
clickable: true
|
||||
on_click:
|
||||
- lvgl.page.show: centauri_carbon_page
|
||||
- arc:
|
||||
id: saturn_overview_ring
|
||||
x: 523
|
||||
y: 235
|
||||
width: 153
|
||||
height: 153
|
||||
min_value: 0
|
||||
max_value: 100
|
||||
value: 100
|
||||
start_angle: 135
|
||||
end_angle: 45
|
||||
arc_width: 20
|
||||
arc_color: 7239294
|
||||
indicator:
|
||||
arc_color: 7239294
|
||||
arc_width: 20
|
||||
adjustable: false
|
||||
hidden: true
|
||||
gesture_bubble: true
|
||||
clickable: true
|
||||
on_click:
|
||||
- lvgl.page.show: saturn_page
|
||||
- arc:
|
||||
id: saturn_overview_arc
|
||||
x: 527
|
||||
|
||||
@@ -130,6 +130,12 @@ int main() {
|
||||
assert(data.active_filament_color() == 0xFF8800);
|
||||
data.trays.clear();
|
||||
assert(data.active_filament_color() == GREEN);
|
||||
assert(filament_is_black(0x000000));
|
||||
assert(filament_is_black(filament_color("#000000FF")));
|
||||
assert(filament_is_black(0x202020));
|
||||
assert(!filament_is_black(0xFFFFFF));
|
||||
assert(!filament_is_black(GREEN));
|
||||
assert(!filament_is_black(0xFF8800));
|
||||
|
||||
FleetCounts counts;
|
||||
data.connected = true;
|
||||
|
||||
@@ -152,9 +152,22 @@ class FleetTests(unittest.TestCase):
|
||||
page = package['lvgl']['pages'][0]
|
||||
self.assertEqual(page['id'], 'fleet_page')
|
||||
self.assertFalse(page.get('skip'))
|
||||
arcs = [widget['arc'] for widget in page['widgets'] if 'arc' in widget]
|
||||
arcs = [widget['arc'] for widget in page['widgets']
|
||||
if widget.get('arc', {}).get('id', '').endswith('_overview_arc')]
|
||||
self.assertEqual([arc['id'][:-len('_overview_arc')] for arc in arcs],
|
||||
[printer['id'] for printer in self.printers])
|
||||
backings = [widget['arc'] for widget in page['widgets']
|
||||
if widget.get('arc', {}).get('id', '').endswith('_overview_ring')]
|
||||
self.assertEqual([arc['id'][:-len('_overview_ring')] for arc in backings],
|
||||
[printer['id'] for printer in self.printers])
|
||||
for backing, arc in zip(backings, arcs):
|
||||
self.assertTrue(backing['hidden'])
|
||||
self.assertEqual(backing['arc_color'], 0x6E767E)
|
||||
self.assertGreater(backing['width'], arc['width'])
|
||||
self.assertGreaterEqual(backing['x'], 0)
|
||||
self.assertGreaterEqual(backing['y'], 0)
|
||||
self.assertLessEqual(backing['x'] + backing['width'], 800)
|
||||
self.assertLessEqual(backing['y'] + backing['height'], 480)
|
||||
for arc, printer in zip(arcs, self.printers):
|
||||
self.assertEqual(arc['on_click'], [{'lvgl.page.show': printer['id'] + '_page'}])
|
||||
self.assertGreaterEqual(arc['width'], 120)
|
||||
@@ -166,6 +179,7 @@ class FleetTests(unittest.TestCase):
|
||||
for printer in self.printers:
|
||||
self.assertIn(f'id({printer["id"]}_overview_arc)', code)
|
||||
self.assertIn(f'id({printer["id"]}_overview_finish)', code)
|
||||
self.assertIn(f'id({printer["id"]}_overview_ring)', 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']})
|
||||
|
||||
Reference in New Issue
Block a user