Printer

High-level SDK facade for the GoojPrt PT-210 thermal printer.

GoojPrtPT210 is the entry point of the SDK. It owns both transports (BLE / SPP), composes goojprt.commands, goojprt.raster and goojprt.rendering into an ergonomic API, and exposes a dual set of methods:

  • BLE (async)connect_ble / print_text / print_image / … . This is the primary, cross-platform path.

  • SPP (sync, Linux only)connect_spp / print_text_spp / … . Preserved for callers that need classic RFCOMM.

The two API surfaces share the underlying byte builders so their output is byte-identical.

class goojprt.printer.GoojPrtPT210[source]

Bases: object

Driver for the GoojPrt PT-210 thermal printer (48 mm / 384 px head).

Supports BLE (async, cross-platform, primary) and classic Bluetooth SPP (sync, Linux only). Both API surfaces are exposed side-by-side for backward compatibility.

Example (BLE):

import asyncio
from goojprt import GoojPrtPT210

async def main() -> None:
    printer = GoojPrtPT210()
    await printer.connect_ble("XX:XX:XX:XX:XX:XX")
    await printer.initialize()
    await printer.print_text("Hello, world!")
    await printer.feed(3)
    await printer.disconnect()

asyncio.run(main())
async connect_ble(address: str, *, on_disconnect=None) None[source]

Connect to the printer over BLE.

Creates the BLE transport lazily on first use.

connect_spp(address: str, port: int = 1) None[source]

Connect to the printer over classic Bluetooth SPP (Linux only).

async cut() None[source]

Trigger the cutter (no-op on PT-210, which has no cutter hardware).

cut_spp() None[source]

Trigger the cutter over SPP (no-op on PT-210).

async disconnect() None[source]

Disconnect the BLE client (see BleTransport.disconnect()).

disconnect_spp() None[source]

Close the SPP socket.

async feed(lines: int = 3) None[source]

Feed paper by lines rows (ESC d n).

feed_spp(lines: int = 3) None[source]

Feed paper over SPP.

async initialize() None[source]

Initialise the printer (ESC @) — reset to factory defaults.

initialize_spp() None[source]

Initialise the printer over SPP (ESC @).

property is_connected_ble: bool

Whether the BLE transport is currently connected.

property is_connected_spp: bool

Whether the SPP socket is currently open.

async print_ekg(beats: int = 4, height_px: int = 160, line_width: int = 2, grid: bool = True, grid_step_px: int = 32, amplitude: float = 0.82, portrait: bool = False, px_per_beat: int = 240) None[source]

Print a synthetic ECG waveform.

portrait=True renders time running down the paper; portrait=False (default) renders time running across the paper width.

async print_grid(columns: list[dict], font_size: int = 22, font_path: str | None = None, padding: int = 6, supersample: int = 3, dither: bool = False, threshold: int = 128) None[source]

Print a single row of a multi-column table over BLE.

See goojprt.rendering.grid.render_grid() for the column dictionary schema.

async print_image(image, strip_height: int = 24) None[source]

Print a PIL.Image.Image over BLE as an ESC/POS raster.

The image is split into horizontal strips of strip_height rows and sent as separate GS v 0 commands. This keeps each payload small enough to fit in the printer’s limited buffer and aligns chunk boundaries to raster row width, preventing pixel-shift artifacts.

Parameters:
  • image – PIL image in any mode.

  • strip_height – Rows per strip (default 24 → 1 152 bytes per strip, safe for cheap hardware with small buffers).

async print_image_from_file(path: str) None[source]

Load an image from disk (via PIL.Image.open()) and print it.

print_image_spp(image, strip_height: int = 24) None[source]

Print a PIL.Image.Image over SPP as an ESC/POS raster.

Parameters:
  • image – PIL image in any mode.

  • strip_height – Rows per strip (default 24).

async print_line(char: str = '-', encoding: str = 'ascii') None[source]

Print a horizontal rule built from a repeated character.

Defaults to roughly 32 characters wide — PAPER_WIDTH_PX // 12, matching Font A metrics.

async print_pdf417(data: str, align: Align = Align.CENTER, scale: int = 2, row_height: int = 5, columns: int = 5, padding: int = 10, min_rows: int | None = None) None[source]

Print a PDF417 barcode over BLE.

The barcode is rendered as a bitmap and padded to the full paper width according to align.

print_pdf417_spp(data: str, align: Align = Align.CENTER, scale: int = 2, row_height: int = 5, columns: int = 5, padding: int = 10, min_rows: int | None = None) None[source]

Print a PDF417 barcode over SPP, padded to paper width per align.

async print_qr(data: str, size: int = 6, align: Align = Align.CENTER, error_correction: int = 1) None[source]

Print a QR code over BLE using the native ESC/POS QR command.

print_qr_spp(data: str, size: int = 6, align: Align = Align.CENTER, error_correction: int = 1) None[source]

Print a QR code over SPP (shares commands.build_qr_block()).

async print_text(text: str, align: Align = Align.LEFT, bold: bool = False, underline: bool = False, size: TextSize = TextSize.NORMAL, newline: bool = True, encoding: str = 'gb2312') None[source]

Print formatted text over BLE using the native ESC/POS engine.

Parameters:
  • text – String to print.

  • align – Horizontal alignment.

  • bold – Enable emphasised printing.

  • underline – Enable underlined printing.

  • size – Character size multiplier.

  • newline – Append a trailing line feed after the text.

  • encoding – Python codec name used for byte encoding.

async print_text_image(text: str, font_size: int = 24, font_path: str | None = None, align: Align = Align.LEFT, line_spacing: int = 6, padding: int = 8, supersample: int = 3, dither: bool = True, threshold: int = 140) None[source]

Print text as an antialiased bitmap (full Unicode / diacritics).

Unlike print_text(), this method does not depend on the firmware code page: the text is rendered via PIL with LANCZOS resampling and Floyd–Steinberg dithering, so any installed font produces a readable result.

print_text_spp(text: str, align: Align = Align.LEFT, bold: bool = False, underline: bool = False, size: TextSize = TextSize.NORMAL, newline: bool = True, encoding: str = 'gb2312') None[source]

Print text over SPP (shares commands.build_text_block() with BLE).

async probe_charsets(test_string: str = 'Příliš žluťoučký kůň', pages: list[CodePage] | None = None) None[source]

Print test_string using each code page plus a bitmap reference.

Useful for verifying which code pages the firmware actually ships — compare the native outputs against the always-correct bitmap row at the bottom.

async query_full_info(timeout: float = 1.5) dict[source]

Read BLE Device Info (0x180A) + Battery (0x180F) + ESC/POS status + GS I.

Returns:

A dictionary with keys ble_device, ble_battery, escpos_status and escpos_info.

async query_printer_info(timeout: float = 2.0) dict[source]

Query model / firmware strings via GS I 1 / 2 / 3.

Returns:

A dictionary with keys model_id, firmware, printer_type and raw_responses — or {"error": ...} when the printer does not expose a notify characteristic.

async scan_ble(timeout: float = 10.0) list[dict][source]

Discover nearby BLE devices.

Parameters:

timeout – Scan duration in seconds.

Returns:

List of {"name", "address"} dictionaries.

async set_charset(code_page: CodePage) None[source]

Switch the printer’s active code page (ESC t n).

Note: this only works if the firmware actually ships the chosen table. For guaranteed diacritic support, use print_text_image() instead.