From 495efeb672a898d7b9d22e59509d19387a9b89a8 Mon Sep 17 00:00:00 2001 From: Joshua King Date: Sat, 17 Oct 2026 17:09:47 -0400 Subject: [PATCH] updates --- .gitignore | 3 + esphome/bambu-display/README.md | 127 + esphome/bambu-display/dashboard.h | 172 + esphome/bambu-display/generate.py | 235 ++ esphome/bambu-display/generated.yaml | 3238 +++++++++++++++++ esphome/bambu-display/preview.py | 128 + .../previews/constipation_orion.png | Bin 0 -> 35412 bytes .../previews/ds_turd_flinger.png | Bin 0 -> 33309 bytes .../previews/jordyns_layer_slayer.png | Bin 0 -> 33736 bytes .../bambu-display/previews/polly_pocket.png | Bin 0 -> 32051 bytes .../previews/prints_charming.png | Bin 0 -> 33779 bytes esphome/bambu-display/printers.yaml | 46 + esphome/bambu-display/test_dashboard.cpp | 54 + esphome/bambu-display/test_generate.py | 67 + esphome/bambu-printer-display.yaml | 114 + 15 files changed, 4184 insertions(+) create mode 100644 esphome/bambu-display/README.md create mode 100644 esphome/bambu-display/dashboard.h create mode 100644 esphome/bambu-display/generate.py create mode 100644 esphome/bambu-display/generated.yaml create mode 100644 esphome/bambu-display/preview.py create mode 100644 esphome/bambu-display/previews/constipation_orion.png create mode 100644 esphome/bambu-display/previews/ds_turd_flinger.png create mode 100644 esphome/bambu-display/previews/jordyns_layer_slayer.png create mode 100644 esphome/bambu-display/previews/polly_pocket.png create mode 100644 esphome/bambu-display/previews/prints_charming.png create mode 100644 esphome/bambu-display/printers.yaml create mode 100644 esphome/bambu-display/test_dashboard.cpp create mode 100644 esphome/bambu-display/test_generate.py create mode 100644 esphome/bambu-printer-display.yaml diff --git a/.gitignore b/.gitignore index 2350c66..ae4fb16 100644 --- a/.gitignore +++ b/.gitignore @@ -61,6 +61,9 @@ ### ESPHome Folders ### !esphome/ !esphome/fonts/** +!esphome/bambu-display/ +!esphome/bambu-display/** +esphome/bambu-display/**/__pycache__/ !esphome/ha-remote/ !esphome/ha-remote/components/ !esphome/ha-remote/components/** diff --git a/esphome/bambu-display/README.md b/esphome/bambu-display/README.md new file mode 100644 index 0000000..7038926 --- /dev/null +++ b/esphome/bambu-display/README.md @@ -0,0 +1,127 @@ +# Bambu fleet display + +ESPHome/LVGL monitor for the **Sunton ESP32-8048S043C**, with an 800×480 landscape RGB +display, GT911 capacitive touch, 16 MB flash and 8 MB octal PSRAM. The hardware pins +and LCD timings follow the [ESPHome device reference](https://devices.esphome.io/devices/sunton-esp32-8048s043c/). +This configuration is for the **C** capacitive-touch version. + +Inspired by [BambuHelper](https://github.com/Keralots/BambuHelper), this implementation +subscribes to the existing Home Assistant Bambu Lab entities over a single encrypted +ESPHome API connection. Home Assistant handles the printer connections. No Bambu +access codes, cloud credentials or additional Home Assistant automations are needed. +Home Assistant must be running and its Bambu integration must have current printer data. + +## Pages and navigation + +![LVGL preview with synthetic printer telemetry](previews/prints_charming.png) + +The configured swipe order is: + +1. PrintsCharming — P1S, Office, both four-slot AMS units. +2. Polly-Pocket — A1 mini, Office, external spool. +3. Ds-Turd-Flinger — A1, Upstairs, four-slot AMS. +4. Jordyns-Layer-Slayer — A1, Upstairs, four-slot AMS. +5. Constipation-Orion — Office, left/right nozzles and four-slot AMS. + +Swipe left for the next printer or right for the previous printer. Navigation wraps +from the last page to the first. Previous/Next buttons provide the same navigation. +Swipes propagate through the metric cards and filament slots. A swipe consumes the +rest of that touch so dragging across a navigation button does not also click it. + +Each page shows print status, job name, progress, nozzle and bed current/target +temperatures, remaining time, current/total layers, print stage, part fan speed and +filament colors/types. The active filament slot has a green outline. Print errors +and HMS alerts change the status badge to red; paused prints use amber. The display +shows an alert badge rather than the detailed HMS diagnostic text. + +When Home Assistant disconnects or a printer is offline, its live metrics are cleared +to `--` rather than continuing to show cached values as live. Unknown individual +values also show `--`. Remaining time respects the HA sensor's `h`, `min` or `s` +unit, and temperature labels use the imported HA temperature unit. Only the visible +page is refreshed each second; every printer's subscriptions remain connected. + +This version provides monitoring and local page navigation. Camera feeds, cover +images, printer pause/stop controls, power switching, cloud login and automatic +printer rotation are outside its current scope. + +## Install + +1. Keep `esphome/bambu-printer-display.yaml` and the entire `bambu-display/` folder + together in the ESPHome configuration directory. The generated package is checked + in, so the ESPHome dashboard can compile it without running the generator first. +2. Supply the existing `api_encryption_key`, `wifi_iot_ssid` and `wifi_password` + entries in that directory's `secrets.yaml`. +3. Use ESPHome **2026.9.0 or newer**. Compile and install + `bambu-printer-display.yaml` over the board's USB-to-UART bridge for the first + flash; subsequent installs can use encrypted OTA. +4. Add **Bambu Printer Display** through Home Assistant's ESPHome integration using + the same API encryption key. The display only subscribes to entities, so it does + not require permission to perform Home Assistant actions. +5. Confirm all pages receive data and verify touch direction and color order on the + physical panel. Entity IDs match the repository's `ha-entities.txt` snapshot; + renamed or disabled entities in live HA must be corrected/enabled there. + +The USB D+/D− GPIO19/20 pins are used by the board's touch bus. Logging therefore +uses UART0. ESPHome may still warn about these two pins; they are intentional for +this board. If GT911 is not found at `0x5D`, inspect the I²C scan and use its reported +address (some hardware revisions select `0x14`). Backlight is GPIO2; RGB data pins +and timings are explicit in the main YAML rather than borrowed from a 5″ board. + +CLI checks from the repository root: + +```sh +esphome config esphome/bambu-printer-display.yaml +esphome compile esphome/bambu-printer-display.yaml +``` + +## Change or expand the fleet + +Edit **`printers.yaml`**, then regenerate and flash the display: + +```sh +python esphome/bambu-display/generate.py +python esphome/bambu-display/generate.py --check +``` + +The generator requires PyYAML (already included in ESPHome's Python environment). +Do not hand-edit `generated.yaml`. There is no two-printer limit in the generator; +adding a printer creates its own subscriptions, widgets and swipe page. The practical +limit depends on the board's available RAM and flash, and adding printers requires +regenerating and installing the firmware. Five printers are configured; generation +is also tested with seven. Each printer's filament strip supports up to eight slots. + +```yaml +- id: another_printer + name: Another Printer + subtitle: Workshop + entity_prefix: my_bambu_printer + entities: + progress: sensor.renamed_progress + time_left: sensor.renamed_remaining_time + filament_banks: + - label: A + entity_prefix: my_bambu_printer_ams_1 +``` + +For a dual-nozzle printer add `dual_nozzle: true`. For external filament add +`external_spools: [{label: EXT, entity: sensor.my_external_spool}]`. Per-metric +`entities` overrides use the keys in `NUMERIC`, `DUAL`, `TEXT` and `BINARY` inside +`generate.py`. A remaining-time override also updates its unit subscription. +Filament entries use the Bambu integration's `type`, `color` and `active` attributes. + +## Development checks and screenshots + +```sh +python -m unittest discover -s esphome/bambu-display -v +clang++ -std=c++17 -Wall -Wextra -Werror esphome/bambu-display/test_dashboard.cpp -o /tmp/bambu-dashboard-test +/tmp/bambu-dashboard-test +python esphome/bambu-display/preview.py +``` + +`preview.py` compiles the same generated LVGL widgets for ESPHome's SDL host with +clearly synthetic telemetry, then captures all five pages into `previews/`. It needs +ESPHome, Pillow, a C++ compiler and SDL2 (`sdl2-config` on PATH). It runs headlessly, +without connecting to Home Assistant or any printer. It also injects LVGL pointer +samples to check left/right swipes, page wraparound and consumption of a swipe that +starts on a navigation button. These are software layout +previews; physical panel timings, touch and Wi-Fi still need a hardware check. diff --git a/esphome/bambu-display/dashboard.h b/esphome/bambu-display/dashboard.h new file mode 100644 index 0000000..945bac2 --- /dev/null +++ b/esphome/bambu-display/dashboard.h @@ -0,0 +1,172 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace bambu_display { + +constexpr uint32_t GREEN = 0x60DE9A; +constexpr uint32_t MUTED = 0x91A3B5; +constexpr uint32_t RED = 0xFF737B; +constexpr uint32_t AMBER = 0xF2C572; +constexpr uint32_t TRACK = 0x263442; + +inline std::string lower(std::string text) { + for (char &c : text) c = static_cast(std::tolower(static_cast(c))); + return text; +} + +inline bool valid_text(const std::string &text) { + const auto value = lower(text); + return !value.empty() && value != "unknown" && value != "unavailable" && value != "none"; +} + +inline bool is_on(const std::string &text) { + const auto value = lower(text); + return value == "on" || value == "true" || value == "1"; +} + +inline std::string humanize(std::string text) { + if (!valid_text(text)) return "--"; + std::replace(text.begin(), text.end(), '_', ' '); + if (!text.empty()) text[0] = static_cast(std::toupper(static_cast(text[0]))); + return text; +} + +inline int gauge_value(float value, int maximum) { + return std::isfinite(value) ? static_cast(std::clamp(value, 0.0f, float(maximum))) : 0; +} + +inline std::string number(float value) { + if (!std::isfinite(value) || value < 0 || value > 1000000) return "--"; + char buffer[24]; + snprintf(buffer, sizeof(buffer), "%.0f", value); + return buffer; +} + +inline std::string temperature(float current, float target, const std::string &unit) { + return number(current) + " / " + number(target) + (valid_text(unit) ? " " + unit : ""); +} + +inline std::string remaining(float value, const std::string &unit) { + if (!std::isfinite(value) || value < 0) return "--"; + double minutes; + if (unit == "h") minutes = double(value) * 60; + else if (unit == "min") minutes = value; + else if (unit == "s") minutes = double(value) / 60; + else return "--"; // Never silently interpret hours as minutes. + if (minutes > 1000000) return "--"; + const auto rounded = static_cast(std::ceil(minutes - 0.001)); + char buffer[32]; + snprintf(buffer, sizeof(buffer), "%dh %02dm", rounded / 60, rounded % 60); + return buffer; +} + +inline uint32_t filament_color(std::string value) { + if (!value.empty() && value[0] == '#') value.erase(0, 1); + // Bambu publishes RGB or RGBA, with alpha at the end. + if (value.size() != 6 && value.size() != 8) return TRACK; + uint32_t rgb = 0; + for (size_t i = 0; i < value.size(); ++i) { + const char c = static_cast(std::tolower(static_cast(value[i]))); + const int digit = c >= '0' && c <= '9' ? c - '0' : c >= 'a' && c <= 'f' ? c - 'a' + 10 : -1; + if (digit < 0) return TRACK; + if (i < 6) rgb = (rgb << 4) | digit; + } + return rgb; +} + +struct Tray { + std::string label, type, color, active; +}; + +struct Snapshot { + bool connected = false; + std::string online, status, task, stage, print_error, hms_error; + std::string remaining_unit, nozzle_unit, bed_unit; + float progress = NAN, nozzle = NAN, nozzle_target = NAN, bed = NAN, bed_target = NAN; + float time_left = NAN, layer = NAN, total_layers = NAN, fan = NAN; + bool dual_nozzle = false; + float left_nozzle = NAN, left_target = NAN, right_nozzle = NAN, right_target = NAN; + std::vector trays; + + bool live() const { return connected && is_on(online) && valid_text(status); } + std::string status_text() const { + if (!connected) return "HA OFFLINE"; + if (lower(online) == "off" || lower(online) == "false") return "PRINTER OFFLINE"; + if (!live()) return "SYNCING"; + if (is_on(print_error)) return "PRINT ERROR"; + if (is_on(hms_error)) return "HMS ALERT"; + const auto state = lower(status); + if (state == "running") return "PRINTING"; + if (state == "pause" || state == "paused") return "PAUSED"; + if (state == "finish" || state == "finished") return "COMPLETE"; + auto text = humanize(status); + for (char &c : text) c = static_cast(std::toupper(static_cast(c))); + return text; + } + uint32_t status_color() const { + if (!live()) return MUTED; + const auto state = lower(status); + if (is_on(print_error) || is_on(hms_error) || state == "failed") return RED; + if (state == "pause" || state == "paused") return AMBER; + return GREEN; + } +}; + +} // namespace bambu_display + +#ifdef USE_LVGL +#include + +namespace bambu_display { + +struct TrayWidgets { lv_obj_t *card, *swatch, *label; }; +struct Widgets { + lv_obj_t *status, *task, *arc, *progress, *nozzle, *bed, *remaining, *layers, *stage; + std::vector trays; +}; + +inline void set_text(lv_obj_t *label, const std::string &text) { + if (text != lv_label_get_text(label)) lv_label_set_text(label, text.c_str()); +} + +inline void render(const Snapshot &data, const Widgets &widgets) { + const bool live = data.live(); + const uint32_t color = data.status_color(); + set_text(widgets.status, data.status_text()); + lv_obj_set_style_text_color(widgets.status, lv_color_hex(color), 0); + lv_obj_set_style_arc_color(widgets.arc, lv_color_hex(color), LV_PART_INDICATOR); + lv_arc_set_value(widgets.arc, live ? gauge_value(data.progress, 100) : 0); + set_text(widgets.progress, live && std::isfinite(data.progress) + ? number(std::clamp(data.progress, 0.0f, 100.0f)) + "%" : "--"); + set_text(widgets.task, live ? (valid_text(data.task) ? data.task : "No active print") + : data.connected ? "Waiting for printer data" : "Waiting for Home Assistant"); + if (live && data.dual_nozzle) { + set_text(widgets.nozzle, "L " + temperature(data.left_nozzle, data.left_target, data.nozzle_unit) + + "\nR " + temperature(data.right_nozzle, data.right_target, data.nozzle_unit)); + } else { + set_text(widgets.nozzle, live ? temperature(data.nozzle, data.nozzle_target, data.nozzle_unit) : "--"); + } + set_text(widgets.bed, live ? temperature(data.bed, data.bed_target, data.bed_unit) : "--"); + set_text(widgets.remaining, live ? remaining(data.time_left, data.remaining_unit) : "--"); + set_text(widgets.layers, live ? number(data.layer) + " / " + number(data.total_layers) : "--"); + std::string stage = live ? humanize(data.stage) : "Telemetry unavailable"; + if (live && std::isfinite(data.fan)) stage += " | Part fan " + number(data.fan) + "%"; + set_text(widgets.stage, stage); + for (size_t i = 0; i < std::min(data.trays.size(), widgets.trays.size()); ++i) { + const auto &tray = data.trays[i]; + const auto &widget = widgets.trays[i]; + set_text(widget.label, tray.label + " " + (live && valid_text(tray.type) ? tray.type : "--")); + lv_obj_set_style_bg_color(widget.swatch, lv_color_hex(live ? filament_color(tray.color) : TRACK), 0); + lv_obj_set_style_border_color(widget.card, lv_color_hex(live && is_on(tray.active) ? GREEN : TRACK), 0); + } +} + +} // namespace bambu_display +#endif diff --git a/esphome/bambu-display/generate.py b/esphome/bambu-display/generate.py new file mode 100644 index 0000000..d731287 --- /dev/null +++ b/esphome/bambu-display/generate.py @@ -0,0 +1,235 @@ +#!/usr/bin/env python3 +"""Generate the ESPHome fleet package from printers.yaml. Requires PyYAML.""" + +import argparse +import json +from pathlib import Path +import re + +import yaml + +HERE = Path(__file__).resolve().parent +NUMERIC = { + 'progress': 'print_progress', 'nozzle': 'nozzle_temperature', + 'nozzle_target': 'nozzle_target_temperature', 'bed': 'bed_temperature', + 'bed_target': 'bed_target_temperature', 'time_left': 'remaining_time', + 'layer': 'current_layer', 'total_layers': 'total_layer_count', + 'fan': 'cooling_fan_speed', +} +DUAL = { + 'left_nozzle': 'left_nozzle_temperature', 'left_target': 'left_nozzle_target_temperature', + 'right_nozzle': 'right_nozzle_temperature', 'right_target': 'right_nozzle_target_temperature', +} +TEXT = {'status': 'print_status', 'task': 'task_name', 'stage': 'current_stage'} +BINARY = {'online': 'online', 'print_error': 'print_error', 'hms_error': 'hms_errors'} +BG, CARD, TRACK, TEXT_COLOR, MUTED, GREEN = ( + 0x0D131B, 0x17222E, 0x263442, 0xEDF3F7, 0x91A3B5, 0x60DE9A) + + +class Lambda(str): + """A C++ lambda serialized with ESPHome's YAML tag.""" + + +class Dumper(yaml.SafeDumper): + def ignore_aliases(self, data): + return True + + +Dumper.add_representer(Lambda, lambda dumper, text: dumper.represent_scalar('!lambda', text, style='|')) + + +def entity(printer, key, suffix, domain='sensor'): + return printer.get('entities', {}).get(key, f'{domain}.{printer["entity_prefix"]}_{suffix}') + + +def trays_for(printer): + result = [] + for bank in printer.get('filament_banks', []): + for slot in range(1, 5): + result.append({'label': f'{bank["label"]}{slot}', + 'entity': f'sensor.{bank["entity_prefix"]}_tray_{slot}'}) + return result + printer.get('external_spools', []) + + +def validate_printers(printers): + if not isinstance(printers, list) or not printers: + raise ValueError('printers must be a nonempty list') + ids = set() + for printer in printers: + for key in ('id', 'name', 'subtitle', 'entity_prefix'): + if not isinstance(printer.get(key), str) or not printer[key]: + raise ValueError(f'Each printer needs a nonempty {key}') + pid = printer['id'] + if not re.fullmatch(r'[a-z][a-z0-9_]*', pid) or pid in ids: + raise ValueError(f'Invalid or duplicate printer id: {pid}') + ids.add(pid) + if len(trays_for(printer)) > 8: + raise ValueError(f'{pid}: the filament strip fits up to eight slots') + if 'dual_nozzle' in printer and not isinstance(printer['dual_nozzle'], bool): + raise ValueError(f'{pid}: dual_nozzle must be true or false') + for value in printer.get('entities', {}).values(): + if not isinstance(value, str) or not re.fullmatch(r'(sensor|binary_sensor)\.[a-z0-9_]+', value): + raise ValueError(f'{pid}: invalid entity override: {value}') + + +def label(text, x, y, width, font=18, **kwargs): + return {'label': {'text': text, 'x': x, 'y': y, 'width': width, + 'height': font + 8, 'text_color': TEXT_COLOR, + 'text_font': f'montserrat_{font}', 'long_mode': 'DOT', + 'gesture_bubble': True, **kwargs}} + + +def card(pid, name, title, x, y, width=238, height=104, font=26): + return {'obj': {'x': x, 'y': y, 'width': width, 'height': height, + 'bg_color': CARD, 'radius': 16, 'border_width': 0, + 'pad_all': 0, 'scrollable': False, 'gesture_bubble': True, + 'widgets': [ + label(title, 16, 12, width - 32, 14, text_color=MUTED), + label('--', 16, 38, width - 32, font, id=f'{pid}_{name}_label', height=height - 42), + ]}} + + +def page_for(printer, index, total): + pid = printer['id'] + widgets = [ + label(printer['name'], 24, 16, 545, 28), + label(printer['subtitle'], 24, 53, 545, 14, text_color=MUTED), + {'obj': {'x': 586, 'y': 20, 'width': 190, 'height': 42, + 'bg_color': CARD, 'radius': 21, 'border_width': 0, 'pad_all': 0, + 'scrollable': False, 'gesture_bubble': True, + 'widgets': [label('SYNCING', 0, 11, 190, 16, + id=f'{pid}_status_label', text_align='CENTER', text_color=MUTED)]}}, + label('Waiting for Home Assistant', 24, 88, 752, 20, id=f'{pid}_task_label'), + {'arc': {'id': f'{pid}_progress_arc', 'x': 28, 'y': 132, 'width': 224, 'height': 224, + 'min_value': 0, 'max_value': 100, 'value': 0, + 'start_angle': 135, 'end_angle': 45, 'arc_width': 14, + 'arc_color': TRACK, 'indicator': {'arc_color': GREEN, 'arc_width': 14}, + 'adjustable': False, 'gesture_bubble': True}}, + label('--', 42, 207, 196, 48, id=f'{pid}_progress_label', text_align='CENTER'), + label('PRINT PROGRESS', 42, 266, 196, 14, text_align='CENTER', text_color=MUTED), + card(pid, 'nozzle', 'NOZZLES L/R / TARGET' if printer.get('dual_nozzle') + else 'NOZZLE / TARGET', 282, 132, height=118, + font=18 if printer.get('dual_nozzle') else 26), + card(pid, 'bed', 'BED / TARGET', 538, 132, height=118), + card(pid, 'remaining', 'REMAINING', 282, 262, height=86), + card(pid, 'layers', 'LAYER', 538, 262, height=86), + label('Telemetry unavailable', 24, 358, 752, 16, id=f'{pid}_stage_label', text_color=MUTED), + label('FILAMENT / ACTIVE SLOT OUTLINED IN GREEN', 24, 383, 752, 12, text_color=MUTED), + ] + trays = trays_for(printer) + if trays: + width = (752 - 8 * (len(trays) - 1)) // len(trays) + for i, tray in enumerate(trays): + widgets.append({'obj': { + 'id': f'{pid}_tray_{i}_card', 'x': 24 + (width + 8) * i, 'y': 401, + 'width': width, 'height': 32, 'bg_color': CARD, 'radius': 6, + 'border_width': 1, 'border_color': TRACK, 'pad_all': 0, + 'scrollable': False, 'gesture_bubble': True, + 'widgets': [ + {'obj': {'id': f'{pid}_tray_{i}_swatch', 'x': 1, 'y': 1, 'width': width - 4, + 'height': 5, 'bg_color': TRACK, 'radius': 2, 'border_width': 0, + 'pad_all': 0, 'scrollable': False, 'gesture_bubble': True}}, + label(f'{tray["label"]} --', 6, 11, width - 12, 12, + id=f'{pid}_tray_{i}_label'), + ]}}) + else: + widgets.append(label('No filament slots configured', 24, 403, 752, 14, text_color=MUTED)) + for direction, x, text in (('previous', 24, '< PREV'), ('next', 688, 'NEXT >')): + widgets.append({'button': {'x': x, 'y': 444, 'width': 88, 'height': 30, + 'bg_color': CARD, 'radius': 8, 'border_width': 0, + 'pad_all': 0, 'gesture_bubble': True, + 'widgets': [{'label': {'text': text, 'align': 'CENTER', + 'text_font': 'montserrat_12'}}], + 'on_click': [{f'lvgl.page.{direction}': {}}]}}) + widgets.append(label(f'{index + 1} / {total} SWIPE LEFT / RIGHT', 130, 451, 540, 14, + text_align='CENTER', text_color=MUTED)) + return {'id': f'{pid}_page', 'bg_color': BG, 'bg_opa': 'COVER', + 'pad_all': 0, 'scrollable': False, 'scrollbar_mode': 'OFF', + 'on_swipe_left': [ + {'lambda': Lambda('if (auto *input = lv_indev_active()) lv_indev_wait_release(input);')}, + {'lvgl.page.next': {'animation': 'MOVE_LEFT', 'time': '180ms'}}], + 'on_swipe_right': [ + {'lambda': Lambda('if (auto *input = lv_indev_active()) lv_indev_wait_release(input);')}, + {'lvgl.page.previous': {'animation': 'MOVE_RIGHT', 'time': '180ms'}}], + 'on_load': [{'script.execute': f'{pid}_refresh'}], 'widgets': widgets} + + +def generate(printers): + validate_printers(printers) + package = {'sensor': [], 'text_sensor': [], 'script': [], + 'interval': [{'interval': '1s', 'then': []}], 'lvgl': {'pages': []}} + for index, printer in enumerate(printers): + pid = printer['id'] + fields = dict(NUMERIC) + if printer.get('dual_nozzle'): + fields.update(DUAL) + expressions = {} + for key, suffix in fields.items(): + sid = f'{pid}_{key}' + eid = entity(printer, key, suffix) + package['sensor'].append({'platform': 'homeassistant', 'id': sid, + 'entity_id': eid, 'internal': True}) + expressions[key] = f'id({sid}).state' + text_fields = {key: (entity(printer, key, suffix), None) for key, suffix in TEXT.items()} + text_fields.update({key: (entity(printer, key, suffix, 'binary_sensor'), None) + for key, suffix in BINARY.items()}) + for key, numeric_key in [('remaining_unit', 'time_left'), ('nozzle_unit', 'nozzle'), ('bed_unit', 'bed')]: + text_fields[key] = (entity(printer, numeric_key, NUMERIC[numeric_key]), 'unit_of_measurement') + trays = trays_for(printer) + for i, tray in enumerate(trays): + for key, attr in [('type', 'type'), ('color', 'color'), ('active', 'active')]: + text_fields[f'tray_{i}_{key}'] = (tray['entity'], attr) + for key, (eid, attribute) in text_fields.items(): + sid = f'{pid}_{key}' + subscription = {'platform': 'homeassistant', 'id': sid, 'entity_id': eid, 'internal': True} + if attribute: + subscription['attribute'] = attribute + package['text_sensor'].append(subscription) + expressions[key] = f'id({sid}).state' + lines = ['bambu_display::Snapshot data;', + 'data.connected = id(ha_api).is_connected_with_state_subscription();'] + for key, expr in expressions.items(): + if not key.startswith('tray_'): + lines.append(f'data.{key} = {expr};') + if printer.get('dual_nozzle'): + lines.append('data.dual_nozzle = true;') + tray_widgets = [] + for i, tray in enumerate(trays): + lines.append('data.trays.push_back({' + ', '.join([ + json.dumps(tray['label']), expressions[f'tray_{i}_type'], + expressions[f'tray_{i}_color'], expressions[f'tray_{i}_active']]) + '});') + tray_widgets.append('{' + ', '.join(f'id({pid}_tray_{i}_{part})' + for part in ('card', 'swatch', 'label')) + '}') + refs = [f'id({pid}_{key})' for key in ( + 'status_label', 'task_label', 'progress_arc', 'progress_label', 'nozzle_label', + 'bed_label', 'remaining_label', 'layers_label', 'stage_label')] + refs.append('{' + ', '.join(tray_widgets) + '}') + lines.append('bambu_display::render(data, {' + ', '.join(refs) + '});') + package['script'].append({'id': f'{pid}_refresh', 'then': [{'lambda': Lambda('\n'.join(lines))}]}) + package['interval'][0]['then'].append({'if': { + 'condition': {'lvgl.page.is_showing': f'{pid}_page'}, + 'then': [{'script.execute': f'{pid}_refresh'}]}}) + package['lvgl']['pages'].append(page_for(printer, index, len(printers))) + return package + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--check', action='store_true', help='Fail if generated.yaml is stale') + args = parser.parse_args() + printers = yaml.safe_load((HERE / 'printers.yaml').read_text())['printers'] + package = generate(printers) + content = ('# AUTO-GENERATED by bambu-display/generate.py. Edit printers.yaml or generate.py.\n' + + yaml.dump(package, Dumper=Dumper, sort_keys=False, allow_unicode=True, width=110)) + destination = HERE / 'generated.yaml' + if args.check: + if not destination.exists() or destination.read_text() != content: + raise SystemExit('generated.yaml is stale; run generate.py') + print(f'Generated configuration is current ({len(printers)} printer pages).') + else: + destination.write_text(content) + print(f'Generated {destination.name} with {len(printers)} printer pages.') + + +if __name__ == '__main__': + main() diff --git a/esphome/bambu-display/generated.yaml b/esphome/bambu-display/generated.yaml new file mode 100644 index 0000000..b9890d9 --- /dev/null +++ b/esphome/bambu-display/generated.yaml @@ -0,0 +1,3238 @@ +# AUTO-GENERATED by bambu-display/generate.py. Edit printers.yaml or generate.py. +sensor: +- platform: homeassistant + id: prints_charming_progress + entity_id: sensor.p1s_01p09c470102673_print_progress + internal: true +- platform: homeassistant + id: prints_charming_nozzle + entity_id: sensor.p1s_01p09c470102673_nozzle_temperature + internal: true +- platform: homeassistant + id: prints_charming_nozzle_target + entity_id: sensor.p1s_01p09c470102673_nozzle_target_temperature + internal: true +- platform: homeassistant + id: prints_charming_bed + entity_id: sensor.p1s_01p09c470102673_bed_temperature + internal: true +- platform: homeassistant + id: prints_charming_bed_target + entity_id: sensor.p1s_01p09c470102673_bed_target_temperature + internal: true +- platform: homeassistant + id: prints_charming_time_left + entity_id: sensor.p1s_01p09c470102673_remaining_time + internal: true +- platform: homeassistant + id: prints_charming_layer + entity_id: sensor.p1s_01p09c470102673_current_layer + internal: true +- platform: homeassistant + id: prints_charming_total_layers + entity_id: sensor.p1s_01p09c470102673_total_layer_count + internal: true +- platform: homeassistant + id: prints_charming_fan + entity_id: sensor.p1s_01p09c470102673_cooling_fan_speed + internal: true +- platform: homeassistant + id: polly_pocket_progress + entity_id: sensor.a1mini_0309ca580403653_print_progress + internal: true +- platform: homeassistant + id: polly_pocket_nozzle + entity_id: sensor.a1mini_0309ca580403653_nozzle_temperature + internal: true +- platform: homeassistant + id: polly_pocket_nozzle_target + entity_id: sensor.a1mini_0309ca580403653_nozzle_target_temperature + internal: true +- platform: homeassistant + id: polly_pocket_bed + entity_id: sensor.a1mini_0309ca580403653_bed_temperature + internal: true +- platform: homeassistant + id: polly_pocket_bed_target + entity_id: sensor.a1mini_0309ca580403653_bed_target_temperature + internal: true +- platform: homeassistant + id: polly_pocket_time_left + entity_id: sensor.a1mini_0309ca580403653_remaining_time + internal: true +- platform: homeassistant + id: polly_pocket_layer + entity_id: sensor.a1mini_0309ca580403653_current_layer + internal: true +- platform: homeassistant + id: polly_pocket_total_layers + entity_id: sensor.a1mini_0309ca580403653_total_layer_count + internal: true +- platform: homeassistant + id: polly_pocket_fan + entity_id: sensor.a1mini_0309ca580403653_cooling_fan_speed + internal: true +- platform: homeassistant + id: ds_turd_flinger_progress + entity_id: sensor.a1_03919d540806387_print_progress + internal: true +- platform: homeassistant + id: ds_turd_flinger_nozzle + entity_id: sensor.a1_03919d540806387_nozzle_temperature + internal: true +- platform: homeassistant + id: ds_turd_flinger_nozzle_target + entity_id: sensor.a1_03919d540806387_nozzle_target_temperature + internal: true +- platform: homeassistant + id: ds_turd_flinger_bed + entity_id: sensor.a1_03919d540806387_bed_temperature + internal: true +- platform: homeassistant + id: ds_turd_flinger_bed_target + entity_id: sensor.a1_03919d540806387_bed_target_temperature + internal: true +- platform: homeassistant + id: ds_turd_flinger_time_left + entity_id: sensor.a1_03919d540806387_remaining_time + internal: true +- platform: homeassistant + id: ds_turd_flinger_layer + entity_id: sensor.a1_03919d540806387_current_layer + internal: true +- platform: homeassistant + id: ds_turd_flinger_total_layers + entity_id: sensor.a1_03919d540806387_total_layer_count + internal: true +- platform: homeassistant + id: ds_turd_flinger_fan + entity_id: sensor.a1_03919d540806387_cooling_fan_speed + internal: true +- platform: homeassistant + id: jordyns_layer_slayer_progress + entity_id: sensor.jordyns_layer_slayer_print_progress + internal: true +- platform: homeassistant + id: jordyns_layer_slayer_nozzle + entity_id: sensor.jordyns_layer_slayer_nozzle_temperature + internal: true +- platform: homeassistant + id: jordyns_layer_slayer_nozzle_target + entity_id: sensor.jordyns_layer_slayer_nozzle_target_temperature + internal: true +- platform: homeassistant + id: jordyns_layer_slayer_bed + entity_id: sensor.jordyns_layer_slayer_bed_temperature + internal: true +- platform: homeassistant + id: jordyns_layer_slayer_bed_target + entity_id: sensor.jordyns_layer_slayer_bed_target_temperature + internal: true +- platform: homeassistant + id: jordyns_layer_slayer_time_left + entity_id: sensor.jordyns_layer_slayer_remaining_time + internal: true +- platform: homeassistant + id: jordyns_layer_slayer_layer + entity_id: sensor.jordyns_layer_slayer_current_layer + internal: true +- platform: homeassistant + id: jordyns_layer_slayer_total_layers + entity_id: sensor.jordyns_layer_slayer_total_layer_count + internal: true +- platform: homeassistant + id: jordyns_layer_slayer_fan + entity_id: sensor.jordyns_layer_slayer_cooling_fan_speed + internal: true +- platform: homeassistant + id: constipation_orion_progress + entity_id: sensor.constipation_orion_print_progress + internal: true +- platform: homeassistant + id: constipation_orion_nozzle + entity_id: sensor.constipation_orion_nozzle_temperature + internal: true +- platform: homeassistant + id: constipation_orion_nozzle_target + entity_id: sensor.constipation_orion_nozzle_target_temperature + internal: true +- platform: homeassistant + id: constipation_orion_bed + entity_id: sensor.constipation_orion_bed_temperature + internal: true +- platform: homeassistant + id: constipation_orion_bed_target + entity_id: sensor.constipation_orion_bed_target_temperature + internal: true +- platform: homeassistant + id: constipation_orion_time_left + entity_id: sensor.constipation_orion_remaining_time + internal: true +- platform: homeassistant + id: constipation_orion_layer + entity_id: sensor.constipation_orion_current_layer + internal: true +- platform: homeassistant + id: constipation_orion_total_layers + entity_id: sensor.constipation_orion_total_layer_count + internal: true +- platform: homeassistant + id: constipation_orion_fan + entity_id: sensor.constipation_orion_cooling_fan_speed + internal: true +- platform: homeassistant + id: constipation_orion_left_nozzle + entity_id: sensor.constipation_orion_left_nozzle_temperature + internal: true +- platform: homeassistant + id: constipation_orion_left_target + entity_id: sensor.constipation_orion_left_nozzle_target_temperature + internal: true +- platform: homeassistant + id: constipation_orion_right_nozzle + entity_id: sensor.constipation_orion_right_nozzle_temperature + internal: true +- platform: homeassistant + id: constipation_orion_right_target + entity_id: sensor.constipation_orion_right_nozzle_target_temperature + internal: true +text_sensor: +- platform: homeassistant + id: prints_charming_status + entity_id: sensor.p1s_01p09c470102673_print_status + internal: true +- platform: homeassistant + id: prints_charming_task + entity_id: sensor.p1s_01p09c470102673_task_name + internal: true +- platform: homeassistant + id: prints_charming_stage + entity_id: sensor.p1s_01p09c470102673_current_stage + internal: true +- platform: homeassistant + id: prints_charming_online + entity_id: binary_sensor.p1s_01p09c470102673_online + internal: true +- platform: homeassistant + id: prints_charming_print_error + entity_id: binary_sensor.p1s_01p09c470102673_print_error + internal: true +- platform: homeassistant + id: prints_charming_hms_error + entity_id: binary_sensor.p1s_01p09c470102673_hms_errors + internal: true +- platform: homeassistant + id: prints_charming_remaining_unit + entity_id: sensor.p1s_01p09c470102673_remaining_time + internal: true + attribute: unit_of_measurement +- platform: homeassistant + id: prints_charming_nozzle_unit + entity_id: sensor.p1s_01p09c470102673_nozzle_temperature + internal: true + attribute: unit_of_measurement +- platform: homeassistant + id: prints_charming_bed_unit + entity_id: sensor.p1s_01p09c470102673_bed_temperature + internal: true + attribute: unit_of_measurement +- platform: homeassistant + id: prints_charming_tray_0_type + entity_id: sensor.p1s_01p09c470102673_ams_1_tray_1 + internal: true + attribute: type +- platform: homeassistant + id: prints_charming_tray_0_color + entity_id: sensor.p1s_01p09c470102673_ams_1_tray_1 + internal: true + attribute: color +- platform: homeassistant + id: prints_charming_tray_0_active + entity_id: sensor.p1s_01p09c470102673_ams_1_tray_1 + internal: true + attribute: active +- platform: homeassistant + id: prints_charming_tray_1_type + entity_id: sensor.p1s_01p09c470102673_ams_1_tray_2 + internal: true + attribute: type +- platform: homeassistant + id: prints_charming_tray_1_color + entity_id: sensor.p1s_01p09c470102673_ams_1_tray_2 + internal: true + attribute: color +- platform: homeassistant + id: prints_charming_tray_1_active + entity_id: sensor.p1s_01p09c470102673_ams_1_tray_2 + internal: true + attribute: active +- platform: homeassistant + id: prints_charming_tray_2_type + entity_id: sensor.p1s_01p09c470102673_ams_1_tray_3 + internal: true + attribute: type +- platform: homeassistant + id: prints_charming_tray_2_color + entity_id: sensor.p1s_01p09c470102673_ams_1_tray_3 + internal: true + attribute: color +- platform: homeassistant + id: prints_charming_tray_2_active + entity_id: sensor.p1s_01p09c470102673_ams_1_tray_3 + internal: true + attribute: active +- platform: homeassistant + id: prints_charming_tray_3_type + entity_id: sensor.p1s_01p09c470102673_ams_1_tray_4 + internal: true + attribute: type +- platform: homeassistant + id: prints_charming_tray_3_color + entity_id: sensor.p1s_01p09c470102673_ams_1_tray_4 + internal: true + attribute: color +- platform: homeassistant + id: prints_charming_tray_3_active + entity_id: sensor.p1s_01p09c470102673_ams_1_tray_4 + internal: true + attribute: active +- platform: homeassistant + id: prints_charming_tray_4_type + entity_id: sensor.p1s_01p09c470102673_ams_2_tray_1 + internal: true + attribute: type +- platform: homeassistant + id: prints_charming_tray_4_color + entity_id: sensor.p1s_01p09c470102673_ams_2_tray_1 + internal: true + attribute: color +- platform: homeassistant + id: prints_charming_tray_4_active + entity_id: sensor.p1s_01p09c470102673_ams_2_tray_1 + internal: true + attribute: active +- platform: homeassistant + id: prints_charming_tray_5_type + entity_id: sensor.p1s_01p09c470102673_ams_2_tray_2 + internal: true + attribute: type +- platform: homeassistant + id: prints_charming_tray_5_color + entity_id: sensor.p1s_01p09c470102673_ams_2_tray_2 + internal: true + attribute: color +- platform: homeassistant + id: prints_charming_tray_5_active + entity_id: sensor.p1s_01p09c470102673_ams_2_tray_2 + internal: true + attribute: active +- platform: homeassistant + id: prints_charming_tray_6_type + entity_id: sensor.p1s_01p09c470102673_ams_2_tray_3 + internal: true + attribute: type +- platform: homeassistant + id: prints_charming_tray_6_color + entity_id: sensor.p1s_01p09c470102673_ams_2_tray_3 + internal: true + attribute: color +- platform: homeassistant + id: prints_charming_tray_6_active + entity_id: sensor.p1s_01p09c470102673_ams_2_tray_3 + internal: true + attribute: active +- platform: homeassistant + id: prints_charming_tray_7_type + entity_id: sensor.p1s_01p09c470102673_ams_2_tray_4 + internal: true + attribute: type +- platform: homeassistant + id: prints_charming_tray_7_color + entity_id: sensor.p1s_01p09c470102673_ams_2_tray_4 + internal: true + attribute: color +- platform: homeassistant + id: prints_charming_tray_7_active + entity_id: sensor.p1s_01p09c470102673_ams_2_tray_4 + internal: true + attribute: active +- platform: homeassistant + id: polly_pocket_status + entity_id: sensor.a1mini_0309ca580403653_print_status + internal: true +- platform: homeassistant + id: polly_pocket_task + entity_id: sensor.a1mini_0309ca580403653_task_name + internal: true +- platform: homeassistant + id: polly_pocket_stage + entity_id: sensor.a1mini_0309ca580403653_current_stage + internal: true +- platform: homeassistant + id: polly_pocket_online + entity_id: binary_sensor.a1mini_0309ca580403653_online + internal: true +- platform: homeassistant + id: polly_pocket_print_error + entity_id: binary_sensor.a1mini_0309ca580403653_print_error + internal: true +- platform: homeassistant + id: polly_pocket_hms_error + entity_id: binary_sensor.a1mini_0309ca580403653_hms_errors + internal: true +- platform: homeassistant + id: polly_pocket_remaining_unit + entity_id: sensor.a1mini_0309ca580403653_remaining_time + internal: true + attribute: unit_of_measurement +- platform: homeassistant + id: polly_pocket_nozzle_unit + entity_id: sensor.a1mini_0309ca580403653_nozzle_temperature + internal: true + attribute: unit_of_measurement +- platform: homeassistant + id: polly_pocket_bed_unit + entity_id: sensor.a1mini_0309ca580403653_bed_temperature + internal: true + attribute: unit_of_measurement +- platform: homeassistant + id: polly_pocket_tray_0_type + entity_id: sensor.a1mini_0309ca580403653_externalspool_external_spool + internal: true + attribute: type +- platform: homeassistant + id: polly_pocket_tray_0_color + entity_id: sensor.a1mini_0309ca580403653_externalspool_external_spool + internal: true + attribute: color +- platform: homeassistant + id: polly_pocket_tray_0_active + entity_id: sensor.a1mini_0309ca580403653_externalspool_external_spool + internal: true + attribute: active +- platform: homeassistant + id: ds_turd_flinger_status + entity_id: sensor.a1_03919d540806387_print_status + internal: true +- platform: homeassistant + id: ds_turd_flinger_task + entity_id: sensor.a1_03919d540806387_task_name + internal: true +- platform: homeassistant + id: ds_turd_flinger_stage + entity_id: sensor.a1_03919d540806387_current_stage + internal: true +- platform: homeassistant + id: ds_turd_flinger_online + entity_id: binary_sensor.a1_03919d540806387_online + internal: true +- platform: homeassistant + id: ds_turd_flinger_print_error + entity_id: binary_sensor.a1_03919d540806387_print_error + internal: true +- platform: homeassistant + id: ds_turd_flinger_hms_error + entity_id: binary_sensor.a1_03919d540806387_hms_errors + internal: true +- platform: homeassistant + id: ds_turd_flinger_remaining_unit + entity_id: sensor.a1_03919d540806387_remaining_time + internal: true + attribute: unit_of_measurement +- platform: homeassistant + id: ds_turd_flinger_nozzle_unit + entity_id: sensor.a1_03919d540806387_nozzle_temperature + internal: true + attribute: unit_of_measurement +- platform: homeassistant + id: ds_turd_flinger_bed_unit + entity_id: sensor.a1_03919d540806387_bed_temperature + internal: true + attribute: unit_of_measurement +- platform: homeassistant + id: ds_turd_flinger_tray_0_type + entity_id: sensor.a1_03919d540806387_ams_1_tray_1 + internal: true + attribute: type +- platform: homeassistant + id: ds_turd_flinger_tray_0_color + entity_id: sensor.a1_03919d540806387_ams_1_tray_1 + internal: true + attribute: color +- platform: homeassistant + id: ds_turd_flinger_tray_0_active + entity_id: sensor.a1_03919d540806387_ams_1_tray_1 + internal: true + attribute: active +- platform: homeassistant + id: ds_turd_flinger_tray_1_type + entity_id: sensor.a1_03919d540806387_ams_1_tray_2 + internal: true + attribute: type +- platform: homeassistant + id: ds_turd_flinger_tray_1_color + entity_id: sensor.a1_03919d540806387_ams_1_tray_2 + internal: true + attribute: color +- platform: homeassistant + id: ds_turd_flinger_tray_1_active + entity_id: sensor.a1_03919d540806387_ams_1_tray_2 + internal: true + attribute: active +- platform: homeassistant + id: ds_turd_flinger_tray_2_type + entity_id: sensor.a1_03919d540806387_ams_1_tray_3 + internal: true + attribute: type +- platform: homeassistant + id: ds_turd_flinger_tray_2_color + entity_id: sensor.a1_03919d540806387_ams_1_tray_3 + internal: true + attribute: color +- platform: homeassistant + id: ds_turd_flinger_tray_2_active + entity_id: sensor.a1_03919d540806387_ams_1_tray_3 + internal: true + attribute: active +- platform: homeassistant + id: ds_turd_flinger_tray_3_type + entity_id: sensor.a1_03919d540806387_ams_1_tray_4 + internal: true + attribute: type +- platform: homeassistant + id: ds_turd_flinger_tray_3_color + entity_id: sensor.a1_03919d540806387_ams_1_tray_4 + internal: true + attribute: color +- platform: homeassistant + id: ds_turd_flinger_tray_3_active + entity_id: sensor.a1_03919d540806387_ams_1_tray_4 + internal: true + attribute: active +- platform: homeassistant + id: jordyns_layer_slayer_status + entity_id: sensor.jordyns_layer_slayer_print_status + internal: true +- platform: homeassistant + id: jordyns_layer_slayer_task + entity_id: sensor.jordyns_layer_slayer_task_name + internal: true +- platform: homeassistant + id: jordyns_layer_slayer_stage + entity_id: sensor.jordyns_layer_slayer_current_stage + internal: true +- platform: homeassistant + id: jordyns_layer_slayer_online + entity_id: binary_sensor.jordyns_layer_slayer_online + internal: true +- platform: homeassistant + id: jordyns_layer_slayer_print_error + entity_id: binary_sensor.jordyns_layer_slayer_print_error + internal: true +- platform: homeassistant + id: jordyns_layer_slayer_hms_error + entity_id: binary_sensor.jordyns_layer_slayer_hms_errors + internal: true +- platform: homeassistant + id: jordyns_layer_slayer_remaining_unit + entity_id: sensor.jordyns_layer_slayer_remaining_time + internal: true + attribute: unit_of_measurement +- platform: homeassistant + id: jordyns_layer_slayer_nozzle_unit + entity_id: sensor.jordyns_layer_slayer_nozzle_temperature + internal: true + attribute: unit_of_measurement +- platform: homeassistant + id: jordyns_layer_slayer_bed_unit + entity_id: sensor.jordyns_layer_slayer_bed_temperature + internal: true + attribute: unit_of_measurement +- platform: homeassistant + id: jordyns_layer_slayer_tray_0_type + entity_id: sensor.jordyns_layer_slayer_ams_tray_1 + internal: true + attribute: type +- platform: homeassistant + id: jordyns_layer_slayer_tray_0_color + entity_id: sensor.jordyns_layer_slayer_ams_tray_1 + internal: true + attribute: color +- platform: homeassistant + id: jordyns_layer_slayer_tray_0_active + entity_id: sensor.jordyns_layer_slayer_ams_tray_1 + internal: true + attribute: active +- platform: homeassistant + id: jordyns_layer_slayer_tray_1_type + entity_id: sensor.jordyns_layer_slayer_ams_tray_2 + internal: true + attribute: type +- platform: homeassistant + id: jordyns_layer_slayer_tray_1_color + entity_id: sensor.jordyns_layer_slayer_ams_tray_2 + internal: true + attribute: color +- platform: homeassistant + id: jordyns_layer_slayer_tray_1_active + entity_id: sensor.jordyns_layer_slayer_ams_tray_2 + internal: true + attribute: active +- platform: homeassistant + id: jordyns_layer_slayer_tray_2_type + entity_id: sensor.jordyns_layer_slayer_ams_tray_3 + internal: true + attribute: type +- platform: homeassistant + id: jordyns_layer_slayer_tray_2_color + entity_id: sensor.jordyns_layer_slayer_ams_tray_3 + internal: true + attribute: color +- platform: homeassistant + id: jordyns_layer_slayer_tray_2_active + entity_id: sensor.jordyns_layer_slayer_ams_tray_3 + internal: true + attribute: active +- platform: homeassistant + id: jordyns_layer_slayer_tray_3_type + entity_id: sensor.jordyns_layer_slayer_ams_tray_4 + internal: true + attribute: type +- platform: homeassistant + id: jordyns_layer_slayer_tray_3_color + entity_id: sensor.jordyns_layer_slayer_ams_tray_4 + internal: true + attribute: color +- platform: homeassistant + id: jordyns_layer_slayer_tray_3_active + entity_id: sensor.jordyns_layer_slayer_ams_tray_4 + internal: true + attribute: active +- platform: homeassistant + id: constipation_orion_status + entity_id: sensor.constipation_orion_print_status + internal: true +- platform: homeassistant + id: constipation_orion_task + entity_id: sensor.constipation_orion_task_name + internal: true +- platform: homeassistant + id: constipation_orion_stage + entity_id: sensor.constipation_orion_current_stage + internal: true +- platform: homeassistant + id: constipation_orion_online + entity_id: binary_sensor.constipation_orion_online + internal: true +- platform: homeassistant + id: constipation_orion_print_error + entity_id: binary_sensor.constipation_orion_print_error + internal: true +- platform: homeassistant + id: constipation_orion_hms_error + entity_id: binary_sensor.constipation_orion_hms_errors + internal: true +- platform: homeassistant + id: constipation_orion_remaining_unit + entity_id: sensor.constipation_orion_remaining_time + internal: true + attribute: unit_of_measurement +- platform: homeassistant + id: constipation_orion_nozzle_unit + entity_id: sensor.constipation_orion_nozzle_temperature + internal: true + attribute: unit_of_measurement +- platform: homeassistant + id: constipation_orion_bed_unit + entity_id: sensor.constipation_orion_bed_temperature + internal: true + attribute: unit_of_measurement +- platform: homeassistant + id: constipation_orion_tray_0_type + entity_id: sensor.constipation_orion_ams_1_tray_1 + internal: true + attribute: type +- platform: homeassistant + id: constipation_orion_tray_0_color + entity_id: sensor.constipation_orion_ams_1_tray_1 + internal: true + attribute: color +- platform: homeassistant + id: constipation_orion_tray_0_active + entity_id: sensor.constipation_orion_ams_1_tray_1 + internal: true + attribute: active +- platform: homeassistant + id: constipation_orion_tray_1_type + entity_id: sensor.constipation_orion_ams_1_tray_2 + internal: true + attribute: type +- platform: homeassistant + id: constipation_orion_tray_1_color + entity_id: sensor.constipation_orion_ams_1_tray_2 + internal: true + attribute: color +- platform: homeassistant + id: constipation_orion_tray_1_active + entity_id: sensor.constipation_orion_ams_1_tray_2 + internal: true + attribute: active +- platform: homeassistant + id: constipation_orion_tray_2_type + entity_id: sensor.constipation_orion_ams_1_tray_3 + internal: true + attribute: type +- platform: homeassistant + id: constipation_orion_tray_2_color + entity_id: sensor.constipation_orion_ams_1_tray_3 + internal: true + attribute: color +- platform: homeassistant + id: constipation_orion_tray_2_active + entity_id: sensor.constipation_orion_ams_1_tray_3 + internal: true + attribute: active +- platform: homeassistant + id: constipation_orion_tray_3_type + entity_id: sensor.constipation_orion_ams_1_tray_4 + internal: true + attribute: type +- platform: homeassistant + id: constipation_orion_tray_3_color + entity_id: sensor.constipation_orion_ams_1_tray_4 + internal: true + attribute: color +- platform: homeassistant + id: constipation_orion_tray_3_active + entity_id: sensor.constipation_orion_ams_1_tray_4 + internal: true + attribute: active +script: +- id: prints_charming_refresh + then: + - lambda: !lambda |- + bambu_display::Snapshot data; + data.connected = id(ha_api).is_connected_with_state_subscription(); + data.progress = id(prints_charming_progress).state; + data.nozzle = id(prints_charming_nozzle).state; + data.nozzle_target = id(prints_charming_nozzle_target).state; + data.bed = id(prints_charming_bed).state; + data.bed_target = id(prints_charming_bed_target).state; + data.time_left = id(prints_charming_time_left).state; + data.layer = id(prints_charming_layer).state; + data.total_layers = id(prints_charming_total_layers).state; + data.fan = id(prints_charming_fan).state; + data.status = id(prints_charming_status).state; + data.task = id(prints_charming_task).state; + data.stage = id(prints_charming_stage).state; + data.online = id(prints_charming_online).state; + data.print_error = id(prints_charming_print_error).state; + data.hms_error = id(prints_charming_hms_error).state; + data.remaining_unit = id(prints_charming_remaining_unit).state; + data.nozzle_unit = id(prints_charming_nozzle_unit).state; + data.bed_unit = id(prints_charming_bed_unit).state; + data.trays.push_back({"A1", id(prints_charming_tray_0_type).state, id(prints_charming_tray_0_color).state, id(prints_charming_tray_0_active).state}); + data.trays.push_back({"A2", id(prints_charming_tray_1_type).state, id(prints_charming_tray_1_color).state, id(prints_charming_tray_1_active).state}); + data.trays.push_back({"A3", id(prints_charming_tray_2_type).state, id(prints_charming_tray_2_color).state, id(prints_charming_tray_2_active).state}); + data.trays.push_back({"A4", id(prints_charming_tray_3_type).state, id(prints_charming_tray_3_color).state, id(prints_charming_tray_3_active).state}); + data.trays.push_back({"B1", id(prints_charming_tray_4_type).state, id(prints_charming_tray_4_color).state, id(prints_charming_tray_4_active).state}); + 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(data, {id(prints_charming_status_label), id(prints_charming_task_label), id(prints_charming_progress_arc), id(prints_charming_progress_label), id(prints_charming_nozzle_label), id(prints_charming_bed_label), id(prints_charming_remaining_label), id(prints_charming_layers_label), id(prints_charming_stage_label), {{id(prints_charming_tray_0_card), id(prints_charming_tray_0_swatch), id(prints_charming_tray_0_label)}, {id(prints_charming_tray_1_card), id(prints_charming_tray_1_swatch), id(prints_charming_tray_1_label)}, {id(prints_charming_tray_2_card), id(prints_charming_tray_2_swatch), id(prints_charming_tray_2_label)}, {id(prints_charming_tray_3_card), id(prints_charming_tray_3_swatch), id(prints_charming_tray_3_label)}, {id(prints_charming_tray_4_card), id(prints_charming_tray_4_swatch), id(prints_charming_tray_4_label)}, {id(prints_charming_tray_5_card), id(prints_charming_tray_5_swatch), id(prints_charming_tray_5_label)}, {id(prints_charming_tray_6_card), id(prints_charming_tray_6_swatch), id(prints_charming_tray_6_label)}, {id(prints_charming_tray_7_card), id(prints_charming_tray_7_swatch), id(prints_charming_tray_7_label)}}}); +- id: polly_pocket_refresh + then: + - lambda: !lambda |- + bambu_display::Snapshot data; + data.connected = id(ha_api).is_connected_with_state_subscription(); + data.progress = id(polly_pocket_progress).state; + data.nozzle = id(polly_pocket_nozzle).state; + data.nozzle_target = id(polly_pocket_nozzle_target).state; + data.bed = id(polly_pocket_bed).state; + data.bed_target = id(polly_pocket_bed_target).state; + data.time_left = id(polly_pocket_time_left).state; + data.layer = id(polly_pocket_layer).state; + data.total_layers = id(polly_pocket_total_layers).state; + data.fan = id(polly_pocket_fan).state; + data.status = id(polly_pocket_status).state; + data.task = id(polly_pocket_task).state; + data.stage = id(polly_pocket_stage).state; + data.online = id(polly_pocket_online).state; + data.print_error = id(polly_pocket_print_error).state; + data.hms_error = id(polly_pocket_hms_error).state; + data.remaining_unit = id(polly_pocket_remaining_unit).state; + data.nozzle_unit = id(polly_pocket_nozzle_unit).state; + data.bed_unit = id(polly_pocket_bed_unit).state; + 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(data, {id(polly_pocket_status_label), id(polly_pocket_task_label), id(polly_pocket_progress_arc), id(polly_pocket_progress_label), id(polly_pocket_nozzle_label), id(polly_pocket_bed_label), id(polly_pocket_remaining_label), id(polly_pocket_layers_label), id(polly_pocket_stage_label), {{id(polly_pocket_tray_0_card), id(polly_pocket_tray_0_swatch), id(polly_pocket_tray_0_label)}}}); +- id: ds_turd_flinger_refresh + then: + - lambda: !lambda |- + bambu_display::Snapshot data; + data.connected = id(ha_api).is_connected_with_state_subscription(); + data.progress = id(ds_turd_flinger_progress).state; + data.nozzle = id(ds_turd_flinger_nozzle).state; + data.nozzle_target = id(ds_turd_flinger_nozzle_target).state; + data.bed = id(ds_turd_flinger_bed).state; + data.bed_target = id(ds_turd_flinger_bed_target).state; + data.time_left = id(ds_turd_flinger_time_left).state; + data.layer = id(ds_turd_flinger_layer).state; + data.total_layers = id(ds_turd_flinger_total_layers).state; + data.fan = id(ds_turd_flinger_fan).state; + data.status = id(ds_turd_flinger_status).state; + data.task = id(ds_turd_flinger_task).state; + data.stage = id(ds_turd_flinger_stage).state; + data.online = id(ds_turd_flinger_online).state; + data.print_error = id(ds_turd_flinger_print_error).state; + data.hms_error = id(ds_turd_flinger_hms_error).state; + data.remaining_unit = id(ds_turd_flinger_remaining_unit).state; + data.nozzle_unit = id(ds_turd_flinger_nozzle_unit).state; + data.bed_unit = id(ds_turd_flinger_bed_unit).state; + data.trays.push_back({"A1", id(ds_turd_flinger_tray_0_type).state, id(ds_turd_flinger_tray_0_color).state, id(ds_turd_flinger_tray_0_active).state}); + 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(data, {id(ds_turd_flinger_status_label), id(ds_turd_flinger_task_label), id(ds_turd_flinger_progress_arc), id(ds_turd_flinger_progress_label), id(ds_turd_flinger_nozzle_label), id(ds_turd_flinger_bed_label), id(ds_turd_flinger_remaining_label), id(ds_turd_flinger_layers_label), id(ds_turd_flinger_stage_label), {{id(ds_turd_flinger_tray_0_card), id(ds_turd_flinger_tray_0_swatch), id(ds_turd_flinger_tray_0_label)}, {id(ds_turd_flinger_tray_1_card), id(ds_turd_flinger_tray_1_swatch), id(ds_turd_flinger_tray_1_label)}, {id(ds_turd_flinger_tray_2_card), id(ds_turd_flinger_tray_2_swatch), id(ds_turd_flinger_tray_2_label)}, {id(ds_turd_flinger_tray_3_card), id(ds_turd_flinger_tray_3_swatch), id(ds_turd_flinger_tray_3_label)}}}); +- id: jordyns_layer_slayer_refresh + then: + - lambda: !lambda |- + bambu_display::Snapshot data; + data.connected = id(ha_api).is_connected_with_state_subscription(); + data.progress = id(jordyns_layer_slayer_progress).state; + data.nozzle = id(jordyns_layer_slayer_nozzle).state; + data.nozzle_target = id(jordyns_layer_slayer_nozzle_target).state; + data.bed = id(jordyns_layer_slayer_bed).state; + data.bed_target = id(jordyns_layer_slayer_bed_target).state; + data.time_left = id(jordyns_layer_slayer_time_left).state; + data.layer = id(jordyns_layer_slayer_layer).state; + data.total_layers = id(jordyns_layer_slayer_total_layers).state; + data.fan = id(jordyns_layer_slayer_fan).state; + data.status = id(jordyns_layer_slayer_status).state; + data.task = id(jordyns_layer_slayer_task).state; + data.stage = id(jordyns_layer_slayer_stage).state; + data.online = id(jordyns_layer_slayer_online).state; + data.print_error = id(jordyns_layer_slayer_print_error).state; + data.hms_error = id(jordyns_layer_slayer_hms_error).state; + data.remaining_unit = id(jordyns_layer_slayer_remaining_unit).state; + data.nozzle_unit = id(jordyns_layer_slayer_nozzle_unit).state; + data.bed_unit = id(jordyns_layer_slayer_bed_unit).state; + data.trays.push_back({"A1", id(jordyns_layer_slayer_tray_0_type).state, id(jordyns_layer_slayer_tray_0_color).state, id(jordyns_layer_slayer_tray_0_active).state}); + 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(data, {id(jordyns_layer_slayer_status_label), id(jordyns_layer_slayer_task_label), id(jordyns_layer_slayer_progress_arc), id(jordyns_layer_slayer_progress_label), id(jordyns_layer_slayer_nozzle_label), id(jordyns_layer_slayer_bed_label), id(jordyns_layer_slayer_remaining_label), id(jordyns_layer_slayer_layers_label), id(jordyns_layer_slayer_stage_label), {{id(jordyns_layer_slayer_tray_0_card), id(jordyns_layer_slayer_tray_0_swatch), id(jordyns_layer_slayer_tray_0_label)}, {id(jordyns_layer_slayer_tray_1_card), id(jordyns_layer_slayer_tray_1_swatch), id(jordyns_layer_slayer_tray_1_label)}, {id(jordyns_layer_slayer_tray_2_card), id(jordyns_layer_slayer_tray_2_swatch), id(jordyns_layer_slayer_tray_2_label)}, {id(jordyns_layer_slayer_tray_3_card), id(jordyns_layer_slayer_tray_3_swatch), id(jordyns_layer_slayer_tray_3_label)}}}); +- id: constipation_orion_refresh + then: + - lambda: !lambda |- + bambu_display::Snapshot data; + data.connected = id(ha_api).is_connected_with_state_subscription(); + data.progress = id(constipation_orion_progress).state; + data.nozzle = id(constipation_orion_nozzle).state; + data.nozzle_target = id(constipation_orion_nozzle_target).state; + data.bed = id(constipation_orion_bed).state; + data.bed_target = id(constipation_orion_bed_target).state; + data.time_left = id(constipation_orion_time_left).state; + data.layer = id(constipation_orion_layer).state; + data.total_layers = id(constipation_orion_total_layers).state; + data.fan = id(constipation_orion_fan).state; + data.left_nozzle = id(constipation_orion_left_nozzle).state; + data.left_target = id(constipation_orion_left_target).state; + data.right_nozzle = id(constipation_orion_right_nozzle).state; + data.right_target = id(constipation_orion_right_target).state; + data.status = id(constipation_orion_status).state; + data.task = id(constipation_orion_task).state; + data.stage = id(constipation_orion_stage).state; + data.online = id(constipation_orion_online).state; + data.print_error = id(constipation_orion_print_error).state; + data.hms_error = id(constipation_orion_hms_error).state; + data.remaining_unit = id(constipation_orion_remaining_unit).state; + data.nozzle_unit = id(constipation_orion_nozzle_unit).state; + data.bed_unit = id(constipation_orion_bed_unit).state; + data.dual_nozzle = true; + data.trays.push_back({"A1", id(constipation_orion_tray_0_type).state, id(constipation_orion_tray_0_color).state, id(constipation_orion_tray_0_active).state}); + data.trays.push_back({"A2", id(constipation_orion_tray_1_type).state, id(constipation_orion_tray_1_color).state, id(constipation_orion_tray_1_active).state}); + data.trays.push_back({"A3", id(constipation_orion_tray_2_type).state, id(constipation_orion_tray_2_color).state, id(constipation_orion_tray_2_active).state}); + data.trays.push_back({"A4", id(constipation_orion_tray_3_type).state, id(constipation_orion_tray_3_color).state, id(constipation_orion_tray_3_active).state}); + bambu_display::render(data, {id(constipation_orion_status_label), id(constipation_orion_task_label), id(constipation_orion_progress_arc), id(constipation_orion_progress_label), id(constipation_orion_nozzle_label), id(constipation_orion_bed_label), id(constipation_orion_remaining_label), id(constipation_orion_layers_label), id(constipation_orion_stage_label), {{id(constipation_orion_tray_0_card), id(constipation_orion_tray_0_swatch), id(constipation_orion_tray_0_label)}, {id(constipation_orion_tray_1_card), id(constipation_orion_tray_1_swatch), id(constipation_orion_tray_1_label)}, {id(constipation_orion_tray_2_card), id(constipation_orion_tray_2_swatch), id(constipation_orion_tray_2_label)}, {id(constipation_orion_tray_3_card), id(constipation_orion_tray_3_swatch), id(constipation_orion_tray_3_label)}}}); +interval: +- interval: 1s + then: + - if: + condition: + lvgl.page.is_showing: prints_charming_page + then: + - script.execute: prints_charming_refresh + - if: + condition: + lvgl.page.is_showing: polly_pocket_page + then: + - script.execute: polly_pocket_refresh + - if: + condition: + lvgl.page.is_showing: ds_turd_flinger_page + then: + - script.execute: ds_turd_flinger_refresh + - if: + condition: + lvgl.page.is_showing: jordyns_layer_slayer_page + then: + - script.execute: jordyns_layer_slayer_refresh + - if: + condition: + lvgl.page.is_showing: constipation_orion_page + then: + - script.execute: constipation_orion_refresh +lvgl: + pages: + - id: prints_charming_page + bg_color: 856859 + bg_opa: COVER + pad_all: 0 + scrollable: false + scrollbar_mode: 'OFF' + on_swipe_left: + - lambda: !lambda |- + if (auto *input = lv_indev_active()) lv_indev_wait_release(input); + - lvgl.page.next: + animation: MOVE_LEFT + time: 180ms + on_swipe_right: + - lambda: !lambda |- + if (auto *input = lv_indev_active()) lv_indev_wait_release(input); + - lvgl.page.previous: + animation: MOVE_RIGHT + time: 180ms + on_load: + - script.execute: prints_charming_refresh + widgets: + - label: + text: PrintsCharming + x: 24 + y: 16 + width: 545 + height: 36 + text_color: 15594487 + text_font: montserrat_28 + long_mode: DOT + gesture_bubble: true + - label: + text: P1S / Office + x: 24 + y: 53 + width: 545 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - obj: + x: 586 + y: 20 + width: 190 + height: 42 + bg_color: 1516078 + radius: 21 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: SYNCING + x: 0 + y: 11 + width: 190 + height: 24 + text_color: 9544629 + text_font: montserrat_16 + long_mode: DOT + gesture_bubble: true + id: prints_charming_status_label + text_align: CENTER + - label: + text: Waiting for Home Assistant + x: 24 + y: 88 + width: 752 + height: 28 + text_color: 15594487 + text_font: montserrat_20 + long_mode: DOT + gesture_bubble: true + id: prints_charming_task_label + - arc: + id: prints_charming_progress_arc + x: 28 + y: 132 + width: 224 + height: 224 + min_value: 0 + max_value: 100 + value: 0 + start_angle: 135 + end_angle: 45 + arc_width: 14 + arc_color: 2503746 + indicator: + arc_color: 6348442 + arc_width: 14 + adjustable: false + gesture_bubble: true + - label: + text: -- + x: 42 + y: 207 + width: 196 + height: 56 + text_color: 15594487 + text_font: montserrat_48 + long_mode: DOT + gesture_bubble: true + id: prints_charming_progress_label + text_align: CENTER + - label: + text: PRINT PROGRESS + x: 42 + y: 266 + width: 196 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + text_align: CENTER + - obj: + x: 282 + y: 132 + width: 238 + height: 118 + bg_color: 1516078 + radius: 16 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: NOZZLE / TARGET + x: 16 + y: 12 + width: 206 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - label: + text: -- + x: 16 + y: 38 + width: 206 + height: 76 + text_color: 15594487 + text_font: montserrat_26 + long_mode: DOT + gesture_bubble: true + id: prints_charming_nozzle_label + - obj: + x: 538 + y: 132 + width: 238 + height: 118 + bg_color: 1516078 + radius: 16 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: BED / TARGET + x: 16 + y: 12 + width: 206 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - label: + text: -- + x: 16 + y: 38 + width: 206 + height: 76 + text_color: 15594487 + text_font: montserrat_26 + long_mode: DOT + gesture_bubble: true + id: prints_charming_bed_label + - obj: + x: 282 + y: 262 + width: 238 + height: 86 + bg_color: 1516078 + radius: 16 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: REMAINING + x: 16 + y: 12 + width: 206 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - label: + text: -- + x: 16 + y: 38 + width: 206 + height: 44 + text_color: 15594487 + text_font: montserrat_26 + long_mode: DOT + gesture_bubble: true + id: prints_charming_remaining_label + - obj: + x: 538 + y: 262 + width: 238 + height: 86 + bg_color: 1516078 + radius: 16 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: LAYER + x: 16 + y: 12 + width: 206 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - label: + text: -- + x: 16 + y: 38 + width: 206 + height: 44 + text_color: 15594487 + text_font: montserrat_26 + long_mode: DOT + gesture_bubble: true + id: prints_charming_layers_label + - label: + text: Telemetry unavailable + x: 24 + y: 358 + width: 752 + height: 24 + text_color: 9544629 + text_font: montserrat_16 + long_mode: DOT + gesture_bubble: true + id: prints_charming_stage_label + - label: + text: FILAMENT / ACTIVE SLOT OUTLINED IN GREEN + x: 24 + y: 383 + width: 752 + height: 20 + text_color: 9544629 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + - obj: + id: prints_charming_tray_0_card + x: 24 + y: 401 + width: 87 + height: 32 + bg_color: 1516078 + radius: 6 + border_width: 1 + border_color: 2503746 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - obj: + id: prints_charming_tray_0_swatch + x: 1 + y: 1 + width: 83 + height: 5 + bg_color: 2503746 + radius: 2 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + - label: + text: A1 -- + x: 6 + y: 11 + width: 75 + height: 20 + text_color: 15594487 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + id: prints_charming_tray_0_label + - obj: + id: prints_charming_tray_1_card + x: 119 + y: 401 + width: 87 + height: 32 + bg_color: 1516078 + radius: 6 + border_width: 1 + border_color: 2503746 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - obj: + id: prints_charming_tray_1_swatch + x: 1 + y: 1 + width: 83 + height: 5 + bg_color: 2503746 + radius: 2 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + - label: + text: A2 -- + x: 6 + y: 11 + width: 75 + height: 20 + text_color: 15594487 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + id: prints_charming_tray_1_label + - obj: + id: prints_charming_tray_2_card + x: 214 + y: 401 + width: 87 + height: 32 + bg_color: 1516078 + radius: 6 + border_width: 1 + border_color: 2503746 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - obj: + id: prints_charming_tray_2_swatch + x: 1 + y: 1 + width: 83 + height: 5 + bg_color: 2503746 + radius: 2 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + - label: + text: A3 -- + x: 6 + y: 11 + width: 75 + height: 20 + text_color: 15594487 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + id: prints_charming_tray_2_label + - obj: + id: prints_charming_tray_3_card + x: 309 + y: 401 + width: 87 + height: 32 + bg_color: 1516078 + radius: 6 + border_width: 1 + border_color: 2503746 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - obj: + id: prints_charming_tray_3_swatch + x: 1 + y: 1 + width: 83 + height: 5 + bg_color: 2503746 + radius: 2 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + - label: + text: A4 -- + x: 6 + y: 11 + width: 75 + height: 20 + text_color: 15594487 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + id: prints_charming_tray_3_label + - obj: + id: prints_charming_tray_4_card + x: 404 + y: 401 + width: 87 + height: 32 + bg_color: 1516078 + radius: 6 + border_width: 1 + border_color: 2503746 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - obj: + id: prints_charming_tray_4_swatch + x: 1 + y: 1 + width: 83 + height: 5 + bg_color: 2503746 + radius: 2 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + - label: + text: B1 -- + x: 6 + y: 11 + width: 75 + height: 20 + text_color: 15594487 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + id: prints_charming_tray_4_label + - obj: + id: prints_charming_tray_5_card + x: 499 + y: 401 + width: 87 + height: 32 + bg_color: 1516078 + radius: 6 + border_width: 1 + border_color: 2503746 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - obj: + id: prints_charming_tray_5_swatch + x: 1 + y: 1 + width: 83 + height: 5 + bg_color: 2503746 + radius: 2 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + - label: + text: B2 -- + x: 6 + y: 11 + width: 75 + height: 20 + text_color: 15594487 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + id: prints_charming_tray_5_label + - obj: + id: prints_charming_tray_6_card + x: 594 + y: 401 + width: 87 + height: 32 + bg_color: 1516078 + radius: 6 + border_width: 1 + border_color: 2503746 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - obj: + id: prints_charming_tray_6_swatch + x: 1 + y: 1 + width: 83 + height: 5 + bg_color: 2503746 + radius: 2 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + - label: + text: B3 -- + x: 6 + y: 11 + width: 75 + height: 20 + text_color: 15594487 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + id: prints_charming_tray_6_label + - obj: + id: prints_charming_tray_7_card + x: 689 + y: 401 + width: 87 + height: 32 + bg_color: 1516078 + radius: 6 + border_width: 1 + border_color: 2503746 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - obj: + id: prints_charming_tray_7_swatch + x: 1 + y: 1 + width: 83 + height: 5 + bg_color: 2503746 + radius: 2 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + - label: + text: B4 -- + x: 6 + y: 11 + width: 75 + height: 20 + text_color: 15594487 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + id: prints_charming_tray_7_label + - button: + x: 24 + y: 444 + width: 88 + height: 30 + bg_color: 1516078 + radius: 8 + border_width: 0 + pad_all: 0 + gesture_bubble: true + widgets: + - label: + text: < PREV + align: CENTER + text_font: montserrat_12 + on_click: + - lvgl.page.previous: {} + - button: + x: 688 + y: 444 + width: 88 + height: 30 + bg_color: 1516078 + radius: 8 + border_width: 0 + pad_all: 0 + gesture_bubble: true + widgets: + - label: + text: NEXT > + align: CENTER + text_font: montserrat_12 + on_click: + - lvgl.page.next: {} + - label: + text: 1 / 5 SWIPE LEFT / RIGHT + x: 130 + y: 451 + width: 540 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + text_align: CENTER + - id: polly_pocket_page + bg_color: 856859 + bg_opa: COVER + pad_all: 0 + scrollable: false + scrollbar_mode: 'OFF' + on_swipe_left: + - lambda: !lambda |- + if (auto *input = lv_indev_active()) lv_indev_wait_release(input); + - lvgl.page.next: + animation: MOVE_LEFT + time: 180ms + on_swipe_right: + - lambda: !lambda |- + if (auto *input = lv_indev_active()) lv_indev_wait_release(input); + - lvgl.page.previous: + animation: MOVE_RIGHT + time: 180ms + on_load: + - script.execute: polly_pocket_refresh + widgets: + - label: + text: Polly-Pocket + x: 24 + y: 16 + width: 545 + height: 36 + text_color: 15594487 + text_font: montserrat_28 + long_mode: DOT + gesture_bubble: true + - label: + text: A1 mini / Office + x: 24 + y: 53 + width: 545 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - obj: + x: 586 + y: 20 + width: 190 + height: 42 + bg_color: 1516078 + radius: 21 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: SYNCING + x: 0 + y: 11 + width: 190 + height: 24 + text_color: 9544629 + text_font: montserrat_16 + long_mode: DOT + gesture_bubble: true + id: polly_pocket_status_label + text_align: CENTER + - label: + text: Waiting for Home Assistant + x: 24 + y: 88 + width: 752 + height: 28 + text_color: 15594487 + text_font: montserrat_20 + long_mode: DOT + gesture_bubble: true + id: polly_pocket_task_label + - arc: + id: polly_pocket_progress_arc + x: 28 + y: 132 + width: 224 + height: 224 + min_value: 0 + max_value: 100 + value: 0 + start_angle: 135 + end_angle: 45 + arc_width: 14 + arc_color: 2503746 + indicator: + arc_color: 6348442 + arc_width: 14 + adjustable: false + gesture_bubble: true + - label: + text: -- + x: 42 + y: 207 + width: 196 + height: 56 + text_color: 15594487 + text_font: montserrat_48 + long_mode: DOT + gesture_bubble: true + id: polly_pocket_progress_label + text_align: CENTER + - label: + text: PRINT PROGRESS + x: 42 + y: 266 + width: 196 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + text_align: CENTER + - obj: + x: 282 + y: 132 + width: 238 + height: 118 + bg_color: 1516078 + radius: 16 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: NOZZLE / TARGET + x: 16 + y: 12 + width: 206 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - label: + text: -- + x: 16 + y: 38 + width: 206 + height: 76 + text_color: 15594487 + text_font: montserrat_26 + long_mode: DOT + gesture_bubble: true + id: polly_pocket_nozzle_label + - obj: + x: 538 + y: 132 + width: 238 + height: 118 + bg_color: 1516078 + radius: 16 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: BED / TARGET + x: 16 + y: 12 + width: 206 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - label: + text: -- + x: 16 + y: 38 + width: 206 + height: 76 + text_color: 15594487 + text_font: montserrat_26 + long_mode: DOT + gesture_bubble: true + id: polly_pocket_bed_label + - obj: + x: 282 + y: 262 + width: 238 + height: 86 + bg_color: 1516078 + radius: 16 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: REMAINING + x: 16 + y: 12 + width: 206 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - label: + text: -- + x: 16 + y: 38 + width: 206 + height: 44 + text_color: 15594487 + text_font: montserrat_26 + long_mode: DOT + gesture_bubble: true + id: polly_pocket_remaining_label + - obj: + x: 538 + y: 262 + width: 238 + height: 86 + bg_color: 1516078 + radius: 16 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: LAYER + x: 16 + y: 12 + width: 206 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - label: + text: -- + x: 16 + y: 38 + width: 206 + height: 44 + text_color: 15594487 + text_font: montserrat_26 + long_mode: DOT + gesture_bubble: true + id: polly_pocket_layers_label + - label: + text: Telemetry unavailable + x: 24 + y: 358 + width: 752 + height: 24 + text_color: 9544629 + text_font: montserrat_16 + long_mode: DOT + gesture_bubble: true + id: polly_pocket_stage_label + - label: + text: FILAMENT / ACTIVE SLOT OUTLINED IN GREEN + x: 24 + y: 383 + width: 752 + height: 20 + text_color: 9544629 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + - obj: + id: polly_pocket_tray_0_card + x: 24 + y: 401 + width: 752 + height: 32 + bg_color: 1516078 + radius: 6 + border_width: 1 + border_color: 2503746 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - obj: + id: polly_pocket_tray_0_swatch + x: 1 + y: 1 + width: 748 + height: 5 + bg_color: 2503746 + radius: 2 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + - label: + text: EXT -- + x: 6 + y: 11 + width: 740 + height: 20 + text_color: 15594487 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + id: polly_pocket_tray_0_label + - button: + x: 24 + y: 444 + width: 88 + height: 30 + bg_color: 1516078 + radius: 8 + border_width: 0 + pad_all: 0 + gesture_bubble: true + widgets: + - label: + text: < PREV + align: CENTER + text_font: montserrat_12 + on_click: + - lvgl.page.previous: {} + - button: + x: 688 + y: 444 + width: 88 + height: 30 + bg_color: 1516078 + radius: 8 + border_width: 0 + pad_all: 0 + gesture_bubble: true + widgets: + - label: + text: NEXT > + align: CENTER + text_font: montserrat_12 + on_click: + - lvgl.page.next: {} + - label: + text: 2 / 5 SWIPE LEFT / RIGHT + x: 130 + y: 451 + width: 540 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + text_align: CENTER + - id: ds_turd_flinger_page + bg_color: 856859 + bg_opa: COVER + pad_all: 0 + scrollable: false + scrollbar_mode: 'OFF' + on_swipe_left: + - lambda: !lambda |- + if (auto *input = lv_indev_active()) lv_indev_wait_release(input); + - lvgl.page.next: + animation: MOVE_LEFT + time: 180ms + on_swipe_right: + - lambda: !lambda |- + if (auto *input = lv_indev_active()) lv_indev_wait_release(input); + - lvgl.page.previous: + animation: MOVE_RIGHT + time: 180ms + on_load: + - script.execute: ds_turd_flinger_refresh + widgets: + - label: + text: Ds-Turd-Flinger + x: 24 + y: 16 + width: 545 + height: 36 + text_color: 15594487 + text_font: montserrat_28 + long_mode: DOT + gesture_bubble: true + - label: + text: A1 / Upstairs + x: 24 + y: 53 + width: 545 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - obj: + x: 586 + y: 20 + width: 190 + height: 42 + bg_color: 1516078 + radius: 21 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: SYNCING + x: 0 + y: 11 + width: 190 + height: 24 + text_color: 9544629 + text_font: montserrat_16 + long_mode: DOT + gesture_bubble: true + id: ds_turd_flinger_status_label + text_align: CENTER + - label: + text: Waiting for Home Assistant + x: 24 + y: 88 + width: 752 + height: 28 + text_color: 15594487 + text_font: montserrat_20 + long_mode: DOT + gesture_bubble: true + id: ds_turd_flinger_task_label + - arc: + id: ds_turd_flinger_progress_arc + x: 28 + y: 132 + width: 224 + height: 224 + min_value: 0 + max_value: 100 + value: 0 + start_angle: 135 + end_angle: 45 + arc_width: 14 + arc_color: 2503746 + indicator: + arc_color: 6348442 + arc_width: 14 + adjustable: false + gesture_bubble: true + - label: + text: -- + x: 42 + y: 207 + width: 196 + height: 56 + text_color: 15594487 + text_font: montserrat_48 + long_mode: DOT + gesture_bubble: true + id: ds_turd_flinger_progress_label + text_align: CENTER + - label: + text: PRINT PROGRESS + x: 42 + y: 266 + width: 196 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + text_align: CENTER + - obj: + x: 282 + y: 132 + width: 238 + height: 118 + bg_color: 1516078 + radius: 16 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: NOZZLE / TARGET + x: 16 + y: 12 + width: 206 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - label: + text: -- + x: 16 + y: 38 + width: 206 + height: 76 + text_color: 15594487 + text_font: montserrat_26 + long_mode: DOT + gesture_bubble: true + id: ds_turd_flinger_nozzle_label + - obj: + x: 538 + y: 132 + width: 238 + height: 118 + bg_color: 1516078 + radius: 16 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: BED / TARGET + x: 16 + y: 12 + width: 206 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - label: + text: -- + x: 16 + y: 38 + width: 206 + height: 76 + text_color: 15594487 + text_font: montserrat_26 + long_mode: DOT + gesture_bubble: true + id: ds_turd_flinger_bed_label + - obj: + x: 282 + y: 262 + width: 238 + height: 86 + bg_color: 1516078 + radius: 16 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: REMAINING + x: 16 + y: 12 + width: 206 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - label: + text: -- + x: 16 + y: 38 + width: 206 + height: 44 + text_color: 15594487 + text_font: montserrat_26 + long_mode: DOT + gesture_bubble: true + id: ds_turd_flinger_remaining_label + - obj: + x: 538 + y: 262 + width: 238 + height: 86 + bg_color: 1516078 + radius: 16 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: LAYER + x: 16 + y: 12 + width: 206 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - label: + text: -- + x: 16 + y: 38 + width: 206 + height: 44 + text_color: 15594487 + text_font: montserrat_26 + long_mode: DOT + gesture_bubble: true + id: ds_turd_flinger_layers_label + - label: + text: Telemetry unavailable + x: 24 + y: 358 + width: 752 + height: 24 + text_color: 9544629 + text_font: montserrat_16 + long_mode: DOT + gesture_bubble: true + id: ds_turd_flinger_stage_label + - label: + text: FILAMENT / ACTIVE SLOT OUTLINED IN GREEN + x: 24 + y: 383 + width: 752 + height: 20 + text_color: 9544629 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + - obj: + id: ds_turd_flinger_tray_0_card + x: 24 + y: 401 + width: 182 + height: 32 + bg_color: 1516078 + radius: 6 + border_width: 1 + border_color: 2503746 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - obj: + id: ds_turd_flinger_tray_0_swatch + x: 1 + y: 1 + width: 178 + height: 5 + bg_color: 2503746 + radius: 2 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + - label: + text: A1 -- + x: 6 + y: 11 + width: 170 + height: 20 + text_color: 15594487 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + id: ds_turd_flinger_tray_0_label + - obj: + id: ds_turd_flinger_tray_1_card + x: 214 + y: 401 + width: 182 + height: 32 + bg_color: 1516078 + radius: 6 + border_width: 1 + border_color: 2503746 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - obj: + id: ds_turd_flinger_tray_1_swatch + x: 1 + y: 1 + width: 178 + height: 5 + bg_color: 2503746 + radius: 2 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + - label: + text: A2 -- + x: 6 + y: 11 + width: 170 + height: 20 + text_color: 15594487 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + id: ds_turd_flinger_tray_1_label + - obj: + id: ds_turd_flinger_tray_2_card + x: 404 + y: 401 + width: 182 + height: 32 + bg_color: 1516078 + radius: 6 + border_width: 1 + border_color: 2503746 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - obj: + id: ds_turd_flinger_tray_2_swatch + x: 1 + y: 1 + width: 178 + height: 5 + bg_color: 2503746 + radius: 2 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + - label: + text: A3 -- + x: 6 + y: 11 + width: 170 + height: 20 + text_color: 15594487 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + id: ds_turd_flinger_tray_2_label + - obj: + id: ds_turd_flinger_tray_3_card + x: 594 + y: 401 + width: 182 + height: 32 + bg_color: 1516078 + radius: 6 + border_width: 1 + border_color: 2503746 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - obj: + id: ds_turd_flinger_tray_3_swatch + x: 1 + y: 1 + width: 178 + height: 5 + bg_color: 2503746 + radius: 2 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + - label: + text: A4 -- + x: 6 + y: 11 + width: 170 + height: 20 + text_color: 15594487 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + id: ds_turd_flinger_tray_3_label + - button: + x: 24 + y: 444 + width: 88 + height: 30 + bg_color: 1516078 + radius: 8 + border_width: 0 + pad_all: 0 + gesture_bubble: true + widgets: + - label: + text: < PREV + align: CENTER + text_font: montserrat_12 + on_click: + - lvgl.page.previous: {} + - button: + x: 688 + y: 444 + width: 88 + height: 30 + bg_color: 1516078 + radius: 8 + border_width: 0 + pad_all: 0 + gesture_bubble: true + widgets: + - label: + text: NEXT > + align: CENTER + text_font: montserrat_12 + on_click: + - lvgl.page.next: {} + - label: + text: 3 / 5 SWIPE LEFT / RIGHT + x: 130 + y: 451 + width: 540 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + text_align: CENTER + - id: jordyns_layer_slayer_page + bg_color: 856859 + bg_opa: COVER + pad_all: 0 + scrollable: false + scrollbar_mode: 'OFF' + on_swipe_left: + - lambda: !lambda |- + if (auto *input = lv_indev_active()) lv_indev_wait_release(input); + - lvgl.page.next: + animation: MOVE_LEFT + time: 180ms + on_swipe_right: + - lambda: !lambda |- + if (auto *input = lv_indev_active()) lv_indev_wait_release(input); + - lvgl.page.previous: + animation: MOVE_RIGHT + time: 180ms + on_load: + - script.execute: jordyns_layer_slayer_refresh + widgets: + - label: + text: Jordyns-Layer-Slayer + x: 24 + y: 16 + width: 545 + height: 36 + text_color: 15594487 + text_font: montserrat_28 + long_mode: DOT + gesture_bubble: true + - label: + text: A1 / Upstairs + x: 24 + y: 53 + width: 545 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - obj: + x: 586 + y: 20 + width: 190 + height: 42 + bg_color: 1516078 + radius: 21 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: SYNCING + x: 0 + y: 11 + width: 190 + height: 24 + text_color: 9544629 + text_font: montserrat_16 + long_mode: DOT + gesture_bubble: true + id: jordyns_layer_slayer_status_label + text_align: CENTER + - label: + text: Waiting for Home Assistant + x: 24 + y: 88 + width: 752 + height: 28 + text_color: 15594487 + text_font: montserrat_20 + long_mode: DOT + gesture_bubble: true + id: jordyns_layer_slayer_task_label + - arc: + id: jordyns_layer_slayer_progress_arc + x: 28 + y: 132 + width: 224 + height: 224 + min_value: 0 + max_value: 100 + value: 0 + start_angle: 135 + end_angle: 45 + arc_width: 14 + arc_color: 2503746 + indicator: + arc_color: 6348442 + arc_width: 14 + adjustable: false + gesture_bubble: true + - label: + text: -- + x: 42 + y: 207 + width: 196 + height: 56 + text_color: 15594487 + text_font: montserrat_48 + long_mode: DOT + gesture_bubble: true + id: jordyns_layer_slayer_progress_label + text_align: CENTER + - label: + text: PRINT PROGRESS + x: 42 + y: 266 + width: 196 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + text_align: CENTER + - obj: + x: 282 + y: 132 + width: 238 + height: 118 + bg_color: 1516078 + radius: 16 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: NOZZLE / TARGET + x: 16 + y: 12 + width: 206 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - label: + text: -- + x: 16 + y: 38 + width: 206 + height: 76 + text_color: 15594487 + text_font: montserrat_26 + long_mode: DOT + gesture_bubble: true + id: jordyns_layer_slayer_nozzle_label + - obj: + x: 538 + y: 132 + width: 238 + height: 118 + bg_color: 1516078 + radius: 16 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: BED / TARGET + x: 16 + y: 12 + width: 206 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - label: + text: -- + x: 16 + y: 38 + width: 206 + height: 76 + text_color: 15594487 + text_font: montserrat_26 + long_mode: DOT + gesture_bubble: true + id: jordyns_layer_slayer_bed_label + - obj: + x: 282 + y: 262 + width: 238 + height: 86 + bg_color: 1516078 + radius: 16 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: REMAINING + x: 16 + y: 12 + width: 206 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - label: + text: -- + x: 16 + y: 38 + width: 206 + height: 44 + text_color: 15594487 + text_font: montserrat_26 + long_mode: DOT + gesture_bubble: true + id: jordyns_layer_slayer_remaining_label + - obj: + x: 538 + y: 262 + width: 238 + height: 86 + bg_color: 1516078 + radius: 16 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: LAYER + x: 16 + y: 12 + width: 206 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - label: + text: -- + x: 16 + y: 38 + width: 206 + height: 44 + text_color: 15594487 + text_font: montserrat_26 + long_mode: DOT + gesture_bubble: true + id: jordyns_layer_slayer_layers_label + - label: + text: Telemetry unavailable + x: 24 + y: 358 + width: 752 + height: 24 + text_color: 9544629 + text_font: montserrat_16 + long_mode: DOT + gesture_bubble: true + id: jordyns_layer_slayer_stage_label + - label: + text: FILAMENT / ACTIVE SLOT OUTLINED IN GREEN + x: 24 + y: 383 + width: 752 + height: 20 + text_color: 9544629 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + - obj: + id: jordyns_layer_slayer_tray_0_card + x: 24 + y: 401 + width: 182 + height: 32 + bg_color: 1516078 + radius: 6 + border_width: 1 + border_color: 2503746 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - obj: + id: jordyns_layer_slayer_tray_0_swatch + x: 1 + y: 1 + width: 178 + height: 5 + bg_color: 2503746 + radius: 2 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + - label: + text: A1 -- + x: 6 + y: 11 + width: 170 + height: 20 + text_color: 15594487 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + id: jordyns_layer_slayer_tray_0_label + - obj: + id: jordyns_layer_slayer_tray_1_card + x: 214 + y: 401 + width: 182 + height: 32 + bg_color: 1516078 + radius: 6 + border_width: 1 + border_color: 2503746 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - obj: + id: jordyns_layer_slayer_tray_1_swatch + x: 1 + y: 1 + width: 178 + height: 5 + bg_color: 2503746 + radius: 2 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + - label: + text: A2 -- + x: 6 + y: 11 + width: 170 + height: 20 + text_color: 15594487 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + id: jordyns_layer_slayer_tray_1_label + - obj: + id: jordyns_layer_slayer_tray_2_card + x: 404 + y: 401 + width: 182 + height: 32 + bg_color: 1516078 + radius: 6 + border_width: 1 + border_color: 2503746 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - obj: + id: jordyns_layer_slayer_tray_2_swatch + x: 1 + y: 1 + width: 178 + height: 5 + bg_color: 2503746 + radius: 2 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + - label: + text: A3 -- + x: 6 + y: 11 + width: 170 + height: 20 + text_color: 15594487 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + id: jordyns_layer_slayer_tray_2_label + - obj: + id: jordyns_layer_slayer_tray_3_card + x: 594 + y: 401 + width: 182 + height: 32 + bg_color: 1516078 + radius: 6 + border_width: 1 + border_color: 2503746 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - obj: + id: jordyns_layer_slayer_tray_3_swatch + x: 1 + y: 1 + width: 178 + height: 5 + bg_color: 2503746 + radius: 2 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + - label: + text: A4 -- + x: 6 + y: 11 + width: 170 + height: 20 + text_color: 15594487 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + id: jordyns_layer_slayer_tray_3_label + - button: + x: 24 + y: 444 + width: 88 + height: 30 + bg_color: 1516078 + radius: 8 + border_width: 0 + pad_all: 0 + gesture_bubble: true + widgets: + - label: + text: < PREV + align: CENTER + text_font: montserrat_12 + on_click: + - lvgl.page.previous: {} + - button: + x: 688 + y: 444 + width: 88 + height: 30 + bg_color: 1516078 + radius: 8 + border_width: 0 + pad_all: 0 + gesture_bubble: true + widgets: + - label: + text: NEXT > + align: CENTER + text_font: montserrat_12 + on_click: + - lvgl.page.next: {} + - label: + text: 4 / 5 SWIPE LEFT / RIGHT + x: 130 + y: 451 + width: 540 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + text_align: CENTER + - id: constipation_orion_page + bg_color: 856859 + bg_opa: COVER + pad_all: 0 + scrollable: false + scrollbar_mode: 'OFF' + on_swipe_left: + - lambda: !lambda |- + if (auto *input = lv_indev_active()) lv_indev_wait_release(input); + - lvgl.page.next: + animation: MOVE_LEFT + time: 180ms + on_swipe_right: + - lambda: !lambda |- + if (auto *input = lv_indev_active()) lv_indev_wait_release(input); + - lvgl.page.previous: + animation: MOVE_RIGHT + time: 180ms + on_load: + - script.execute: constipation_orion_refresh + widgets: + - label: + text: Constipation-Orion + x: 24 + y: 16 + width: 545 + height: 36 + text_color: 15594487 + text_font: montserrat_28 + long_mode: DOT + gesture_bubble: true + - label: + text: Dual nozzle / Office + x: 24 + y: 53 + width: 545 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - obj: + x: 586 + y: 20 + width: 190 + height: 42 + bg_color: 1516078 + radius: 21 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: SYNCING + x: 0 + y: 11 + width: 190 + height: 24 + text_color: 9544629 + text_font: montserrat_16 + long_mode: DOT + gesture_bubble: true + id: constipation_orion_status_label + text_align: CENTER + - label: + text: Waiting for Home Assistant + x: 24 + y: 88 + width: 752 + height: 28 + text_color: 15594487 + text_font: montserrat_20 + long_mode: DOT + gesture_bubble: true + id: constipation_orion_task_label + - arc: + id: constipation_orion_progress_arc + x: 28 + y: 132 + width: 224 + height: 224 + min_value: 0 + max_value: 100 + value: 0 + start_angle: 135 + end_angle: 45 + arc_width: 14 + arc_color: 2503746 + indicator: + arc_color: 6348442 + arc_width: 14 + adjustable: false + gesture_bubble: true + - label: + text: -- + x: 42 + y: 207 + width: 196 + height: 56 + text_color: 15594487 + text_font: montserrat_48 + long_mode: DOT + gesture_bubble: true + id: constipation_orion_progress_label + text_align: CENTER + - label: + text: PRINT PROGRESS + x: 42 + y: 266 + width: 196 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + text_align: CENTER + - obj: + x: 282 + y: 132 + width: 238 + height: 118 + bg_color: 1516078 + radius: 16 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: NOZZLES L/R / TARGET + x: 16 + y: 12 + width: 206 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - label: + text: -- + x: 16 + y: 38 + width: 206 + height: 76 + text_color: 15594487 + text_font: montserrat_18 + long_mode: DOT + gesture_bubble: true + id: constipation_orion_nozzle_label + - obj: + x: 538 + y: 132 + width: 238 + height: 118 + bg_color: 1516078 + radius: 16 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: BED / TARGET + x: 16 + y: 12 + width: 206 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - label: + text: -- + x: 16 + y: 38 + width: 206 + height: 76 + text_color: 15594487 + text_font: montserrat_26 + long_mode: DOT + gesture_bubble: true + id: constipation_orion_bed_label + - obj: + x: 282 + y: 262 + width: 238 + height: 86 + bg_color: 1516078 + radius: 16 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: REMAINING + x: 16 + y: 12 + width: 206 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - label: + text: -- + x: 16 + y: 38 + width: 206 + height: 44 + text_color: 15594487 + text_font: montserrat_26 + long_mode: DOT + gesture_bubble: true + id: constipation_orion_remaining_label + - obj: + x: 538 + y: 262 + width: 238 + height: 86 + bg_color: 1516078 + radius: 16 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - label: + text: LAYER + x: 16 + y: 12 + width: 206 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + - label: + text: -- + x: 16 + y: 38 + width: 206 + height: 44 + text_color: 15594487 + text_font: montserrat_26 + long_mode: DOT + gesture_bubble: true + id: constipation_orion_layers_label + - label: + text: Telemetry unavailable + x: 24 + y: 358 + width: 752 + height: 24 + text_color: 9544629 + text_font: montserrat_16 + long_mode: DOT + gesture_bubble: true + id: constipation_orion_stage_label + - label: + text: FILAMENT / ACTIVE SLOT OUTLINED IN GREEN + x: 24 + y: 383 + width: 752 + height: 20 + text_color: 9544629 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + - obj: + id: constipation_orion_tray_0_card + x: 24 + y: 401 + width: 182 + height: 32 + bg_color: 1516078 + radius: 6 + border_width: 1 + border_color: 2503746 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - obj: + id: constipation_orion_tray_0_swatch + x: 1 + y: 1 + width: 178 + height: 5 + bg_color: 2503746 + radius: 2 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + - label: + text: A1 -- + x: 6 + y: 11 + width: 170 + height: 20 + text_color: 15594487 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + id: constipation_orion_tray_0_label + - obj: + id: constipation_orion_tray_1_card + x: 214 + y: 401 + width: 182 + height: 32 + bg_color: 1516078 + radius: 6 + border_width: 1 + border_color: 2503746 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - obj: + id: constipation_orion_tray_1_swatch + x: 1 + y: 1 + width: 178 + height: 5 + bg_color: 2503746 + radius: 2 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + - label: + text: A2 -- + x: 6 + y: 11 + width: 170 + height: 20 + text_color: 15594487 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + id: constipation_orion_tray_1_label + - obj: + id: constipation_orion_tray_2_card + x: 404 + y: 401 + width: 182 + height: 32 + bg_color: 1516078 + radius: 6 + border_width: 1 + border_color: 2503746 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - obj: + id: constipation_orion_tray_2_swatch + x: 1 + y: 1 + width: 178 + height: 5 + bg_color: 2503746 + radius: 2 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + - label: + text: A3 -- + x: 6 + y: 11 + width: 170 + height: 20 + text_color: 15594487 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + id: constipation_orion_tray_2_label + - obj: + id: constipation_orion_tray_3_card + x: 594 + y: 401 + width: 182 + height: 32 + bg_color: 1516078 + radius: 6 + border_width: 1 + border_color: 2503746 + pad_all: 0 + scrollable: false + gesture_bubble: true + widgets: + - obj: + id: constipation_orion_tray_3_swatch + x: 1 + y: 1 + width: 178 + height: 5 + bg_color: 2503746 + radius: 2 + border_width: 0 + pad_all: 0 + scrollable: false + gesture_bubble: true + - label: + text: A4 -- + x: 6 + y: 11 + width: 170 + height: 20 + text_color: 15594487 + text_font: montserrat_12 + long_mode: DOT + gesture_bubble: true + id: constipation_orion_tray_3_label + - button: + x: 24 + y: 444 + width: 88 + height: 30 + bg_color: 1516078 + radius: 8 + border_width: 0 + pad_all: 0 + gesture_bubble: true + widgets: + - label: + text: < PREV + align: CENTER + text_font: montserrat_12 + on_click: + - lvgl.page.previous: {} + - button: + x: 688 + y: 444 + width: 88 + height: 30 + bg_color: 1516078 + radius: 8 + border_width: 0 + pad_all: 0 + gesture_bubble: true + widgets: + - label: + text: NEXT > + align: CENTER + text_font: montserrat_12 + on_click: + - lvgl.page.next: {} + - label: + text: 5 / 5 SWIPE LEFT / RIGHT + x: 130 + y: 451 + width: 540 + height: 22 + text_color: 9544629 + text_font: montserrat_14 + long_mode: DOT + gesture_bubble: true + text_align: CENTER diff --git a/esphome/bambu-display/preview.py b/esphome/bambu-display/preview.py new file mode 100644 index 0000000..58537ea --- /dev/null +++ b/esphome/bambu-display/preview.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python3 +"""Render the real LVGL pages with demo telemetry using ESPHome's headless SDL host.""" + +import argparse +import json +from pathlib import Path +import subprocess +import tempfile + +from PIL import Image +import yaml + +from generate import Dumper, HERE, Lambda, generate + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--output', type=Path, default=HERE / 'previews') + args = parser.parse_args() + printers = yaml.safe_load((HERE / 'printers.yaml').read_text())['printers'] + package = generate(printers) + demo_values = {'progress': 67, 'nozzle': 218, 'nozzle_target': 220, 'bed': 60, + 'bed_target': 60, 'time_left': 1.75, 'layer': 134, 'total_layers': 200, + 'fan': 80, 'left_nozzle': 219, 'left_target': 220, + 'right_nozzle': 37, 'right_target': 0} + demo_text = {'status': 'running', 'task': 'Workshop organizer - plate 2', + 'stage': 'printing', 'online': 'on', 'print_error': 'off', 'hms_error': 'off', + 'remaining_unit': 'h', 'nozzle_unit': '°C', 'bed_unit': '°C'} + colors = ['#60DE9AFF', '#F4C96BFF', '#74A9E8FF', '#F8F4ECFF', + '#DF8BBFFF', '#FA936BFF', '#8E79CAFF', '#4CC9C1FF'] + for printer in printers: + prefix = printer['id'] + '_' + for section in ('sensor', 'text_sensor'): + for entry in package[section]: + if not entry['id'].startswith(prefix): + continue + key = entry['id'][len(prefix):] + if section == 'sensor': + value = str(demo_values[key]) + else: + if key.startswith('tray_'): + _, index, attribute = key.split('_') + text = {'type': 'PLA', 'color': colors[int(index) % len(colors)], + 'active': 'on' if index == '0' else 'off'}[attribute] + else: + text = demo_text[key] + value = 'std::string(' + json.dumps(text, ensure_ascii=False) + ')' + entry.clear() + entry.update({'platform': 'template', 'id': prefix + key, 'internal': True, + 'lambda': Lambda('return ' + value + ';'), 'update_interval': '60s'}) + for script in package['script']: + code = script['then'][0]['lambda'] + script['then'][0]['lambda'] = Lambda(code.replace( + 'id(ha_api).is_connected_with_state_subscription()', 'true')) + + args.output.mkdir(parents=True, exist_ok=True) + with tempfile.TemporaryDirectory(prefix='bambu-lvgl-preview-') as work: + root = Path(work) + # Inject real LVGL pointer samples; test bubbling through cards/buttons + # without a GUI window or a physical touchscreen. + touch_header = root / 'preview_touch.h' + touch_header.write_text('''#pragma once +#include +namespace bambu_preview { +inline int x = 0, y = 0; +inline bool pressed = false; +inline void setup() { + auto *input = lv_indev_create(); + lv_indev_set_type(input, LV_INDEV_TYPE_POINTER); + lv_indev_set_display(input, lv_display_get_default()); + lv_indev_set_read_cb(input, [](lv_indev_t *, lv_indev_data_t *data) { + data->point.x = x; + data->point.y = y; + data->state = pressed ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED; + }); +} +} +''') + steps = [{'component.update': entry['id']} + for section in ('sensor', 'text_sensor') for entry in package[section]] + steps += [{'delay': '1s'}] + for printer in printers: + steps += [{'lvgl.page.show': printer['id'] + '_page'}, + {'script.execute': printer['id'] + '_refresh'}, {'delay': '300ms'}, + {'snapshot.take': {'id': 'panel_display', 'filename': printer['id'] + '.bmp'}}] + steps += [{'lvgl.page.show': printers[0]['id'] + '_page'}, {'delay': '250ms'}, + {'lambda': Lambda('bambu_preview::setup();')}] + if len(printers) > 1: + # First -> second -> first -> last -> first, then a swipe starting + # on NEXT must advance exactly once even when released over PREV. + gestures = [(650, 180, 180, printers[1]['id']), + (180, 650, 180, printers[0]['id']), + (180, 650, 180, printers[-1]['id']), + (650, 180, 180, printers[0]['id']), + (730, 60, 460, printers[1]['id'])] + for start, end, y, expected in gestures: + steps += [ + {'lambda': Lambda(f'bambu_preview::x = {start}; bambu_preview::y = {y}; bambu_preview::pressed = true;')}, + {'delay': '70ms'}, + {'lambda': Lambda(f'bambu_preview::x = {end};')}, {'delay': '70ms'}, + {'lambda': Lambda('bambu_preview::pressed = false;')}, {'delay': '350ms'}, + {'lambda': Lambda(f'if (!id({expected}_page).is_showing()) {{ ESP_LOGE("preview", "Swipe navigation failed"); exit(2); }}')}, + ] + steps += [{'lambda': Lambda('exit(0);')}] + config = {'esphome': {'name': 'bambu-display-preview', + 'includes': [str(HERE / 'dashboard.h'), str(touch_header)], + 'on_boot': {'priority': -100, 'then': steps}}, + 'host': {}, 'logger': {'level': 'WARN'}, + 'display': [{'platform': 'sdl', 'id': 'panel_display', 'dimensions': '800x480', + 'headless': True, 'auto_clear_enabled': False, 'update_interval': 'never'}], + 'lvgl': {'id': 'dashboard', 'displays': ['panel_display'], 'buffer_size': '100%', + 'color_depth': 16, 'bg_color': 0x0D131B, 'text_color': 0xEDF3F7, + 'default_font': 'montserrat_18', **package.pop('lvgl')}, **package} + filename = root / 'preview.yaml' + filename.write_text(yaml.dump(config, Dumper=Dumper, sort_keys=False, allow_unicode=True)) + subprocess.run(['esphome', 'compile', str(filename)], check=True) + binary = root / '.esphome/build/bambu-display-preview/.pioenvs/bambu-display-preview/program' + subprocess.run([str(binary)], check=True, timeout=30, cwd=root) + for printer in printers: + bmp = root / '.esphome/snapshots/bambu-display-preview' / (printer['id'] + '.bmp') + with Image.open(bmp) as image: + image.save(args.output / (printer['id'] + '.png')) + print(f'Saved {len(printers)} demo screenshots to {args.output}') + print('Passed LVGL pointer swipe tests, including wraparound and button gesture consumption.') + + +if __name__ == '__main__': + main() diff --git a/esphome/bambu-display/previews/constipation_orion.png b/esphome/bambu-display/previews/constipation_orion.png new file mode 100644 index 0000000000000000000000000000000000000000..8814633dc7792cae949f5f14072899b2ce02bb59 GIT binary patch literal 35412 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 literal 0 HcmV?d00001 diff --git a/esphome/bambu-display/previews/jordyns_layer_slayer.png b/esphome/bambu-display/previews/jordyns_layer_slayer.png new file mode 100644 index 0000000000000000000000000000000000000000..4d38a1a2d106017b736dca71ff700d2176410c9a GIT binary patch literal 33736 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

