updates
This commit is contained in:
@@ -10,11 +10,11 @@
|
||||
|
||||
namespace bambu_display {
|
||||
|
||||
constexpr uint32_t GREEN = 0x60DE9A;
|
||||
constexpr uint32_t MUTED = 0x91A3B5;
|
||||
constexpr uint32_t GREEN = 0x00FF00;
|
||||
constexpr uint32_t MUTED = 0xAEB3B7;
|
||||
constexpr uint32_t RED = 0xFF737B;
|
||||
constexpr uint32_t AMBER = 0xF2C572;
|
||||
constexpr uint32_t TRACK = 0x263442;
|
||||
constexpr uint32_t TRACK = 0x19232B;
|
||||
|
||||
inline std::string lower(std::string text) {
|
||||
for (char &c : text) c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
|
||||
@@ -67,6 +67,20 @@ inline std::string remaining(float value, const std::string &unit) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
inline int duration_seconds(float value, const std::string &unit) {
|
||||
if (!std::isfinite(value) || value < 0) return -1;
|
||||
double seconds;
|
||||
if (unit == "h") seconds = double(value) * 3600;
|
||||
else if (unit == "min") seconds = double(value) * 60;
|
||||
else if (unit == "s") seconds = value;
|
||||
else return -1;
|
||||
return seconds <= 60000000 ? static_cast<int>(std::round(seconds)) : -1;
|
||||
}
|
||||
|
||||
inline float celsius(float value, const std::string &unit) {
|
||||
return unit == "°F" || unit == "F" ? (value - 32.0f) * 5.0f / 9.0f : value;
|
||||
}
|
||||
|
||||
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.
|
||||
@@ -89,8 +103,10 @@ struct Snapshot {
|
||||
bool connected = false;
|
||||
std::string online, status, task, stage, print_error, hms_error;
|
||||
std::string remaining_unit, nozzle_unit, bed_unit;
|
||||
std::string finish_time;
|
||||
float progress = NAN, nozzle = NAN, nozzle_target = NAN, bed = NAN, bed_target = NAN;
|
||||
float time_left = NAN, layer = NAN, total_layers = NAN, fan = NAN;
|
||||
float aux_fan = NAN, exhaust_fan = NAN;
|
||||
bool dual_nozzle = false;
|
||||
float left_nozzle = NAN, left_target = NAN, right_nozzle = NAN, right_target = NAN;
|
||||
std::vector<Tray> trays;
|
||||
@@ -127,8 +143,10 @@ struct Snapshot {
|
||||
namespace bambu_display {
|
||||
|
||||
struct TrayWidgets { lv_obj_t *card, *swatch, *label; };
|
||||
struct GaugeWidgets { lv_obj_t *arc, *value, *detail; };
|
||||
struct Widgets {
|
||||
lv_obj_t *status, *task, *arc, *progress, *nozzle, *bed, *remaining, *layers, *stage;
|
||||
lv_obj_t *status, *task, *top_progress, *remaining, *layers, *stage;
|
||||
GaugeWidgets progress, nozzle, bed, fan, aux, exhaust;
|
||||
std::vector<TrayWidgets> trays;
|
||||
};
|
||||
|
||||
@@ -136,33 +154,49 @@ 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_gauge(const GaugeWidgets &widgets, float value, float position,
|
||||
int maximum, const std::string &detail) {
|
||||
lv_arc_set_value(widgets.arc, gauge_value(position, maximum));
|
||||
set_text(widgets.value, number(value));
|
||||
set_text(widgets.detail, detail);
|
||||
}
|
||||
|
||||
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)) + "%" : "--");
|
||||
lv_obj_set_style_arc_color(widgets.progress.arc, lv_color_hex(color), LV_PART_INDICATOR);
|
||||
lv_bar_set_value(widgets.top_progress, live ? gauge_value(data.progress, 100) : 0, LV_ANIM_OFF);
|
||||
render_gauge(widgets.progress, live && std::isfinite(data.progress)
|
||||
? std::clamp(data.progress, 0.0f, 100.0f) : NAN, live ? data.progress : NAN, 100,
|
||||
live ? remaining(data.time_left, data.remaining_unit) : "--");
|
||||
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) : "--");
|
||||
const float nozzle = data.dual_nozzle ? data.left_nozzle : data.nozzle;
|
||||
const float target = data.dual_nozzle ? data.left_target : data.nozzle_target;
|
||||
render_gauge(widgets.nozzle, live ? nozzle : NAN, live ? celsius(nozzle, data.nozzle_unit) : NAN,
|
||||
300, live ? "/ " + number(target) + " " + data.nozzle_unit : "--");
|
||||
render_gauge(widgets.bed, live ? data.bed : NAN, live ? celsius(data.bed, data.bed_unit) : NAN,
|
||||
120, live ? "/ " + number(data.bed_target) + " " + data.bed_unit : "--");
|
||||
render_gauge(widgets.fan, live ? data.fan : NAN, live ? data.fan : NAN, 100, "%");
|
||||
if (data.dual_nozzle)
|
||||
render_gauge(widgets.aux, live ? data.right_nozzle : NAN,
|
||||
live ? celsius(data.right_nozzle, data.nozzle_unit) : NAN,
|
||||
300, live ? "/ " + number(data.right_target) + " " + data.nozzle_unit : "--");
|
||||
else
|
||||
render_gauge(widgets.aux, live ? data.aux_fan : NAN, live ? data.aux_fan : NAN, 100, "%");
|
||||
render_gauge(widgets.exhaust, live ? data.exhaust_fan : NAN, live ? data.exhaust_fan : NAN, 100, "%");
|
||||
std::string time_line = live ? remaining(data.time_left, data.remaining_unit) : "--";
|
||||
if (live && !data.finish_time.empty()) time_line = data.finish_time + " | " + time_line;
|
||||
set_text(widgets.remaining, time_line);
|
||||
set_text(widgets.layers, live ? "Layer " + 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 : "--"));
|
||||
set_text(widget.label, tray.label + "\n" + (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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user