Skip to content

Commit add9186

Browse files
committed
Blacken & fix pylint
1 parent b5e610e commit add9186

File tree

3 files changed

+125
-87
lines changed

3 files changed

+125
-87
lines changed
Lines changed: 25 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,9 @@
1-
import seekablebitmap
2-
3-
import gc
41
import os
5-
import struct
6-
import time
72

83
import board
9-
import digitalio
104
import keypad
115
import ulab.numpy as np
126

13-
import adafruit_ble
147
from adafruit_ble import BLERadio
158
from adafruit_ble.advertising import Advertisement
169

@@ -21,41 +14,6 @@
2114

2215
buttons = keypad.Keys([board.BUTTON_A, board.BUTTON_B], value_when_pressed=False)
2316

24-
def pnmopen(filename):
25-
"""
26-
Scan for netpbm format info, skip over comments, and read header data.
27-
28-
Return the format, header, and the opened file positioned at the start of
29-
the bitmap data.
30-
"""
31-
# pylint: disable=too-many-branches
32-
image_file = open(filename, "rb")
33-
magic_number = image_file.read(2)
34-
image_file.seek(2)
35-
pnm_header = []
36-
next_value = bytearray()
37-
while True:
38-
# We have all we need at length 3 for formats P2, P3, P5, P6
39-
if len(pnm_header) == 3:
40-
return image_file, magic_number, pnm_header
41-
42-
if len(pnm_header) == 2 and magic_number in [b"P1", b"P4"]:
43-
return image_file, magic_number, pnm_header
44-
45-
next_byte = image_file.read(1)
46-
if next_byte == b"":
47-
raise RuntimeError("Unsupported image format {}".format(magic_number))
48-
if next_byte == b"#": # comment found, seek until a newline or EOF is found
49-
while image_file.read(1) not in [b"", b"\n"]: # EOF or NL
50-
pass
51-
elif not next_byte.isdigit(): # boundary found in header data
52-
if next_value:
53-
# pull values until space is found
54-
pnm_header.append(int("".join(["%c" % char for char in next_value])))
55-
next_value = bytearray() # reset the byte array
56-
else:
57-
next_value += next_byte # push the digit into the byte array
58-
5917
def wait_for_press(kbd):
6018
"""
6119
Wait for a keypress and return the event
@@ -65,6 +23,7 @@ def wait_for_press(kbd):
6523
if event and event.pressed:
6624
return event
6725

26+
6827
def show(s):
6928
"""
7029
Display a message on the screen
@@ -74,43 +33,54 @@ def show(s):
7433
print(s)
7534
board.DISPLAY.auto_refresh = True
7635

36+
7737
def show_error(s):
7838
"""
7939
Display a message on the screen and wait for a button press
8040
"""
8141
show(s + "\nPress a button to continue")
8242
wait_for_press(buttons)
8343

44+
8445
def find_cat_printer(radio):
8546
"""
8647
Connect to the cat printer device using BLE
8748
"""
8849
while True:
8950
show("Scanning for GB02 device...")
9051
for adv in radio.start_scan(Advertisement):
91-
complete_name = getattr(adv, 'complete_name')
52+
complete_name = getattr(adv, "complete_name")
9253
if complete_name is not None:
9354
print(f"Saw {complete_name}")
94-
if complete_name == 'GB02':
55+
if complete_name == "GB02":
9556
radio.stop_scan()
9657
return radio.connect(adv, timeout=10)[CatPrinter]
9758

98-
image_files = [i for i in os.listdir('/') if i.lower().endswith(".pbm") or i.lower().endswith(".bmp")]
59+
60+
image_files = [
61+
i
62+
for i in os.listdir("/")
63+
if i.lower().endswith(".pbm") or i.lower().endswith(".bmp")
64+
]
9965
image_files.sort(key=lambda filename: filename.lower())
10066

67+
10168
def select_image():
10269
i = 0
10370
while True:
104-
show(f"Select image file\nA: next image\nB: print this image\n\n{image_files[i]}")
71+
show(
72+
f"Select image file\nA: next image\nB: print this image\n\n{image_files[i]}"
73+
)
10574
event = wait_for_press(buttons)
106-
if event.key_number == 0: # button "A"
75+
if event.key_number == 0: # button "A"
10776
i = (i + 1) % len(image_files)
108-
if event.key_number == 1: # button "B"
77+
if event.key_number == 1: # button "B"
10978
return image_files[i]
110-
79+
80+
11181
printer = find_cat_printer(ble)
11282

113-
while True:
83+
def main():
11484
try:
11585
filename = select_image()
11686

@@ -134,9 +104,11 @@ def select_image():
134104

135105
# Print blank lines until the paper can be torn off
136106
for i in range(80):
137-
printer.print_bitmap_row(b'\0' * 48)
107+
printer.print_bitmap_row(b"\0" * 48)
138108

139-
except Exception as e:
109+
except Exception as e: # pylint: disable=broad-except
140110
show_error(str(e))
141111
image_files.remove(filename)
142-
continue
112+
113+
while True:
114+
main()

CircuitPython_BLEThermalPrinter/seekablebitmap.py

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,29 @@
11
import struct
2-
import ulab
2+
3+
# pylint: disable=consider-using-with
34

45
class SeekableBitmap:
5-
def __init__(self, image_file, width, height, bits_per_pixel, *, bytes_per_row=None, data_start=None, stride=None, palette=None):
6+
"""Allow random access to an uncompressed bitmap file on disk"""
7+
def __init__(
8+
self,
9+
image_file,
10+
width,
11+
height,
12+
bits_per_pixel,
13+
*,
14+
bytes_per_row=None,
15+
data_start=None,
16+
stride=None,
17+
palette=None,
18+
):
19+
"""Construct a SeekableBitmap"""
620
self.image_file = image_file
721
self.width = width
822
self.height = height
923
self.bits_per_pixel = bits_per_pixel
10-
self.bytes_per_row = bytes_per_row if bytes_per_row else (bits_per_pixel * width + 7) // 8
24+
self.bytes_per_row = (
25+
bytes_per_row if bytes_per_row else (bits_per_pixel * width + 7) // 8
26+
)
1127
self.stride = stride if stride else self.bytes_per_row
1228
self.palette = palette
1329
self.data_start = data_start if data_start else image_file.tell()
@@ -16,6 +32,7 @@ def get_row(self, row):
1632
self.image_file.seek(self.data_start + row * self.stride)
1733
return self.image_file.read(self.bytes_per_row)
1834

35+
1936
def _pnmopen(filename):
2037
"""
2138
Scan for netpbm format info, skip over comments, and read header data.
@@ -51,40 +68,71 @@ def _pnmopen(filename):
5168
else:
5269
next_value += next_byte # push the digit into the byte array
5370

71+
5472
def pnmopen(filename):
73+
"""
74+
Interpret netpbm format info and construct a SeekableBitmap
75+
"""
5576
image_file, magic_number, pnm_header = _pnmopen(filename)
56-
if magic_number == b'P4':
57-
return SeekableBitmap(image_file, pnm_header[0], pnm_header[1], 1, palette=b'\xff\xff\xff\x00\x00\x00\x00\x00')
58-
if magic_number == b'P5':
59-
return SeekableBitmap(image_file, pnm_header[0], pnm_header[1], pnm_header[2].bit_length())
60-
if magic_number == b'P6':
61-
return SeekableBitmap(image_file, pnm_header[0], pnm_header[1], 3*pnm_header[2].bit_length())
77+
if magic_number == b"P4":
78+
return SeekableBitmap(
79+
image_file,
80+
pnm_header[0],
81+
pnm_header[1],
82+
1,
83+
palette=b"\xff\xff\xff\x00\x00\x00\x00\x00",
84+
)
85+
if magic_number == b"P5":
86+
return SeekableBitmap(
87+
image_file, pnm_header[0], pnm_header[1], pnm_header[2].bit_length()
88+
)
89+
if magic_number == b"P6":
90+
return SeekableBitmap(
91+
image_file, pnm_header[0], pnm_header[1], 3 * pnm_header[2].bit_length()
92+
)
6293
raise ValueError(f"Unknown or unsupported magic number {magic_number}")
6394

95+
6496
def bmpopen(filename):
97+
"""
98+
Interpret bmp format info and construct a SeekableBitmap
99+
"""
65100
image_file = open(filename, "rb")
66101

67102
header = image_file.read(34)
68103

69-
data_start, header_size, width, height, planes, bits_per_pixel, method = struct.unpack("<10x4l2hl", header)
104+
data_start, header_size, width, height, _, bits_per_pixel, _ = struct.unpack(
105+
"<10x4l2hl", header
106+
)
70107

71108
bits_per_pixel = bits_per_pixel if bits_per_pixel != 0 else 1
72109

73-
mask_size = (12 if header_size < 56 else 16) if method == 3 else 0
74110
palette_start = header_size + 14
75111
image_file.seek(palette_start)
76112
palette = image_file.read(4 << bits_per_pixel)
77113

78-
stride=(bits_per_pixel*width+31)//32*4
114+
stride = (bits_per_pixel * width + 31) // 32 * 4
79115
if height < 0:
80116
height = -height
81117
else:
82118
data_start = data_start + stride * (height - 1)
83119
stride = -stride
84120

85-
return SeekableBitmap(image_file, width, height, bits_per_pixel, data_start=data_start, stride=stride, palette=palette)
121+
return SeekableBitmap(
122+
image_file,
123+
width,
124+
height,
125+
bits_per_pixel,
126+
data_start=data_start,
127+
stride=stride,
128+
palette=palette,
129+
)
130+
86131

87132
def imageopen(filename):
133+
"""
134+
Open a bmp or pnm file as a seekable bitmap
135+
"""
88136
if filename.lower().endswith(".bmp"):
89137
return bmpopen(filename)
90138
return pnmopen(filename)

CircuitPython_BLEThermalPrinter/thermalprinter.py

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,9 @@
11
# Protocol information from Thermal_Printer Arduino library
22
# https://github.com/bitbank2/Thermal_Printer/
3-
import collections
4-
import time
53
from adafruit_ble.uuid import StandardUUID
64
from adafruit_ble.services import Service
75
from adafruit_ble.characteristics.stream import StreamIn
86

9-
PrinterConfig = collections.namedtuple(
10-
"PrinterConfig", ("width", "service", "characteristic")
11-
)
12-
137
# Switch the printing mode to bitmap
148
printimage = b"Qx\xbe\x00\x01\x00\x00\x00\xff"
159
# Switch the printing mode to text
@@ -19,10 +13,44 @@
1913

2014
# this table helps compute the checksum of transmitted data
2115
# it is crc-8-ccitt
22-
checksumtable = b"\x00\x07\x0e\t\x1c\x1b\x12\x158?61$#*-pw~ylkbeHOFATSZ]\xe0\xe7\xee\xe9\xfc\xfb\xf2\xf5\xd8\xdf\xd6\xd1\xc4\xc3\xca\xcd\x90\x97\x9e\x99\x8c\x8b\x82\x85\xa8\xaf\xa6\xa1\xb4\xb3\xba\xbd\xc7\xc0\xc9\xce\xdb\xdc\xd5\xd2\xff\xf8\xf1\xf6\xe3\xe4\xed\xea\xb7\xb0\xb9\xbe\xab\xac\xa5\xa2\x8f\x88\x81\x86\x93\x94\x9d\x9a' ).;<52\x1f\x18\x11\x16\x03\x04\r\nWPY^KLEBohafst}z\x89\x8e\x87\x80\x95\x92\x9b\x9c\xb1\xb6\xbf\xb8\xad\xaa\xa3\xa4\xf9\xfe\xf7\xf0\xe5\xe2\xeb\xec\xc1\xc6\xcf\xc8\xdd\xda\xd3\xd4ing`ur{|QV_XMJCD\x19\x1e\x17\x10\x05\x02\x0b\x0c!&/(=:34NI@GRU\\[vqx\x7fjmdc>907\"%,+\x06\x01\x08\x0f\x1a\x1d\x14\x13\xae\xa9\xa0\xa7\xb2\xb5\xbc\xbb\x96\x91\x98\x9f\x8a\x8d\x84\x83\xde\xd9\xd0\xd7\xc2\xc5\xcc\xcb\xe6\xe1\xe8\xef\xfa\xfd\xf4\xf3"
16+
checksumtable = (
17+
b"\x00\x07\x0e\t\x1c\x1b\x12\x158?61$#*-"
18+
b"pw~ylkbeHOFATSZ]"
19+
b"\xe0\xe7\xee\xe9\xfc\xfb\xf2\xf5\xd8\xdf\xd6\xd1\xc4\xc3\xca\xcd"
20+
b"\x90\x97\x9e\x99\x8c\x8b\x82\x85\xa8\xaf\xa6\xa1\xb4\xb3\xba\xbd"
21+
b"\xc7\xc0\xc9\xce\xdb\xdc\xd5\xd2\xff\xf8\xf1\xf6\xe3\xe4\xed\xea"
22+
b"\xb7\xb0\xb9\xbe\xab\xac\xa5\xa2\x8f\x88\x81\x86\x93\x94\x9d\x9a"
23+
b"' ).;<52\x1f\x18\x11\x16\x03\x04\r\n"
24+
b"WPY^KLEBohafst}z"
25+
b"\x89\x8e\x87\x80\x95\x92\x9b\x9c\xb1\xb6\xbf\xb8\xad\xaa\xa3\xa4"
26+
b"\xf9\xfe\xf7\xf0\xe5\xe2\xeb\xec\xc1\xc6\xcf\xc8\xdd\xda\xd3\xd4"
27+
b"ing`ur{|QV_XMJCD"
28+
b"\x19\x1e\x17\x10\x05\x02\x0b\x0c!&/(=:34"
29+
b"NI@GRU\\[vqx\x7fjmdc"
30+
b'>907"%,+\x06\x01\x08\x0f\x1a\x1d\x14\x13'
31+
b"\xae\xa9\xa0\xa7\xb2\xb5\xbc\xbb\x96\x91\x98\x9f\x8a\x8d\x84\x83"
32+
b"\xde\xd9\xd0\xd7\xc2\xc5\xcc\xcb\xe6\xe1\xe8\xef\xfa\xfd\xf4\xf3"
33+
)
2334

2435
# mirrortable[i] is the bit reversed version of the byte i
25-
mirrortable = b"\x00\x80@\xc0 \xa0`\xe0\x10\x90P\xd00\xb0p\xf0\x08\x88H\xc8(\xa8h\xe8\x18\x98X\xd88\xb8x\xf8\x04\x84D\xc4$\xa4d\xe4\x14\x94T\xd44\xb4t\xf4\x0c\x8cL\xcc,\xacl\xec\x1c\x9c\\\xdc<\xbc|\xfc\x02\x82B\xc2\"\xa2b\xe2\x12\x92R\xd22\xb2r\xf2\n\x8aJ\xca*\xaaj\xea\x1a\x9aZ\xda:\xbaz\xfa\x06\x86F\xc6&\xa6f\xe6\x16\x96V\xd66\xb6v\xf6\x0e\x8eN\xce.\xaen\xee\x1e\x9e^\xde>\xbe~\xfe\x01\x81A\xc1!\xa1a\xe1\x11\x91Q\xd11\xb1q\xf1\t\x89I\xc9)\xa9i\xe9\x19\x99Y\xd99\xb9y\xf9\x05\x85E\xc5%\xa5e\xe5\x15\x95U\xd55\xb5u\xf5\r\x8dM\xcd-\xadm\xed\x1d\x9d]\xdd=\xbd}\xfd\x03\x83C\xc3#\xa3c\xe3\x13\x93S\xd33\xb3s\xf3\x0b\x8bK\xcb+\xabk\xeb\x1b\x9b[\xdb;\xbb{\xfb\x07\x87G\xc7'\xa7g\xe7\x17\x97W\xd77\xb7w\xf7\x0f\x8fO\xcf/\xafo\xef\x1f\x9f_\xdf?\xbf\x7f\xff"
36+
mirrortable = (
37+
b"\x00\x80@\xc0 \xa0`\xe0\x10\x90P\xd00\xb0p\xf0"
38+
b"\x08\x88H\xc8(\xa8h\xe8\x18\x98X\xd88\xb8x\xf8"
39+
b"\x04\x84D\xc4$\xa4d\xe4\x14\x94T\xd44\xb4t\xf4"
40+
b"\x0c\x8cL\xcc,\xacl\xec\x1c\x9c\\\xdc<\xbc|\xfc"
41+
b'\x02\x82B\xc2"\xa2b\xe2\x12\x92R\xd22\xb2r\xf2'
42+
b"\n\x8aJ\xca*\xaaj\xea\x1a\x9aZ\xda:\xbaz\xfa"
43+
b"\x06\x86F\xc6&\xa6f\xe6\x16\x96V\xd66\xb6v\xf6"
44+
b"\x0e\x8eN\xce.\xaen\xee\x1e\x9e^\xde>\xbe~\xfe"
45+
b"\x01\x81A\xc1!\xa1a\xe1\x11\x91Q\xd11\xb1q\xf1"
46+
b"\t\x89I\xc9)\xa9i\xe9\x19\x99Y\xd99\xb9y\xf9"
47+
b"\x05\x85E\xc5%\xa5e\xe5\x15\x95U\xd55\xb5u\xf5"
48+
b"\r\x8dM\xcd-\xadm\xed\x1d\x9d]\xdd=\xbd}\xfd"
49+
b"\x03\x83C\xc3#\xa3c\xe3\x13\x93S\xd33\xb3s\xf3"
50+
b"\x0b\x8bK\xcb+\xabk\xeb\x1b\x9b[\xdb;\xbb{\xfb"
51+
b"\x07\x87G\xc7'\xa7g\xe7\x17\x97W\xd77\xb7w\xf7"
52+
b"\x0f\x8fO\xcf/\xafo\xef\x1f\x9f_\xdf?\xbf\x7f\xff"
53+
)
2654

2755

2856
def checksum(data, start, count):
@@ -32,24 +60,17 @@ def checksum(data, start, count):
3260
return cs
3361

3462

35-
PRINTER_CAT = PrinterConfig(width=384, service=0xA3E0, characteristic=0xAE01)
36-
3763
MODE_TEXT = "MODE_TEXT"
3864
MODE_BITMAP = "MODE_BITMAP"
3965

40-
printers = {"GB02": PRINTER_CAT, "GB01": PRINTER_CAT}
41-
4266
class CatPrinter(Service):
4367

4468
uuid = StandardUUID(0xAE30)
4569

46-
_tx = StreamIn(uuid=StandardUUID(0xAE01),
47-
timeout=1.0,
48-
buffer_size=256,
49-
)
70+
_tx = StreamIn(uuid=StandardUUID(0xAE01), timeout=1.0, buffer_size=256)
5071

5172
def _write_data(self, buf):
52-
result = self._tx.write(buf)
73+
self._tx.write(buf)
5374

5475
@property
5576
def bitmap_width(self):
@@ -59,7 +80,6 @@ def __init__(self, service=None):
5980
super().__init__(service=service)
6081
self._mode = None
6182

62-
6383
@property
6484
def mode(self):
6585
return self._mode
@@ -80,14 +100,12 @@ def mode(self, value):
80100

81101
def feed_lines(self, lines):
82102
buf = bytearray(paperfeed)
83-
buf[6] = lines & 0xff
103+
buf[6] = lines & 0xFF
84104
buf[7] = lines >> 8
85105
buf[8] = checksum(buf, 6, 2)
86106
self._write_data(buf)
87107

88108
def _print_common(self, text, reverse_bits=True):
89-
90-
offset = 0
91109
data = memoryview(text)
92110
while data:
93111
sz = min(112, len(data))

0 commit comments

Comments
 (0)