問題描述
在網絡環境中從 Brother TD‑4100N 打印機檢索打印機狀態 (Retrieving the printer status from the Brother TD‑4100N printer in a network environment)
我們正在切換到一個系統,在該系統中,我們的托運人需要將帶有我們商品 ID 的條形碼放在他們今後發送的產品上。我們的管理層願意借給他們 Brother TD‑4100N 標籤打印機,條件是他們不會將其用於打印我們的條形碼以外的其他用途,現在我的任務是編寫一個允許他們打印我們的條形碼的接口。
然而,他們的核心能力在於運輸管理,而不是 IT 管理,所以我必須保持簡單和平台獨立——或者至少盡可能獨立於平台。這裡的想法是能夠通過以太網插入其中一台打印機而無需任何設置 ‑ 盡可能簡單。沒有司機,什麼都沒有,保持簡單,愚蠢。我只想使用以太網端口和套接字。有了這個具有以太網端口並接受 ESC/P 代碼的特定型號,這不應該那麼難,對吧?
在使用一台測試機器一周後,我已經對 ESC/P 有了足夠的了解代碼和 Brother 的專有擴展(至少他們聲稱是)用 C 編寫一個小框架。以所需格式(Code128)打印條形碼本身不會造成問題,但圍繞它的簿記會造成問題;此時我在我的第三本手冊中聲稱只需發送命令“\x1B\x69\x53”(ESC i S)應該會導致打印機向我發送其當前狀態的 32 字節記錄,但對於某些原因打印機根本不想向我發送它是如何做的:
char buffer_send[] = "x1B\x69\x53";
send(sock_jet,buffer_send,sizeof(buffer_send) ‑ 1,0);
char buffer[32];
memset(buffer,0,sizeof(buffer));
recv(sock_jet,buffer,sizeof(buffer),0);
fprintf
(
stderr,
"%02x%02x%02x%02x%02x%02x%02x%02x\n",
buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5],buffer[6],buffer[7]
);
fprintf
(
stderr,
"%02x%02x%02x%02x%02x%02x%02x%02x\n",
buffer[8],buffer[9],buffer[10],buffer[11],buffer[12],buffer[13],buffer[14],buffer[15]
);
fprintf
(
stderr,
"%02x%02x%02x%02x%02x%02x%02x%02x\n",
buffer[16],buffer[17],buffer[18],buffer[19],buffer[20],buffer[21],buffer[22],buffer[23]
);
fprintf
(
stderr,
"%02x%02x%02x%02x%02x%02x%02x%02x\n",
buffer[24],buffer[25],buffer[26],buffer[27],buffer[28],buffer[29],buffer[30],buffer[31]
);
此代碼只是暫停一段時間,直到超時命中或其他,並且 recv
不會將任何數據寫入我的緩衝區:
0000000000000000
0000000000000000
0000000000000000
0000000000000000
而且我顯然不是唯一遇到此類問題的人。這個 Ruby Python 包(https://pypi.org/project/brotherprint /#files) 聲稱專門為 Brother 打印機提供服務,但我從未見過他們收到任何數據(至少在 brotherprint/brotherprint.py
中)。事實上,我什至沒有看到他們正確拼寫“receive”。
在 SO(用php socket編程操作打印機 ) 有人嘗試在 PHP 中做同樣的事情,我在 C 中嘗試做 ‑ 他們遇到了與我完全相同的問題,打印機拒絕向他們提供狀態數據。該解決方案似乎涉及從端口 9100 切換到端口 515 並使用不同的協議,雖然我看到打印機上打開了端口 515,但我從未看到該打印機的任何輸出,在紙上或在插座上。此時我會聯繫 Brother 支持,但我已經打開了 另一個 票證,因為他們的 另一個 打印機似乎在將狀態報告發送回給CUPS。
我嘗試在我的有效負載末尾添加一個 NUL 字節,以防打印機正在等待頁面饋送,但這也沒有奏效。再說一遍:將條形碼打印到該死的東西上有效,因此 IP、端口和連接至少在一定程度上有效 ‑ 但接收狀態報告卻沒有。
strace
來自我的程序:
connect(3, {sa_family=AF_INET, sin_port=htons(9100), sin_addr=inet_addr("192.168.XXX.XXX")}, 16) = 0
sendto(3, "\33iS", 3, 0, NULL, 0) = 3
recvfrom(3, <blocks here for minutes> "", 32, 0, NULL, NULL) = 0
write(2, "0000000000000000\n", 170000000000000000
) = 17
write(2, "0000000000000000\n", 170000000000000000
) = 17
write(2, "0000000000000000\n", 170000000000000000
) = 17
write(2, "0000000000000000\n", 170000000000000000
) = 17
close(3)
以及我正在使用的主要手冊:https://download.brother.com/welcome/docp000579/cv_td4000_eng_escp_120.pdf(搜索“ESC i S”)。
參考解法
方法 1:
OK, so I actually got a response from the Japanese Brother support. And there is so much wrong with that response that I may come off as rambling a little right now.
Brother insists that
ESC/P is not supposed to be for bi‑directional communications.
, which is a load of steaming BS seeing as Brother MADE their implementation bi‑directional. That is what the documentation says! Read it for yourself in the ESC/P documentation they provide.
Requests the printer status. The printer status comprises 32 bytes.
So I've already caught them either lying or being incompetent.
The next lie/being incompetent is:
Namely what you have reported is within our specifications.
I'd have LOVED to actually see those specifications they've quoted here. The only thing I've found so far was section 5 "Additional Functions" in my manual, which has a paragraph called "ESC/P commands" in which they link to the aforementioned ESC/P manual. This manual specifically states:
This information is provided assuming that the user has full understanding of the operating system being used and basic mastery of RS‑232C, USB or Ethernet in a developer's environment.
In section 8 "Using Interface Cables" they state that RS‑232C (serial) and RJ‑45 (ethernet) cables are not standard accessories, and that it's not possible to connect a RS‑232C and a USB cable to the same printer at the same time. Then there are some installation instructions on MS Windows computers, and that's about it.
Their FAQ doesn't mention anything (https://www.brother.co.jp/eng/dev/command/faq/index.aspx) except for using SNMP (which doesn't work on this printer because Port 161/162 are not even open), and their network reference is just as mute (https://download.brother.com/welcome/docp000592/cv_td2130n_eng_net.c.pdf ‑ not one mentioning of ESC/P). I'm seriously wondering if I'm too stupid to find this, or if they pulled that one out of their ar**s just to not have to deal with this.
And don't tell me they wouldn't do this. This printer also runs a webserver on port 80 that has a confirmed secvuln (https://threatpost.com/tag/debut‑embedded‑web‑server/).
But then they actually get to the core of the issue here:
Besides, our specification never ruturns when using Netwrokd even if an error does not happen
This little part of Engrish here is probably supposed to mean:
Even if an error occurs our hardware does not send status reports over ethernet.
, which would explain why the printer remains silent. However I don't believe this is part of their specification, which I couldn't even find; I believe they got caught with their pants down yet again and refuse to acknowledge it. It shouldn't make any difference how you connect to the machine ‑ ethernet, serial, or USB ‑ as long as the transport layer works, which obviously is the case since I can send other commands to the printer. However this is supposed to be used on different machines on the same network. Why do they even have an ethernet port if the firmware is unable to send a status report? Who came up with this idea?
I can honestly only discourage people from getting Brother devices. This is the second printer I've seen from this company that simply doesn't work over ethernet, and what good is a printer if you cannot query its status to determine if you're to send a job to it? And they sell those unreliable machines for 600 € apiece.