Skip to content

A line from the environment

The physical worldMQTTDashboardLineDefMachines.loadLineMACHINE_LINE_CONFIGqueueDepthrequireArtifact

A 3D printer on the lineStep 1 of 7The route asks for a print

A P1S arrives at site 1. Its screen shows an IP address, a serial and an access code.

← OverviewThe file goes to the machine first →

The printers in .env become a line: one station per enabled printer, its serial as its address, its access code kept out of the repository.

The situation

A printer’s serial, address and access code are what it takes to reach it, and the access code is a password. They belong in one file nobody commits, and the line should follow from them: add a printer, enable it, and it is on the line. Built by hand, that is a config service and a deploy for every printer. Here .env describes the printers and the site setup writes the line.

The setup

One block per station, named in BAMBU_PRINTERS:

.env
# The site and line the printers form
BAMBU_SITE_ID=site-1
BAMBU_LINE_ID=print-1
# One block per station in BAMBU_PRINTERS: the station upper-cased, - as _
BAMBU_PRINTERS=p1s-01
BAMBU_P1S_01_SERIAL=<printer serial>
BAMBU_P1S_01_HOST=<printer LAN address>
BAMBU_P1S_01_CODE=<printer access code>
BAMBU_P1S_01_ENABLED=true
# A Long Tail login the print driver signs in with
LT_USERNAME=superadmin
LT_PASSWORD=<the password you set>

env.ts turns each enabled printer into a print station:

examples/workflows/bambu-printer/env.ts
function printerDef(p: BambuPrinter): MachineDef {
return {
machineId: p.station,
address: p.serial,
process: PRINT_PROCESS,
description: `Bambu printer ${p.station}`,
carrier: 'none',
cycleSec: 3600,
changeoverSec: 0,
rejectReason: 'PRINT-FAILED',
recipes: { [PRINT_RECIPE.id]: [PRINT_RECIPE.version] },
materials: [],
measurements: [],
faults: {},
queueDepth: 1,
requireArtifact: true,
};
}
/** The line of enabled printers: one print station each, a person unloads, a person services. */
export function bambuLine(printers: BambuPrinter[], env: Env = process.env): LineDef {
const enabled = printers.filter((p) => p.enabled);
if (!enabled.length) throw new Error('no printer is enabled; set BAMBU_<STATION>_ENABLED=true for one');
return {
siteId: required(env, 'BAMBU_SITE_ID'),
lineId: required(env, 'BAMBU_LINE_ID'),
roles: { exit: BAMBU_ROLES.UNLOAD, operator: BAMBU_ROLES.SERVICING },
machines: enabled.map(printerDef),
};
}

machine-site writes the result next to the site’s certificates, and Long Tail loads it with MACHINE_LINE_CONFIG or Machines.loadLine:

deploy/bambu-site/line.json
{
"siteId": "site-1",
"lineId": "print-1",
"roles": {
"exit": "print-unload",
"operator": "print-servicing"
},
"machines": [
{
"machineId": "p1s-01",
"address": "01P00A000000001",
"process": "print",
"description": "Bambu printer p1s-01",
"carrier": "none",
"cycleSec": 3600,
"changeoverSec": 0,
"rejectReason": "PRINT-FAILED",
"recipes": { "print-file": ["1"] },
"materials": [],
"measurements": [],
"faults": {},
"queueDepth": 1,
"requireArtifact": true
}
]
}

On the floor

A second printer is one more station in BAMBU_PRINTERS and one more block. Setting ENABLED=false takes a printer off the line without deleting its block, for a nozzle swap or a repair. .env is gitignored, so the access codes stay on the machine that runs the site.

The guarantee

The line holds only enabled printers, each addressed by its serial. queueDepth: 1 gives each printer one print at a time, and requireArtifact: true refuses a print escalation that names no file. See Machines.