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.
This commit is contained in:
Philipp Klaus
2016-07-19 18:18:05 +02:00
parent d1a8599df5
commit 0d04a2efde
+56 -37
View File
@@ -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('<L', payload[4:8])[0]
self.mwidth = rem_script[len(command) + 2]
self.mlength = rem_script[len(command) + 3]*256
self.mwidth = instruction[len(command) + 2]
self.mlength = instruction[len(command) + 3]*256
fmt = " media width: {}mm, media length: {}mm, raster no: {}dots"
logger.info(fmt.format(self.mwidth, self.mlength, self.raster_no))
if cmd[0] == 'print':
@@ -111,12 +139,3 @@ class BrotherQLReader(object):
im.save(img_name)
print('Page saved as {}'.format(img_name))
self.page += 1
rem_script = rem_script[num_bytes:]
cmd_found = True
if cmd_found:
continue
else:
logger.error('cmd not found: {0}... ({1}...)'.format(hex_format(rem_script[0:4]), rem_script[0:4]))
rem_script = rem_script[1:]