Использование Javax-usb для получения статуса от принтера ZJiang POS
Обновление: не тратьте свое время. Даже включенный SDK не может успешно получить какой-либо статус от этого принтера, поэтому он, вероятно, не поддерживается.
Оригинальный вопрос:
У меня есть отличный маленький чековый термопринтер Zjiang ZJ-5802LD, который, к сожалению, не имеет никакой документации, кроме очень скудного "SDK", включающего банку и пару примеров.
Чтобы обойти ограничения, я пытаюсь отправить коды ESC/POS напрямую через Javax-USB, но я подозреваю, что мое плохое понимание 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();
}
}
}