2012-09-24 04:24:45 +00:00
|
|
|
#!/usr/bin/python
|
2016-03-28 13:54:43 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
""" This module contains the implementations of abstract base class :py:class:`Escpos`.
|
2016-01-05 16:30:40 +00:00
|
|
|
|
|
|
|
:author: `Manuel F Martinez <manpaz@bashlinux.com>`_ and others
|
|
|
|
:organization: Bashlinux and `python-escpos <https://github.com/python-escpos>`_
|
|
|
|
:copyright: Copyright (c) 2012 Bashlinux
|
|
|
|
:license: GNU GPL v3
|
2014-05-21 05:15:54 +00:00
|
|
|
"""
|
2012-09-24 04:24:45 +00:00
|
|
|
|
2016-03-02 23:47:30 +00:00
|
|
|
from __future__ import absolute_import
|
|
|
|
from __future__ import division
|
|
|
|
from __future__ import print_function
|
2016-03-03 03:42:27 +00:00
|
|
|
from __future__ import unicode_literals
|
2016-03-02 23:47:30 +00:00
|
|
|
|
2012-09-24 04:24:45 +00:00
|
|
|
import usb.core
|
|
|
|
import usb.util
|
|
|
|
import serial
|
|
|
|
import socket
|
|
|
|
|
2016-04-02 13:33:24 +00:00
|
|
|
from .escpos import Escpos
|
2015-05-07 18:54:32 +00:00
|
|
|
from .exceptions import *
|
2012-09-24 04:24:45 +00:00
|
|
|
|
|
|
|
class Usb(Escpos):
|
2016-01-05 16:30:40 +00:00
|
|
|
""" USB printer
|
|
|
|
|
|
|
|
This class describes a printer that natively speaks USB.
|
2016-03-08 19:06:19 +00:00
|
|
|
|
|
|
|
inheritance:
|
|
|
|
|
|
|
|
.. inheritance-diagram:: escpos.printer.Usb
|
|
|
|
:parts: 1
|
|
|
|
|
2016-01-05 16:30:40 +00:00
|
|
|
"""
|
2012-09-24 04:24:45 +00:00
|
|
|
|
2015-06-04 11:57:59 +00:00
|
|
|
def __init__(self, idVendor, idProduct, interface=0, in_ep=0x82, out_ep=0x01, *args, **kwargs):
|
2012-09-24 04:24:45 +00:00
|
|
|
"""
|
2015-11-27 22:10:20 +00:00
|
|
|
: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
|
2012-09-24 04:24:45 +00:00
|
|
|
"""
|
2015-06-04 11:57:59 +00:00
|
|
|
Escpos.__init__(self, *args, **kwargs)
|
2016-01-08 02:34:14 +00:00
|
|
|
self.idVendor = idVendor
|
2012-09-24 04:24:45 +00:00
|
|
|
self.idProduct = idProduct
|
|
|
|
self.interface = interface
|
2015-11-27 20:20:12 +00:00
|
|
|
self.in_ep = in_ep
|
|
|
|
self.out_ep = out_ep
|
2014-05-21 06:50:06 +00:00
|
|
|
self.open()
|
2012-09-24 04:24:45 +00:00
|
|
|
|
|
|
|
def open(self):
|
2015-11-27 22:10:20 +00:00
|
|
|
""" Search device on USB tree and set it as escpos device """
|
2012-09-24 04:24:45 +00:00
|
|
|
self.device = usb.core.find(idVendor=self.idVendor, idProduct=self.idProduct)
|
|
|
|
if self.device is None:
|
2013-02-27 14:10:34 +00:00
|
|
|
raise USBNotFoundError("Device not found or cable not plugged in.")
|
2012-09-24 04:24:45 +00:00
|
|
|
|
2015-09-04 21:48:58 +00:00
|
|
|
check_driver = None
|
|
|
|
|
|
|
|
try:
|
|
|
|
check_driver = self.device.is_kernel_driver_active(0)
|
|
|
|
except NotImplementedError:
|
|
|
|
pass
|
|
|
|
|
|
|
|
if check_driver is None or check_driver:
|
2012-09-24 04:24:45 +00:00
|
|
|
try:
|
|
|
|
self.device.detach_kernel_driver(0)
|
|
|
|
except usb.core.USBError as e:
|
2015-09-04 21:48:58 +00:00
|
|
|
if check_driver is not None:
|
2016-01-08 02:43:33 +00:00
|
|
|
print("Could not detatch kernel driver: {0}".format(str(e)))
|
2012-09-24 04:24:45 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
self.device.set_configuration()
|
|
|
|
self.device.reset()
|
|
|
|
except usb.core.USBError as e:
|
2016-01-08 02:43:33 +00:00
|
|
|
print("Could not set configuration: {0}".format(str(e)))
|
2012-09-24 04:24:45 +00:00
|
|
|
|
|
|
|
def _raw(self, msg):
|
2016-01-05 16:30:40 +00:00
|
|
|
""" Print any command sent in raw format
|
|
|
|
|
|
|
|
:param msg: arbitrary code to be printed
|
2016-03-03 02:37:43 +00:00
|
|
|
:type msg: bytes
|
2016-01-05 16:30:40 +00:00
|
|
|
"""
|
2012-09-24 04:24:45 +00:00
|
|
|
self.device.write(self.out_ep, msg, self.interface)
|
|
|
|
|
2016-03-28 13:54:43 +00:00
|
|
|
def close(self):
|
2012-09-24 04:24:45 +00:00
|
|
|
""" Release USB interface """
|
|
|
|
if self.device:
|
|
|
|
usb.util.dispose_resources(self.device)
|
|
|
|
self.device = None
|
|
|
|
|
|
|
|
|
|
|
|
class Serial(Escpos):
|
2016-01-05 16:30:40 +00:00
|
|
|
""" Serial printer
|
|
|
|
|
|
|
|
This class describes a printer that is connected by serial interface.
|
2016-03-08 19:06:19 +00:00
|
|
|
|
|
|
|
inheritance:
|
|
|
|
|
|
|
|
.. inheritance-diagram:: escpos.printer.Serial
|
|
|
|
:parts: 1
|
|
|
|
|
2016-01-05 16:30:40 +00:00
|
|
|
"""
|
2012-09-24 04:24:45 +00:00
|
|
|
|
2015-07-04 15:23:31 +00:00
|
|
|
def __init__(self, devfile="/dev/ttyS0", baudrate=9600, bytesize=8, timeout=1,
|
|
|
|
parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE,
|
2016-01-05 16:30:40 +00:00
|
|
|
xonxoff=False, dsrdtr=True, *args, **kwargs):
|
2012-09-24 04:24:45 +00:00
|
|
|
"""
|
2016-01-05 16:30:40 +00:00
|
|
|
|
|
|
|
:param devfile: Device file under dev filesystem
|
|
|
|
:param baudrate: Baud rate for serial transmission
|
|
|
|
:param bytesize: Serial buffer size
|
|
|
|
:param timeout: Read/Write timeout
|
|
|
|
:param parity: Parity checking
|
|
|
|
:param stopbits: Number of stop bits
|
|
|
|
:param xonxoff: Software flow control
|
|
|
|
:param dsrdtr: Hardware flow control (False to enable RTS/CTS)
|
2012-09-24 04:24:45 +00:00
|
|
|
"""
|
2015-06-04 11:57:59 +00:00
|
|
|
Escpos.__init__(self, *args, **kwargs)
|
2016-01-08 02:34:14 +00:00
|
|
|
self.devfile = devfile
|
2012-09-24 04:24:45 +00:00
|
|
|
self.baudrate = baudrate
|
|
|
|
self.bytesize = bytesize
|
2016-01-08 02:34:14 +00:00
|
|
|
self.timeout = timeout
|
2015-07-04 15:23:31 +00:00
|
|
|
self.parity = parity
|
|
|
|
self.stopbits = stopbits
|
|
|
|
self.xonxoff = xonxoff
|
|
|
|
self.dsrdtr = dsrdtr
|
2015-08-27 21:37:44 +00:00
|
|
|
|
2012-09-24 04:24:45 +00:00
|
|
|
self.open()
|
|
|
|
|
|
|
|
def open(self):
|
|
|
|
""" Setup serial port and set is as escpos device """
|
2015-07-04 15:23:31 +00:00
|
|
|
self.device = serial.Serial(port=self.devfile, baudrate=self.baudrate,
|
|
|
|
bytesize=self.bytesize, parity=self.parity,
|
|
|
|
stopbits=self.stopbits, timeout=self.timeout,
|
|
|
|
xonxoff=self.xonxoff, dsrdtr=self.dsrdtr)
|
2012-09-24 04:24:45 +00:00
|
|
|
|
|
|
|
if self.device is not None:
|
2015-05-07 18:54:32 +00:00
|
|
|
print("Serial printer enabled")
|
2012-09-24 04:24:45 +00:00
|
|
|
else:
|
2016-01-08 02:43:33 +00:00
|
|
|
print("Unable to open serial printer on: {0}".format(str(self.devfile)))
|
2012-09-24 04:24:45 +00:00
|
|
|
|
|
|
|
def _raw(self, msg):
|
2016-01-05 16:30:40 +00:00
|
|
|
""" Print any command sent in raw format
|
|
|
|
|
|
|
|
:param msg: arbitrary code to be printed
|
2016-03-03 02:37:43 +00:00
|
|
|
:type msg: bytes
|
2016-01-05 16:30:40 +00:00
|
|
|
"""
|
2012-09-24 04:24:45 +00:00
|
|
|
self.device.write(msg)
|
|
|
|
|
2016-03-28 13:54:43 +00:00
|
|
|
def close(self):
|
2012-09-24 04:24:45 +00:00
|
|
|
""" Close Serial interface """
|
|
|
|
if self.device is not None:
|
2016-03-20 03:08:20 +00:00
|
|
|
self.device.flush()
|
2012-09-24 04:24:45 +00:00
|
|
|
self.device.close()
|
|
|
|
|
|
|
|
|
|
|
|
class Network(Escpos):
|
2016-01-05 16:30:40 +00:00
|
|
|
""" Network printer
|
2012-09-24 04:24:45 +00:00
|
|
|
|
2016-01-05 16:30:40 +00:00
|
|
|
This class is used to attach to a networked printer. You can also use this in order to attach to a printer that
|
2016-01-17 15:00:03 +00:00
|
|
|
is forwarded with ``socat``.
|
|
|
|
|
|
|
|
If you have a local printer on parallel port ``/dev/usb/lp0`` then you could start ``socat`` with:
|
|
|
|
|
|
|
|
.. code-block:: none
|
|
|
|
|
|
|
|
socat -u TCP4-LISTEN:4242,reuseaddr,fork OPEN:/dev/usb/lp0
|
|
|
|
|
|
|
|
Then you should be able to attach to port ``4242`` with this class.
|
|
|
|
Otherwise the normal usecase would be to have a printer with ethernet interface. This type of printer should
|
|
|
|
work the same with this class. For the address of the printer check its manuals.
|
2016-03-08 19:06:19 +00:00
|
|
|
|
|
|
|
inheritance:
|
|
|
|
|
|
|
|
.. inheritance-diagram:: escpos.printer.Network
|
|
|
|
:parts: 1
|
|
|
|
|
2016-01-05 16:30:40 +00:00
|
|
|
"""
|
|
|
|
|
2016-02-29 17:09:11 +00:00
|
|
|
def __init__(self, host, port=9100, timeout=60, *args, **kwargs):
|
2012-09-24 04:24:45 +00:00
|
|
|
"""
|
2016-01-05 16:30:40 +00:00
|
|
|
|
|
|
|
:param host : Printer's hostname or IP address
|
|
|
|
:param port : Port to write to
|
2016-02-29 17:09:11 +00:00
|
|
|
:param timeout : timeout in seconds for the socket-library
|
2012-09-24 04:24:45 +00:00
|
|
|
"""
|
2015-06-04 11:57:59 +00:00
|
|
|
Escpos.__init__(self, *args, **kwargs)
|
2012-09-24 04:24:45 +00:00
|
|
|
self.host = host
|
|
|
|
self.port = port
|
2016-02-29 17:09:11 +00:00
|
|
|
self.timeout = timeout
|
2012-09-24 04:24:45 +00:00
|
|
|
self.open()
|
|
|
|
|
|
|
|
def open(self):
|
2016-01-17 15:00:03 +00:00
|
|
|
""" Open TCP socket with ``socket``-library and set it as escpos device """
|
2012-09-24 04:24:45 +00:00
|
|
|
self.device = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
2016-02-29 17:09:11 +00:00
|
|
|
self.device.settimeout(self.timeout)
|
2012-09-24 04:24:45 +00:00
|
|
|
self.device.connect((self.host, self.port))
|
|
|
|
|
|
|
|
if self.device is None:
|
2016-01-08 02:43:33 +00:00
|
|
|
print("Could not open socket for {0}".format(self.host))
|
2012-09-24 04:24:45 +00:00
|
|
|
|
|
|
|
def _raw(self, msg):
|
2016-01-05 16:30:40 +00:00
|
|
|
""" Print any command sent in raw format
|
|
|
|
|
|
|
|
:param msg: arbitrary code to be printed
|
2016-03-03 02:37:43 +00:00
|
|
|
:type msg: bytes
|
2016-01-05 16:30:40 +00:00
|
|
|
"""
|
2014-03-14 16:05:47 +00:00
|
|
|
self.device.sendall(msg)
|
2012-09-24 04:24:45 +00:00
|
|
|
|
2016-03-28 13:54:43 +00:00
|
|
|
def close(self):
|
2012-09-24 04:24:45 +00:00
|
|
|
""" Close TCP connection """
|
2016-03-20 03:08:20 +00:00
|
|
|
self.device.shutdown(socket.SHUT_RDWR)
|
2012-09-24 04:24:45 +00:00
|
|
|
self.device.close()
|
2013-04-12 21:04:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
class File(Escpos):
|
2016-01-05 16:30:40 +00:00
|
|
|
""" Generic file printer
|
|
|
|
|
|
|
|
This class is used for parallel port printer or other printers that are directly attached to the filesystem.
|
|
|
|
Note that you should stay away from using USB-to-Parallel-Adapter since they are unreliable
|
|
|
|
and produce arbitrary errors.
|
2016-03-08 19:06:19 +00:00
|
|
|
|
|
|
|
inheritance:
|
|
|
|
|
|
|
|
.. inheritance-diagram:: escpos.printer.File
|
|
|
|
:parts: 1
|
|
|
|
|
2016-01-05 16:30:40 +00:00
|
|
|
"""
|
2013-04-12 21:04:48 +00:00
|
|
|
|
2015-06-04 11:57:59 +00:00
|
|
|
def __init__(self, devfile="/dev/usb/lp0", *args, **kwargs):
|
2013-04-12 21:04:48 +00:00
|
|
|
"""
|
2016-01-05 16:30:40 +00:00
|
|
|
|
|
|
|
:param devfile : Device file under dev filesystem
|
2013-04-12 21:04:48 +00:00
|
|
|
"""
|
2015-06-04 11:57:59 +00:00
|
|
|
Escpos.__init__(self, *args, **kwargs)
|
2013-04-12 21:04:48 +00:00
|
|
|
self.devfile = devfile
|
|
|
|
self.open()
|
|
|
|
|
|
|
|
def open(self):
|
|
|
|
""" Open system file """
|
2014-05-21 06:50:06 +00:00
|
|
|
self.device = open(self.devfile, "wb")
|
2013-04-12 21:04:48 +00:00
|
|
|
|
|
|
|
if self.device is None:
|
2016-01-08 02:43:33 +00:00
|
|
|
print("Could not open the specified file {0}".format(self.devfile))
|
2013-04-12 21:04:48 +00:00
|
|
|
|
2015-11-29 15:03:56 +00:00
|
|
|
def flush(self):
|
2016-01-05 16:30:40 +00:00
|
|
|
""" Flush printing content """
|
2015-11-29 15:03:56 +00:00
|
|
|
self.device.flush()
|
|
|
|
|
2013-04-12 21:04:48 +00:00
|
|
|
def _raw(self, msg):
|
2016-01-05 16:30:40 +00:00
|
|
|
""" Print any command sent in raw format
|
|
|
|
|
|
|
|
:param msg: arbitrary code to be printed
|
2016-03-03 02:37:43 +00:00
|
|
|
:type msg: bytes
|
2016-01-05 16:30:40 +00:00
|
|
|
"""
|
2016-03-03 03:42:27 +00:00
|
|
|
self.device.write(msg)
|
2013-04-12 21:04:48 +00:00
|
|
|
|
2016-03-28 13:54:43 +00:00
|
|
|
def close(self):
|
2013-04-12 21:04:48 +00:00
|
|
|
""" Close system file """
|
2016-03-20 03:08:20 +00:00
|
|
|
self.device.flush()
|
2013-04-12 21:04:48 +00:00
|
|
|
self.device.close()
|
2016-04-03 07:36:54 +00:00
|
|
|
|
|
|
|
class Dummy(Escpos):
|
|
|
|
""" Dummy printer
|
|
|
|
|
|
|
|
This class is used for saving commands to a variable, for use in situations where
|
|
|
|
there is no need to send commands to an actual printer. This includes
|
|
|
|
generating print jobs for later use, or testing output.
|
|
|
|
|
|
|
|
inheritance:
|
|
|
|
|
|
|
|
.. inheritance-diagram:: escpos.printer.Dummy
|
|
|
|
:parts: 1
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
Escpos.__init__(self, *args, **kwargs)
|
|
|
|
self._output_list = []
|
|
|
|
|
|
|
|
def _raw(self, msg):
|
|
|
|
""" Print any command sent in raw format
|
|
|
|
|
|
|
|
:param msg: arbitrary code to be printed
|
|
|
|
:type msg: bytes
|
|
|
|
"""
|
|
|
|
self._output_list.append(msg)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def output(self):
|
2016-04-06 11:05:32 +00:00
|
|
|
""" Get the data that was sent to this printer """
|
2016-04-03 07:36:54 +00:00
|
|
|
return b''.join(self._output_list)
|
2016-03-28 13:54:43 +00:00
|
|
|
|
|
|
|
def close(self):
|
|
|
|
pass
|