Initial commit for i0T.app and migration here with a fresh repo
This commit is contained in:
224
README.md
Normal file
224
README.md
Normal file
@@ -0,0 +1,224 @@
|
||||
# printcontrol
|
||||
|
||||
A keyboard-driven TUI for monitoring and controlling a 3D printer over USB
|
||||
serial. One static Go binary, zero runtime dependencies, theme-aware via
|
||||
your terminal's 16-colour palette — designed to feel at home on Omarchy
|
||||
alongside `wiremix`, `lazygit`, `lazydocker`, and friends.
|
||||
|
||||
The model: **the printer is in charge during an SD print, we observe and
|
||||
adjust.** Start a print from the LCD, the SD card, or printcontrol's own
|
||||
SD picker — then live-monitor temps, progress, and ETA, and tweak feedrate,
|
||||
flow, fan, hotend / bed setpoints, or babystep Z without ever leaving the
|
||||
keyboard. Quit and come back later; the printer keeps printing and
|
||||
printcontrol rediscovers the in-progress job on reconnect.
|
||||
|
||||
```
|
||||
┌─ printcontrol · 3D printer TUI ────────────────────────────────────────┐
|
||||
│ ● Status │ ● Temperatures │
|
||||
│ Connection: /dev/ttyUSB1 @ 115200 │ Hotend: 201.3 / 210.0 °C │
|
||||
│ · Marlin 2.1.2 │ Bed: 60.2 / 60.0 °C │
|
||||
│ File: benchy.gcode SD PRINT │ │
|
||||
│ Progress: [██████████··········] │ set hotend: [h] │
|
||||
│ ETA: 1h 12m │ set bed: [b] │
|
||||
├─────────────────────────────────────┴────────────────────────────────────┤
|
||||
│ ● Controls │
|
||||
│ Feedrate: 110% [-/+] [0] Flow: 100% [ [ / ] ] Fan: 30% [f/F] │
|
||||
│ Babystep Z: -0.050 [{ / }] [Z] │
|
||||
│ press [g] to send raw G-code │
|
||||
├──────────────────────────────────────────────────────────────────────────┤
|
||||
│ ● Log │
|
||||
│ > M105 │
|
||||
│ < ok T:201.3 /210.0 B:60.2 /60.0 @:127 B@:0 │
|
||||
├──────────────────────────────────────────────────────────────────────────┤
|
||||
│ [c] connect [d] disconnect [s] sd start [p] pause [r] resume [x] cancel │
|
||||
│ [h] hotend [b] bed [g] gcode [q] quit │
|
||||
└──────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Install
|
||||
|
||||
Build from source — needs Go 1.22+. The repo's canonical install target is
|
||||
`~/.local/bin` (matches Omarchy's PATH); adjust `GOBIN` if you want it
|
||||
elsewhere.
|
||||
|
||||
```bash
|
||||
cd go
|
||||
GOBIN=$HOME/.local/bin go install ./cmd/printcontrol
|
||||
```
|
||||
|
||||
You need permission to open the serial port. On Arch / Omarchy that means
|
||||
membership in the `uucp` group:
|
||||
|
||||
```bash
|
||||
groups | grep -q uucp || sudo usermod -aG uucp "$USER" # then log out and back in
|
||||
```
|
||||
|
||||
Verify the printer is visible:
|
||||
|
||||
```bash
|
||||
ls /dev/ttyACM* /dev/ttyUSB* 2>/dev/null
|
||||
```
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
printcontrol # auto-detect port AND baud
|
||||
printcontrol -port /dev/ttyUSB1 # lock the port, still auto-baud
|
||||
printcontrol -port /dev/ttyUSB1 -baud 250000
|
||||
printcontrol -no-connect # launch without touching serial
|
||||
```
|
||||
|
||||
### Flags
|
||||
|
||||
| Flag | Default | Description |
|
||||
|---------------|----------|----------------------------------------------------------|
|
||||
| `-port` | *(auto)* | Serial device path. Scans `/dev/ttyACM*` + `/dev/ttyUSB*` if empty. |
|
||||
| `-baud` | `0` | Baud rate. `0` = auto-detect from `[250000, 115200, 230400, 500000, 57600]`. |
|
||||
| `-no-connect` | `false` | Skip auto-connect on launch. |
|
||||
|
||||
### Auto-detect
|
||||
|
||||
With no flags, printcontrol scans every plausible serial device and probes
|
||||
each candidate baud until something replies with an unmistakably
|
||||
printer-shaped line (`Marlin`, `FIRMWARE_NAME`, `RepRapFirmware`, `Klipper`,
|
||||
or a `T:.../...` temperature report). Two-letter tokens like `"ok"` are
|
||||
*not* accepted as a match because they appear too easily in
|
||||
misaligned-baud garbage. Worst-case probe time is ~15 s; first match wins
|
||||
and the rest are skipped.
|
||||
|
||||
The connect flash at the bottom of the screen reports the chosen
|
||||
combination — e.g. `connected: /dev/ttyUSB1 @ 115200`.
|
||||
|
||||
### Keys (top-level)
|
||||
|
||||
| Key | Action |
|
||||
|-----------|-----------------------------------------|
|
||||
| `c` | Connect / reconnect |
|
||||
| `d` | Disconnect |
|
||||
| `s` | List SD card and pick a file to print |
|
||||
| `p` | Pause SD print (`M25`) |
|
||||
| `r` | Resume (`M24`) |
|
||||
| `x` | Cancel SD print (`M524`) |
|
||||
| `h` | Focus hotend setpoint input |
|
||||
| `b` | Focus bed setpoint input |
|
||||
| `g` | Focus raw G-code input |
|
||||
| `+` / `-` | Feedrate ±10% |
|
||||
| `0` | Feedrate back to 100% |
|
||||
| `[` / `]` | Flow ±5% (`M221`) |
|
||||
| `f` / `F` | Fan ±10% |
|
||||
| `{` / `}` | Babystep Z ∓0.05 mm (`M290`, Marlin) |
|
||||
| `Z` | Reset babystep to zero |
|
||||
| `q` | Quit |
|
||||
|
||||
When a text input is focused: type the value, `Enter` to commit, `Esc` to
|
||||
cancel.
|
||||
|
||||
### SD start workflow (key: `s`)
|
||||
|
||||
1. Press `s`. printcontrol sends `M21` (mount SD) and `M20` (list files).
|
||||
2. A picker appears in place of the Log panel.
|
||||
3. `↑`/`↓` (or `k`/`j`) to highlight, `Enter` to start the print, `Esc` to
|
||||
dismiss without printing.
|
||||
4. Selecting a file sends `M23 <filename>` then `M24`. The print runs from
|
||||
the SD card, autonomously of printcontrol.
|
||||
5. You can `q` immediately after — the printer doesn't care. Reconnect any
|
||||
time; the `M27` poll discovers the in-progress print within ~5 seconds
|
||||
and Status / Progress / ETA repopulate.
|
||||
|
||||
Notes:
|
||||
- The picker shows the long filename if the firmware reports one, but
|
||||
always passes the **short 8.3 name** to `M23` (that's what Marlin
|
||||
requires).
|
||||
- Nested folders are listed but can't currently be entered. File a request
|
||||
if you need it.
|
||||
|
||||
## Register with the Omarchy launcher
|
||||
|
||||
Once you're happy with it, drop a desktop entry so SUPER+SPACE finds it:
|
||||
|
||||
```bash
|
||||
omarchy-tui-install printcontrol printcontrol float <icon-url>
|
||||
```
|
||||
|
||||
`float` makes Hyprland treat it as a floating window — usually the right
|
||||
call for a single-pane TUI. Switch to `tile` if you'd rather have it in
|
||||
your tiling layout.
|
||||
|
||||
## What works · what doesn't
|
||||
|
||||
**Works today**
|
||||
|
||||
- Auto-detect serial port and baud rate
|
||||
- Connect / disconnect over USB serial (multi-port scan)
|
||||
- Live temperatures (hotend, bed, chamber if present) every 2 s
|
||||
- SD-card print detection, progress %, ETA
|
||||
- SD card file listing (`M20`) and start (`M23` + `M24`) from the TUI
|
||||
- Pause / resume / cancel (`M25` / `M24` / `M524`)
|
||||
- Temperature setpoints (`M104` / `M140`)
|
||||
- Fan, feedrate, flow controls (`M106` / `M220` / `M221`)
|
||||
- Babystep Z (`M290` — Marlin)
|
||||
- Raw G-code entry
|
||||
- Firmware identification (`M115`)
|
||||
- Adaptive log panel (footer stays visible on short terminals)
|
||||
|
||||
**Not yet**
|
||||
|
||||
- Host-side print streaming (sending a `.gcode` file from the computer).
|
||||
Needs the line-numbered protocol with checksum + resend handling.
|
||||
- Klipper-specific babystep (`SET_GCODE_OFFSET`). Sends `M290` today, which
|
||||
Klipper rejects.
|
||||
- SD folder navigation (`M20 <dir>`).
|
||||
- Octoprint / Moonraker backends. Architecture supports it; see
|
||||
`ARCHITECTURE.md`.
|
||||
- Persisted profiles (per-printer last setpoints, preferred port).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**"no responsive printer on \[...]"** — Auto-detect probed every
|
||||
`ttyACM`/`ttyUSB` device at every common baud and didn't find a printer
|
||||
signature. Most often this means another program (OctoPrint, Klipper's
|
||||
`klippy`, `pronsole`) already owns the port. Quit it first, or pass
|
||||
`-port` explicitly. If you have an unusual baud (e.g. `1000000`), pass
|
||||
`-baud` to override the probe.
|
||||
|
||||
**"could not auto-detect baud rate"** — printcontrol *opened* the port but
|
||||
saw no recognisable reply at any candidate baud. Confirm the device is
|
||||
actually a printer (`screen /dev/ttyUSB1 115200`, then send `M115`); also
|
||||
common: the printer is mid-firmware-flash, or the USB cable is power-only.
|
||||
|
||||
**Temps show but progress stays at 0%** — `M27` only reports SD progress.
|
||||
If you started the print from a host (OctoPrint, etc.) progress won't
|
||||
appear here.
|
||||
|
||||
**Babystep does nothing** — You're likely on Klipper, which doesn't
|
||||
implement `M290`. Klipper support is on the roadmap.
|
||||
|
||||
**Mangled lines like `TT::57.4957.49`** — This was the symptom of Marlin's
|
||||
auto-temperature report colliding with our explicit `M105` poll. Fixed
|
||||
upstream: the prime block now sends `M155 S0` / `M27 S0` to disable
|
||||
auto-reports.
|
||||
|
||||
## Layout
|
||||
|
||||
```
|
||||
printcontrol/
|
||||
├── go/
|
||||
│ ├── cmd/printcontrol/main.go # entry point, flag parsing
|
||||
│ ├── internal/printer/ # serial driver + G-code state machine
|
||||
│ │ ├── state.go # State / PrintState / TempPair / SDFile
|
||||
│ │ ├── parse.go # line parsing (M105, M27, M115, M20, ...)
|
||||
│ │ ├── printer.go # Connect/Disconnect, owning goroutine, probe
|
||||
│ │ └── parse_test.go
|
||||
│ └── internal/tui/ # Bubble Tea model + Lipgloss styling
|
||||
│ ├── model.go # Model, key handling, SD picker, layout
|
||||
│ └── style.go
|
||||
├── README.md
|
||||
└── ARCHITECTURE.md # protocol + design notes
|
||||
```
|
||||
|
||||
See `ARCHITECTURE.md` for the wire protocol, the state model, the
|
||||
auto-detect probe strategy, and why things are wired the way they are.
|
||||
|
||||
## License
|
||||
|
||||
GPL-3.0-or-later (matches Printrun, which inspired the protocol layer).
|
||||
Reference in New Issue
Block a user