+()ciiWgBcn-|FI^Plq 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 literal 0 HcmV?d00001 diff --git a/esphome/bambu-display/previews/polly_pocket.png b/esphome/bambu-display/previews/polly_pocket.png new file mode 100644 index 0000000000000000000000000000000000000000..f15fa099f7c63ca26f5525cc9b7ac6e9dc76823c GIT binary patch literal 32051 zcmc$GRa6{N*JYCgNYDfi8rPyLYDj{sssYP{Q?5PY`%X39GNlA%msnG9wkME zRNT@}Uwkd_%v(8MCkdYi-#Ht+#8y}=` zNQg$R{a8~+ZoRL0ySP3zAYjU=_-jf0gN+gFcEcNe`?&(k-D=5#ui*S@_Sl>p<3=-f zhc~!f{$oTBJEQjy3iKD8@gdUVg(orUC^p^ZqmL7+qz z1r>N%pKRX7&4>oj;ga&v(z5(y{tZzoPj@c;^<6Y!qGyu+-t66MP1R0K5Y9Z>@~ImP zNDEn(wAf10c`#|8c_Qh?Ksrtf@-F<;WJ&IK)52iZCMq(K?ZfwiMxOQ99a0Q2(fI7vHe zDoL8M8$<+6mD91+mM`PW+Q;%x(J(eF>jp{);zn*n#XAz%cO_f7oI=_`ph(1N%<|X( zo6%)kWO}ti;_Hy`UHAn#*NeJJ-Ltx`v{wqpV-2`w2AN$XK2eR!GUt8a2nu^6 z@CtfycmD5RK*(DaVt&ohs`6mpaRfx2LyB2&OzcsM}1$88!{ac%HIbN>Hcky0&V0 zE_xR0afFC*OrrAs_Hj`zDVHkPa8VAjtHG3bADpkKPVY=13OU%IlwVB5;KSG1XrA-Z z55Q-1pRcI0dxvsATsHJqW77}%Tb+}lkiw;LWaT^~S|^7}3PUW~HM%-gwW~jJ@!4xP zY@a@QhDjpY_;L17g=A}4l|<$p$im`BrGb-iIb3OgnD&7RNe>fJ%kCs&AB!|tXM6pS zf?Ec-MNtbaFM_-(Yph`Ps&P+N*P`j&lJUoewYJ6UzYfi$+C+brG*a_axJp*Y1d) zukWRu5j`5R7{eq>m4;+FRu@6mqis+V9B9$zM`bort8utViKKv<_ZzxF2<5|fsE`6- zyTch>OR+?i1h7X+`3PHZ2?+4Ax;Tyx9NpG0-=V^n66zsjphjlkkhUoFbGDTPR|z9~ zwqs9ZkWZ`jlu^;}xLC!tOZnbRZy!jlF_DLn7$Me7Jxo0}(ArSq3Ap|~gh;zfYK$YO zsHJdXI2o0#Q-1)Bhl#84s)W^8T$P#3n};#oUm0GCT&_Rfq#gg^vv=QJsxP=6bqtUh zk$y{r6q;L%5>WcFldo;vPl;OX`&$t*huEr2;`IBz=r{Rbk)DKUfDI|pxgrgbBqmKsvcAhj>*9dLzw~`R$@`NjSkJ zk9vI6j6n;fs@xv-v1246G2c*jHukbs>U*n z`(7XC`BANIxA5EfQ!^cn16F=Ez;^N3% zm3xdq}`|B?z4po%t5uM@qn{v6NF_FZ+ zDl7&9WAA>cU{$u;l+h|dYfqnJ9n8Ran`@7`riJ~LV>|*p%DV5Bx^{7kDt0EtLQ(3I zWg{O1C(B9Rz&{UrhHi_pU1E7?(0eq!0~Mnp>3=6?vo)glT}aVlP3M#D8Am#6h|Acd z^*akw?IDtl)LB3V4(uNiK&BhI`|YBv-NS?m%&ujZTCO)(wy(Muqh63a12`hYoH{Uz z=Yh?I1-?6CSnlfr^wkmb{0(U8EAD~#L+y!o`SGrFe}E|QAY=YRnPmnZ)k>dW3g$WD zh+sVW^vSk#vb0&q_|@S@_f>30?FTAuV*RIxv%md$Z2hNBORi24<1~BZ7b|p7m)6ao z(BvjU?=F2vEv(Q!jY8$OA;N~b zi$dZ0btt`S>_ukcXGB;ICyn#pVaU#|!ZgL~)=5uxjrpcEblP#Yint7kDJI11vU0K} z1U0tpZpyfY$Vb>(j2Xq-QJ%yUn~!^88#0?lm_MtVmRZNOJ&P)?-h+RQs2Kcp@LMgU z4BLhqEaTX6Gp`b-=`7XxaDQ-9jP_%WRcDN-WG+vc8|p8<&@SdQy`R!2h%;)&7)Zg!O*dSE; z1bR9ASty~x47Wm5%vj?(Qf3o$125RKS%bBAET_M1aml+!=*)-6H>P)}ns?)AAD


*}v+eZkzaI0w4-*jfXExu+EkeGKjEfmR3s&k$I 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ν-Ik! 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 literal 0 HcmV?d00001 diff --git a/esphome/bambu-display/printers.yaml b/esphome/bambu-display/printers.yaml new file mode 100644 index 0000000..894ab0e --- /dev/null +++ b/esphome/bambu-display/printers.yaml @@ -0,0 +1,46 @@ +# Order here is the swipe order. Add/remove entries and rerun generate.py. +# entity_prefix is the HA entity ID between the domain and the metric suffix. +# Optional entities: {metric: sensor.custom_entity} overrides individual mappings. +printers: + - id: prints_charming + name: PrintsCharming + subtitle: P1S / Office + entity_prefix: p1s_01p09c470102673 + filament_banks: + - label: A + entity_prefix: p1s_01p09c470102673_ams_1 + - label: B + entity_prefix: p1s_01p09c470102673_ams_2 + + - id: polly_pocket + name: Polly-Pocket + subtitle: A1 mini / Office + entity_prefix: a1mini_0309ca580403653 + external_spools: + - label: EXT + entity: sensor.a1mini_0309ca580403653_externalspool_external_spool + + - id: ds_turd_flinger + name: Ds-Turd-Flinger + subtitle: A1 / Upstairs + entity_prefix: a1_03919d540806387 + filament_banks: + - label: A + entity_prefix: a1_03919d540806387_ams_1 + + - id: jordyns_layer_slayer + name: Jordyns-Layer-Slayer + subtitle: A1 / Upstairs + entity_prefix: jordyns_layer_slayer + filament_banks: + - label: A + entity_prefix: jordyns_layer_slayer_ams + + - id: constipation_orion + name: Constipation-Orion + subtitle: Dual nozzle / Office + entity_prefix: constipation_orion + dual_nozzle: true + filament_banks: + - label: A + entity_prefix: constipation_orion_ams_1 diff --git a/esphome/bambu-display/test_dashboard.cpp b/esphome/bambu-display/test_dashboard.cpp new file mode 100644 index 0000000..80dc8ce --- /dev/null +++ b/esphome/bambu-display/test_dashboard.cpp @@ -0,0 +1,54 @@ +#include "dashboard.h" +#include + +int main() { + using namespace bambu_display; + assert(remaining(1.75f, "h") == "1h 45m"); + assert(remaining(105.0f, "min") == "1h 45m"); + assert(remaining(6300.0f, "s") == "1h 45m"); + assert(remaining(0.15f, "h") == "0h 09m"); + assert(remaining(NAN, "h") == "--"); + assert(remaining(-1, "min") == "--"); + assert(remaining(10, "") == "--"); + assert(remaining(INFINITY, "h") == "--"); + assert(number(NAN) == "--"); + assert(temperature(219, 220, "°C") == "219 / 220 °C"); + assert(filament_color("#60DE9AFF") == GREEN); + assert(filament_color("60de9a") == GREEN); + assert(filament_color("#60DE9AZZ") == TRACK); + assert(filament_color("unknown") == TRACK); + assert(gauge_value(NAN, 100) == 0); + assert(gauge_value(110, 100) == 100); + assert(gauge_value(-10, 100) == 0); + + Snapshot data; + data.online = "on"; + data.status = "running"; + assert(!data.live()); + assert(data.status_text() == "HA OFFLINE"); + data.connected = true; + assert(data.live()); + assert(data.status_text() == "PRINTING"); + data.online = "off"; + assert(!data.live()); + assert(data.status_text() == "PRINTER OFFLINE"); + data.online = "unavailable"; + assert(data.status_text() == "SYNCING"); + data.online = "on"; + data.status = "unknown"; + assert(!data.live()); + data.status = "pause"; + assert(data.status_text() == "PAUSED"); + assert(data.status_color() == AMBER); + data.print_error = "on"; + assert(data.status_text() == "PRINT ERROR"); + assert(data.status_color() == RED); + data.print_error = "off"; + data.hms_error = "True"; + assert(data.status_text() == "HMS ALERT"); + assert(data.status_color() == RED); + data.hms_error = "off"; + data.status = "finish"; + assert(data.status_text() == "COMPLETE"); + assert(data.status_color() == GREEN); +} diff --git a/esphome/bambu-display/test_generate.py b/esphome/bambu-display/test_generate.py new file mode 100644 index 0000000..822b82b --- /dev/null +++ b/esphome/bambu-display/test_generate.py @@ -0,0 +1,67 @@ +"""Run with: python -m unittest discover -s esphome/bambu-display -v.""" + +import copy +import unittest + +import yaml + +from generate import HERE, generate, validate_printers + + +class FleetTests(unittest.TestCase): + def setUp(self): + self.printers = yaml.safe_load((HERE / 'printers.yaml').read_text())['printers'] + + def test_all_subscriptions_match_repository_entities(self): + known = {line.split(' | ')[0] for line in + (HERE.parent / 'ha-entities.txt').read_text().splitlines()} + package = generate(self.printers) + subscribed = {entry['entity_id'] for domain in ('sensor', 'text_sensor') + for entry in package[domain]} + self.assertFalse(subscribed - known) + + def test_seven_printers_have_independent_pages_and_metrics(self): + for index in (6, 7): + extra = copy.deepcopy(self.printers[0]) + extra.update(id=f'printer_{index}', entity_prefix=f'new_printer_{index}') + self.printers.append(extra) + package = generate(self.printers) + self.assertEqual(len(package['lvgl']['pages']), 7) + self.assertEqual(len(package['script']), 7) + subscriptions = {entry['id']: entry['entity_id'] for entry in package['sensor']} + self.assertEqual(subscriptions['printer_7_progress'], 'sensor.new_printer_7_print_progress') + for page in package['lvgl']['pages']: + self.assertIn('lvgl.page.next', page['on_swipe_left'][-1]) + self.assertIn('lvgl.page.previous', page['on_swipe_right'][-1]) + + def test_overrides_apply_to_values_and_unit_subscriptions(self): + self.printers[0]['entities'] = {'time_left': 'sensor.custom_remaining'} + package = generate(self.printers) + for domain, key in [('sensor', 'time_left'), ('text_sensor', 'remaining_unit')]: + entry = next(row for row in package[domain] if row['id'] == f'prints_charming_{key}') + self.assertEqual(entry['entity_id'], 'sensor.custom_remaining') + + def test_reject_empty_duplicate_and_malformed_printer_ids(self): + for invalid in ([], self.printers + [self.printers[0]], + [{**self.printers[0], 'id': 'invalid-id'}]): + with self.subTest(invalid=invalid), self.assertRaises(ValueError): + validate_printers(invalid) + + def test_reject_overflowing_filament_strip(self): + self.printers[0]['external_spools'] = [{'label': 'EXT', 'entity': 'sensor.external_spool'}] + with self.assertRaisesRegex(ValueError, 'eight slots'): + generate(self.printers) + + def test_progress_and_dual_nozzle_widgets_fit_the_panel(self): + package = generate(self.printers) + for page in package['lvgl']['pages']: + for widget in page['widgets']: + props = next(iter(widget.values())) + self.assertGreaterEqual(props.get('x', 0), 0) + self.assertGreaterEqual(props.get('y', 0), 0) + self.assertLessEqual(props.get('x', 0) + props.get('width', 0), 800) + self.assertLessEqual(props.get('y', 0) + props.get('height', 0), 480) + + +if __name__ == '__main__': + unittest.main() diff --git a/esphome/bambu-printer-display.yaml b/esphome/bambu-printer-display.yaml new file mode 100644 index 0000000..b34030b --- /dev/null +++ b/esphome/bambu-printer-display.yaml @@ -0,0 +1,114 @@ +# Sunton ESP32-8048S043C: 4.3" 800x480 RGB LCD + GT911 capacitive touch. +# Edit bambu-display/printers.yaml, then run its generate.py to change the fleet. +substitutions: + device_name: bambu-printer-display + friendly_name: Bambu Printer Display + +esphome: + name: ${device_name} + friendly_name: ${friendly_name} + min_version: 2026.9.0 + includes: + - bambu-display/dashboard.h + +esp32: + board: esp32-s3-devkitc-1 + flash_size: 16MB + flash_mode: dio + cpu_frequency: 240MHz + framework: + type: esp-idf + sdkconfig_options: + CONFIG_ESP32S3_DATA_CACHE_64KB: "y" + CONFIG_ESP32S3_DATA_CACHE_LINE_64B: "y" + CONFIG_SPIRAM_FETCH_INSTRUCTIONS: "y" + CONFIG_SPIRAM_RODATA: "y" + +psram: + mode: octal + speed: 80MHz + +logger: + hardware_uart: UART0 # GPIO19/20 are the touch bus, not native USB. + +api: + id: ha_api + encryption: + key: !secret api_encryption_key + +ota: + - platform: esphome + encryption: + key: !secret api_encryption_key + +wifi: + ssid: !secret wifi_iot_ssid + password: !secret wifi_password + +i2c: + id: touch_bus + sda: GPIO19 + scl: GPIO20 + scan: true + +display: + - platform: mipi_rgb + id: panel_display + model: RPI + dimensions: 800x480 + color_order: RGB + byte_order: little_endian + de_pin: GPIO40 + hsync_pin: GPIO39 + vsync_pin: GPIO41 + pclk_pin: GPIO42 + pclk_inverted: true + pclk_frequency: 16MHz + hsync_front_porch: 8 + hsync_pulse_width: 4 + hsync_back_porch: 8 + vsync_front_porch: 8 + vsync_pulse_width: 4 + vsync_back_porch: 8 + data_pins: + red: [GPIO45, GPIO48, GPIO47, GPIO21, GPIO14] + green: [GPIO5, GPIO6, GPIO7, GPIO15, GPIO16, GPIO4] + blue: [GPIO8, GPIO3, GPIO46, GPIO9, GPIO1] + auto_clear_enabled: false + update_interval: never + +touchscreen: + - platform: gt911 + id: panel_touch + display: panel_display + i2c_id: touch_bus + address: 0x5D + # Polling avoids the GT911 INT pin's boot/address-selection behaviour. + update_interval: 20ms + +output: + - platform: ledc + id: backlight_output + pin: GPIO2 + +light: + - platform: monochromatic + id: panel_backlight + name: Backlight + output: backlight_output + restore_mode: ALWAYS_ON + default_transition_length: 0s + +packages: + fleet: !include bambu-display/generated.yaml + +lvgl: + id: dashboard + displays: [panel_display] + touchscreens: [panel_touch] + buffer_size: 12% + color_depth: 16 + byte_order: little_endian + bg_color: 0x0D131B + text_color: 0xEDF3F7 + default_font: montserrat_18