From 21f9c34508c0dce270d8ab7f64b263d9e6c6b9ba Mon Sep 17 00:00:00 2001 From: William Rogers Date: Thu, 14 May 2015 14:39:05 -0500 Subject: [PATCH 1/2] Added an image cache to allow for faster image printing --- escpos/escpos.py | 53 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 8 deletions(-) mode change 100644 => 100755 escpos/escpos.py diff --git a/escpos/escpos.py b/escpos/escpos.py old mode 100644 new mode 100755 index b6befdd..f4c3627 --- a/escpos/escpos.py +++ b/escpos/escpos.py @@ -20,7 +20,7 @@ from exceptions import * class Escpos: """ ESC/POS Printer object """ device = None - + img_cache = [] def _check_image_size(self, size): """ Check and fix the size of the image to 32 bits """ @@ -33,13 +33,45 @@ class Escpos: else: return (image_border / 2, (image_border / 2) + 1) + def cache_image(self, path_img): + """ Open image file and store in the printer's cache """ + + img_no = len(self.img_cache) + + im_open = Image.open(path_img) + im = im_open.convert("RGB") + # Convert the RGB image into printable image + (pix_line, img_size) = self._convert_image(im) + + # Convert the buffered data directly to the printer readable format + cache = "" + buffer = "" + i = 0 + cont = 0 + + buffer = "%02X%02X%02X%02X" % (((img_size[0]/img_size[1])/8), 0, img_size[1], 0) + cache = buffer.decode('hex') + buffer = "" + + while i < len(pix_line): + hex_string = int(pix_line[i:i+8],2) + buffer += "%02X" % hex_string + i += 8 + cont += 1 + if cont % 4 == 0: + cache += buffer.decode("hex") + buffer = "" + cont = 0 + + self.img_cache.append(cache) + return img_no def _print_image(self, line, size): """ Print formatted image """ i = 0 cont = 0 buffer = "" - + self._raw(S_RASTER_N) buffer = "%02X%02X%02X%02X" % (((size[0]/size[1])/8), 0, size[1], 0) self._raw(buffer.decode('hex')) @@ -97,20 +129,25 @@ class Escpos: break elif im_color > (255 * 3 / pattern_len * pattern_len) and im_color <= (255 * 3): pix_line += im_pattern[-1] - break + break pix_line += im_right img_size[0] += im_border[1] - self._print_image(pix_line, img_size) - + return pix_line, img_size def image(self,path_img): - """ Open image file """ + """ Open and immediately print image file """ im_open = Image.open(path_img) im = im_open.convert("RGB") - # Convert the RGB image in printable image - self._convert_image(im) + # Convert the RGB image in printable image + (pix_line, img_size) = self._convert_image(im) + self._print_image(pix_line, img_size) + + def cached_image(self, index): + """ Prints an image from the image cache """ + self._raw(S_RASTER_N) + self._raw(self.img_cache[index]) def qr(self,text): """ Print QR Code for the provided string """ From 940306295c2aca973d87fe51f1e99d6c321d92e7 Mon Sep 17 00:00:00 2001 From: William Rogers Date: Fri, 15 May 2015 11:16:30 -0500 Subject: [PATCH 2/2] Added interface to allow the printer device to be manually opened and closed. This allows the printer object to retain the host side image cache and helps the developer to open the printer only as needed to help avoid issues if the device has been disconnected. NOTE: This style of usage is optional and standard usage is otherwise unaffected. --- escpos/printer.py | 83 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 9 deletions(-) mode change 100644 => 100755 escpos/printer.py diff --git a/escpos/printer.py b/escpos/printer.py old mode 100644 new mode 100755 index a34edb4..1ea162c --- a/escpos/printer.py +++ b/escpos/printer.py @@ -18,6 +18,8 @@ from exceptions import * class Usb(Escpos): """ Define USB printer """ + is_open = False + def __init__(self, idVendor, idProduct, interface=0, in_ep=0x82, out_ep=0x01): """ @param idVendor : Vendor ID @@ -36,9 +38,14 @@ class Usb(Escpos): def open(self): """ Search device on USB tree and set is as escpos device """ + if self.is_open: + return # Already open; no need to reopen + self.device = usb.core.find(idVendor=self.idVendor, idProduct=self.idProduct) if self.device is None: print "Cable isn't plugged in" + else: + self.is_open = True if self.device.is_kernel_driver_active(0): try: @@ -50,9 +57,21 @@ class Usb(Escpos): self.device.set_configuration() self.device.reset() except usb.core.USBError as e: + # Seems fatal when it occurs. Should the device be closed as a result? + #self.close() print "Could not set configuration: %s" % str(e) + def close(self): + """ Manually release USB interface """ + self.is_open = False + + if self.device: + usb.util.dispose_resources(self.device) + + self.device = None + + def _raw(self, msg): """ Print any command sent in raw format """ self.device.write(self.out_ep, msg, self.interface) @@ -60,15 +79,15 @@ class Usb(Escpos): def __del__(self): """ Release USB interface """ - if self.device: - usb.util.dispose_resources(self.device) - self.device = None + self.close() class Serial(Escpos): """ Define Serial printer """ + is_open = False + def __init__(self, devfile="/dev/ttyS0", baudrate=9600, bytesize=8, timeout=1): """ @param devfile : Device file under dev filesystem @@ -84,15 +103,29 @@ class Serial(Escpos): def open(self): - """ Setup serial port and set is as escpos device """ + """ Setup serial port and set it as escpos device """ + if self.is_open: + return # Already open; no need to reopen + self.device = serial.Serial(port=self.devfile, baudrate=self.baudrate, bytesize=self.bytesize, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, timeout=self.timeout, dsrdtr=True) if self.device is not None: print "Serial printer enabled" + self.is_open = True else: print "Unable to open serial printer on: %s" % self.devfile + def close(self): + """ Manually close Serial interface """ + self.is_open = False + + if self.device is not None: + self.device.close() + + self.device = None + + def _raw(self, msg): """ Print any command sent in raw format """ self.device.write(msg) @@ -100,14 +133,14 @@ class Serial(Escpos): def __del__(self): """ Close Serial interface """ - if self.device is not None: - self.device.close() - + self.close() class Network(Escpos): """ Define Network printer """ + is_open = False + def __init__(self,host,port=9100): """ @param host : Printer's hostname or IP address @@ -120,11 +153,26 @@ class Network(Escpos): def open(self): """ Open TCP socket and set it as escpos device """ + if self.is_open: + return # Already open; no need to reopen + self.device = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.device.connect((self.host, self.port)) if self.device is None: print "Could not open socket for %s" % self.host + else: + self.is_open = True + + + def close(self): + """ Manually close TCP connection """ + self.is_open = False + + if self.device is not None: + self.device.close() + + self.device = None def _raw(self, msg): @@ -134,13 +182,15 @@ class Network(Escpos): def __del__(self): """ Close TCP connection """ - self.device.close() + self.close() class File(Escpos): """ Define Generic file printer """ + is_open = False + def __init__(self, devfile="/dev/usb/lp0"): """ @param devfile : Device file under dev filesystem @@ -151,10 +201,25 @@ class File(Escpos): def open(self): """ Open system file """ + if self.is_open: + return # Already open; no need to reopen + self.device = open(self.devfile, "wb") if self.device is None: print "Could not open the specified file %s" % self.devfile + else: + self.is_open = True + + + def close(self): + """ Manually close system file """ + self.is_open = False + + if self.device is not None: + self.device.close() + + self.device = None def _raw(self, msg): @@ -164,4 +229,4 @@ class File(Escpos): def __del__(self): """ Close system file """ - self.device.close() + self.close()