From 970f64e8406fc9203f676e73ec1b80c89e3585dc Mon Sep 17 00:00:00 2001 From: HK-Moebius Date: Tue, 20 Oct 2026 23:28:31 +0200 Subject: [PATCH] Mainsail: show chamber temperature and compact ETA - Show the chamber temperature when the printer reports a heater or sensor with "chamber" in its name: heater_generic, temperature_sensor and temperature_fan first, then printer-specific objects such as heater_chamber on the Prusa Pro HT90. Sensors come from heaters.available_sensors in the existing query, so printers without a chamber make no extra request and look as before. - Show the remaining time as "2h 05min" instead of "2 hours from now", "Soon!" below one minute. Co-Authored-By: Claude Opus 5.5 --- Mainsail/Mainsail.php | 48 ++++++++++++++++++++++++++++++------ Mainsail/livestats.blade.php | 10 ++++++-- 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/Mainsail/Mainsail.php b/Mainsail/Mainsail.php index e08556ab0a..be48c74be9 100644 --- a/Mainsail/Mainsail.php +++ b/Mainsail/Mainsail.php @@ -2,8 +2,6 @@ namespace App\SupportedApps\Mainsail; -use Carbon\Carbon; - class Mainsail extends \App\SupportedApps implements \App\EnhancedApps { public $config; @@ -23,7 +21,9 @@ public function livestats() { $status = "standby"; //https://moonraker.readthedocs.io/en/latest/web_api/#query-printer-object-status - $res = parent::execute($this->url('/printer/objects/query?display_status&print_stats&virtual_sdcard')); + $res = parent::execute( + $this->url('/printer/objects/query?display_status&print_stats&virtual_sdcard&heaters=available_sensors') + ); if (!$res) { return parent::getLiveStats($status, ["error" => "Connection"]); } @@ -33,6 +33,12 @@ public function livestats() $status = $printer->print_stats->state ?? "standby"; + // Only shown if the printer has a chamber sensor + $chamber = $this->chamberTemperature($printer->heaters->available_sensors ?? []); + if ($chamber !== null) { + $data["chamber"] = round($chamber) . '°C'; + } + if ($status == 'printing') { // Moonraker reports progress as a fraction between 0.0 and 1.0. // display_status is set by M73, virtual_sdcard is the file position fallback. @@ -68,12 +74,12 @@ public function livestats() if ($remaining === null) { $data["estimated"] = "N/A"; - } elseif ($remaining <= 0) { + } elseif ($remaining < 60) { $data["estimated"] = "Soon!"; } else { - $data["estimated"] = Carbon::now() - ->addSeconds((int) round($remaining)) - ->diffForHumans(); + // Remaining time, e.g. "2h 05min" + $remaining = (int) round($remaining); + $data["estimated"] = sprintf('%dh %02dmin', intdiv($remaining, 3600), intdiv($remaining % 3600, 60)); } } else { $data["state"] = ucwords($status); @@ -81,6 +87,34 @@ public function livestats() return parent::getLiveStats($status, $data); } + /** + * Temperature of the chamber sensor, or null if the printer doesn't have one. + * Klipper has no dedicated chamber object, so look for a heater or sensor + * with "chamber" in its name, e.g. [heater_generic chamber] or [temperature_sensor chamber]. + * Some printers use their own object, e.g. heater_chamber on the Prusa Pro HT90. + */ + private function chamberTemperature($sensors) + { + $chamber = null; + foreach (['heater_generic ', 'temperature_sensor ', 'temperature_fan ', ''] as $type) { + foreach ($sensors as $sensor) { + if (strpos($sensor, $type) === 0 && stripos($sensor, 'chamber') !== false) { + $chamber = $sensor; + break 2; + } + } + } + if ($chamber === null) { + return null; + } + + $res = parent::execute($this->url('/printer/objects/query?' . rawurlencode($chamber) . '=temperature')); + if (!$res) { + return null; + } + return json_decode($res->getBody())->result->status->{$chamber}->temperature ?? null; + } + public function url($endpoint) { $api_url = parent::normaliseurl($this->config->url, false) . ':' . $this->config->moonraker_port . $endpoint; diff --git a/Mainsail/livestats.blade.php b/Mainsail/livestats.blade.php index 25e6cb81fd..ab60361879 100644 --- a/Mainsail/livestats.blade.php +++ b/Mainsail/livestats.blade.php @@ -16,12 +16,18 @@ Complete {!! $completed_pct !!} - @endif + @endif @if (isset($estimated))
  • - Finish + ETA {!! $estimated !!}
  • @endif @endif + @if (isset($chamber)) +
  • + Chamber + {!! $chamber !!} +
  • + @endif