From 0d04a2efde442a142e5b18fac9fe1a0d83e61c8e Mon Sep 17 00:00:00 2001 From: Philipp Klaus Date: Tue, 19 Jul 2016 18:18:05 +0200 Subject: [PATCH] Reworking brother_ql/reader.py The code used in BrotherQLReader.analyse() is now is now split into a chunker() function which separates (=chunks) a data stream of bytes into individual printer instructions and into the main functionality of the analyse() method: Stating debug information about each instruction and generating images of the expected printer output. --- brother_ql/reader.py | 93 ++++++++++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 37 deletions(-) diff --git a/brother_ql/reader.py b/brother_ql/reader.py index 8e38a3d..72154cb 100755 --- a/brother_ql/reader.py +++ b/brother_ql/reader.py @@ -12,21 +12,21 @@ from matplotlib import pyplot as plt logger = logging.getLogger(__name__) cmds = { - # signature name following bytes description - b'\x00': ("preamble", 0, "Preamble, 200-300x 0x00 to clear comamnd buffer"), - b'\x4D': ("compression", 1, ""), - b'\x67': ("raster", -1, ""), - b'\x0C': ("print", 0, "print intermediate page"), - b'\x1A': ("print", 0, "print final page"), - b'\x1b\x40': ("init", 0, "initialization"), - b'\x1b\x69\x61': ("mode setting", 1, ""), - b'\x1b\x69\x7A': ("media/quality", 10, "print-media and print-quality"), - b'\x1b\x69\x4D': ("various", 1, "Auto cut flag in bit 7"), - b'\x1b\x69\x41': ("cut-every", 1, "cut every n-th page"), - b'\x1b\x69\x4B': ("expanded", 1, ""), - b'\x1b\x69\x64': ("margins", 2, ""), - b'\x1b\x69\x55\x77\x01': ('amedia',127, "Additional media information command"), - b'\x1b\x69\x55\x4A': ('jobid', 14, "Job ID setting command"), + # signature name following bytes description + b'\x00': ("preamble", -1, "Preamble, 200-300x 0x00 to clear comamnd buffer"), + b'\x4D': ("compression", 1, ""), + b'\x67': ("raster", -1, ""), + b'\x0C': ("print", 0, "print intermediate page"), + b'\x1A': ("print", 0, "print final page"), + b'\x1b\x40': ("init", 0, "initialization"), + b'\x1b\x69\x61': ("mode setting", 1, ""), + b'\x1b\x69\x7A': ("media/quality", 10, "print-media and print-quality"), + b'\x1b\x69\x4D': ("various", 1, "Auto cut flag in bit 7"), + b'\x1b\x69\x41': ("cut-every", 1, "cut every n-th page"), + b'\x1b\x69\x4B': ("expanded", 1, ""), + b'\x1b\x69\x64': ("margins", 2, ""), + b'\x1b\x69\x55\x77\x01': ('amedia', 127, "Additional media information command"), + b'\x1b\x69\x55\x4A': ('jobid', 14, "Job ID setting command"), } dot_widths = { @@ -39,6 +39,41 @@ def hex_format(data): except ValueError: # Py2 return ' '.join('{:02X}'.format(ord(byte)) for byte in data) +def chunker(data, raise_exception=False): + """ + Breaks data stream (bytes) into a list of bytes containing single instructions each. + + Logs warnings for unknown commands. + If raise_exception is set to True it raise exceptions instead. + + returns: list of bytes + """ + instructions = [] + while True: + if len(data) == 0: break + cmd_found = False + for command in cmds.keys(): + if data.startswith(command): + cmd = cmds[command] + num_bytes = len(command) + if cmd[1] > 0: num_bytes += cmd[1] + if cmd[0] == 'raster': + num_bytes += data[2] + 2 + #payload = data[len(command):num_bytes] + instructions.append(data[:num_bytes]) + data = data[num_bytes:] + cmd_found = True + if cmd_found: + continue + else: + msg = 'unknown instruction starting with {}...)'.format(hex_format(data[0:4])) + if raise_exception: + raise ValueError(msg) + else: + logger.warning(msg) + data = data[1:] + return instructions + class BrotherQLReader(object): def __init__(self, brother_file): @@ -52,23 +87,16 @@ class BrotherQLReader(object): self.page = 1 def analyse(self): - rem_script = self.brother_file.read() - while True: - if len(rem_script) == 0: break - cmd_found = False + instructions = self.brother_file.read() + for instruction in chunker(instructions): for command in cmds.keys(): - if rem_script.startswith(command): + if instruction.startswith(command): cmd = cmds[command] - num_bytes = len(command) - if cmd[1] > 0: num_bytes += cmd[1] if cmd[0] == 'init': self.mwidth, self.mheight = None, None self.raster_no = None self.rows = [] - if cmd[0] == 'raster': - num_bytes += rem_script[2] + 2 - payload = rem_script[len(command):num_bytes] - # now num_bytes and payload are accessable + payload = instruction[len(command):] logger.info(" {} ({}) --> found! (payload: {})".format(cmd[0], hex_format(command), hex_format(payload))) if cmd[0] == 'compression': self.compression = payload[0] == 0x02 @@ -95,8 +123,8 @@ class BrotherQLReader(object): self.rows.append(row) if cmd[0] == 'media/quality': self.raster_no = struct.unpack('