Printing with ESC/POS Printers in Python
2nd December 2016
Small thermal printers commonly used for printing receipts have become more affordable and can be useful for all sorts of projects like interactive exhibits, custom Point Of Sale system or just printing notes.
The ESC/POS specification can be found in this document from EPSON however the functionality actually implemented in each model of printer varies.
This ZJ-5802LD printer from ebay can be connected with USB, serial or Bluetooth and contains a lithium battery allowing printing from mobile phones or tablets in the field.
This example implements all the text functionality of the ZJ-5802LD
printer and produces the output shown above. We are connecting the
printer using the USB port which is presented as
/dev/usb/lp0
in Linux.
In a future post I will cover printing barcodes and images.
#!/usr/bin/env python
= 0x00 # null
NUL = 0x0a # line feed
LF = 0x1b # escape
ESC = 0x1d # group selector
GS
= 0x00 # normal
FONTA = 0x01 # small
FONTB = 0x08
EMPHASIS = 0x10
DOUBLE_HEIGHT = 0x20
DOUBLE_WIDTH = 0x80
UNDERLINE
= 0
NORMAL = 1
SMALL
= 0
LEFT = 1
CENTRE = 2
RIGHT
def reset(stream):
chr(ESC))
stream.write("@")
stream.write(
def mode(stream, value):
chr(ESC))
stream.write("!%s" % chr(value))
stream.write(
def emphasis(stream, value):
chr(ESC))
stream.write("E%d" % (0, 1)[value])
stream.write(
def underline(stream, value):
chr(ESC))
stream.write("-%d" % (0, 1)[value])
stream.write(
def font(stream, value):
assert value >= 0 and value <= 2
chr(ESC))
stream.write("M%d" % value)
stream.write(
def justification(stream, value):
assert value >= 0 and value <= 2
chr(ESC))
stream.write("a%d" % value)
stream.write(
def inverted(stream, value):
chr(GS))
stream.write("B%d" % (0, 1)[value])
stream.write(
def main():
= open("/dev/usb/lp0", "wb")
stream
try:
reset(stream)"normal text\n")
stream.write(
True)
emphasis(stream, "with emphasis\n")
stream.write(False)
emphasis(stream,
True)
underline(stream, "and underlined\n")
stream.write(False)
underline(stream,
font(stream, SMALL)"getting smaller\n")
stream.write(
font(stream, NORMAL)
justification(stream, LEFT)"left\n")
stream.write(
justification(stream, CENTRE)"centre\n")
stream.write(
justification(stream, RIGHT)"right\n")
stream.write(
True)
inverted(stream, "all inverted\n")
stream.write(False)
inverted(stream,
reset(stream)| DOUBLE_HEIGHT)
mode(stream, DOUBLE_WIDTH "bigger\n")
stream.write(
stream.flush()
finally:
stream.close()
if __name__ == "__main__":
main()