PrinterPrinter is a local daemon that runs alongside Bambuddy, watches configured Bambu printers for print starts, and auto-prints job labels to a USB-connected Dymo LabelWriter (such as the LabelWriter 400 Turbo via CUPS) or a network Brother QL-820NWB.
flowchart LR
A["Bambu P1S Printers"] -->|"Status + Print State"| B["Bambuddy API"]
B -->|"Poll every N seconds"| C["PrinterPrinter Daemon"]
C --> D[("SQLite Event Store")]
C --> E["Dymo LabelWriter 400 Turbo (USB/CUPS)\nor Brother QL-820NWB (TCP)"]
C --> F["Admin UI & Endpoints\n/admin /probes/printer /admin/print-event/{id}"]
Dymo 30336 compact label (1" x 2-1/8" / 25x54mm):
Brother DK-1202 / Dymo 30256 full shipping label (62x100mm / 59x102mm):
- Bambuddy connectivity check and printer discovery
- Print-start detection from printer state transitions
- Event persistence in SQLite
- Automatic label print on new start events
- Manual reprint endpoint
- Configurable price-per-gram and optional price display
- User-friendly date/time and duration formatting
GET /healthGET /probes/bambuddyGET /probes/printerPOST /admin/poll-onceGET /admin/printersGET /admin/eventsGET /admin/uiGET /adminGET /admin/configPOST /admin/configPOST /admin/actions/setup-dymoPOST /admin/actions/restartPOST /admin/actions/updateGET /admin/label-preview/{event_id}.pngPOST /admin/print-event/{event_id}
Copy .env.example to .env and update values.
PRINTERPRINTER_HOST(default0.0.0.0)PRINTERPRINTER_PORT(default8080)PRINTERPRINTER_LOG_LEVEL(defaultINFO)PRINTERPRINTER_DB_PATH(default./data/printerprinter.sqlite3)PRINTERPRINTER_POLL_INTERVAL_SECONDS(default5)PRINTERPRINTER_LABEL_WAIT_SECONDS(default60; wait window for missing duration/filament before deferring print)PRINTERPRINTER_LABEL_WAIT_POLL_SECONDS(default5; refresh interval during wait window)PRINTERPRINTER_PENDING_LABEL_MAX_AGE_SECONDS(default900; only auto-print deferred events younger than this)PRINTERPRINTER_ENV_FILE_PATH(default.env; config file used by admin UI save flow)PRINTERPRINTER_SERVICE_NAME(defaultprinterprinter; systemd service name for restart/update actions)PRINTERPRINTER_INSTALL_DIR(default/opt/printerprinter; repository path used by update action)PRINTERPRINTER_UPDATE_BRANCH(defaultmain; branch used by update action)PRINTERPRINTER_VENV_PATH(default/opt/printerprinter/venv; virtualenv used for update install)PRINTERPRINTER_MONITORED_PRINTER_IDS(comma-separated Bambuddy numeric IDs, empty means all)PRINTERPRINTER_MONITORED_PRINTER_IDENTIFIERS(comma-separated IDs, names, serials, or IPs to auto-resolve)
BAMBUDDY_BASE_URL(examplehttp://10.206.50.172:8000)BAMBUDDY_API_TOKENBAMBUDDY_TIMEOUT_SECONDS(default15)BAMBUDDY_AUTH_MODE(bearer,api_key_header,none)BAMBUDDY_AUTH_HEADER_NAME(defaultX-API-Key)BAMBUDDY_JOBS_ENDPOINT(default/api/v1/print-log/)BAMBUDDY_PRINTERS_ENDPOINT(default/api/v1/printers/)BAMBUDDY_PRINTER_STATUS_ENDPOINT_TEMPLATE(default/api/v1/printers/{printer_id}/status)
PRINTER_BACKEND(dymoorbrother, defaultbrother)PRINTER_ENABLED(true/false, fallback aliasBROTHER_ENABLED)PRINTER_INTERFACE(usb,auto,wifi; defaultusbfor Dymo)PRINTER_LABEL_SIZE(media SKU, fallback aliasesDYMO_LABEL_SIZE/BROTHER_LABEL_SIZE)
DYMO_MODEL(defaultLabelWriter-400-Turbo)DYMO_USB_QUEUE_NAME(optional; auto-discovers USB Dymo CUPS queue when blank, or set e.g.DYMO_LabelWriter_400_Turbo)DYMO_WIFI_QUEUE_NAME(required only whenPRINTER_INTERFACE=wifi)DYMO_PRINT_QUALITY(GraphicsorText, defaultGraphics)DYMO_PRINT_DENSITY(Light,Medium,Normal,Dark, defaultNormal)DYMO_JOB_EXPIRE_SECONDS(default300; auto-cancels unprinted CUPS jobs after 5 minutes if out of paper so old jobs never pile up)
Supported Dymo media SKUs (automatically mapped to exact 300 DPI lw400t.ppd PageSize dimensions and compact/full layouts):
30336(1" x 2-1/8"/25x54mmSmall Multipurpose — uses high-density compact layout)30252/30320/99010(1-1/8" x 3-1/2"/28x89mmStandard Address)30321/99012(1-4/10" x 3-1/2"/36x89mmLarge Address)30256(2-5/16" x 4"/59x102mmShipping — full layout)30323/99014(2-1/8" x 4"/54x101mmShipping — full layout)30334/11354(2-1/4" x 1-1/4"/57x32mmMulti-Purpose)
Quick Dymo USB setup on an existing Raspberry Pi installation:
sudo bash /opt/printerprinter/scripts/setup-dymo-cups.sh DYMO_LabelWriter_400_Turbo 30336Or click Setup Dymo USB directly in the Admin UI (http://<pi-host>:8080/admin).
BROTHER_MODEL(defaultQL-820NWB)BROTHER_PRINTER_URI(exampletcp://10.206.58.111:9100)BROTHER_CUT(true/false)PRINTER_LABEL_SIZE=62x100(DK-1202)
SHOW_PRICE_ON_LABEL(true/false)FILAMENT_PRICE_PER_GRAM(default0.10)
If price display is enabled, filament is shown as:
Filament: 42g ($4.20)
Mass is rounded to the nearest gram before both display and price calculation.
- Create and activate a virtual environment.
- Install dependencies.
- Configure
.env. - Run the daemon.
python3 -m venv .venv
. .venv/bin/activate
pip install -e .
uvicorn printerprinter.main:app --host 0.0.0.0 --port 8080Quick checks:
curl http://localhost:8080/health
curl http://localhost:8080/probes/bambuddy
curl http://localhost:8080/admin/printers
curl -X POST http://localhost:8080/admin/poll-once
curl http://localhost:8080/admin/eventsRun the setup script to fully set up PrinterPrinter with interactive configuration prompts. Choose one of the methods below:
If an existing .env is present, the installer will show the current values first and let you keep them to skip the prompts.
Method 1: Pipe directly to bash (requires bash 4.1+, use Method 2 if this fails)
curl -fsSL https://raw.githubusercontent.com/firstbuild/PrinterPrinter/main/scripts/setup-rpi.sh | sudo bashMethod 2: Download then run (most reliable, recommended if Method 1 fails)
curl -fsSL https://raw.githubusercontent.com/firstbuild/PrinterPrinter/main/scripts/setup-rpi.sh -o /tmp/setup.sh
sudo bash /tmp/setup.shMethod 3: Clone repo locally (manual)
cd /tmp
git clone -b main https://github.com/firstbuild/PrinterPrinter.git
cd PrinterPrinter
sudo bash scripts/setup-rpi.shSpecify a different branch by passing it as an argument (Methods 2 & 3):
sudo bash /tmp/setup.sh developThe setup script will:
- Check and install system dependencies
- Clone or update the repository
- Create a Python virtual environment
- Install dependencies
- Prompt you for all configuration values (Bambuddy address, API key, printer IPs, pricing, etc.)
- Create a systemd service file
- Enable and start the daemon
After setup completes, monitor logs with:
journalctl -u printerprinter -fIf you prefer to set up manually, follow these steps:
These instructions assume Raspberry Pi OS 64-bit and Python 3.11+.
- Install system packages.
sudo apt update
sudo apt install -y git python3 python3-venv python3-pip- Clone and install.
git clone <your-repo-url> PrinterPrinter
cd PrinterPrinter
python3 -m venv .venv
. .venv/bin/activate
pip install -e .
cp .env.example .env- Edit
.envfor your network:
BAMBUDDY_BASE_URL=http://<bambuddy-ip>:8000BROTHER_PRINTER_URI=tcp://<brother-ip>:9100BAMBUDDY_API_TOKEN=<token>
- Create systemd service.
/etc/systemd/system/printerprinter.service
[Unit]
Description=PrinterPrinter Daemon
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=pi
WorkingDirectory=/home/pi/PrinterPrinter
EnvironmentFile=/home/pi/PrinterPrinter/.env
ExecStart=/home/pi/PrinterPrinter/.venv/bin/uvicorn printerprinter.main:app --host 0.0.0.0 --port 8080
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target- Enable and start.
sudo systemctl daemon-reload
sudo systemctl enable printerprinter
sudo systemctl start printerprinter
sudo systemctl status printerprinter- View logs.
journalctl -u printerprinter -fThis repository includes:
Dockerfiledocker-compose.example.yml
- Set
.envwith Bambuddy LAN URL, for example:
BAMBUDDY_BASE_URL=http://bambuddy.local:8000
- Build and run:
docker compose -f docker-compose.example.yml up -d --buildIf your Bambuddy service is named bambuddy in compose, set:
BAMBUDDY_BASE_URL=http://bambuddy.local:8000
Use shared compose network (default) so service DNS works.
- On Linux,
network_mode: hostmay simplify LAN printer discovery/access. - On macOS/Windows Docker Desktop, host networking differs; prefer direct IP routing where possible.
- Ensure container can reach TCP
9100on Brother printer.
- Keep API tokens out of git; do not commit
.env. - Use
PRINTERPRINTER_MONITORED_PRINTER_IDSto limit label scope. - If labels fail, test printer reachability:
ping <brother-ip>
nc -vz <brother-ip> 9100- Trigger manual reprint by event ID:
curl -X POST http://localhost:8080/admin/print-event/123- Dymo USB not appearing in
lsusb: The Dymo LabelWriter 400 Turbo is not USB-bus-powered. Confirm its 24V DC power adapter is plugged into live AC power (front blue feed LED lit or flashing) and both the barrel plug and USB-B plug are firmly seated in the recessed channel underneath the base. - Dymo out of paper: When out of labels, the front LED flashes and PrinterPrinter detects the out-of-paper state via USB/CUPS (
GET /probes/printer), failing cleanly (and expiring any queued CUPS job afterDYMO_JOB_EXPIRE_SECONDS) so stale jobs will not mass-print when a new roll is loaded. Wrong roll type/ clipped print: verifyPRINTER_LABEL_SIZEmatches the physical roll (30336for1" x 2-1/8",30256for2-5/16" x 4",62x100for Brother DK-1202).- No prints: verify
PRINTER_ENABLED=trueand check/probes/printeror/admin. - Bambuddy timeout/DNS issues: use direct IP in
BAMBUDDY_BASE_URL. - Price hidden unexpectedly: verify
SHOW_PRICE_ON_LABEL=true.

