更新: 不要浪费你的时间。甚至包含的 SDK 也无法从该打印机成功获取任何状态,因此它可能不受支持。
原始问题:
我有一个漂亮的小Zjiang ZJ-5802LD 热敏收据打印机,不幸的是,除了一个非常糟糕的“SDK”之外,它没有任何文档,包括一个 jar 和几个示例。
为了绕过这些限制,我尝试使用 Javax-USB 直接发送 ESC/POS 代码,但我怀疑我对 USB 的理解不足会造成干扰。它打印得非常愉快,但我完全被困在试图从小野兽那里恢复状态。
它只有一个输入和一个输出端点,分别位于 0x81 和 0x03。下面的代码,以及我在那里找到的每组与状态相关的消息字节,总是只返回一串零,然后抛出javax.usb.UsbException: Pipe is still busy
.
您是否期望以下方法编写请求并返回状态?有更好的想法如何获得状态码?
public void checkStatus(UsbPipe readpipe, UsbPipe writepipe) {
byte[] msg= { 0x1b, 0x76 }; // ESC-v = { status, per https://www.sparkfun.com/datasheets/Components/General/Driver%20board.pdf
//byte[] msg= { 0x00, 0x04 }; // DLE EOT is the epson standard status req
//byte[] msg= { 0x1d, '(', 'H' }; // Another status request from somewhere.
//byte[] msg= { 0x1d, 'a' }; // Sets Automatic Status Back (ASB) mode.
//byte[] msg= { 0x1c, '(', 'e' }; // Another way to set ASB -- https://reference.epson-biz.com/modules/ref_escpos/index.php?content_id= {72
try {
// Prepare to read response
readpipe.open();
byte[] data = new byte[8];
final UsbIrp rirp = readpipe.asyncSubmit(data);
rirp.setComplete(false);
// Send away.
writepipe.open();
final UsbIrp wirp = writepipe.asyncSubmit(msg);
wirp.waitUntilComplete(500);
writepipe.close();
// Wait until we get something back
rirp.waitUntilComplete(500);
System.out.println("returned data: " + DatatypeConverter.printHexBinary(rirp.getData()));
readpipe.close();
} catch (UsbNotActiveException | UsbNotClaimedException | UsbDisconnectedException | UsbException e1) {
e1.printStackTrace();
}
}
如果您有类似的打印机并受到启发尝试运行它,这里是完整的程序。
package posprint;
import javax.usb.*;
import javax.usb.event.*;
import javax.xml.bind.DatatypeConverter;
import java.util.List;
public class Main {
UsbServices services;
UsbHub roothub;
UsbDevice dev;
UsbInterface iface;
UsbEndpoint endpointOut;
UsbEndpoint endpointIn;
UsbPipe mWritepipe;
UsbPipe mReadpipe;
public static void main(String[] args) throws Exception {
Main mn = new Main();
if(mn.dev == null) return;
mn.checkStatus(mn.mReadpipe, mn.mWritepipe);
mn.iface.release();
}
public Main() throws Exception {
services = UsbHostManager.getUsbServices();
short vid = (short) 0x0493;
short pid = (short) 0x8760;
roothub = services.getRootUsbHub();
dev = findDevice(roothub, vid, pid);
if( dev == null) {
System.out.println("not found");
return;
}
getPipes(dev);
}
UsbDevice findDevice(UsbHub hub, short vendorId, short productId)
{
for (UsbDevice device : (List<UsbDevice>) hub.getAttachedUsbDevices())
{
UsbDeviceDescriptor desc = device.getUsbDeviceDescriptor();
if (desc.idVendor() == vendorId && desc.idProduct() == productId) return device;
if (device.isUsbHub())
{
device = findDevice((UsbHub) device, vendorId, productId);
if (device != null) return device;
}
}
return null;
}
void getPipes(UsbDevice device) throws Exception {
UsbConfiguration configuration = device.getActiveUsbConfiguration();
List<UsbInterface> ifaces = configuration.getUsbInterfaces();
for ( UsbInterface ifac : ifaces ) {
System.out.println(ifac.toString());
}
iface = configuration.getUsbInterface((byte) 0);
iface.claim(new UsbInterfacePolicy() {
@Override public boolean forceClaim(UsbInterface usbInterface) {
return true;
}
});
List<UsbEndpoint> eps = iface.getUsbEndpoints();
for( UsbEndpoint ep : eps ) {
UsbEndpointDescriptor desc = ep.getUsbEndpointDescriptor();
System.out.println(ep.toString() + " has endpoint: " + desc.bEndpointAddress());
}
endpointOut = iface.getUsbEndpoint((byte) 0x03);
mWritepipe = endpointOut.getUsbPipe();
endpointIn = iface.getUsbEndpoint((byte) 0x81); // -127
mReadpipe = endpointIn.getUsbPipe();
}
public void checkControlStatus() throws UsbNotActiveException, UsbNotClaimedException, UsbDisconnectedException, UsbException {
int ret = 0;
byte[] readbuf = new byte[2];
try {
// Write status request
UsbControlIrp devirp = mWritepipe.createUsbControlIrp(
(byte) (UsbConst.REQUESTTYPE_DIRECTION_IN
| UsbConst.REQUESTTYPE_TYPE_STANDARD
| UsbConst.REQUESTTYPE_RECIPIENT_DEVICE),
UsbConst.REQUEST_GET_STATUS, //UsbConst.REQUEST_GET_CONFIGURATION,
(short) 0,
(short) 0
);
devirp.setData(readbuf);
dev.syncSubmit(devirp);
System.out.println(DatatypeConverter.printHexBinary(devirp.getData()));
} catch (RuntimeException e) {
System.out.println(e.getMessage());
return;
}
System.out.println( "Control status: " + DatatypeConverter.printHexBinary(readbuf));
}
private class MyListener implements UsbPipeListener {
public MyListener(String prefix) {this.prefix = prefix; }
String prefix;
// used with
// mReadpipe.addUsbPipeListener(new MyListener("read")); // For backup, because the async read isn't working.
@Override public void errorEventOccurred(UsbPipeErrorEvent event) {
System.out.println(prefix + " pipe error: " + event.toString());
}
@Override public void dataEventOccurred(UsbPipeDataEvent event) {
System.out.println(prefix + " listener data: " + DatatypeConverter.printHexBinary(event.getData()));
}
}
public void checkStatus(UsbPipe readpipe, UsbPipe writepipe) {
byte[] msg= { 0x1b, 0x76 }; // ESC-v = { status, per https://www.sparkfun.com/datasheets/Components/General/Driver%20board.pdf
//byte[] msg= { 0x00, 0x04 }; // DLE EOT is the epson standard status req
//byte[] msg= { 0x1d, '(', 'H' }; // Another status request from somewhere.
//byte[] msg= { 0x1d, 'a' }; // Sets Automatic Status Back (ASB) mode.
//byte[] msg= { 0x1c, '(', 'e' }; // Another way to set ASB -- https://reference.epson-biz.com/modules/ref_escpos/index.php?content_id= {72
try {
// Prepare to read response
readpipe.open();
byte[] data = new byte[8];
final UsbIrp rirp = readpipe.asyncSubmit(data);
rirp.setComplete(false);
// Send away.
writepipe.open();
final UsbIrp wirp = writepipe.asyncSubmit(msg);
wirp.waitUntilComplete(500);
writepipe.close();
// Wait until we get something back
rirp.waitUntilComplete(500);
System.out.println("returned data: " + DatatypeConverter.printHexBinary(rirp.getData()));
readpipe.close();
} catch (UsbNotActiveException | UsbNotClaimedException | UsbDisconnectedException | UsbException e1) {
e1.printStackTrace();
}
}
}