print_dispatch_context.py 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. """Whether Bambuddy injected End G-code into the print now running (#2547).
  2. The finish-photo path has to know one thing at print completion that no MQTT
  3. field reports: did this print end with user End G-code? If it did, a SwapMod
  4. snippet may already have ejected the plate, so the scene in front of the camera
  5. at ``gcode_state=FINISH`` is not the finished print and the photo must come from
  6. the in-print frame bank instead (#1867).
  7. Only the dispatcher ever sees this, so it is recorded here in two steps:
  8. 1. ``mark_pending`` when the scheduler injects an End G-code snippet.
  9. 2. ``adopt`` when the printer reports a print starting, which moves the pending
  10. flag onto the running print and consumes it.
  11. The two steps exist so the flag can never outlive its print. A print Bambuddy
  12. did not dispatch — started from the slicer, the SD card, or the printer's own
  13. screen — finds no pending flag and correctly adopts ``False``, instead of
  14. inheriting the answer from whatever ran before it.
  15. In-memory and best-effort: a restart mid-print loses the flag, and ``False`` is
  16. the safe way to be wrong (a live grab that might show a swapped plate, rather
  17. than silently substituting a mid-print frame).
  18. """
  19. from __future__ import annotations
  20. import logging
  21. logger = logging.getLogger(__name__)
  22. # Printers the scheduler has injected End G-code for, awaiting a print start.
  23. _pending: set[int] = set()
  24. # Printers whose *currently running* print has injected End G-code.
  25. _active: set[int] = set()
  26. def mark_pending(printer_id: int) -> None:
  27. """Record that the job now being sent to ``printer_id`` has End G-code."""
  28. _pending.add(printer_id)
  29. logger.debug("[DISPATCH-CTX] printer %s: End G-code injected, awaiting print start", printer_id)
  30. def adopt(printer_id: int) -> bool:
  31. """Bind any pending flag to the print that just started, and return it.
  32. Called once per print start. Always writes ``_active`` — including the
  33. ``False`` case — so a print Bambuddy didn't dispatch clears its
  34. predecessor's flag rather than inheriting it.
  35. """
  36. injected = printer_id in _pending
  37. _pending.discard(printer_id)
  38. if injected:
  39. _active.add(printer_id)
  40. logger.debug("[DISPATCH-CTX] printer %s: running print has injected End G-code", printer_id)
  41. else:
  42. _active.discard(printer_id)
  43. return injected
  44. def end_gcode_injected(printer_id: int) -> bool:
  45. """True if the print currently running on ``printer_id`` has End G-code."""
  46. return printer_id in _active
  47. def clear(printer_id: int) -> None:
  48. """Forget everything about this printer (disconnect, removal, tests)."""
  49. _pending.discard(printer_id)
  50. _active.discard(printer_id)