Fix printing via a Brother QL
This commit is contained in:
128
src/printer.py
128
src/printer.py
@@ -20,10 +20,11 @@ import numpy as np
|
||||
# Importing the modules needed for each supported printer Type
|
||||
import escpos.printer
|
||||
from brother_ql.models import ModelsManager
|
||||
from brother_ql.backends import backend_factory
|
||||
from brother_ql.backends import backend_factory, guess_backend
|
||||
from brother_ql.raster import BrotherQLRaster
|
||||
from brother_ql.conversion import convert
|
||||
from brother_ql.backends.helpers import send
|
||||
from brother_ql import create_label
|
||||
|
||||
|
||||
class PrinterType(Enum):
|
||||
@@ -444,6 +445,7 @@ class BrotherPrinter(Printer):
|
||||
vendor_id=vendor_id,
|
||||
product_id=self.device_id,
|
||||
serial_number=serial_number,
|
||||
label_type="62",
|
||||
)
|
||||
self.app.logger.debug("Created a Brother printer !")
|
||||
self.ready = True
|
||||
@@ -462,86 +464,49 @@ class BrotherPrinter(Printer):
|
||||
"""
|
||||
Print a raster image via a Brother QL printer
|
||||
"""
|
||||
# TODO : make this label type go in the configuration
|
||||
label_type = "62"
|
||||
rotate = 0
|
||||
dither = False
|
||||
|
||||
data = _process_image(self, path=data, max_width=720, max_height=720)
|
||||
self.app.logger.debug("Printing image %s", data)
|
||||
self.ready = False
|
||||
try:
|
||||
# Prepare the image for printing
|
||||
qlr = BrotherQLRaster(self.printer_info["model"])
|
||||
|
||||
instructions = convert(
|
||||
qlr=qlr,
|
||||
images=[data],
|
||||
label=label_type,
|
||||
rotate=rotate,
|
||||
threshold=70,
|
||||
dither=dither,
|
||||
compress=True,
|
||||
red=False,
|
||||
dpi_600=False,
|
||||
hq=False,
|
||||
cut=True,
|
||||
)
|
||||
|
||||
# Debug logging
|
||||
if os.getenv("FLASK_DEBUG"):
|
||||
self.app.logger.debug(f"""
|
||||
Print parameters:
|
||||
- Label type: {label_type}
|
||||
- Rotate: {rotate}
|
||||
- Dither: {dither}
|
||||
- Model: {self.printer_info['model']}
|
||||
- Backend: {self.printer_info['backend']}
|
||||
- Identifier: {self.printer_info['identifier']}
|
||||
""")
|
||||
|
||||
# Try to print using Python API
|
||||
# send() = status = {
|
||||
# 'instructions_sent': True, # The instructions were sent to the printer.
|
||||
# 'outcome': 'unknown', # String description of the outcome of the sending operation like: 'unknown', 'sent', 'printed', 'error'
|
||||
# 'printer_state': None, # If the selected backend supports reading back the printer state, this key will contain it.
|
||||
# 'did_print': False, # If True, a print was produced. It defaults to False if the outcome is uncertain (due to a backend without read-back capability).
|
||||
# 'ready_for_next_job': False, # If True, the printer is ready to receive the next instructions. It defaults to False if the state is unknown.
|
||||
# }
|
||||
status = send(
|
||||
instructions=instructions,
|
||||
printer_identifier=self.printer_info["identifier"],
|
||||
backend_identifier="pyusb",
|
||||
)
|
||||
self.app.logger.debug("Status: " + str(status))
|
||||
|
||||
if (
|
||||
not status["did_print"]
|
||||
or status["outcome"] == "error"
|
||||
or status["outcome"] == "unknown"
|
||||
):
|
||||
raise RuntimeError("Failed to print using Python API")
|
||||
|
||||
# if status["printer_state"]:
|
||||
# self.ready = bool(status["printer_state"])
|
||||
# self.app.logger.debug("Printer is borky : " + str(self.ready))
|
||||
# else:
|
||||
# self.ready = True
|
||||
|
||||
except usb.core.USBError as e:
|
||||
# Treat timeout errors as successful since they often occur after print completion
|
||||
if e.errno == 110: # Operation timed out
|
||||
self.app.logger.debug(
|
||||
"USB timeout occurred - this is normal and the print likely completed"
|
||||
)
|
||||
self.app.logger.debug("Print completed (timeout is normal)")
|
||||
self.ready = True
|
||||
|
||||
self.app.logger.debug(f"USBError encountered: {e}")
|
||||
raise RuntimeError from e
|
||||
|
||||
selected_backend = guess_backend(self.printer_info.identifier)
|
||||
BACKEND_CLASS = backend_factory(selected_backend)['backend_class']
|
||||
BACKEND_STRING_DESCR = self.printer_info.identifier
|
||||
except Exception as e:
|
||||
self.app.logger.debug(f"Unexpected error during printing: {str(e)}")
|
||||
raise RuntimeError from e
|
||||
self.app.logger.error("Couldn't guess the backend to use from the printer string descriptor")
|
||||
|
||||
try:
|
||||
im = Image.open(data)
|
||||
qlr = BrotherQLRaster(self.printer_info.model)
|
||||
create_label(qlr, im, self.printer_info.label_type, threshold=70, cut=False, rotate=0)
|
||||
|
||||
# noinspection PyCallingNonCallable
|
||||
be = BACKEND_CLASS(BACKEND_STRING_DESCR)
|
||||
be.write(qlr.data)
|
||||
be.dispose()
|
||||
del be
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def _cut(self):
|
||||
self.ready = False
|
||||
try:
|
||||
selected_backend = guess_backend(self.printer_info.identifier)
|
||||
BACKEND_CLASS = backend_factory(selected_backend)['backend_class']
|
||||
BACKEND_STRING_DESCR = self.printer_info.identifier
|
||||
except Exception as e:
|
||||
self.app.logger.error("Couldn't guess the backend to use from the printer string descriptor")
|
||||
|
||||
data = "src/static/images/1x1.png"
|
||||
try:
|
||||
im = Image.open(data)
|
||||
qlr = BrotherQLRaster(self.printer_info.model)
|
||||
create_label(qlr, im, self.printer_info.label_type, threshold=70, cut=True, rotate=0)
|
||||
|
||||
# noinspection PyCallingNonCallable
|
||||
be = BACKEND_CLASS(BACKEND_STRING_DESCR)
|
||||
be.write(qlr.data)
|
||||
be.dispose()
|
||||
del be
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def print_task(self, task_type, data):
|
||||
"""Execute actual print based on task type"""
|
||||
@@ -551,9 +516,10 @@ class BrotherPrinter(Printer):
|
||||
match (task_type.value):
|
||||
case "image":
|
||||
self._print_img(data["img"])
|
||||
self.ready = True
|
||||
case "cut":
|
||||
# The cut happens by default on Brother QL printers.
|
||||
pass
|
||||
self._cut()
|
||||
self.ready = True
|
||||
case "text":
|
||||
self._print_txt(data["txt"], signature=data["sign"])
|
||||
self.ready = True
|
||||
|
||||
Reference in New Issue
Block a user