Skip to content

sgrankin/phomemo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

36 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

phomemo

A Go CLI and library for the Phomemo M02X pocket thermal printer. Connects over Bluetooth Low Energy, renders text / images / barcodes / weather / Markdown / etc. into 1-bit bitmaps, and prints them.

The M02X uses a vendor-specific protocol that's similar to but not compatible with the older M02 / M02 Pro / M02S / T02 family — it's not ESC/POS and not the cat-printer framing. The full wire format is documented in PROTOCOL.md, reverse-engineered from a PacketLogger capture of the official iOS app.

Status

  • ✅ M02X — the protocol the code was built against; verified working.
  • ⚠ Older M02 / M02 Pro / M02S — not currently supported. The bones of ESC/POS framing exist in earlier commits if you want to build that path.
  • 🐉 Other Phomemo / re-branded thermal printers — unknown; capture and diff their protocol against ours.

Install

Requires Go 1.26+ and macOS or Linux with a working Bluetooth stack.

go install github.com/sgrankin/phomemo@latest

Or from a clone:

git clone https://github.com/sgrankin/phomemo.git
cd phomemo
go build -o phomemo .

The first BLE scan on macOS will trigger a Bluetooth permission prompt for whichever terminal you're running from.

Usage

phomemo <subcommand> [flags] [args...]

Content

phomemo image photo.jpg                 # PNG/JPEG/GIF/WebP/BMP/TIFF, dithered
phomemo text "Hello world"              # text; reads stdin if arg is "-"
phomemo qr "https://example.com"        # QR code
phomemo pdf417 "wide URL"               # PDF417 (iPhone Camera reads it)
phomemo notify "DOORBELL" "Package on porch"
phomemo weather                         # IP-geolocated forecast w/ icon + sparkline
phomemo wifi MyHomeNet secretpw         # WIFI: QR — phone scans to join
phomemo vcard "Sergey Grankin" -phone +15550100 -email me@example.com
phomemo url "https://news.ycombinator.com"  # QR + page <title> caption
phomemo md NOTES.md                     # render Markdown (headings, lists, code)

Test patterns

phomemo selftest      # text + QR + timestamp
phomemo qualitytest   # bars + gradient + dithered photo
phomemo fonts         # one labeled line per vendored font
phomemo fonts -list   # print family names + sizes (no print)
phomemo bar           # solid or striped bar
phomemo pattern       # stripes / checkerboards / diagonals
phomemo curve hilbert # Hilbert space-filling curve (try -order 5..8)
phomemo curve dragon  # Heighway dragon (try -iter 8..14)
phomemo curve gosper  # flowsnake / hexagonal space-filling
phomemo curve rule30  # Wolfram 1-D CA (try -rule 30, 90, 110, 184)

Daemon

Persistent BLE connection so prints don't pay the scan latency:

phomemo serve -addr 127.0.0.1:8080

Then from anywhere:

curl -d "Hello!" http://localhost:8080/print/text
curl -d '{"title":"DOORBELL","body":"Package on porch"}' \
     -H "Content-Type: application/json" \
     http://localhost:8080/print/notify
curl --data-binary @photo.webp -H "Content-Type: image/webp" \
     http://localhost:8080/print/image

GET / on the running server returns the full endpoint list. Image endpoints accept any format the CLI does (PNG / JPEG / GIF / WebP / BMP / TIFF), driven by Content-Type.

Debug

phomemo scan          # list nearby BLE devices
phomemo ping          # connect + feed paper
phomemo info          # serial, firmware, battery, paper, cover, temperature
phomemo discover      # enumerate GATT services / characteristics
phomemo raw "1b 40" "Hello\n" "1b 64 04"   # send raw hex bytes (multi-arg)

Common flags

-name NAME       BLE local name; default $PHOMEMO_NAME or "M02X"
-feed N          blank lines after content; default 4
-density N       head energy 1..15 (default 2 — what the iOS app uses)
-rotate N        rotate output by 0/90/180/270
-font NAME       body font family (helvetica, times, geneva, chicago,
                 monaco, courier, spleen, sungallant)
-codefont NAME   monospace family for code blocks (monaco, courier, spleen)
-no-print        write rendered PNG to stdout instead of printing
-v               log every BLE write to stderr

Architecture

main.go, serve.go CLI dispatcher + HTTP daemon (module root)
printer/          BLE driver + M02X wire-format protocol
render/           Image rendering (text, QR, PDF417, dither, compose, fonts)
content/          Data sources (weather, wifi, vcard, url, markdown)
internal/smolfont/   Vendored Apple + Spleen + Sun Gallant bitmap fonts

Tests are golden-PNG comparisons in render/testdata/ and content/testdata/. Run go test ./render -update to regenerate after intentional rendering changes.

Credits

Protocol reverse-engineering inheritance:

Bitmap fonts come from the smol collection (Apple classic Mac fonts, Spleen, Sun Gallant).

License

MIT — see LICENSE.

About

Print to Phomemo M02X over bluetooth

Topics

Resources

License

Stars

Watchers

Forks

Contributors

Languages