Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to send raw string to a dotmatrix printer using python in ubuntu?

I have a dot-matrix printer LX-300 connected to my computer through the network. How do I send a raw string with ESCP characters directly to my printer in Python?

The computer is connected to the printer through another computer. I need to send a raw string because LX-300 image printing result is blurry.

like image 514
William Wino Avatar asked Oct 06 '16 08:10

William Wino


2 Answers

The Problem

To send data down this route:

Client computer ---> Server (Windows machine) ---> printer (dot-matrix)

...and to not let Windows mess with the data; instead to send the raw data, including printer control codes, straight from the client computer.

My Solution

Here's how I solved a near-identical problem for a small in-house database application:

Step 1) Make the printer network-accessible without Windows getting its fingers in the data routed to it. I accomplished this by installing the printer using the "Generic/Text Only" driver, then installing RawPrintServer on the Windows machine connected to the printer.

Step 2) Send raw data over the network to the TCP/IP port specified when you set up RawPrintServer (default is 9100). There are various ways to do that, here's what I did:

data = b"\x1B@A String To Print\x1B@" # be sure to use the right codes for your printer
ip_addr = 123.123.123.123 # address of the machine with the printer
port = 9100 # or whatever you set it to
s = socket.socket()
try:
    s.connect((ip_addr, port))
    s.send(data)
except:
    # deal with the error
finally:
    s.close()

Background

I thought about the problem in two parts:

  1. Client machine: spitting out the data I need from Python with the correct formatting/control codes for my printer, and sending it across the network
  2. Print server machine: transmitting the data to the locally connected printer

Number 1 is the easy part. There are actually some libraries in PyPI that may help with all the printer codes, but I found most of them are aimed at the little point-of-sale label printers, and were of limited use to me. So I just hard-coded what I needed into my Python program.

Of course, the way you choose to solve number 2 will effect how you send the data from Python. I chose the TCP/IP route to avoid dealing with Samba and Windows print issues.

As you probably discovered, Windows normally tries very hard to convert whatever you want to print to a bitmap and run the printer in graphics mode. We can use the generic driver and dump the data straight into the (local) printer port in order to prevent this.

The missing link, then, is getting from the network to the local printer port on the machine connected to the printer. Again, there are various ways to solve this. You could attempt to access the Windows printer share in some way. If you go the TCP/IP route like I did, you could write your own print server in Python. In my case, the RawPrintServer program "just worked" so I didn't investigate any further. Apparently all it does is grab incoming data from TCP port 9100 and shove it into the local printer port. Obviously you'll have to be sure the firewall isn't blocking the incoming connections on the print server machine. This method does not require the printer to be "shared" as far as Windows is concerned.

Depending on your situation (if you use DHCP), you might need to do some extra work to get the server's IP address in Python. In my case, I got the IP for free because of the peculiarity of my application.

This solution seems to be working out very well for me. I've got an old Panasonic printer running in Epson ESC/P compatibility mode connected to a Windows 7 machine, which I can print to from any other computer on the local network. Incidentally, this general idea should work regardless of what OS the client computer is running.

like image 63
ASL Avatar answered Oct 27 '22 11:10

ASL


Ultimately, you will need and want to write your own wrapper/script to do this. And since you are using a distribution of Linux, this is relatively easy.

On a Linux OS, the simplest way to issue a print job is to open a subprocess to the lpr. Generally, using lpr lets you access the printer without the need to be logged in as root (being a superuser), which is desirable considering the amount of damage that can be done while logged in as a "superuser".

Code like the following:

import subprocess
lpr = subprocess.Popen("/usr/bin/lpr", stdin=subprocess.PIPE)
lpr.stdin.write(data_to_send_to_printer)

Should be a good jumping off point for you. Essentially, this code should allow you to accomplish what you need.

Be careful though; depending on your privilege levels, a call to open a subprocess might need root level/Superuser permissions.

Subprocesses generally inherit the User IDs and access rights by the user that is running the command. For example, if the subprocess is created by a root user, then you will need root user/Superuser rights to access that subprocess.

For more information, check out the hyperlinks I've included in the post.

Good luck!

like image 38
Jake Samz Avatar answered Oct 27 '22 11:10

Jake Samz