140 lines
4.5 KiB
Python
140 lines
4.5 KiB
Python
# Protocol information from Thermal_Printer Arduino library
|
|
# https://github.com/bitbank2/Thermal_Printer/
|
|
from adafruit_ble.uuid import StandardUUID
|
|
from adafruit_ble.services import Service
|
|
from adafruit_ble.characteristics.stream import StreamIn
|
|
|
|
# Switch the printing mode to bitmap
|
|
printimage = b"Qx\xbe\x00\x01\x00\x00\x00\xff"
|
|
# Switch the printing mode to text
|
|
printtext = b"Qx\xbe\x00\x01\x00\x01\x07\xff"
|
|
# Command to feed paper
|
|
paperfeed = b"Qx\xa1\x00\x02\x00\x1eZ\xff\xff"
|
|
|
|
# this table helps compute the checksum of transmitted data
|
|
# it is crc-8-ccitt
|
|
checksumtable = (
|
|
b"\x00\x07\x0e\t\x1c\x1b\x12\x158?61$#*-"
|
|
b"pw~ylkbeHOFATSZ]"
|
|
b"\xe0\xe7\xee\xe9\xfc\xfb\xf2\xf5\xd8\xdf\xd6\xd1\xc4\xc3\xca\xcd"
|
|
b"\x90\x97\x9e\x99\x8c\x8b\x82\x85\xa8\xaf\xa6\xa1\xb4\xb3\xba\xbd"
|
|
b"\xc7\xc0\xc9\xce\xdb\xdc\xd5\xd2\xff\xf8\xf1\xf6\xe3\xe4\xed\xea"
|
|
b"\xb7\xb0\xb9\xbe\xab\xac\xa5\xa2\x8f\x88\x81\x86\x93\x94\x9d\x9a"
|
|
b"' ).;<52\x1f\x18\x11\x16\x03\x04\r\n"
|
|
b"WPY^KLEBohafst}z"
|
|
b"\x89\x8e\x87\x80\x95\x92\x9b\x9c\xb1\xb6\xbf\xb8\xad\xaa\xa3\xa4"
|
|
b"\xf9\xfe\xf7\xf0\xe5\xe2\xeb\xec\xc1\xc6\xcf\xc8\xdd\xda\xd3\xd4"
|
|
b"ing`ur{|QV_XMJCD"
|
|
b"\x19\x1e\x17\x10\x05\x02\x0b\x0c!&/(=:34"
|
|
b"NI@GRU\\[vqx\x7fjmdc"
|
|
b'>907"%,+\x06\x01\x08\x0f\x1a\x1d\x14\x13'
|
|
b"\xae\xa9\xa0\xa7\xb2\xb5\xbc\xbb\x96\x91\x98\x9f\x8a\x8d\x84\x83"
|
|
b"\xde\xd9\xd0\xd7\xc2\xc5\xcc\xcb\xe6\xe1\xe8\xef\xfa\xfd\xf4\xf3"
|
|
)
|
|
|
|
# mirrortable[i] is the bit reversed version of the byte i
|
|
mirrortable = (
|
|
b"\x00\x80@\xc0 \xa0`\xe0\x10\x90P\xd00\xb0p\xf0"
|
|
b"\x08\x88H\xc8(\xa8h\xe8\x18\x98X\xd88\xb8x\xf8"
|
|
b"\x04\x84D\xc4$\xa4d\xe4\x14\x94T\xd44\xb4t\xf4"
|
|
b"\x0c\x8cL\xcc,\xacl\xec\x1c\x9c\\\xdc<\xbc|\xfc"
|
|
b'\x02\x82B\xc2"\xa2b\xe2\x12\x92R\xd22\xb2r\xf2'
|
|
b"\n\x8aJ\xca*\xaaj\xea\x1a\x9aZ\xda:\xbaz\xfa"
|
|
b"\x06\x86F\xc6&\xa6f\xe6\x16\x96V\xd66\xb6v\xf6"
|
|
b"\x0e\x8eN\xce.\xaen\xee\x1e\x9e^\xde>\xbe~\xfe"
|
|
b"\x01\x81A\xc1!\xa1a\xe1\x11\x91Q\xd11\xb1q\xf1"
|
|
b"\t\x89I\xc9)\xa9i\xe9\x19\x99Y\xd99\xb9y\xf9"
|
|
b"\x05\x85E\xc5%\xa5e\xe5\x15\x95U\xd55\xb5u\xf5"
|
|
b"\r\x8dM\xcd-\xadm\xed\x1d\x9d]\xdd=\xbd}\xfd"
|
|
b"\x03\x83C\xc3#\xa3c\xe3\x13\x93S\xd33\xb3s\xf3"
|
|
b"\x0b\x8bK\xcb+\xabk\xeb\x1b\x9b[\xdb;\xbb{\xfb"
|
|
b"\x07\x87G\xc7'\xa7g\xe7\x17\x97W\xd77\xb7w\xf7"
|
|
b"\x0f\x8fO\xcf/\xafo\xef\x1f\x9f_\xdf?\xbf\x7f\xff"
|
|
)
|
|
|
|
|
|
def checksum(data, start, count):
|
|
cs = 0
|
|
for i in range(start, start + count):
|
|
cs = checksumtable[cs ^ data[i]]
|
|
return cs
|
|
|
|
|
|
MODE_TEXT = "MODE_TEXT"
|
|
MODE_BITMAP = "MODE_BITMAP"
|
|
|
|
class CatPrinter(Service):
|
|
|
|
uuid = StandardUUID(0xAE30)
|
|
|
|
_tx = StreamIn(uuid=StandardUUID(0xAE01), timeout=1.0, buffer_size=256)
|
|
|
|
def _write_data(self, buf):
|
|
self._tx.write(buf)
|
|
|
|
@property
|
|
def bitmap_width(self):
|
|
return 384
|
|
|
|
def __init__(self, service=None):
|
|
super().__init__(service=service)
|
|
self._mode = None
|
|
|
|
@property
|
|
def mode(self):
|
|
return self._mode
|
|
|
|
@mode.setter
|
|
def mode(self, value):
|
|
if value == self.mode:
|
|
return
|
|
|
|
if value == MODE_TEXT:
|
|
self._write_data(printtext)
|
|
elif value == MODE_BITMAP:
|
|
self._write_data(printimage)
|
|
else:
|
|
raise ValueError("Invalid mode %r" % value)
|
|
|
|
self._mode = value
|
|
|
|
def feed_lines(self, lines):
|
|
buf = bytearray(paperfeed)
|
|
buf[6] = lines & 0xFF
|
|
buf[7] = lines >> 8
|
|
buf[8] = checksum(buf, 6, 2)
|
|
self._write_data(buf)
|
|
|
|
def _print_common(self, text, reverse_bits=True):
|
|
data = memoryview(text)
|
|
while data:
|
|
sz = min(112, len(data))
|
|
sub_data = data[:sz]
|
|
data = data[sz:]
|
|
buf = bytearray(sz + 8)
|
|
buf[0] = 0x51
|
|
buf[1] = 0x78
|
|
buf[2] = 0xA2
|
|
buf[3] = 0x0
|
|
buf[4] = sz
|
|
buf[5] = 0
|
|
if reverse_bits:
|
|
buf[6 : 6 + sz] = bytes(mirrortable[c] for c in sub_data)
|
|
else:
|
|
buf[6 : 6 + sz] = sub_data
|
|
buf[6 + sz] = checksum(buf, 6, len(sub_data))
|
|
buf[6 + sz + 1] = 0xFF
|
|
|
|
self._write_data(buf)
|
|
|
|
def print_text(self, text):
|
|
self.mode = MODE_TEXT
|
|
self._print_common(text.encode("utf-8"))
|
|
|
|
def print_line(self, text):
|
|
self.print_text(text)
|
|
self._print_common(b"\n")
|
|
|
|
def print_bitmap_row(self, data, reverse_bits=True):
|
|
self.mode = MODE_BITMAP
|
|
self._print_common(data, reverse_bits)
|