No description
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-07-21 18:11:40 +08:00
spoolman_audit Add keyboard emulation mode, add info mode 2026-07-21 18:11:40 +08:00
tests Add keyboard emulation mode, add info mode 2026-07-21 18:11:40 +08:00
.env.example Add keyboard emulation mode, add info mode 2026-07-21 18:11:40 +08:00
.gitignore Proof of concept desktop app 2026-07-19 03:44:13 +08:00
.pre-commit-config.yaml Proof of concept desktop app 2026-07-19 03:44:13 +08:00
prices.json Proof of concept desktop app 2026-07-19 03:44:13 +08:00
pyproject.toml Proof of concept desktop app 2026-07-19 03:44:13 +08:00
README.md Add keyboard emulation mode, add info mode 2026-07-21 18:11:40 +08:00
uv.lock Proof of concept desktop app 2026-07-19 03:44:13 +08:00

Spoolman Audit

Link a set of USB scales, a USB barcode scanner (serial or keyboard emulation), and a Spoolman instance.

Scan a Spoolman spool QR code → wait for a stable scale reading → send the gross weight to Spoolman (PUT /api/v1/spool/{id}/measure). Spoolman subtracts the configured empty-spool weight and updates remaining filament.

Setup

Requires uv.

uv sync
copy .env.example .env
uv run pre-commit install

Edit .env with your Spoolman URL and hardware settings. Serial ports look like COM18 on Windows and /dev/cu.usbmodem14101 on macOS/Linux. Set SCANNER_INPUT_MODE=keyboard when the scanner uses keyboard emulation; SCANNER_PORT is then optional.

Run

Opens the CustomTkinter desktop UI by default:

uv run spoolman-audit

Console-only mode:

uv run spoolman-audit --headless

Demo mode (no hardware)

Mocks the scanner, scales, and Spoolman so you can exercise the UI locally:

uv run spoolman-audit --demo

Use Place on scales then Scan with spool IDs 1, 2, or 3 (sample mock spools). Same via env: DEMO_MODE=true.

Individual mocks: SCANNER_MOCK, SCALES_MOCK, SPOOLMAN_MOCK. With only SCALES_MOCK=true, the UI still shows Place on scales / Clear scales.

Development

uv sync --group dev
uv run ruff check .
uv run ruff format .

A git pre-commit hook runs Ruff (check with autofix, then format) on staged files. Install it once with uv run pre-commit install.

Flow

  1. Resting overlay asks you to place filament on the scales (≥100 g), then scan the inventory QR code.
  2. App listens on the scanner serial port or captures keyboard-emulated scans anywhere in its window.
  3. On a web+spoolman:s-{id} barcode, it fetches the spool from Spoolman.
  4. If the scales are below 100 g, it shows the spool in info mode without updating its weight.
  5. Otherwise, it waits until the scales report a stable weight for SCALES_STABLE_SECONDS.
  6. That gross weight (grams) is posted to Spoolmans measure endpoint.
  7. Remaining weight from the API response is shown for 60 seconds, then the UI returns to the resting overlay.

Scales protocol

Expected frame shape (from the original prototype):

<stability>\r<weight>\r<unused>\r\n

Stability byte 0x00 means stable; non-zero means unstable. Weight is parsed as grams.

Pricing

Tier rates live in prices.json (member and non-member price per gram). Filament tier is read from Spoolmans filament extra.tier field and shown in the UI with rates when defined.

Settings

Variable Required Default Meaning
SPOOLMAN_URL yes Base URL, e.g. http://192.168.3.6:7912
SCANNER_INPUT_MODE no serial serial or keyboard
SCANNER_PORT yes* Scanner serial port
SCALES_PORT yes* Scales serial port
SCALES_MOCK no false Random weights; skips real scales
SCANNER_BAUDRATE no 9600
SCALES_BAUDRATE no 9600
SCALES_STABLE_SECONDS no 1.0 How long weight must stay stable
SCALES_TIMEOUT_SECONDS no 10.0 Give up waiting for a stable reading

* SCANNER_PORT is only required in serial mode. SCALES_PORT is not required when SCALES_MOCK=true.