printer
All checks were successful
Deploy WebSocket Server / deploy (push) Successful in 4s

This commit is contained in:
jeremygan2021
2026-03-05 19:59:56 +08:00
parent efbe08f2cd
commit c66f80d0eb
6 changed files with 537 additions and 30 deletions

185
printer_driver.py Normal file
View File

@@ -0,0 +1,185 @@
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)