printer

package
v0.0.0-...-a626a07 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 3, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package printer is the BLE driver and wire-format implementation for the Phomemo M02X pocket thermal printer. See PROTOCOL.md for byte-level details — verified by capturing the official iOS app.

Index

Constants

View Source
const (
	QueryFirmware    = 0x07 // → 1A 07 vL 00 vR  → firmware version "vL.0.vR"
	QueryBattery     = 0x08 // → 1A 04 NN        → battery percent (?)
	QuerySerial      = 0x09 // → 1A 08 <ascii>   → device serial number
	QueryDeviceTimer = 0x0E // → 1A 09 NN
	QueryPaper       = 0x11 // → 1A 06 89/88     → 0x89 paper / 0x88 no paper
	QueryCover       = 0x12 // → 1A 05 98/99     → 0x98 closed / 0x99 open
	QueryTemperature = 0x13 // → 1A 03 a8/a9     → 0xA8 normal / 0xA9 too hot
)

Sensor query opcodes — second byte of `1F 11 NN`. Verified against the M02X by capture; corroborated against the M02-family notification table in jeffrafter/phomemo. Opcodes ≥ 0x15 are unmapped — see PROTOCOL.md for the warning about probing them.

View Source
const (
	DefaultNameEnv = "PHOMEMO_NAME"
)
View Source
const DefaultWidthPx = 384

DefaultWidthPx is the print width for the M02X (53 mm paper, 203 dpi). Other M02 family members use different widths — M02S=512, M02 Pro=576 — override per Printer.Width if needed.

Variables

View Source
var Density byte = 2

Density sets the per-pixel heat the M02X applies, sent in the per-print header as the second byte of the `1F 11 02 NN` sequence. The official iOS app uses 0x02. Higher values may produce darker output but the upper bound is undocumented.

View Source
var Verbose bool

Verbose dumps every BLE write and notification to stderr in hex.

Functions

func Pack1bpp

func Pack1bpp(img image.Image, width int) ([]byte, int)

Pack1bpp converts an image to 1-bit-per-pixel packed bytes, MSB-first across each row, with 1=black so the M02 firmware prints it correctly.

The image is assumed to already be the target width. Height is preserved. Anything ≥ mid-luminance is treated as white; pre-dither before calling.

Types

type Printer

type Printer struct {
	Width int
	// contains filtered or unexported fields
}

func Open

func Open(ctx context.Context, name string) (*Printer, error)

Open scans for a Phomemo printer by advertised local name and connects.

macOS hides the device's actual MAC behind a per-host opaque CBUUID, so we cannot pin by MAC; matching is always by name. Empty name defaults to "M02X" (and falls back to any name starting with "M0").

func (*Printer) Close

func (p *Printer) Close() error

func (*Printer) Feed

func (p *Printer) Feed(n int) error

Feed advances n blank lines. Unused on M02X for normal prints (head auto-feeds when raster ends) but exposed for interactive testing.

func (*Printer) Init

func (p *Printer) Init() error

Init wakes the printer and primes its print state. Sequence captured from the iOS Phomemo app — every byte is required, in order, with a brief pause between each step.

func (*Printer) PrintImage

func (p *Printer) PrintImage(img image.Image) error

PrintImage emits one raster block containing the entire image, padded with blank lines so the printed content advances past the tear bar. The caller is responsible for any resize / dither — this method packs to 1bpp and frames as ESC@ + M02X init + GS v 0 + raster bytes.

PrintImage blocks until either the printer notifies "print complete" or a generous timeout expires. Without this wait, Close() may disconnect while the firmware is still draining its raster buffer, causing the last several rows to silently not fire the head.

func (*Printer) Query

func (p *Printer) Query(opcode byte) ([]byte, error)

Query sends `1F 11 NN` and waits up to 1 s for the printer's reply. Returns the raw notification frame (including the leading `0x1A`).

func (*Printer) Write

func (p *Printer) Write(data []byte) error

Write uses GATT Write Request (with response). Most M02X protocol bytes don't work this way; use WriteData for everything except interactive debugging.

func (*Printer) WriteData

func (p *Printer) WriteData(data []byte) error

WriteData sends bytes via GATT Write Without Response, the only mode the M02X firmware acts on for the print sequence.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL