/ CircuitPython_BLEThermalPrinter / code.py
code.py
1 # SPDX-FileCopyrightText: 2021 Jeff Epler for Adafruit Industries 2 # 3 # SPDX-License-Identifier: MIT 4 5 import os 6 7 import board 8 import keypad 9 import ulab.numpy as np 10 11 from adafruit_ble import BLERadio 12 from adafruit_ble.advertising import Advertisement 13 14 from thermalprinter import CatPrinter 15 from seekablebitmap import imageopen 16 17 ble = BLERadio() # pylint: disable=no-member 18 19 buttons = keypad.Keys([board.BUTTON_A, board.BUTTON_B], value_when_pressed=False) 20 21 def wait_for_press(kbd): 22 """ 23 Wait for a keypress and return the event 24 """ 25 while True: 26 event = kbd.events.get() 27 if event and event.pressed: 28 return event 29 30 31 def show(s): 32 """ 33 Display a message on the screen 34 """ 35 board.DISPLAY.auto_refresh = False 36 print("\n" * 24) 37 print(s) 38 board.DISPLAY.auto_refresh = True 39 40 41 def show_error(s): 42 """ 43 Display a message on the screen and wait for a button press 44 """ 45 show(s + "\nPress a button to continue") 46 wait_for_press(buttons) 47 48 49 def find_cat_printer(radio): 50 """ 51 Connect to the cat printer device using BLE 52 """ 53 while True: 54 show("Scanning for GB02 device...") 55 for adv in radio.start_scan(Advertisement): 56 complete_name = getattr(adv, "complete_name") 57 if complete_name is not None: 58 print(f"Saw {complete_name}") 59 if complete_name == "GB02": 60 radio.stop_scan() 61 return radio.connect(adv, timeout=10)[CatPrinter] 62 63 64 image_files = [ 65 i 66 for i in os.listdir("/") 67 if i.lower().endswith(".pbm") or i.lower().endswith(".bmp") 68 ] 69 image_files.sort(key=lambda filename: filename.lower()) 70 71 72 def select_image(): 73 i = 0 74 while True: 75 show( 76 f"Select image file\nA: next image\nB: print this image\n\n{image_files[i]}" 77 ) 78 event = wait_for_press(buttons) 79 if event.key_number == 0: # button "A" 80 i = (i + 1) % len(image_files) 81 if event.key_number == 1: # button "B" 82 return image_files[i] 83 84 85 printer = find_cat_printer(ble) 86 87 def main(): 88 try: 89 filename = select_image() 90 91 show(f"Loading {filename}") 92 93 image = imageopen(filename) 94 if image.width != 384: 95 raise ValueError("Invalid image. Must be 384 pixels wide") 96 if image.bits_per_pixel != 1: 97 raise ValueError("Invalid image. Must be 1 bit per pixel (black & white)") 98 99 invert_image = image.palette and image.palette[0] == 0 100 101 show(f"Printing {filename}") 102 103 for i in range(image.height): 104 row_data = image.get_row(i) 105 if invert_image: 106 row_data = ~np.frombuffer(row_data, dtype=np.uint8) 107 printer.print_bitmap_row(row_data) 108 109 # Print blank lines until the paper can be torn off 110 for i in range(80): 111 printer.print_bitmap_row(b"\0" * 48) 112 113 except Exception as e: # pylint: disable=broad-except 114 show_error(str(e)) 115 image_files.remove(filename) 116 117 while True: 118 main()