Files
V2_micropython/printer_driver.py
jeremygan2021 c66f80d0eb
All checks were successful
Deploy WebSocket Server / deploy (push) Successful in 4s
printer
2026-03-05 19:59:56 +08:00

186 lines
6.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import time
class TsplPrinter:
"""
基于 TSPL (TSC Printer Language) 的标签打印机驱动
适用于 HPRT (汉印), TSC, 佳博等支持 TSPL 指令集的打印机
参考 Android SDK: Serialport_Factory
"""
def __init__(self, uart, encoding='gbk'):
"""
:param uart: machine.UART 对象
:param encoding: 文本编码,默认 'gbk' (国产打印机通用)
"""
self.uart = uart
self.encoding = encoding
def send_raw(self, data):
"""发送原始数据 (bytes 或 str)"""
if isinstance(data, str):
try:
data = data.encode(self.encoding)
except Exception:
# 如果无法用指定编码,尝试 utf-8 或直接发送 ascii
data = data.encode('utf-8')
self.uart.write(data)
def send_command(self, cmd):
"""发送 TSPL 指令 (自动添加换行)"""
self.send_raw(cmd + "\r\n")
# =================================================================
# 基础设置指令
# =================================================================
def size(self, width_mm, height_mm):
"""
设置标签尺寸
:param width_mm: 宽度 (mm)
:param height_mm: 高度 (mm)
"""
# TSPL 标准: SIZE m, n (单位 mm)
# 如果打印机只支持 dots可能需要修改为 "SIZE 384 dot, 240 dot"
# SDK 注释: 384*0.125=48mm
self.send_command(f"SIZE {width_mm} mm, {height_mm} mm")
def gap(self, gap_mm=2, offset_mm=0):
"""
设置标签间隙 (定位用)
:param gap_mm: 间隙高度 (mm),通常为 2mm
:param offset_mm: 偏移量 (mm)
"""
self.send_command(f"GAP {gap_mm} mm, {offset_mm} mm")
def cls(self):
"""清除图像缓冲区 (每次打印新标签前调用)"""
self.send_command("CLS")
def feed(self, len_mm=None):
"""进纸"""
if len_mm:
self.send_command(f"FEED {len_mm} mm")
else:
self.send_command("FORMFEED") # 进纸到下一张标签开头
def home(self):
"""寻找标签原点 (自动测纸后定位)"""
self.send_command("HOME")
# =================================================================
# 绘图与文本指令
# =================================================================
def text(self, x, y, content, font="TSS24.BF2", rotation=0, x_mul=1, y_mul=1):
"""
打印文本
:param x: x 坐标 (dots)
:param y: y 坐标 (dots)
:param content: 文本内容
:param font: 字体名称。
"TSS24.BF2" 是常用的内置简体中文字体。
"1"~"5" 是内置英文字体。
:param rotation: 旋转角度 (0, 90, 180, 270)
:param x_mul: 横向放大倍数 (1-10)
:param y_mul: 纵向放大倍数 (1-10)
"""
# TEXT x,y,"font",rotation,x_mul,y_mul,"content"
# 注意: content 需要用双引号包围,且内部双引号需要转义
safe_content = content.replace('"', '\\"')
cmd = f'TEXT {x},{y},"{font}",{rotation},{x_mul},{y_mul},"{safe_content}"'
self.send_command(cmd)
def barcode(self, x, y, content, type="128", height=100, human=1, rotation=0, narrow=2, wide=2):
"""
打印条码
:param x: x 坐标
:param y: y 坐标
:param content: 条码内容
:param type: 条码类型 ("128", "39", "EAN13", "QRCODE"等) - 注意 TSPL 有专门的 QRCODE 指令
:param height: 条码高度 (dots)
:param human: 是否打印人眼可读字符 (0:不可见, 1:可见)
:param rotation: 旋转 (0, 90, 180, 270)
:param narrow: 窄条宽度 (dots)
:param wide: 宽条宽度 (dots)
"""
# BARCODE x,y,"type",height,human,rotation,narrow,wide,"content"
safe_content = content.replace('"', '\\"')
cmd = f'BARCODE {x},{y},"{type}",{height},{human},{rotation},{narrow},{wide},"{safe_content}"'
self.send_command(cmd)
def qrcode(self, x, y, content, ecc="L", cell_width=5, mode="A", rotation=0):
"""
打印二维码
:param x: x 坐标
:param y: y 坐标
:param content: 二维码内容
:param ecc: 纠错级别 (L, M, Q, H)
:param cell_width: 单元格宽度 (dots, 1-10),控制二维码大小
:param mode: 模式 (A:自动, M:手动)
:param rotation: 旋转 (0, 90, 180, 270)
"""
# QRCODE x,y,ECC,cell_width,mode,rotation,"content"
safe_content = content.replace('"', '\\"')
cmd = f'QRCODE {x},{y},{ecc},{cell_width},{mode},{rotation},"{safe_content}"'
self.send_command(cmd)
def box(self, x, y, x_end, y_end, thickness=1):
"""绘制矩形框"""
self.send_command(f"BOX {x},{y},{x_end},{y_end},{thickness}")
def line(self, x, y, width, height):
"""绘制直线 (TSPL 中 BAR 命令用于画线)"""
# BAR x,y,width,height
self.send_command(f"BAR {x},{y},{width},{height}")
# =================================================================
# 执行打印
# =================================================================
def print_out(self, quantity=1):
"""
开始打印
:param quantity: 打印份数
"""
self.send_command(f"PRINT {quantity}")
# =================================================================
# SDK 特殊指令兼容 (参考 Android SDK)
# =================================================================
def set_special_mode(self, enabled=True):
"""
发送 SDK 中出现的神秘指令 0x12 0x43
可能是某种私有模式开关(如加粗或特殊字体)
"""
if enabled:
self.send_raw(b'\x12\x43\x01')
self.send_raw(b'\x12\x45\x01')
else:
self.send_raw(b'\x12\x43\x00')
self.send_raw(b'\x12\x45\x00')
# =================================================================
# 快捷组合方法 (仿 Android SDK 逻辑)
# =================================================================
def label_begin(self, width_dots, height_dots):
"""
开始标签任务 (仿 SDK 接口)
自动将 dots 转换为 mm (假设 203dpi, 8 dots/mm)
"""
width_mm = int(width_dots / 8)
height_mm = int(height_dots / 8)
# 1. 清除缓冲区
self.cls()
# 2. 设置尺寸
self.size(width_mm, height_mm)
# 3. 设置间隙 (默认 2mm)
self.gap(2, 0)
# 4. 寻原点 (可选,防止跑偏)
# self.home()
def label_end(self):
"""结束标签任务并打印 (仿 SDK 接口)"""
self.print_out(1)