diff zebra.py @ 29:63d1260cc64e 0.1.0

- class name is now 'Zebra' instead of 'zebra' - Fix for missing win32print module in pypi - Drop python 2 support - use setuptools instead of distutils - improve documentation - Added reset(), reset_default(), autosense(), print_config_label() and print_graphic() functions
author Ben Croston <ben@croston.org>
date Tue, 01 Sep 2020 15:57:24 +0100
parents 7c132e01c281
children f77ca0963d6d
line wrap: on
line diff
--- a/zebra.py	Mon Apr 27 11:39:37 2015 +0100
+++ b/zebra.py	Tue Sep 01 15:57:24 2020 +0100
@@ -1,6 +1,6 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
-# Copyright (c) 2011-2015 Ben Croston
+# Copyright (c) 2011-2020 Ben Croston
 #
 # Permission is hereby granted, free of charge, to any person obtaining a copy of
 # this software and associated documentation files (the "Software"), to deal in
@@ -30,8 +30,8 @@
     IS_WINDOWS = False
     import subprocess
 
-class zebra(object):
-    """A class to communicate with (Zebra) label printers using EPL2"""
+class Zebra:
+    """A class to communicate with (Zebra) label printers"""
 
     def __init__(self, queue=None):
         """queue - name of the printer queue (optional)"""
@@ -47,7 +47,7 @@
 
     def _output_win(self, commands):
         if self.queue == 'zebra_python_unittest':
-            print commands
+            print(commands)
             return
         hPrinter = win32print.OpenPrinter(self.queue)
         try:
@@ -61,22 +61,26 @@
         finally:
             win32print.ClosePrinter(hPrinter)
 
-    def output(self, commands):
-        """Output EPL2 commands to the label printer
+    def output(self, commands, encoding='cp437'):
+        """Send raw commands to the label printer
 
-        commands - EPL2 commands to send to the printer
+        commands - commands to send to the printer.  Converted to a byte string if necessary.
+        encoding - Encoding used if 'commands' is not a byte string
         """
         assert self.queue is not None
-        if sys.version_info[0] == 3:
-            if type(commands) != bytes:
-                commands = str(commands).encode()
-        else:
-            commands = str(commands).encode()
+        if type(commands) != bytes:
+            commands = str(commands).encode(encoding=encoding)
         if IS_WINDOWS:
             self._output_win(commands)
         else:
             self._output_unix(commands)
 
+    def print_config_label(self):
+        """
+        Send an EPL2 command to print label(s) with current config settings
+        """
+        self.output('\nU\n')
+
     def _getqueues_unix(self):
         queues = []
         try:
@@ -106,7 +110,8 @@
         self.queue = queue
 
     def setup(self, direct_thermal=None, label_height=None, label_width=None):
-        """Set up the label printer. Parameters are not set if they are None.
+        """Set up the label printer using EPL2. Parameters are not set if they are None.
+        Not necessary if using AutoSense (hold feed button while powering on)
 
         direct_thermal - True if using direct thermal labels
         label_height   - tuple (label height, label gap) in dots
@@ -114,15 +119,29 @@
         """
         commands = '\n'
         if direct_thermal:
-            commands += ('OD\n')
+            commands += 'OD\n'
         if label_height:
-           commands += ('Q%s,%s\n'%(label_height[0],label_height[1]))
+           commands += 'Q%s,%s\n'%(label_height[0],label_height[1])
         if label_width:
-            commands += ('q%s\n'%label_width)
+            commands += 'q%s\n'%label_width
         self.output(commands)
 
+    def reset_default(self):
+        """Reset the printer to factory settings using EPL2"""
+        self.output('\n^default\n')
+
+    def reset(self):
+        """Resets the printer using EPL2 - equivalent to switching off/on"""
+        self.output('\n^@\n')
+
+    def autosense(self):
+         """Run AutoSense by sending an EPL2 command
+         Get the printer to detect label and gap length and set the sensor levels
+         """
+         self.output('\nxa\n')
+
     def store_graphic(self, name, filename):
-        """Store a .PCX file on the label printer
+        """Store a 1 bit PCX file on the label printer, using EPL2.
 
         name     - name to be used on printer
         filename - local filename
@@ -135,9 +154,24 @@
         self.output(commands)
         self.output(open(filename,'rb').read())
 
+    def print_graphic(self, x, y, width, length, data, qty):
+        """Print a label from 1 bit data, using EPL2
+
+        x,y    - top left coordinates of the image, in dots
+        width  - width of image, in dots.  Must be a multiple of 8.
+        length - length of image, in dots
+        data   - raw graphical data, in bytes
+        qty    - number of labels to print
+        """
+        assert type(data) == bytes
+        assert width % 8 == 0  # make sure width is a multiple of 8
+        assert (width//8) * length == len(data)
+        commands = b"\nN\nGW%d,%d,%d,%d,%s\nP%d\n"%(x, y, width//8, length, data, qty)
+        self.output(commands)
+
 if __name__ == '__main__':
-    z = zebra()
-    print 'Printer queues found:',z.getqueues()
+    z = Zebra()
+    print('Printer queues found:',z.getqueues())
     z.setqueue('zebra_python_unittest')
     z.setup(direct_thermal=True, label_height=(406,32), label_width=609)    # 3" x 2" direct thermal label
     z.store_graphic('logo','logo.pcx')