Milestones on the escalation
A 3D printer on the lineStep 5 of 7The printer claims and reports
The boat takes eleven minutes. Someone across the room wants to know how far along it is.
← A codec for a device's own protocolAn alarm pauses the job, not the escalation →
While a printer works a job, the gateway notes started, each progress step, pauses and the arrival as items on the escalation that holds it.
The situation
A printer reports about once a second. Nobody wants a thousand entries on a print, but everyone wants to see that it started, how far it is, whether it stopped, and when it finished. Built by hand, that is a progress table and a poller. Here the stream keeps every report and the escalation gets the milestones.
The setup
Turn lifecycle notes on and choose the step:
services: long-tail: environment: MACHINE_LINE_CONFIG: /etc/site/line.json MACHINE_CODEC_MODULE: /app/examples/workflows/bambu-printer/codec.ts MACHINE_LIFECYCLE: "on" MACHINE_PROGRESS_STEP: ${MACHINE_PROGRESS_STEP:-25} MACHINE_QUIET_MS: ${MACHINE_QUIET_MS:-0} volumes: - ./deploy/bambu-site:/etc/site:ro
machine-site: env_file: - path: .env required: false environment: MACHINE_SITE_DIR: /app/deploy/bambu-site command: ["npx", "ts-node", "--transpile-only", "examples/workflows/bambu-printer/site/setup.ts"]The codec reads each report as a line-protocol event; a crossed step becomes an item:
{ "v": "1", "id": "83215978-41a0-5638-82ce-aec6fbe47d6f", "at": "2026-11-08T22:06:00.563Z", "source": { "site": "site-1", "line": "print-1", "machine": "01P00A000000001", "station": "p1s-01" }, "body": { "event": "progress", "jobId": "Pmw8druzy-p1s-01", "unitId": "U-Pmw8druzy", "orderRef": "Pmw8druzy-p1s-01", "recipe": null, "carrierId": null, "percent": 75, "remainingSec": 60, "detail": { "layer": 45, "layers": 60 } }}// gateway: accumulate progress:U-Pmw8druzy:75 on the print escalationOn the floor
| Item | When |
|---|---|
started:<unit> | The printer starts laying down material |
progress:<unit>:25, :50, :75 | Progress crosses each step. The progress facet holds the latest percent, time left and layer |
paused:print-error:<at>, resumed:print-error:<at> | The printer stops on an error and later resumes |
arrived:<unit> | The print finishes. This resolves the escalation |
The driver prints the items as they land:
[22:05:09] copying p1s-0.8-tpu.gcode.3mf to p1s-01 (a minute or two for a few MB)[22:05:09] file:///sdcard/cache/Pmw8druzy.gcode.3mf (sha256 708d5acd78cd…)[22:05:09] started bambu-Pmw8druzy on p1s-01; unload the part on the dashboard (print-unload) when it finishes[22:05:12] c5ea0fcd handoff/line-print pending claimed [started:U-Pmw8druzy][22:05:24] c5ea0fcd handoff/line-print pending claimed [started:U-Pmw8druzy, progress:U-Pmw8druzy:25][22:05:27] c5ea0fcd handoff/line-print pending claimed [started:U-Pmw8druzy, progress:U-Pmw8druzy:25, paused:print-error:2026-11-08T22:05:25.810Z][22:05:33] c5ea0fcd handoff/line-print pending claimed [started:U-Pmw8druzy, progress:U-Pmw8druzy:25, paused:print-error:2026-11-08T22:05:25.810Z, resumed:print-error:2026-11-08T22:05:25.810Z][22:05:45] c5ea0fcd handoff/line-print pending claimed [started:U-Pmw8druzy, progress:U-Pmw8druzy:25, paused:print-error:2026-11-08T22:05:25.810Z, resumed:print-error:2026-11-08T22:05:25.810Z, progress:U-Pmw8druzy:50][22:06:00] c5ea0fcd handoff/line-print pending claimed [started:U-Pmw8druzy, progress:U-Pmw8druzy:25, paused:print-error:2026-11-08T22:05:25.810Z, resumed:print-error:2026-11-08T22:05:25.810Z, progress:U-Pmw8druzy:50, progress:U-Pmw8druzy:75][22:06:15] c5ea0fcd handoff/line-print resolved claimed [started:U-Pmw8druzy, progress:U-Pmw8druzy:25, paused:print-error:2026-11-08T22:05:25.810Z, resumed:print-error:2026-11-08T22:05:25.810Z, progress:U-Pmw8druzy:50, progress:U-Pmw8druzy:75, arrived:U-Pmw8druzy][22:06:15] 894d7c92 handoff/print-unload pending [][22:06:18] 894d7c92 handoff/print-unload resolved claimed [][22:06:19] route ended: {"status":"complete","units":["U-Pmw8druzy"],"history":[{"hop":0,"to":"p1s-01","attempt":1,"received":true},{"hop":1,"to":"exit","attempt":1,"received":true}]}The guarantee
Items are noted as the printer’s bot on the escalation that holds the job, and the escalation resolves only at the arrival. Every report stays in JetStream. See Machines.
Related patterns
The physical world
Handoff escalation
Step 2 of 12 · A factory line over MQTT
Each move between stations is one escalation naming the units that move; it resolves with a receipt or a typed error code.
The physical world
A machine is a resolver
Step 1 of 12 · A factory line over MQTT
A workflow parks an escalation and waits; a machine resolves it over MQTT exactly as a person would from the dashboard.
The physical world
Offline, quiet and alarm escalations
Step 12 of 12 · A factory line over MQTT
A stopping alarm, a dropped machine and a silent one each become an escalation for the line operator, resolved when the machine recovers.
