Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to send ESC/POS commands to thermal printer in Linux

I am trying to send ESC/POS commands on a thermal printer. But whenever i send them thermal printer prints them as a text instead of executing them as commands. I am writing these commands in a .prn file and whenever i executes lp command to print a file these .prn file also get printed but as a text.

I tried following method to write ESC/POS command in .prn file :

1) PRINT #1, CHR$(&H1D);"h";CHR$(80);
   PRINT #1, CHR$(&H1D);"k";CHR$(2);
   PRINT #1, "48508007";CHR$(0);
   PRINT #1, CHR$(&HA);
   PRINT #1, CHR$(&H1D);"k";CHR$(67);CHR$(12);
   PRINT #1, "48508007";

2) <ESC>(0x1B) <L>(0x4C)
   <GS>(0x1D) <k>(0x6B) 73 2 4 5 6 7 8 9 NUL
   <FF>(0x0c)

3) <ESC L>
   <GS k 73 2 4 5 6 7 8 9 NUL>

4) "ESC L" "GS k 73 2 4 5 6 7 8 9 NUL" "FF" I also tried sending ESC/POS command using C program as:

#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>

int main() {
   int fd,ret;
   char buf[] = "HELLO"

   fd = open("/dev/bus/usb/003/007",O_WRONLY);
   if(fd < 3) {
      perror(open failed);
   }

   ret = write(fd,&buf,sizeof(buf));
   if(ret == -1) {
      perror("write failed");
   }
}

Upon execution the above code gives error as:

write failed: invalid arguments
like image 898
user3860949 Avatar asked Jun 05 '15 08:06

user3860949


1 Answers

There are actually two issues here: data transport, and the data being transported.

Data transport: Use usblp

For getting the data to the printer, check that usblp is loaded. It allows you to expose the printer as a file in the lp group, so that you can open it as /dev/usb/lp0.

Once this works, as a regular user you can write:

echo "Hello" > /dev/usb/lp0

I wrote a blog post on the topic which covers the permissions side of this.

Data format

Secondly, the data itself needs to be sent in the correct binary format. A printer will not understand this human-readable .prn (print?) file directly, so it needs to be converted to the correct binary format.

To interpret a few things from your question:

  • ESC means \x1b, an ASCII escape
  • k means ``, the actual ASCII letter k
  • CHR$(80) means \x50, which is how the number 80 is sent to the printer.
  • CHR$(&H1D); means \x1d, an ASCII group separator (GS)

You can write some basic commands directly on the CLI using echo -e. Maybe the simplest non-text example is a CODE39 barcode that says '000'.

This same command in human-readable form, then hex, then as a terminal command would be:

  • GS k 4 0 0 0 NUL
  • 1d 6b 04 30 30 30 00
  • echo -e '\x1d\x6b\x04000\x00' > /dev/usb/lp0

Your best reference for this format is your printer's programming manual, but hopefully this helps you to interpret it.

Be aware that the commands you are trying to execute contain errors, and one of them will even will trap you in page mode.

Aside, the answers by @scruss and @abartek are completely accurate: Check that CUPS hasn't claimed the port by using the lsusb command, and use a hex editor to review your output, or a library to generate known-good commands.

like image 149
mike42 Avatar answered Sep 20 '22 06:09

mike42