Transport

I/O transports for the GoojPrt PT-210.

Two independent transports are provided without a common abstract base class. BLE is inherently asynchronous (via bleak) while SPP is inherently synchronous (via socket); forcing a single interface on top of both would produce a leaky abstraction. The GoojPrtPT210 facade keeps a reference to each transport and dispatches calls to whichever one the caller has activated.

  • BleTransport — asynchronous BLE transport; implements MTU chunking, pacing between chunks, and post-raster throttling.

  • SppTransport — thin RFCOMM socket wrapper; Linux only.

class goojprt.transport.BleTransport(on_disconnect=None)[source]

Bases: object

Asynchronous BLE transport for GoojPrt PT-210 printers.

All methods are async. Instances are not thread-safe — use a single transport from a single event loop at a time.

CHUNK_DELAY = 0.04

Pause between chunks, covers the typical BLE connection interval (~30 ms).

CHUNK_SIZE = 182

BLE MTU minus protocol overhead. Most GoojPrt firmware handles 182 bytes.

CHUNK_SIZE_RASTER = 192

Row-aligned chunk size for raster data. Must be a multiple of 48 (PAPER_WIDTH_PX // 8) so chunk boundaries never split a raster row.

clear_notify_buffer() None[source]

Drop any buffered notify bytes (call before issuing a new query).

async connect(address: str) None[source]

Connect to the printer and locate the write/notify characteristics.

Parameters:

address – Bluetooth MAC address (or UUID on macOS).

Raises:
  • ImportError – When bleak is not installed.

  • RuntimeError – When no write characteristic can be found (the device is probably not a GoojPrt PT-210).

async disconnect() None[source]

Disconnect from the printer and release all references.

property has_notify: bool

Whether the remote device exposes a notify characteristic.

property is_connected: bool

Whether the BLE client is currently connected.

async read_gatt(uuid: str) bytes[source]

Read a raw value from a GATT characteristic (e.g. Device Info).

Raises:

RuntimeError – When the transport is not connected.

async read_notify(timeout: float) bytes[source]

Return the current notify buffer after waiting timeout seconds.

Callers typically call clear_notify_buffer() beforehand to discard responses from earlier queries.

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

Discover nearby BLE devices.

Parameters:

timeout – Scan duration in seconds.

Returns:

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

Raises:

ImportError – When bleak is not installed.

async write(data: bytes) None[source]

Send raw bytes over BLE with MTU chunking and pacing.

Parameters:

data – Bytes to send.

Raises:

RuntimeError – When the transport is not connected.

async write_raster_strip(data: bytes, rows: int = 24) None[source]

Send one raster strip using row-aligned 192-byte chunks.

Chunk boundaries are aligned to CHUNK_SIZE_RASTER (a multiple of 48 bytes = one raster row) so the printer never receives a partial row at a chunk boundary, which would cause a pixel-shift on the next line. After all chunks are sent, sleeps max(0.05, rows * 0.002) seconds so the paper motor can advance before the next strip is issued.

Parameters:
  • data – A complete GS v 0 strip payload as returned by image_to_raster_strips().

  • rows – Number of raster rows in this strip (used to compute the post-strip throttle). Defaults to 24.

Raises:

RuntimeError – When the transport is not connected.

class goojprt.transport.SppTransport[source]

Bases: object

Synchronous Bluetooth SPP / RFCOMM transport.

Only supported on Linux. Attempts to connect() on macOS raise OSError with a hint to switch to BLE.

CHUNK_DELAY = 0.04
CHUNK_SIZE_RASTER = 192
connect(address: str, port: int = 1) None[source]

Open an RFCOMM socket to the printer.

Parameters:
  • address – Bluetooth MAC address of the printer.

  • port – RFCOMM channel, usually 1.

Raises:

OSError – On platforms without AF_BLUETOOTH support (notably macOS).

disconnect() None[source]

Close the RFCOMM socket (if open).

property is_connected: bool

Whether the RFCOMM socket is currently open.

write(data: bytes) None[source]

Send raw bytes over the RFCOMM socket.

Raises:

RuntimeError – When the transport is not connected.

write_raster_strip(data: bytes, rows: int = 24) None[source]

Send one raster strip using row-aligned 192-byte chunks.

Mirrors write_raster_strip() but synchronous. Chunk boundaries are aligned to 48 bytes (one raster row) to prevent pixel-shift artifacts on cheap printer firmware. After all chunks are sent, sleeps max(0.05, rows * 0.002) seconds so the paper motor can advance before the next strip is issued.

Parameters:
  • data – A complete GS v 0 strip payload.

  • rows – Number of raster rows in this strip (used to compute the post-strip throttle). Defaults to 24.

Raises:

RuntimeError – When the transport is not connected.

BLE Transport

Bluetooth Low Energy transport backed by bleak.

Handles three concerns that any BLE-facing printer driver must address:

  1. Characteristic discovery. The write characteristic is located by UUID (primary then alternate GoojPrt family UUIDs); the optional notify characteristic is registered if present, so the printer’s responses can be read back.

  2. MTU chunking with pacing. BLE packets are limited by the connection MTU; write-without-response is used (no ACK from the link layer) so a small sleep between chunks is required to avoid overflowing the peripheral’s queue.

  3. Post-raster throttle. After a large raster image, the peripheral needs time to actually feed paper. A short sleep proportional to the number of raster rows is inserted to keep the producer in sync with the paper motor.

class goojprt.transport.ble.BleTransport(on_disconnect=None)[source]

Bases: object

Asynchronous BLE transport for GoojPrt PT-210 printers.

All methods are async. Instances are not thread-safe — use a single transport from a single event loop at a time.

CHUNK_DELAY = 0.04

Pause between chunks, covers the typical BLE connection interval (~30 ms).

CHUNK_SIZE = 182

BLE MTU minus protocol overhead. Most GoojPrt firmware handles 182 bytes.

CHUNK_SIZE_RASTER = 192

Row-aligned chunk size for raster data. Must be a multiple of 48 (PAPER_WIDTH_PX // 8) so chunk boundaries never split a raster row.

clear_notify_buffer() None[source]

Drop any buffered notify bytes (call before issuing a new query).

async connect(address: str) None[source]

Connect to the printer and locate the write/notify characteristics.

Parameters:

address – Bluetooth MAC address (or UUID on macOS).

Raises:
  • ImportError – When bleak is not installed.

  • RuntimeError – When no write characteristic can be found (the device is probably not a GoojPrt PT-210).

async disconnect() None[source]

Disconnect from the printer and release all references.

property has_notify: bool

Whether the remote device exposes a notify characteristic.

property is_connected: bool

Whether the BLE client is currently connected.

async read_gatt(uuid: str) bytes[source]

Read a raw value from a GATT characteristic (e.g. Device Info).

Raises:

RuntimeError – When the transport is not connected.

async read_notify(timeout: float) bytes[source]

Return the current notify buffer after waiting timeout seconds.

Callers typically call clear_notify_buffer() beforehand to discard responses from earlier queries.

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

Discover nearby BLE devices.

Parameters:

timeout – Scan duration in seconds.

Returns:

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

Raises:

ImportError – When bleak is not installed.

async write(data: bytes) None[source]

Send raw bytes over BLE with MTU chunking and pacing.

Parameters:

data – Bytes to send.

Raises:

RuntimeError – When the transport is not connected.

async write_raster_strip(data: bytes, rows: int = 24) None[source]

Send one raster strip using row-aligned 192-byte chunks.

Chunk boundaries are aligned to CHUNK_SIZE_RASTER (a multiple of 48 bytes = one raster row) so the printer never receives a partial row at a chunk boundary, which would cause a pixel-shift on the next line. After all chunks are sent, sleeps max(0.05, rows * 0.002) seconds so the paper motor can advance before the next strip is issued.

Parameters:
  • data – A complete GS v 0 strip payload as returned by image_to_raster_strips().

  • rows – Number of raster rows in this strip (used to compute the post-strip throttle). Defaults to 24.

Raises:

RuntimeError – When the transport is not connected.

SPP Transport

Classic Bluetooth Serial Port Profile (RFCOMM) transport.

Synchronous, Linux-only. macOS does not expose AF_BLUETOOTH through the CPython socket module; BLE should be used there instead.

class goojprt.transport.spp.SppTransport[source]

Bases: object

Synchronous Bluetooth SPP / RFCOMM transport.

Only supported on Linux. Attempts to connect() on macOS raise OSError with a hint to switch to BLE.

CHUNK_DELAY = 0.04
CHUNK_SIZE_RASTER = 192
connect(address: str, port: int = 1) None[source]

Open an RFCOMM socket to the printer.

Parameters:
  • address – Bluetooth MAC address of the printer.

  • port – RFCOMM channel, usually 1.

Raises:

OSError – On platforms without AF_BLUETOOTH support (notably macOS).

disconnect() None[source]

Close the RFCOMM socket (if open).

property is_connected: bool

Whether the RFCOMM socket is currently open.

write(data: bytes) None[source]

Send raw bytes over the RFCOMM socket.

Raises:

RuntimeError – When the transport is not connected.

write_raster_strip(data: bytes, rows: int = 24) None[source]

Send one raster strip using row-aligned 192-byte chunks.

Mirrors write_raster_strip() but synchronous. Chunk boundaries are aligned to 48 bytes (one raster row) to prevent pixel-shift artifacts on cheap printer firmware. After all chunks are sent, sleeps max(0.05, rows * 0.002) seconds so the paper motor can advance before the next strip is issued.

Parameters:
  • data – A complete GS v 0 strip payload.

  • rows – Number of raster rows in this strip (used to compute the post-strip throttle). Defaults to 24.

Raises:

RuntimeError – When the transport is not connected.