Drive Klipper, OctoPrint and PrusaLink for real
Windows discovery tool / windows (push) Successful in 1m2s
Windows discovery tool / windows (push) Successful in 1m2s
The three were println stubs. Each is now an HTTP client (Moonraker, OctoPrint's REST API, PrusaLink's v1 API) behind a small shared helper: status polled in the background, pause/resume/cancel, G-code lines, fan speed, and upload-and-start of a sliced file. A slicer project (.3mf) is refused for these, and so is an upload while a print is running. Telemetry and the completion watcher now read a vendor-neutral PrinterStatus instead of Bambu's PrintReport, so these printers report progress, temperatures and job state to the cloud. Written from the public API docs and tested against mock servers only; no real Klipper, OctoPrint or PrusaLink machine has been on the bench.
This commit is contained in:
+19
-20
@@ -374,29 +374,28 @@ async fn collect_telemetry(fleet: &SharedFleet) -> Vec<PrinterTelemetry> {
|
||||
|
||||
for printer in fleet.iter() {
|
||||
let base = printer.base();
|
||||
let Some(report) = printer.print_status().await else {
|
||||
let Some(status) = printer.status().await else {
|
||||
continue;
|
||||
};
|
||||
// Only Bambu has a camera report to derive these from.
|
||||
let report = printer.print_status().await;
|
||||
|
||||
out.push(PrinterTelemetry {
|
||||
printer_id: base.id.clone(),
|
||||
name: base.name.clone(),
|
||||
state: report.gcode_state.clone(),
|
||||
percent: report.mc_percent,
|
||||
stage: report.stg_cur,
|
||||
layer: report.layer_num,
|
||||
total_layers: report.total_layer_num,
|
||||
remaining_minutes: report.mc_remaining_time,
|
||||
// An idle printer reports `""` rather than omitting the field;
|
||||
// empty-string-as-absent is worth normalising here so the cloud
|
||||
// doesn't have to know that.
|
||||
job_name: report.subtask_name.clone().filter(|s| !s.is_empty()),
|
||||
nozzle_temp: report.nozzle_temper,
|
||||
nozzle_target: report.nozzle_target_temper,
|
||||
bed_temp: report.bed_temper,
|
||||
bed_target: report.bed_target_temper,
|
||||
print_error: report.print_error,
|
||||
active_alerts: report.hms.as_ref().map(|h| h.len()),
|
||||
state: status.state,
|
||||
percent: status.percent,
|
||||
stage: status.stage,
|
||||
layer: status.layer,
|
||||
total_layers: status.total_layers,
|
||||
remaining_minutes: status.remaining_minutes,
|
||||
job_name: status.job_name,
|
||||
nozzle_temp: status.nozzle_temp,
|
||||
nozzle_target: status.nozzle_target,
|
||||
bed_temp: status.bed_temp,
|
||||
bed_target: status.bed_target,
|
||||
print_error: status.print_error,
|
||||
active_alerts: status.active_alerts,
|
||||
// Derived from the same reported URL `camera::sources` builds
|
||||
// the go2rtc config from, so a printer is advertised as
|
||||
// streamable here only if it is also actually being served
|
||||
@@ -404,13 +403,13 @@ async fn collect_telemetry(fleet: &SharedFleet) -> Vec<PrinterTelemetry> {
|
||||
// the rule means the two cannot drift apart.
|
||||
camera_stream: crate::camera::source_for(
|
||||
printer,
|
||||
report.ipcam.as_ref().and_then(|c| c.rtsp_url.as_deref()),
|
||||
report.as_ref().and_then(|r| r.ipcam.as_ref()).and_then(|c| c.rtsp_url.as_deref()),
|
||||
)
|
||||
.map(|source| source.stream_name),
|
||||
camera_snapshot: crate::camera::wants_snapshot(
|
||||
printer,
|
||||
report.ipcam.is_some(),
|
||||
report.ipcam.as_ref().and_then(|c| c.rtsp_url.as_deref()),
|
||||
report.as_ref().is_some_and(|r| r.ipcam.is_some()),
|
||||
report.as_ref().and_then(|r| r.ipcam.as_ref()).and_then(|c| c.rtsp_url.as_deref()),
|
||||
)
|
||||
.then_some(true),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user