Add GenericPrinter::set_fan_speed() across all five printer kinds

Same override pattern as connect(): required, no default body, five
completely different bodies.

- BambuGenericPrinter::set_fan_speed_impl() is shared by BambuV1Printer and
  BambuV2Printer (composition reuse, same as connect_impl) - both speak
  the same MQTT gcode-injection mechanism.
- PrusaLinkPrinter and PrusaSerialPrinter both send the same M106 gcode
  but over different transports (HTTP command injection vs. raw serial
  bytes) - they share the percent->PWM conversion despite having unrelated
  connect() implementations.
- KlipperPrinter uses a hypothetical Moonraker-native endpoint that takes
  a percentage directly - no PWM conversion at all, since that math only
  applies to the gcode-speaking vendors.

percent_to_pwm() lives in mod.rs as a private free function rather than a
trait default: it's genuine shared logic, but only for the subset of
vendors that need it, which is exactly the case a trait default can't
express cleanly. Visible to bambu.rs/prusa.rs via super:: because Rust's
module privacy reaches into child modules.

Verified with cargo check --all-targets and a full run of
printer_polymorphism: 50% converges on the same PWM value (127) across all
three gcode-based printers, Klipper's native path takes 0.50 directly.
This commit is contained in:
2026-08-28 21:40:11 +00:00
parent aa471ff906
commit 6e18215af5
5 changed files with 80 additions and 6 deletions
+9
View File
@@ -62,4 +62,13 @@ async fn main() {
_ => {}
}
}
// A second trait method, same uniform call site as connect(): every
// vendor sends "50%" a completely different way — an MQTT gcode
// command, Moonraker's native API, gcode over HTTP, gcode over serial
// — but the caller doesn't need to know or care which.
println!();
for printer in &mut fleet {
let _ = printer.set_fan_speed(50).await;
}
}