Closed GoogleCodeExporter closed 9 years ago
I realised I had libusb-1.0 and that python-escpos was developed for the old
version. So I installed libusb-compat-0.1.4
Now I get lsusb full output for my printer and the InterfaceNumber is 0 and
EndPoint is 0x01 (as per the defaults)
However, my python code is just:
self.ReceiptPrinter = escpos.Escpos(0x67b,0x2305,0,0x01)
self.ReceiptPrinter.text('Hello Wolrd')
and I now get:
# ./POS.py
1659 8965
Traceback (most recent call last):
File "./POS.py", line 1654, in <module>
AppWindow = POSApplication()
File "./POS.py", line 1316, in __init__
self.ReceiptPrinter = escpos.Escpos(0x67b,0x2305,0,0x01)
File "/initrd/mnt/dev_save/my-applications/POSLogic/escpos/escpos.py", line 47, in __init__
self.device = device_descriptor.get_device()
File "/initrd/mnt/dev_save/my-applications/POSLogic/escpos/escpos.py", line 24, in get_device
buses = usb.busses()
File "/usr/lib/python2.7/site-packages/usb/legacy.py", line 333, in busses
return (Bus(),)
File "/usr/lib/python2.7/site-packages/usb/legacy.py", line 329, in __init__
self.devices = [Device(d) for d in core.find(find_all=True)]
File "/usr/lib/python2.7/site-packages/usb/legacy.py", line 314, in __init__
self.configurations = [Configuration(c) for c in dev]
File "/usr/lib/python2.7/site-packages/usb/core.py", line 723, in __iter__
yield Configuration(self, i)
File "/usr/lib/python2.7/site-packages/usb/core.py", line 419, in __init__
configuration
File "/usr/lib/python2.7/site-packages/usb/backend/libusb10.py", line 471, in get_configuration_descriptor
config, byref(cfg)))
File "/usr/lib/python2.7/site-packages/usb/backend/libusb10.py", line 403, in _check
raise USBError(_str_error[ret], ret, _libusb_errno[ret])
usb.core.USBError: [Errno 5] Input/output error
#
Hoping some of this makes sense to you Manuel?
Original comment by phildain...@gmail.com
on 29 Apr 2012 at 9:31
Hi, your current printer definition says
self.ReceiptPrinter = escpos.Escpos(0x67b,0x2305,0,0x01)
Do you mint to post the results with the leading 0?
self.ReceiptPrinter = escpos.Escpos(0x067b,0x2305,0,0x01)
Thanks,
Original comment by manpaz
on 30 Apr 2012 at 2:05
I have got this working but had to re-write the pyusb stuff to work with
libusb_1.0 - not sure if you want to bring it back into the trunk?
Original comment by phildain...@gmail.com
on 8 May 2012 at 5:33
my amended escpos.py as follows to work with usblib 1.0
#!/usr/bin/env python
'''
@author: Manuel F Martinez <manpaz@bashlinux.com>
@adapted for usblib 1.0 by Phil Daintree <phil@logicworks.co.nz>
@organization: Bashlinux and Logic Works Ltd
@copyright: Copyright (c) 2010 Bashlinux and 2012 Logic Works Ltd
@license: GPL
'''
import usb.core
import usb.util
import Image
import time
from constants import *
from exceptions import *
class Escpos:
""" ESC/POS Printer object """
handle = None
device = None
def __init__(self, PrinterVendorID, PrinterProductID) :
#PrinterVendorID and PrinterProductID must be integer or hex values
# find our device
self.device = usb.core.find(idVendor=PrinterVendorID, idProduct=PrinterProductID)
# was it found?
if self.device is None:
print "Cable isn't plugged in"
raise ValueError('Device not found')
if self.device.is_kernel_driver_active(0) is True:
self.device.detach_kernel_driver(0)
# set the active configuration. With no arguments, the first
# configuration will be the active one
self.device.set_configuration()
#get the configuration
cfg = self.device.get_active_configuration()
#get the first interface/alternate interface
interface_number = cfg[(0,0)].bInterfaceNumber
alternate_setting = usb.control.get_interface(self.device, interface_number)
intf = usb.util.find_descriptor(
cfg, bInterfaceNumber = interface_number,
bAlternateSetting = alternate_setting
)
self.handle = usb.util.find_descriptor(
intf,
# match the first OUT endpoint
custom_match = \
lambda e: \
usb.util.endpoint_direction(e.bEndpointAddress) == \
usb.util.ENDPOINT_OUT
)
assert self.handle is not None
def _raw(self, msg):
""" Print any of the commands above, or clear text """
self.handle.write(msg)
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):
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 then print it"""
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)
def __del__(self):
""" Release device interface """
if self.handle:
try:
self.handle.releaseInterface()
self.handle.resetEndpoint(self.out_ep)
self.handle.reset()
except Exception, err:
print err
self.handle, self.device = None, None
# Give a chance to return the interface to the system
# The following message could appear if the application is executed
# too fast twice or more times.
#
# >> could not detach kernel driver from interface 0: No data available
# >> No interface claimed
time.sleep(1)
Original comment by phildain...@gmail.com
on 8 May 2012 at 7:26
Thank you Phil for your contribution.
I have reviewed your code, but unfortunately I cannot get rid of
deviceDescriptor class, as this is intended to be there intentionally so it can
inherit to other printers, i.e. serial & network type.
The code has been updated accordingly to PyUSB 1.0 documentation, hope this
helps to you and other developers interested in the project.
Thank you.
Original comment by manpaz
on 28 Jul 2012 at 11:29
@phildain
Nice It Works
Original comment by crok...@gmail.com
on 7 Nov 2012 at 3:44
glad to contribute :-)
Original comment by phildain...@gmail.com
on 21 Nov 2012 at 11:40
Original issue reported on code.google.com by
phildain...@gmail.com
on 28 Apr 2012 at 3:27