Skip to content

Commit 5f320ca

Browse files
committed
Initial commit: core library and CLI for Bluetooth thermal printers
- @thermoprint/core: L11 protocol, image pipeline (grayscale β†’ dither β†’ 1bpp), device profiles (P15, P12), credit-based flow control, Printer orchestrator - @thermoprint/cli: Noble BLE transport, sharp image loading, commander CLI with discover, print, status, and config commands - Reverse engineering documentation for Marklife printer protocol - Architecture docs, CI workflow, and project README
0 parents  commit 5f320ca

51 files changed

Lines changed: 4473 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

β€Ž.github/workflows/ci.ymlβ€Ž

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
lint:
11+
name: Lint
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- uses: oven-sh/setup-bun@v2
17+
with:
18+
bun-version: latest
19+
20+
- name: Install dependencies
21+
run: bun install
22+
working-directory: packages/core
23+
24+
- name: Typecheck
25+
run: bun run typecheck
26+
working-directory: packages/core
27+
28+
test:
29+
name: Test
30+
runs-on: ubuntu-latest
31+
steps:
32+
- uses: actions/checkout@v4
33+
34+
- uses: oven-sh/setup-bun@v2
35+
with:
36+
bun-version: latest
37+
38+
- name: Install dependencies
39+
run: bun install
40+
working-directory: packages/core
41+
42+
- name: Run tests
43+
run: bun test
44+
working-directory: packages/core

β€Ž.gitignoreβ€Ž

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
node_modules/
2+
dist/
3+
bun.lockb
4+
*.tsbuildinfo
5+
6+
# OS
7+
.DS_Store
8+
Thumbs.db
9+
10+
# Editor
11+
.vscode/
12+
.idea/
13+
*.swp
14+
*.swo
15+
16+
# Decompiled APK
17+
com.feioou.deliprint.yxq.apk/
18+
19+
# Test artifacts
20+
test-label.png
21+
22+
# Config
23+
.env
24+
.env.*
25+
26+
# Claude Code local settings
27+
.claude/settings.local.json

