如何在 Linux 中向热敏打印机发送 ESC/POS 命令

Posted

技术标签:

【中文标题】如何在 Linux 中向热敏打印机发送 ESC/POS 命令【英文标题】:How to send ESC/POS commands to thermal printer in Linux 【发布时间】:2015-08-20 03:18:50 【问题描述】:

我正在尝试在热敏打印机上发送 ESC/POS 命令。但是,每当我发送它们时,热敏打印机都会将它们打印为文本,而不是将它们作为命令执行。我在 .prn 文件中编写这些命令,每当我执行 lp 命令打印文件时,这些 .prn 文件也会被打印,但作为文本。

我尝试了以下方法在 .prn 文件中写入 ESC/POS 命令:

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 无” “FF” 我还尝试使用 C 程序发送 ESC/POS 命令:

#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");
   

上面的代码在执行时会报错:

write failed: invalid arguments

【问题讨论】:

【参考方案1】:

如果您确定十六进制代码,您可以使用您最喜欢的十六进制编辑器来制作正确的命令 prn 文件。 或者您可以从这里选择一个:Need a good hex editor for Linux 为什么选择十六进制编辑器?因为所有其他方式包括一些 隐藏 内容(如新行 0x0d)和打印机无法理解命令顺序。可能其他问题是您用于传递命令的程序 - 某些程序有时会添加其他内容或在将其发送到打印机时进行一些对话(例如额外的页面向下)。请确保 - 您的程序无法做到这一点。 我这次解决问题的方式:

可以肯定,转义序列是正确的。 (有些打印机使用特殊的转义序列来标记 - 下一个比特流将是命令,而不是数据) 请确保,您要发送到打印机的文件是正确的(文件中没有其他代码 - 简单的检查方法是 mc 查看器 - 十六进制模式视图 (F4)) 可以肯定的是,传送到打印机的方式是正确的 - 传送程序不操纵命令文件(使用 man 来检查) - 比如将不可打印的字符转换为十六进制代码

【讨论】:

感谢@abartek 的回复。我试过这个没有成功。 我使用lp命令将这个文件发送到打印机,也就是打印一个文件。这是向打印机发送命令的正确方法还是有其他方法可以做到这一点。此热敏打印机使用 USB 端口连接到系统。 C 语言中是否有任何库支持来做到这一点。【参考方案2】:

如果热敏打印机是通过 USB 连接的,CUPS 很有可能会占用该端口。因此,您将无法以普通用户的身份向其发送数据。

要通过 cups 发送原始字节,请使用 lpr -l filelp -o raw file。要检查您要发送的字节,请使用 xxd 十六进制查看器。这些打印机通常在行尾采用 CRLF,因此请务必发送\r\n

我没有适合你的 C 库,但我使用 python-escpos 取得了成功

【讨论】:

【参考方案3】:

这里实际上有两个问题:数据传输和正在传输的数据。

数据传输:使用usblp

为了将数据传送到打印机,请检查 usblp 是否已加载。它允许您将打印机公开为lp 组中的文件,以便您可以将其打开为/dev/usb/lp0

一旦成功,作为普通用户,您可以编写:

echo "Hello" > /dev/usb/lp0

我写了一个blog post on the topic,其中涵盖了权限方面。

数据格式

其次,数据本身需要以正确的二进制格式发送。打印机无法直接理解这个人类可读的.prn(打印?)文件,因此需要将其转换为正确的二进制格式。

从您的问题中解释几件事:

ESC 表示 \x1b,一个 ASCII 转义符 k 表示 ``,实际的 ASCII 字母 k CHR$(80) 表示\x50,这是数字 80 发送到打印机的方式。 CHR$(&amp;H1D); 表示\x1d,ASCII 组分隔符(GS

您可以使用echo -e 在 CLI 上直接编写一些基本命令。也许最简单的非文本示例是 CODE39 条形码,上面写着“000”。

以人类可读形式的相同命令,然后是十六进制,然后作为终端命令将是:

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

这种格式的最佳参考是您的打印机的编程手册,但希望这有助于您理解它。

请注意,您尝试执行的命令包含错误,其中之一甚至会将您困在页面模式中。

除此之外,@scruss 和 @abartek 的答案是完全准确的:使用 lsusb 命令检查 CUPS 是否没有声明该端口,并使用十六进制编辑器查看您的输出,或使用库生成已知的- 好命令。

【讨论】:

以上是关于如何在 Linux 中向热敏打印机发送 ESC/POS 命令的主要内容,如果未能解决你的问题,请参考以下文章

使用 JavaScript 通过 ESC/POS 将图像打印命令发送到以太网上的热敏打印机

如何使用通过 USB 连接的 star webPRNT js SDK 连接到 SK1 sanei 热敏打印机?

如何在 Flutter 中打印到热敏网络打印机?

如何使用 PrintDocument 在热敏打印机上打印文本文件?

如何用Lodop能过USB热敏打印机打开钱箱

佳博热敏条码打印机怎么使用