iljabauer / python-escpos

Automatically exported from code.google.com/p/python-escpos
GNU General Public License v3.0
0 stars 0 forks source link

Configuration #3

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Hi Manuel,

I am trying to get this going using the code downloaded from here yesterday.

Output of lsusb is:

# lsusb
Bus 001 Device 001: ID 1d6b:0002
Bus 002 Device 001: ID 1d6b:0001
Bus 001 Device 002: ID 0c45:62e0
Bus 001 Device 003: ID 05e3:070e
Bus 002 Device 002: ID 067b:2305

it is the last device that is the printer as it disappears when it is turned 
off!

This is a BusyBox lsusb and HardInfo says it is on Bus 2 level 1
I also compiled proper lsusb and got the following info relating to the printer:

Bus 002 Device 002: ID 067b:2305 Prolific Technology Inc.
    Intf 2-1:1.0 ((null))

Following the README to get the interface and endpoint - the output of the 
command:

# ./lsusb -vvv -d 067b:2305 |grep iInterface
# 
is nothing at all!

similarly:

#lsusb -vvv -d 067b:2305 | grep bEndpointAddress | grep OUT  
# 

I am running the example script:

#!/usr/bin/python

from escpos import *

Epson = escpos.Escpos(0x67b,0x2305,2)
Epson.text("Hello World")
Epson.barcode
Epson.barcode('1324354657687','EAN13',64,2,'','')
Epson.cut()

with python 2.7.2 and I get the following - I have tried with a number of 
permutations of:
Epson = escpos.Escpos(0x67b,0x2305,0)
Epson = escpos.Escpos(0x67b,0x2305,1)

# ./test.py
[Errno 22] Invalid parameter
Traceback (most recent call last):
  File "./test.py", line 6, in <module>
    Epson.text("Hello World")
  File "/initrd/mnt/dev_save/my-applications/POSLogic/escpos/escpos.py", line 201, in text
    self._raw(txt)
  File "/initrd/mnt/dev_save/my-applications/POSLogic/escpos/escpos.py", line 60, in _raw
    self.handle.bulkWrite(self.out_ep, msg, 1000)
  File "/usr/lib/python2.6/site-packages/usb/legacy.py", line 148, in bulkWrite
    return self.dev.write(endpoint, buffer, self.__claimed_interface, timeout)
  File "/usr/lib/python2.6/site-packages/usb/core.py", line 617, in write
    intf.bInterfaceNumber,
AttributeError: 'NoneType' object has no attribute 'bInterfaceNumber'
'NoneType' object is not iterable

On what operating system?

I am on racy puppy linux with kernel 3.02

Appreciate any pointers?

Thanks

Please provide any additional information below.

Original issue reported on code.google.com by phildain...@gmail.com on 28 Apr 2012 at 3:27

GoogleCodeExporter commented 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

GoogleCodeExporter commented 9 years ago
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

GoogleCodeExporter commented 9 years ago
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

GoogleCodeExporter commented 9 years ago
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

GoogleCodeExporter commented 9 years ago
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

GoogleCodeExporter commented 9 years ago
@phildain
Nice It Works

Original comment by crok...@gmail.com on 7 Nov 2012 at 3:44

GoogleCodeExporter commented 9 years ago
glad to contribute :-)

Original comment by phildain...@gmail.com on 21 Nov 2012 at 11:40