β€ŽREADME.mdβ€Ž

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
# πŸ–¨οΈ thermoprint
2+
3+
TypeScript toolkit for Bluetooth thermal printers. Discover, connect, and print from the command line or your own code.
4+
5+
```
6+
$ thermoprint discover
7+
Found 1 printer(s):
8+
9+
P15 a1b2c3d4-... RSSI: -52 Model: p15
10+
11+
$ thermoprint print label.png
12+
βœ” Print complete!
13+
```
14+
15+
## Supported Printers
16+
17+
| Model | Protocol | Print Width | Status |
18+
|-------|----------|-------------|--------|
19+
| Marklife P15 | L11 | 384 px (48 mm) | Fully supported |
20+
| Marklife P12 | L11 | 384 px (48 mm) | Fully supported |
21+
| Marklife P7 | L11 | 384 px (48 mm) | Fully supported |
22+
| Other L11-compatible | L11 | Varies | Should work |
23+
24+
Adding a new printer is just a [device profile](docs/adding-a-printer.md) β€” a plain object with UUIDs and settings.
25+
26+
## Packages
27+
28+
```
29+
thermoprint/
30+
packages/
31+
core/ @thermoprint/core β€” protocol, image pipeline, device profiles
32+
cli/ @thermoprint/cli β€” command-line interface (Noble + sharp)
33+
```
34+
35+
### `@thermoprint/core`
36+
37+
Platform-agnostic library. No BLE dependency β€” you inject a `BleTransport` for your runtime.
38+
39+
```typescript
40+
import { Printer, discover } from "@thermoprint/core";
41+
import { NobleBleTransport } from "./my-transport";
42+
43+
const transport = new NobleBleTransport();
44+
const peripheral = await discover(transport, { timeoutMs: 5000 });
45+
const printer = await Printer.connect(transport, peripheral);
46+
47+
await printer.print(myImageData, { density: 2, paperType: "gap" });
48+
await printer.disconnect();
49+
```
50+
51+
### `@thermoprint/cli`
52+
53+
Ready-to-use CLI powered by Noble and sharp.
54+
55+
```bash
56+
thermoprint discover # Find nearby printers
57+
thermoprint print photo.png # Print an image
58+
thermoprint status # Battery + status
59+
thermoprint config set width 320 # Configure for your label size
60+
```
61+
62+
See the full [CLI documentation](packages/cli/README.md).
63+
64+
## Quick Start
65+
66+
```bash
67+
# Clone
68+
git clone <repo-url> && cd thermoprint
69+
70+
# Install
71+
bun install
72+
73+
# Discover printers (requires Bluetooth)
74+
bun run packages/cli/src/index.ts discover
75+
76+
# Print an image
77+
bun run packages/cli/src/index.ts print my-label.png
78+
```
79+
80+
## Architecture
81+
82+
```
83+
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
84+
β”‚ CLI β”‚ commander + chalk + ora
85+
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
86+
β”‚ Printer orchestrator β”‚ connect, print, events
87+
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
88+
β”‚ Image β”‚ Protocol β”‚ Device β”‚
89+
β”‚ pipeline β”‚ (L11) β”‚ registry β”‚
90+
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
91+
β”‚ FlowController β”‚ Credit-based BLE chunking
92+
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
93+
β”‚ BleTransport (injected) β”‚ Noble, Web Bluetooth, etc.
94+
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
95+
```
96+
97+
**Image pipeline:** RGBA β†’ grayscale β†’ Floyd-Steinberg dither β†’ 1-bit pack β†’ raster commands
98+
99+
**Flow control:** Credit-based backpressure prevents buffer overflow on the printer. The host waits for credit grants before sending each packet.
100+
101+
**Protocol:** L11 is a binary raster protocol. The printer has no built-in fonts β€” all content (text, images, barcodes) is rendered to a bitmap before sending.
102+
103+
## Project Structure
104+
105+
```
106+
thermoprint/
107+
β”œβ”€β”€ packages/
108+
β”‚ β”œβ”€β”€ core/
109+
β”‚ β”‚ └── src/
110+
β”‚ β”‚ β”œβ”€β”€ printer.ts # Printer orchestrator
111+
β”‚ β”‚ β”œβ”€β”€ discovery.ts # BLE discovery helpers
112+
β”‚ β”‚ β”œβ”€β”€ transport/ # BleTransport interface + FlowController
113+
β”‚ β”‚ β”œβ”€β”€ protocol/l11/ # L11 binary protocol
114+
β”‚ β”‚ β”œβ”€β”€ device/ # Device profiles + registry
115+
β”‚ β”‚ └── image/ # RGBA β†’ 1bpp pipeline
116+
β”‚ └── cli/
117+
β”‚ └── src/
118+
β”‚ β”œβ”€β”€ cli/commands/ # discover, print, status, config
119+
β”‚ β”œβ”€β”€ transport/noble.ts # Noble BLE adapter
120+
β”‚ β”œβ”€β”€ image/load.ts # Image loading with sharp
121+
β”‚ └── store/config.ts # ~/.thermoprint/config.json
122+
β”œβ”€β”€ docs/ # Architecture & guides
123+
└── REVERSE_ENGINEERING.md # Protocol documentation
124+
```
125+
126+
## Documentation
127+
128+
- [Architecture](docs/architecture.md) β€” design decisions, layer diagram, data flow
129+
- [Transport](docs/transport.md) β€” BleTransport interface and flow control
130+
- [Image Pipeline](docs/image-pipeline.md) β€” grayscale, dithering, bit packing
131+
- [Adding a Printer](docs/adding-a-printer.md) β€” how to add a new device profile
132+
- [Reverse Engineering](REVERSE_ENGINEERING.md) β€” protocol analysis from the Android app
133+
134+
## Tech Stack
135+
136+
- **Runtime:** [Bun](https://bun.sh)
137+
- **Language:** TypeScript (strict, ESNext)
138+
- **BLE:** [@stoprocent/noble](https://github.com/nicedoc/noble) (CLI), pluggable via `BleTransport`
139+
- **Image processing:** [sharp](https://sharp.pixelplumbing.com)
140+
- **CLI:** [Commander.js](https://github.com/tj/commander.js) + [chalk](https://github.com/chalk/chalk) + [ora](https://github.com/sindresorhus/ora)
141+
142+
## License
143+
144+
MIT

0 commit comments

Comments
Β (0)