Source code for goojprt.commands

"""ESC/POS command builders for the GoojPrt PT-210.

Every function in this module is *pure*: it has no side effects, performs
no I/O, and merely returns the byte sequence that the caller sends over
the chosen transport (BLE or SPP).

Two levels of helpers are provided:

* **Low-level builders** (:func:`init`, :func:`align`, :func:`bold`,
  :func:`feed`, :func:`cut`, …) emit a single ESC/POS escape sequence.
* **Composite builders** (:func:`build_text_block`, :func:`build_qr_block`)
  concatenate several low-level commands into a ready-to-send block.
  These are shared by the BLE and SPP print APIs of
  :class:`~goojprt.printer.GoojPrtPT210` to avoid duplicating byte
  construction logic.

Reference: ``ESC/POS Command Reference`` by Epson. Only the subset
implemented by the PT-210 firmware is exposed here.
"""

from goojprt.encoding import text_to_bytes
from goojprt.enums import Align, CodePage, TextSize


[docs] def init() -> bytes: """``ESC @`` — initialise the printer (reset it to its default state).""" return b"\x1b\x40"
[docs] def align(a: Align) -> bytes: """``ESC a n`` — set horizontal alignment (LEFT / CENTER / RIGHT).""" return bytes([0x1B, 0x61, int(a)])
[docs] def text_size(s: TextSize) -> bytes: """``GS ! n`` — set character size (NORMAL / DOUBLE_HEIGHT / …).""" return bytes([0x1D, 0x21, int(s)])
[docs] def bold(enabled: bool) -> bytes: """``ESC E n`` — toggle emphasised (bold) printing.""" return bytes([0x1B, 0x45, 0x01 if enabled else 0x00])
[docs] def underline(enabled: bool) -> bytes: """``ESC - n`` — toggle underline printing.""" return bytes([0x1B, 0x2D, 0x01 if enabled else 0x00])
[docs] def feed(lines: int = 1) -> bytes: """``ESC d n`` — feed paper by ``lines`` rows (clamped to 0–255).""" return bytes([0x1B, 0x64, max(0, min(lines, 255))])
[docs] def line_spacing(dots: int = 30) -> bytes: """``ESC 3 n`` — set line spacing, measured in motion units (0–255).""" return bytes([0x1B, 0x33, max(0, min(dots, 255))])
[docs] def cut() -> bytes: """``GS V A`` — paper cut (no-op on PT-210, which lacks a cutter).""" return bytes([0x1D, 0x56, 0x41, 0x00])
[docs] def charset(cp: CodePage) -> bytes: """``ESC t n`` — select code page for native ESC/POS text output.""" return bytes([0x1B, 0x74, int(cp)])
[docs] def energy(dots: int = 7, heating: int = 120, interval: int = 2) -> bytes: """``ESC 7 n1 n2 n3`` — configure thermal head heating parameters. :param dots: Maximum number of simultaneously heated dots, 0–7. Higher values print faster but draw more current. :param heating: Heating time, 0–255. Higher values produce darker output (the factory default is ≈ 80). :param interval: Heating interval, 0–255. Lower values print faster (the factory default is ≈ 2). """ return bytes([0x1B, 0x37, dots & 0xFF, heating & 0xFF, interval & 0xFF])
[docs] def font(font_b: bool = False) -> bytes: """``ESC M n`` — select font. ``False`` = Font A (12×24), ``True`` = Font B (9×17).""" return bytes([0x1B, 0x4D, 0x01 if font_b else 0x00])
[docs] def barcode_qr(data: str, size: int = 6, error_correction: int = 1) -> bytes: r"""``GS ( k`` — build the four-command sequence that prints a QR code. The sequence configures the model/error-correction level, stores the payload into the printer's symbol buffer, and then triggers printing. :param data: Payload to encode (encoded as UTF-8 on the wire). :param size: Module size, 1–16 (default ``6``). :param error_correction: Correction level — ``0``\ =L, ``1``\ =M, ``2``\ =Q, ``3``\ =H (default ``1``). :returns: Bytes containing the complete QR command sequence. """ encoded = data.encode("utf-8") length = len(encoded) + 3 cmds = bytearray() # Select model (Model 2 = 0x32, required for size to take effect) cmds += bytes([0x1D, 0x28, 0x6B, 0x04, 0x00, 0x31, 0x41, 0x32, 0x00]) # EC level cmds += bytes([0x1D, 0x28, 0x6B, 0x03, 0x00, 0x31, 0x45, error_correction + 48]) # Module size cmds += bytes([0x1D, 0x28, 0x6B, 0x03, 0x00, 0x31, 0x43, size]) # Store data cmds += bytes([0x1D, 0x28, 0x6B, length & 0xFF, (length >> 8) & 0xFF, 0x31, 0x50, 0x30]) cmds += encoded # Print cmds += bytes([0x1D, 0x28, 0x6B, 0x03, 0x00, 0x31, 0x51, 0x30]) return bytes(cmds)
[docs] def build_text_block( text: str, align_val: Align = Align.LEFT, bold_on: bool = False, underline_on: bool = False, size_val: TextSize = TextSize.NORMAL, newline: bool = True, encoding: str = "gb2312", ) -> bytes: """Build the full ESC/POS block that prints a single text line. The resulting byte stream contains, in order: alignment, bold toggle, underline toggle, text-size setting, the encoded text, and (optionally) a trailing line feed. This function is shared by BLE and SPP print APIs to keep the wire format identical. """ data = bytearray() data += align(align_val) data += bold(bold_on) data += underline(underline_on) data += text_size(size_val) data += text_to_bytes(text, encoding) if newline: data += b"\n" return bytes(data)
[docs] def build_qr_block( data: str, size: int = 6, align_val: Align = Align.CENTER, error_correction: int = 1, ) -> bytes: """Build a QR block: alignment + QR command sequence + trailing newline. Shared by both the BLE and SPP QR APIs. """ return align(align_val) + barcode_qr(data, size, error_correction) + b"\n"