Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,22 @@ InvenTree imports so it is unit-tested here:
| any other fault | `ERROR`, carrying the reason |
| agent will / shutdown | `DISCONNECTED` |

### When it refreshes

The status is read from the retained topic in three places, which between them keep the
page honest without polling the printer itself:

| when | hook |
|---|---|
| machine initialisation | `init_machine` |
| a manual restart from the Admin Center | `restart_machine` |
| periodically | `ping_machines`, driven by InvenTree's `MACHINE_PING_ENABLED` (on by default) |

The periodic one is not a nicety. Machine status lives in the Django cache, so clearing
that cache drops every `machine:*` key at once — and this deployment runs Redis without
persistence, so a restart does exactly that. With only `init_machine` the page then sat
at `UNKNOWN` with an empty status text until someone printed or the pods restarted.

Two deliberate distinctions. **Unreported media is not healthy media**: `media_ok` is a
tri-state, and a printer that has said nothing shows "media unreported" rather than
"media ok". And **battery percentage alone is not enough** — it pins at 100% whenever
Expand Down
31 changes: 31 additions & 0 deletions inventree_label_dispatch/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,37 @@ def _apply(self, machine, member: str, text: str) -> None:
machine.set_status(getattr(LabelPrinterStatus, member))
machine.set_status_text(text)

def restart_machine(self, machine) -> None:
"""Re-read the printer's state after a manual restart.

A restart clears the machine's shared state, and without this nothing puts it
back: the page then shows UNKNOWN with an empty status text -- the defaults
`get_shared_state` returns for missing keys -- while the machine itself
reports `initialized`, no errors and a driver available. An empty status text
is diagnostic on its own, since no path in this driver produces one.
"""
self._refresh_status(machine)

def ping_machines(self) -> None:
"""Periodic refresh, driven by InvenTree's MACHINE_PING_ENABLED (default on).

This is what keeps the page honest between prints. It matters more than it
looks: machine status lives in the Django cache, so when that cache is cleared
-- a Redis restart, and this deployment runs Redis deliberately without
persistence -- every `machine:*` key vanishes at once. Before this hook the
only thing that re-read the retained topic was machine initialisation, so the
page stayed blank until someone printed or the pods restarted.

One machine's broker trouble must not stop the others being refreshed, hence
the per-machine guard. `_refresh_status` already turns an unreachable broker
into an UNKNOWN status rather than an exception; this catches anything else.
"""
for machine in self.get_machines():
try:
self._refresh_status(machine)
except Exception as exc: # noqa: BLE001 - one machine must not break the loop
machine.handle_error(exc)

def _refresh_status(self, machine) -> None:
printer_id = machine.get_setting("PRINTER_ID", "D")
try:
Expand Down
2 changes: 1 addition & 1 deletion inventree_label_dispatch/version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Single source of truth for the plugin version."""

__version__ = "0.2.0"
__version__ = "0.2.1"
Loading