Mercurial > hg > zebra
comparison 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 |
comparison
equal
deleted
inserted
replaced
28:172de216b85d | 29:63d1260cc64e |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python3 |
2 | 2 |
3 # Copyright (c) 2011-2015 Ben Croston | 3 # Copyright (c) 2011-2020 Ben Croston |
4 # | 4 # |
5 # Permission is hereby granted, free of charge, to any person obtaining a copy of | 5 # Permission is hereby granted, free of charge, to any person obtaining a copy of |
6 # this software and associated documentation files (the "Software"), to deal in | 6 # this software and associated documentation files (the "Software"), to deal in |
7 # the Software without restriction, including without limitation the rights to | 7 # the Software without restriction, including without limitation the rights to |
8 # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | 8 # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
28 import win32print | 28 import win32print |
29 else: | 29 else: |
30 IS_WINDOWS = False | 30 IS_WINDOWS = False |
31 import subprocess | 31 import subprocess |
32 | 32 |
33 class zebra(object): | 33 class Zebra: |
34 """A class to communicate with (Zebra) label printers using EPL2""" | 34 """A class to communicate with (Zebra) label printers""" |
35 | 35 |
36 def __init__(self, queue=None): | 36 def __init__(self, queue=None): |
37 """queue - name of the printer queue (optional)""" | 37 """queue - name of the printer queue (optional)""" |
38 self.queue = queue | 38 self.queue = queue |
39 | 39 |
45 p.communicate(commands) | 45 p.communicate(commands) |
46 p.stdin.close() | 46 p.stdin.close() |
47 | 47 |
48 def _output_win(self, commands): | 48 def _output_win(self, commands): |
49 if self.queue == 'zebra_python_unittest': | 49 if self.queue == 'zebra_python_unittest': |
50 print commands | 50 print(commands) |
51 return | 51 return |
52 hPrinter = win32print.OpenPrinter(self.queue) | 52 hPrinter = win32print.OpenPrinter(self.queue) |
53 try: | 53 try: |
54 hJob = win32print.StartDocPrinter(hPrinter, 1, ('Label',None,'RAW')) | 54 hJob = win32print.StartDocPrinter(hPrinter, 1, ('Label',None,'RAW')) |
55 try: | 55 try: |
59 finally: | 59 finally: |
60 win32print.EndDocPrinter(hPrinter) | 60 win32print.EndDocPrinter(hPrinter) |
61 finally: | 61 finally: |
62 win32print.ClosePrinter(hPrinter) | 62 win32print.ClosePrinter(hPrinter) |
63 | 63 |
64 def output(self, commands): | 64 def output(self, commands, encoding='cp437'): |
65 """Output EPL2 commands to the label printer | 65 """Send raw commands to the label printer |
66 | 66 |
67 commands - EPL2 commands to send to the printer | 67 commands - commands to send to the printer. Converted to a byte string if necessary. |
68 encoding - Encoding used if 'commands' is not a byte string | |
68 """ | 69 """ |
69 assert self.queue is not None | 70 assert self.queue is not None |
70 if sys.version_info[0] == 3: | 71 if type(commands) != bytes: |
71 if type(commands) != bytes: | 72 commands = str(commands).encode(encoding=encoding) |
72 commands = str(commands).encode() | |
73 else: | |
74 commands = str(commands).encode() | |
75 if IS_WINDOWS: | 73 if IS_WINDOWS: |
76 self._output_win(commands) | 74 self._output_win(commands) |
77 else: | 75 else: |
78 self._output_unix(commands) | 76 self._output_unix(commands) |
77 | |
78 def print_config_label(self): | |
79 """ | |
80 Send an EPL2 command to print label(s) with current config settings | |
81 """ | |
82 self.output('\nU\n') | |
79 | 83 |
80 def _getqueues_unix(self): | 84 def _getqueues_unix(self): |
81 queues = [] | 85 queues = [] |
82 try: | 86 try: |
83 output = subprocess.check_output(['lpstat','-p'], universal_newlines=True) | 87 output = subprocess.check_output(['lpstat','-p'], universal_newlines=True) |
104 def setqueue(self, queue): | 108 def setqueue(self, queue): |
105 """Set the printer queue""" | 109 """Set the printer queue""" |
106 self.queue = queue | 110 self.queue = queue |
107 | 111 |
108 def setup(self, direct_thermal=None, label_height=None, label_width=None): | 112 def setup(self, direct_thermal=None, label_height=None, label_width=None): |
109 """Set up the label printer. Parameters are not set if they are None. | 113 """Set up the label printer using EPL2. Parameters are not set if they are None. |
114 Not necessary if using AutoSense (hold feed button while powering on) | |
110 | 115 |
111 direct_thermal - True if using direct thermal labels | 116 direct_thermal - True if using direct thermal labels |
112 label_height - tuple (label height, label gap) in dots | 117 label_height - tuple (label height, label gap) in dots |
113 label_width - in dots | 118 label_width - in dots |
114 """ | 119 """ |
115 commands = '\n' | 120 commands = '\n' |
116 if direct_thermal: | 121 if direct_thermal: |
117 commands += ('OD\n') | 122 commands += 'OD\n' |
118 if label_height: | 123 if label_height: |
119 commands += ('Q%s,%s\n'%(label_height[0],label_height[1])) | 124 commands += 'Q%s,%s\n'%(label_height[0],label_height[1]) |
120 if label_width: | 125 if label_width: |
121 commands += ('q%s\n'%label_width) | 126 commands += 'q%s\n'%label_width |
122 self.output(commands) | 127 self.output(commands) |
123 | 128 |
129 def reset_default(self): | |
130 """Reset the printer to factory settings using EPL2""" | |
131 self.output('\n^default\n') | |
132 | |
133 def reset(self): | |
134 """Resets the printer using EPL2 - equivalent to switching off/on""" | |
135 self.output('\n^@\n') | |
136 | |
137 def autosense(self): | |
138 """Run AutoSense by sending an EPL2 command | |
139 Get the printer to detect label and gap length and set the sensor levels | |
140 """ | |
141 self.output('\nxa\n') | |
142 | |
124 def store_graphic(self, name, filename): | 143 def store_graphic(self, name, filename): |
125 """Store a .PCX file on the label printer | 144 """Store a 1 bit PCX file on the label printer, using EPL2. |
126 | 145 |
127 name - name to be used on printer | 146 name - name to be used on printer |
128 filename - local filename | 147 filename - local filename |
129 """ | 148 """ |
130 assert filename.lower().endswith('.pcx') | 149 assert filename.lower().endswith('.pcx') |
133 size = os.path.getsize(filename) | 152 size = os.path.getsize(filename) |
134 commands += 'GM"%s"%s\n'%(name,size) | 153 commands += 'GM"%s"%s\n'%(name,size) |
135 self.output(commands) | 154 self.output(commands) |
136 self.output(open(filename,'rb').read()) | 155 self.output(open(filename,'rb').read()) |
137 | 156 |
157 def print_graphic(self, x, y, width, length, data, qty): | |
158 """Print a label from 1 bit data, using EPL2 | |
159 | |
160 x,y - top left coordinates of the image, in dots | |
161 width - width of image, in dots. Must be a multiple of 8. | |
162 length - length of image, in dots | |
163 data - raw graphical data, in bytes | |
164 qty - number of labels to print | |
165 """ | |
166 assert type(data) == bytes | |
167 assert width % 8 == 0 # make sure width is a multiple of 8 | |
168 assert (width//8) * length == len(data) | |
169 commands = b"\nN\nGW%d,%d,%d,%d,%s\nP%d\n"%(x, y, width//8, length, data, qty) | |
170 self.output(commands) | |
171 | |
138 if __name__ == '__main__': | 172 if __name__ == '__main__': |
139 z = zebra() | 173 z = Zebra() |
140 print 'Printer queues found:',z.getqueues() | 174 print('Printer queues found:',z.getqueues()) |
141 z.setqueue('zebra_python_unittest') | 175 z.setqueue('zebra_python_unittest') |
142 z.setup(direct_thermal=True, label_height=(406,32), label_width=609) # 3" x 2" direct thermal label | 176 z.setup(direct_thermal=True, label_height=(406,32), label_width=609) # 3" x 2" direct thermal label |
143 z.store_graphic('logo','logo.pcx') | 177 z.store_graphic('logo','logo.pcx') |
144 label = """ | 178 label = """ |
145 N | 179 N |