copy files from google code repo
This commit is contained in:
parent
4daece43e7
commit
a6c72adc58
|
@ -1,35 +1,2 @@
|
||||||
*.py[cod]
|
*.py[cod]
|
||||||
|
.DS_Store
|
||||||
# C extensions
|
|
||||||
*.so
|
|
||||||
|
|
||||||
# Packages
|
|
||||||
*.egg
|
|
||||||
*.egg-info
|
|
||||||
dist
|
|
||||||
build
|
|
||||||
eggs
|
|
||||||
parts
|
|
||||||
bin
|
|
||||||
var
|
|
||||||
sdist
|
|
||||||
develop-eggs
|
|
||||||
.installed.cfg
|
|
||||||
lib
|
|
||||||
lib64
|
|
||||||
|
|
||||||
# Installer logs
|
|
||||||
pip-log.txt
|
|
||||||
|
|
||||||
# Unit test / coverage reports
|
|
||||||
.coverage
|
|
||||||
.tox
|
|
||||||
nosetests.xml
|
|
||||||
|
|
||||||
# Translations
|
|
||||||
*.mo
|
|
||||||
|
|
||||||
# Mr Developer
|
|
||||||
.mr.developer.cfg
|
|
||||||
.project
|
|
||||||
.pydevproject
|
|
91
README.md
91
README.md
|
@ -1,4 +1,89 @@
|
||||||
python-escpos
|
ESCPOS
|
||||||
=============
|
======
|
||||||
|
|
||||||
|
Python library to manipulate ESC/POS Printers.
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
1. Dependencies
|
||||||
|
|
||||||
|
In order to start getting access to your printer, you must ensure
|
||||||
|
you have previously installed the following python modules:
|
||||||
|
|
||||||
|
* pyusb (python-usb)
|
||||||
|
* PIL (Python Image Library)
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
2. Description
|
||||||
|
|
||||||
|
Python ESC/POS is a library which lets the user have access to all
|
||||||
|
those printers handled by ESC/POS commands, as defined by Epson,
|
||||||
|
from a Python application.
|
||||||
|
|
||||||
|
The standard usage is send raw text to the printer, but in also
|
||||||
|
helps the user to enhance the experience with those printers by
|
||||||
|
facilitating the bar code printing in many different standards,
|
||||||
|
as well as manipulating images so they can be printed as brand
|
||||||
|
logo or any other usage images migh have.
|
||||||
|
|
||||||
|
Text can be aligned/justified and fonts can be changed by size,
|
||||||
|
type and weight.
|
||||||
|
|
||||||
|
Also, this module handles some hardware functionalities like, cut
|
||||||
|
paper, carrier return, printer reset and others concerned to the
|
||||||
|
carriage alignment.
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
3. Define your printer
|
||||||
|
|
||||||
|
Before start create your Python ESC/POS printer instance, you must
|
||||||
|
see at your system for the printer parameters. This is done with
|
||||||
|
the 'lsusb' command.
|
||||||
|
|
||||||
|
First run the command to look for the "Vendor ID" and "Product ID",
|
||||||
|
then write down the values, these values are displayed just before
|
||||||
|
the name of the device with the following format:
|
||||||
|
|
||||||
|
xxxx:xxxx
|
||||||
|
|
||||||
|
Example:
|
||||||
|
Bus 002 Device 001: ID 1a2b:1a2b Device name
|
||||||
|
|
||||||
|
Write down the the values in question, then issue the following
|
||||||
|
command so you can get the "Interface" number and "End Point"
|
||||||
|
|
||||||
|
lsusb -vvv -d xxxx:xxxx | grep iInterface
|
||||||
|
lsusb -vvv -d xxxx:xxxx | grep bEndpointAddress | grep OUT
|
||||||
|
|
||||||
|
The first command will yields the "Interface" number that must
|
||||||
|
be handy to have and the second yields the "Output Endpoint"
|
||||||
|
address.
|
||||||
|
|
||||||
|
By default the "Interface" number is "0" and the "Output Endpoint"
|
||||||
|
address is "0x82", if you have other values then you can define
|
||||||
|
with your instance.
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
4. Define your instance
|
||||||
|
|
||||||
|
The following example shows how to initialize the Epson TM-TI88IV
|
||||||
|
*** NOTE: Always finish the sequence with Epson.cut() otherwise
|
||||||
|
you will endup with weird chars being printed.
|
||||||
|
|
||||||
|
from escpos import *
|
||||||
|
|
||||||
|
""" Seiko Epson Corp. Receipt Printer M129 Definitions (EPSON TM-T88IV) """
|
||||||
|
Epson = escpos.Escpos(0x04b8,0x0202,0)
|
||||||
|
Epson.text("Hello World")
|
||||||
|
Epson.image("logo.gif")
|
||||||
|
Epson.barcode
|
||||||
|
Epson.barcode('1324354657687','EAN13',64,2,'','')
|
||||||
|
Epson.cut()
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
5. Links
|
||||||
|
|
||||||
|
Please visit project homepage at:
|
||||||
|
http://repo.bashlinux.com/projects/escpos.html
|
||||||
|
|
||||||
|
Manuel F Martinez <manpaz@bashlinux.com>
|
||||||
|
|
||||||
Fork of the python-escpos project for printing to POS printers.
|
|
|
@ -0,0 +1 @@
|
||||||
|
__all__ = ["constants","escpos","exceptions","printer"]
|
|
@ -0,0 +1,53 @@
|
||||||
|
""" ESC/POS Commands (Constants) """
|
||||||
|
|
||||||
|
# Feed control sequences
|
||||||
|
CTL_LF = '\x0a' # Print and line feed
|
||||||
|
CTL_FF = '\x0c' # Form feed
|
||||||
|
CTL_CR = '\x0d' # Carriage return
|
||||||
|
CTL_HT = '\x09' # Horizontal tab
|
||||||
|
CTL_VT = '\x0b' # Vertical tab
|
||||||
|
# Printer hardware
|
||||||
|
HW_INIT = '\x1b\x40' # Clear data in buffer and reset modes
|
||||||
|
HW_SELECT = '\x1b\x3d\x01' # Printer select
|
||||||
|
HW_RESET = '\x1b\x3f\x0a\x00' # Reset printer hardware
|
||||||
|
# Cash Drawer
|
||||||
|
CD_KICK_2 = '\x1b\x70\x00' # Sends a pulse to pin 2 []
|
||||||
|
CD_KICK_5 = '\x1b\x70\x01' # Sends a pulse to pin 5 []
|
||||||
|
# Paper
|
||||||
|
PAPER_FULL_CUT = '\x1d\x56\x00' # Full cut paper
|
||||||
|
PAPER_PART_CUT = '\x1d\x56\x01' # Partial cut paper
|
||||||
|
# Text format
|
||||||
|
TXT_NORMAL = '\x1b\x21\x00' # Normal text
|
||||||
|
TXT_2HEIGHT = '\x1b\x21\x10' # Double height text
|
||||||
|
TXT_2WIDTH = '\x1b\x21\x20' # Double width text
|
||||||
|
TXT_UNDERL_OFF = '\x1b\x2d\x00' # Underline font OFF
|
||||||
|
TXT_UNDERL_ON = '\x1b\x2d\x01' # Underline font 1-dot ON
|
||||||
|
TXT_UNDERL2_ON = '\x1b\x2d\x02' # Underline font 2-dot ON
|
||||||
|
TXT_BOLD_OFF = '\x1b\x45\x00' # Bold font OFF
|
||||||
|
TXT_BOLD_ON = '\x1b\x45\x01' # Bold font ON
|
||||||
|
TXT_FONT_A = '\x1b\x4d\x00' # Font type A
|
||||||
|
TXT_FONT_B = '\x1b\x4d\x01' # Font type B
|
||||||
|
TXT_ALIGN_LT = '\x1b\x61\x00' # Left justification
|
||||||
|
TXT_ALIGN_CT = '\x1b\x61\x01' # Centering
|
||||||
|
TXT_ALIGN_RT = '\x1b\x61\x02' # Right justification
|
||||||
|
# Barcode format
|
||||||
|
BARCODE_TXT_OFF = '\x1d\x48\x00' # HRI barcode chars OFF
|
||||||
|
BARCODE_TXT_ABV = '\x1d\x48\x01' # HRI barcode chars above
|
||||||
|
BARCODE_TXT_BLW = '\x1d\x48\x02' # HRI barcode chars below
|
||||||
|
BARCODE_TXT_BTH = '\x1d\x48\x03' # HRI barcode chars both above and below
|
||||||
|
BARCODE_FONT_A = '\x1d\x66\x00' # Font type A for HRI barcode chars
|
||||||
|
BARCODE_FONT_B = '\x1d\x66\x01' # Font type B for HRI barcode chars
|
||||||
|
BARCODE_HEIGHT = '\x1d\x68\x64' # Barcode Height [1-255]
|
||||||
|
BARCODE_WIDTH = '\x1d\x77\x03' # Barcode Width [2-6]
|
||||||
|
BARCODE_UPC_A = '\x1d\x6b\x00' # Barcode type UPC-A
|
||||||
|
BARCODE_UPC_E = '\x1d\x6b\x01' # Barcode type UPC-E
|
||||||
|
BARCODE_EAN13 = '\x1d\x6b\x02' # Barcode type EAN13
|
||||||
|
BARCODE_EAN8 = '\x1d\x6b\x03' # Barcode type EAN8
|
||||||
|
BARCODE_CODE39 = '\x1d\x6b\x04' # Barcode type CODE39
|
||||||
|
BARCODE_ITF = '\x1d\x6b\x05' # Barcode type ITF
|
||||||
|
BARCODE_NW7 = '\x1d\x6b\x06' # Barcode type NW7
|
||||||
|
# Image format
|
||||||
|
S_RASTER_N = '\x1d\x76\x30\x00' # Set raster image normal size
|
||||||
|
S_RASTER_2W = '\x1d\x76\x30\x01' # Set raster image double width
|
||||||
|
S_RASTER_2H = '\x1d\x76\x30\x02' # Set raster image double height
|
||||||
|
S_RASTER_Q = '\x1d\x76\x30\x03' # Set raster image quadruple
|
|
@ -0,0 +1,255 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
'''
|
||||||
|
@author: Manuel F Martinez <manpaz@bashlinux.com>
|
||||||
|
@organization: Bashlinux
|
||||||
|
@copyright: Copyright (c) 2012 Bashlinux
|
||||||
|
@license: GPL
|
||||||
|
'''
|
||||||
|
|
||||||
|
import Image
|
||||||
|
import time
|
||||||
|
|
||||||
|
from constants import *
|
||||||
|
from exceptions import *
|
||||||
|
|
||||||
|
class Escpos:
|
||||||
|
""" ESC/POS Printer object """
|
||||||
|
device = None
|
||||||
|
|
||||||
|
|
||||||
|
def _check_image_size(self, size):
|
||||||
|
""" Check and fix the size of the image to 32 bits """
|
||||||
|
if size % 32 == 0:
|
||||||
|
return (0, 0)
|
||||||
|
else:
|
||||||
|
image_border = 32 - (size % 32)
|
||||||
|
if (image_border % 2) == 0:
|
||||||
|
return (image_border / 2, image_border / 2)
|
||||||
|
else:
|
||||||
|
return (image_border / 2, (image_border / 2) + 1)
|
||||||
|
|
||||||
|
|
||||||
|
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'))
|
||||||
|
buffer = ""
|
||||||
|
|
||||||
|
while i < len(line):
|
||||||
|
hex_string = int(line[i:i+8],2)
|
||||||
|
buffer += "%02X" % hex_string
|
||||||
|
i += 8
|
||||||
|
cont += 1
|
||||||
|
if cont % 4 == 0:
|
||||||
|
self._raw(buffer.decode("hex"))
|
||||||
|
buffer = ""
|
||||||
|
cont = 0
|
||||||
|
|
||||||
|
|
||||||
|
def image(self, img):
|
||||||
|
""" Parse image and prepare it to a printable format """
|
||||||
|
pixels = []
|
||||||
|
pix_line = ""
|
||||||
|
im_left = ""
|
||||||
|
im_right = ""
|
||||||
|
switch = 0
|
||||||
|
img_size = [ 0, 0 ]
|
||||||
|
|
||||||
|
im_open = Image.open(img)
|
||||||
|
im = im_open.convert("RGB")
|
||||||
|
|
||||||
|
if im.size[0] > 512:
|
||||||
|
print "WARNING: Image is wider than 512 and could be truncated at print time "
|
||||||
|
if im.size[1] > 255:
|
||||||
|
raise ImageSizeError()
|
||||||
|
|
||||||
|
im_border = self._check_image_size(im.size[0])
|
||||||
|
for i in range(im_border[0]):
|
||||||
|
im_left += "0"
|
||||||
|
for i in range(im_border[1]):
|
||||||
|
im_right += "0"
|
||||||
|
|
||||||
|
for y in range(im.size[1]):
|
||||||
|
img_size[1] += 1
|
||||||
|
pix_line += im_left
|
||||||
|
img_size[0] += im_border[0]
|
||||||
|
for x in range(im.size[0]):
|
||||||
|
img_size[0] += 1
|
||||||
|
RGB = im.getpixel((x, y))
|
||||||
|
im_color = (RGB[0] + RGB[1] + RGB[2])
|
||||||
|
im_pattern = "1X0"
|
||||||
|
pattern_len = len(im_pattern)
|
||||||
|
switch = (switch - 1 ) * (-1)
|
||||||
|
for x in range(pattern_len):
|
||||||
|
if im_color <= (255 * 3 / pattern_len * (x+1)):
|
||||||
|
if im_pattern[x] == "X":
|
||||||
|
pix_line += "%d" % switch
|
||||||
|
else:
|
||||||
|
pix_line += im_pattern[x]
|
||||||
|
break
|
||||||
|
elif im_color > (255 * 3 / pattern_len * pattern_len) and im_color <= (255 * 3):
|
||||||
|
pix_line += im_pattern[-1]
|
||||||
|
break
|
||||||
|
pix_line += im_right
|
||||||
|
img_size[0] += im_border[1]
|
||||||
|
|
||||||
|
self._print_image(pix_line, img_size)
|
||||||
|
|
||||||
|
|
||||||
|
def barcode(self, code, bc, width, height, pos, font):
|
||||||
|
""" Print Barcode """
|
||||||
|
# Align Bar Code()
|
||||||
|
self._raw(TXT_ALIGN_CT)
|
||||||
|
# Height
|
||||||
|
if height >=2 or height <=6:
|
||||||
|
self._raw(BARCODE_HEIGHT)
|
||||||
|
else:
|
||||||
|
raise BarcodeSizeError()
|
||||||
|
# Width
|
||||||
|
if width >= 1 or width <=255:
|
||||||
|
self._raw(BARCODE_WIDTH)
|
||||||
|
else:
|
||||||
|
raise BarcodeSizeError()
|
||||||
|
# Font
|
||||||
|
if font.upper() == "B":
|
||||||
|
self._raw(BARCODE_FONT_B)
|
||||||
|
else: # DEFAULT FONT: A
|
||||||
|
self._raw(BARCODE_FONT_A)
|
||||||
|
# Position
|
||||||
|
if pos.upper() == "OFF":
|
||||||
|
self._raw(BARCODE_TXT_OFF)
|
||||||
|
elif pos.upper() == "BOTH":
|
||||||
|
self._raw(BARCODE_TXT_BTH)
|
||||||
|
elif pos.upper() == "ABOVE":
|
||||||
|
self._raw(BARCODE_TXT_ABV)
|
||||||
|
else: # DEFAULT POSITION: BELOW
|
||||||
|
self._raw(BARCODE_TXT_BLW)
|
||||||
|
# Type
|
||||||
|
if bc.upper() == "UPC-A":
|
||||||
|
self._raw(BARCODE_UPC_A)
|
||||||
|
elif bc.upper() == "UPC-E":
|
||||||
|
self._raw(BARCODE_UPC_E)
|
||||||
|
elif bc.upper() == "EAN13":
|
||||||
|
self._raw(BARCODE_EAN13)
|
||||||
|
elif bc.upper() == "EAN8":
|
||||||
|
self._raw(BARCODE_EAN8)
|
||||||
|
elif bc.upper() == "CODE39":
|
||||||
|
self._raw(BARCODE_CODE39)
|
||||||
|
elif bc.upper() == "ITF":
|
||||||
|
self._raw(BARCODE_ITF)
|
||||||
|
elif bc.upper() == "NW7":
|
||||||
|
self._raw(BARCODE_NW7)
|
||||||
|
else:
|
||||||
|
raise BarcodeTypeError()
|
||||||
|
# Print Code
|
||||||
|
if code:
|
||||||
|
self._raw(code)
|
||||||
|
else:
|
||||||
|
raise exception.BarcodeCodeError()
|
||||||
|
|
||||||
|
|
||||||
|
def text(self, txt):
|
||||||
|
""" Print alpha-numeric text """
|
||||||
|
if txt:
|
||||||
|
self._raw(txt)
|
||||||
|
else:
|
||||||
|
raise TextError()
|
||||||
|
|
||||||
|
|
||||||
|
def set(self, align='left', font='a', type='normal', width=1, height=1):
|
||||||
|
""" Set text properties """
|
||||||
|
# Align
|
||||||
|
if align.upper() == "CENTER":
|
||||||
|
self._raw(TXT_ALIGN_CT)
|
||||||
|
elif align.upper() == "RIGHT":
|
||||||
|
self._raw(TXT_ALIGN_RT)
|
||||||
|
elif align.upper() == "LEFT":
|
||||||
|
self._raw(TXT_ALIGN_LT)
|
||||||
|
# Font
|
||||||
|
if font.upper() == "B":
|
||||||
|
self._raw(TXT_FONT_B)
|
||||||
|
else: # DEFAULT FONT: A
|
||||||
|
self._raw(TXT_FONT_A)
|
||||||
|
# Type
|
||||||
|
if type.upper() == "B":
|
||||||
|
self._raw(TXT_BOLD_ON)
|
||||||
|
self._raw(TXT_UNDERL_OFF)
|
||||||
|
elif type.upper() == "U":
|
||||||
|
self._raw(TXT_BOLD_OFF)
|
||||||
|
self._raw(TXT_UNDERL_ON)
|
||||||
|
elif type.upper() == "U2":
|
||||||
|
self._raw(TXT_BOLD_OFF)
|
||||||
|
self._raw(TXT_UNDERL2_ON)
|
||||||
|
elif type.upper() == "BU":
|
||||||
|
self._raw(TXT_BOLD_ON)
|
||||||
|
self._raw(TXT_UNDERL_ON)
|
||||||
|
elif type.upper() == "BU2":
|
||||||
|
self._raw(TXT_BOLD_ON)
|
||||||
|
self._raw(TXT_UNDERL2_ON)
|
||||||
|
elif type.upper == "NORMAL":
|
||||||
|
self._raw(TXT_BOLD_OFF)
|
||||||
|
self._raw(TXT_UNDERL_OFF)
|
||||||
|
# Width
|
||||||
|
if width == 2 and height != 2:
|
||||||
|
self._raw(TXT_NORMAL)
|
||||||
|
self._raw(TXT_2WIDTH)
|
||||||
|
elif height == 2 and width != 2:
|
||||||
|
self._raw(TXT_NORMAL)
|
||||||
|
self._raw(TXT_2HEIGHT)
|
||||||
|
elif height == 2 and width == 2:
|
||||||
|
self._raw(TXT_2WIDTH)
|
||||||
|
self._raw(TXT_2HEIGHT)
|
||||||
|
else: # DEFAULT SIZE: NORMAL
|
||||||
|
self._raw(TXT_NORMAL)
|
||||||
|
|
||||||
|
|
||||||
|
def cut(self, mode=''):
|
||||||
|
""" Cut paper """
|
||||||
|
# Fix the size between last line and cut
|
||||||
|
# TODO: handle this with a line feed
|
||||||
|
self._raw("\n\n\n\n\n\n")
|
||||||
|
if mode.upper() == "PART":
|
||||||
|
self._raw(PAPER_PART_CUT)
|
||||||
|
else: # DEFAULT MODE: FULL CUT
|
||||||
|
self._raw(PAPER_FULL_CUT)
|
||||||
|
|
||||||
|
|
||||||
|
def cashdraw(self, pin):
|
||||||
|
""" Send pulse to kick the cash drawer """
|
||||||
|
if pin == 2:
|
||||||
|
self._raw(CD_KICK_2)
|
||||||
|
elif pin == 5:
|
||||||
|
self._raw(CD_KICK_5)
|
||||||
|
else:
|
||||||
|
raise CashDrawerError()
|
||||||
|
|
||||||
|
|
||||||
|
def hw(self, hw):
|
||||||
|
""" Hardware operations """
|
||||||
|
if hw.upper() == "INIT":
|
||||||
|
self._raw(HW_INIT)
|
||||||
|
elif hw.upper() == "SELECT":
|
||||||
|
self._raw(HW_SELECT)
|
||||||
|
elif hw.upper() == "RESET":
|
||||||
|
self._raw(HW_RESET)
|
||||||
|
else: # DEFAULT: DOES NOTHING
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def control(self, ctl):
|
||||||
|
""" Feed control sequences """
|
||||||
|
if ctl.upper() == "LF":
|
||||||
|
self._raw(CTL_LF)
|
||||||
|
elif ctl.upper() == "FF":
|
||||||
|
self._raw(CTL_FF)
|
||||||
|
elif ctl.upper() == "CR":
|
||||||
|
self._raw(CTL_CR)
|
||||||
|
elif ctl.upper() == "HT":
|
||||||
|
self._raw(CTL_HT)
|
||||||
|
elif ctl.upper() == "VT":
|
||||||
|
self._raw(CTL_VT)
|
|
@ -0,0 +1,80 @@
|
||||||
|
""" ESC/POS Exceptions classes """
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
class Error(Exception):
|
||||||
|
""" Base class for ESC/POS errors """
|
||||||
|
def __init__(self, msg, status=None):
|
||||||
|
Exception.__init__(self)
|
||||||
|
self.msg = msg
|
||||||
|
self.resultcode = 1
|
||||||
|
if status is not None:
|
||||||
|
self.resultcode = status
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.msg
|
||||||
|
|
||||||
|
# Result/Exit codes
|
||||||
|
# 0 = success
|
||||||
|
# 10 = No Barcode type defined
|
||||||
|
# 20 = Barcode size values are out of range
|
||||||
|
# 30 = Barcode text not supplied
|
||||||
|
# 40 = Image height is too large
|
||||||
|
# 50 = No string supplied to be printed
|
||||||
|
# 60 = Invalid pin to send Cash Drawer pulse
|
||||||
|
|
||||||
|
|
||||||
|
class BarcodeTypeError(Error):
|
||||||
|
def __init__(self, msg=""):
|
||||||
|
Error.__init__(self, msg)
|
||||||
|
self.msg = msg
|
||||||
|
self.resultcode = 10
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "No Barcode type is defined"
|
||||||
|
|
||||||
|
class BarcodeSizeError(Error):
|
||||||
|
def __init__(self, msg=""):
|
||||||
|
Error.__init__(self, msg)
|
||||||
|
self.msg = msg
|
||||||
|
self.resultcode = 20
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "Barcode size is out of range"
|
||||||
|
|
||||||
|
class BarcodeCodeError(Error):
|
||||||
|
def __init__(self, msg=""):
|
||||||
|
Error.__init__(self, msg)
|
||||||
|
self.msg = msg
|
||||||
|
self.resultcode = 30
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "Code was not supplied"
|
||||||
|
|
||||||
|
class ImageSizeError(Error):
|
||||||
|
def __init__(self, msg=""):
|
||||||
|
Error.__init__(self, msg)
|
||||||
|
self.msg = msg
|
||||||
|
self.resultcode = 40
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "Image height is longer than 255px and can't be printed"
|
||||||
|
|
||||||
|
class TextError(Error):
|
||||||
|
def __init__(self, msg=""):
|
||||||
|
Error.__init__(self, msg)
|
||||||
|
self.msg = msg
|
||||||
|
self.resultcode = 50
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "Text string must be supplied to the text() method"
|
||||||
|
|
||||||
|
|
||||||
|
class CashDrawerError(Error):
|
||||||
|
def __init__(self, msg=""):
|
||||||
|
Error.__init__(self, msg)
|
||||||
|
self.msg = msg
|
||||||
|
self.resultcode = 60
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "Valid pin must be set to send pulse"
|
|
@ -0,0 +1,136 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
'''
|
||||||
|
@author: Manuel F Martinez <manpaz@bashlinux.com>
|
||||||
|
@organization: Bashlinux
|
||||||
|
@copyright: Copyright (c) 2012 Bashlinux
|
||||||
|
@license: GPL
|
||||||
|
'''
|
||||||
|
|
||||||
|
import usb.core
|
||||||
|
import usb.util
|
||||||
|
import serial
|
||||||
|
import socket
|
||||||
|
|
||||||
|
from escpos import *
|
||||||
|
from constants import *
|
||||||
|
from exceptions import *
|
||||||
|
|
||||||
|
class Usb(Escpos):
|
||||||
|
""" Define USB printer """
|
||||||
|
|
||||||
|
def __init__(self, idVendor, idProduct, interface=0, in_ep=0x82, out_ep=0x01):
|
||||||
|
"""
|
||||||
|
@param idVendor : Vendor ID
|
||||||
|
@param idProduct : Product ID
|
||||||
|
@param interface : USB device interface
|
||||||
|
@param in_ep : Input end point
|
||||||
|
@param out_ep : Output end point
|
||||||
|
"""
|
||||||
|
self.idVendor = idVendor
|
||||||
|
self.idProduct = idProduct
|
||||||
|
self.interface = interface
|
||||||
|
self.in_ep = in_ep
|
||||||
|
self.out_ep = out_ep
|
||||||
|
self.open()
|
||||||
|
|
||||||
|
|
||||||
|
def open(self):
|
||||||
|
""" Search device on USB tree and set is as escpos device """
|
||||||
|
self.device = usb.core.find(idVendor=self.idVendor, idProduct=self.idProduct)
|
||||||
|
if self.device is None:
|
||||||
|
print "Cable isn't plugged in"
|
||||||
|
|
||||||
|
if self.device.is_kernel_driver_active(0):
|
||||||
|
try:
|
||||||
|
self.device.detach_kernel_driver(0)
|
||||||
|
except usb.core.USBError as e:
|
||||||
|
print "Could not detatch kernel driver: %s" % str(e)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.device.set_configuration()
|
||||||
|
self.device.reset()
|
||||||
|
except usb.core.USBError as e:
|
||||||
|
print "Could not set configuration: %s" % str(e)
|
||||||
|
|
||||||
|
|
||||||
|
def _raw(self, msg):
|
||||||
|
""" Print any command sent in raw format """
|
||||||
|
self.device.write(self.out_ep, msg, self.interface)
|
||||||
|
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
""" Release USB interface """
|
||||||
|
if self.device:
|
||||||
|
usb.util.dispose_resources(self.device)
|
||||||
|
self.device = None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Serial(Escpos):
|
||||||
|
""" Define Serial printer """
|
||||||
|
|
||||||
|
def __init__(self, devfile="/dev/ttyS0", baudrate=9600, bytesize=8, timeout=1):
|
||||||
|
"""
|
||||||
|
@param devfile : Device file under dev filesystem
|
||||||
|
@param baudrate : Baud rate for serial transmission
|
||||||
|
@param bytesize : Serial buffer size
|
||||||
|
@param timeout : Read/Write timeout
|
||||||
|
"""
|
||||||
|
self.devfile = devfile
|
||||||
|
self.baudrate = baudrate
|
||||||
|
self.bytesize = bytesize
|
||||||
|
self.timeout = timeout
|
||||||
|
self.open()
|
||||||
|
|
||||||
|
|
||||||
|
def open(self):
|
||||||
|
""" Setup serial port and set is as escpos device """
|
||||||
|
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"
|
||||||
|
else:
|
||||||
|
print "Unable to open serial printer on: %s" % self.devfile
|
||||||
|
|
||||||
|
|
||||||
|
def _raw(self, msg):
|
||||||
|
""" Print any command sent in raw format """
|
||||||
|
self.device.write(msg)
|
||||||
|
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
""" Close Serial interface """
|
||||||
|
if self.device is not None:
|
||||||
|
self.device.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Network(Escpos):
|
||||||
|
""" Define Network printer """
|
||||||
|
|
||||||
|
def __init__(self,host,port=9100):
|
||||||
|
"""
|
||||||
|
@param host : Printer's hostname or IP address
|
||||||
|
@param port : Port to write to
|
||||||
|
"""
|
||||||
|
self.host = host
|
||||||
|
self.port = port
|
||||||
|
self.open()
|
||||||
|
|
||||||
|
|
||||||
|
def open(self):
|
||||||
|
""" Open TCP socket and set it as escpos device """
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
def _raw(self, msg):
|
||||||
|
self.device.send(msg)
|
||||||
|
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
""" Close TCP connection """
|
||||||
|
self.device.close()
|
Loading…
Reference in New Issue