How to receive feedback messages from the printer 9100 port through AppSocket/JetDirect protocol?

47 Views Asked by At

I am trying to get printer status, config and type info from printer(by AppSocket/JetDirect protocol, also known as Raw or JetDirect, defaults to using TCP 9100 port) use java socket communication on my android application.

Normaly, the printer will reply the printer type if we send "@PJL INFO ID"(PJL:Printer Job Language) to printer 9100 port.

so i am try doing this by java code like this.

    // check if user cliek the button we call WifiPrinter to create object
    if(view.getId() ==R.id.btn_pdf_print){
            WifiPrinter.CrazyThreadPool.THREAD_POOL_EXECUTOR.execute(new Runnable() {
                @Override
                public void run() {
                    WifiPrinter wifiPrintHelper = new WifiPrinter("172.18.*.*", 9100); // call WifiPrinter constructor
                }
            });

    // WifiPrinter constructor will call getInfo() function
    public WifiPrinter(String ip, int port) {
        mEncode = StandardCharsets.UTF_8.name();
        this.mIp = ip;
        this.mPort = port;
        try {
            if (mSocket != null) {
                closeIOAndSocket();
            } else {
                mSocket = new Socket();
            }
            mSocket.connect(new InetSocketAddress(mIp, mPort));
            mInputStream = mSocket.getInputStream();
            mOutputStream = mSocket.getOutputStream();
            mWriter = new OutputStreamWriter(mOutputStream, mEncode);
            mReader = new InputStreamReader(mInputStream, mEncode);
            getInfo();  // send pjl command
        } catch (Exception e) {
            Log.e(TAG, "create object error:" + e.toString());
        }
    }

    // send command and receive information from socket InputStream
    public void getInfo() {
        Log.i(TAG, "getInfo start.");
        String cmd = "@PJL INFO ID";
        try {
            // send command to printer 9100 port
            byte[] content = cmd.getBytes(mEncode);
            mOutputStream.write(content);
            mOutputStream.flush();

            // read data from socket
            char[] data = new char[1024];
            int size = mReader.read(data);
            Log.i(TAG, "receive size=" + size + ", info:" + Arrays.toString(data));
        } catch (IOException e) {
            Log.e(TAG, "get info exception:" + e.getMessage());
        }
        Log.i(TAG, "getInfo end!");
    }

but the logcat print is

2024-03-07 11:29:47.467  8312-8383  WifiPrinter    I  getInfo start.
2024-03-07 11:30:47.512  8312-8383  WifiPrinter    E  get info exception:Connection reset
2024-03-07 11:30:47.512  8312-8383  WifiPrinter    I  getInfo end!

Why can't I receive the correct message? where is the problem in my code? How to receive printer reply information by java socket from printer 9100 port? Who can help me, please!

I use nc tool to test and find it can works well.

D:\workspace
$ nc -vn 172.18.*.* 9100
(UNKNOWN) [172.18.*.*] 9100 (?) open

@PJL INFO ID
@PJL INFO ID
"FUJI XEROX DocuCentre-V C3373 T2"

@PJL INFO STATUS
@PJL INFO STATUS
CODE=10023
DISPLAY=""
ONLINE=TRUE

when i send

"@PJL INFO ID"

printer reply two line information to my nc tool client.

"@PJL INFO ID"
"FUJI XEROX DocuCentre-V C3373 T2"
1

There are 1 best solutions below

1
On

According to PJL doc(https://developers.hp.com/system/files/attachments/PJLReference%282003%29_0.pdf) discribe, if we want get printer type by AppSocket, we need send this command

@PJL INFO ID<CR><LF>

The <CR><LF> means enter and new line.If we want send this command by java, we should send this String cmd = "@PJL INFO ID\r\n", and convert it to UTF-8 format.

public WifiPrinter(String ip, int port) {
    mEncode = StandardCharsets.UTF_8.name();
    this.mIp = ip;
    this.mPort = port;
    System.out.println(TAG + "constructor done.");
}

public static void main(String[] args) {
    WifiPrinter wifi = new WifiPrinter("172.18.*.*", 9100);
    wifi.connect();
    wifi.printerInfo();
}

public void connect() {
    try {
        mSocket = new Socket(mIp, mPort);
        mInputStream = mSocket.getInputStream();
        mOutputStream = mSocket.getOutputStream();
        mReader = new BufferedReader(new InputStreamReader(mInputStream));
    } catch (UnknownHostException e) {
        System.out.println(TAG + "UnknownHostException" + e);
    } catch (IOException e) {
        System.out.println(TAG + "IOException" + e);
    }

    new Thread(new ReadHandlerThread(mSocket)).start();
}

/*
 * receive message from remote printer
 */
class ReadHandlerThread implements Runnable{
    private Socket client;

    public ReadHandlerThread(Socket client) {
        this.client = client;
    }

    @Override
    public void run() {
        System.out.println(TAG + "start ReadHandlerThread.");
        try {
            while(true) {
                // convert message and print
                String message = mReader.readLine();
                if (message != null)
                    System.out.println(TAG + "Receive message:" + message);
            }
        } catch (IOException e) {
            System.out.println("ReadHandlerThread IOException:" + e);
        }
    }
}

public void sendMsg(String message) {
    new Thread(new Runnable() {
        @Override
        public void run() {
            if (mSocket != null && isConnect()) {
                try {
                    // mOutputStream.write(UEL.getBytes());
                    mOutputStream.write(message.getBytes(mEncode));
                    //mOutputStream.write(UEL.getBytes());
                    mOutputStream.flush();
                    // mSocket.shutdownOutput();
                    System.out.println(TAG + "Send message:" + message + "done!");
                } catch (IOException e) {
                    System.out.println(TAG + "sendMsg message error!" + e);
                }
            } else {
                System.out.println(TAG + "Socket is null while send message!");
            }
        }
    }).start();
}

public String printerInfo() {
    sendMsg("@PJL INFO ID\r\n");
    //sendMsg(cmdStatus);
    return "printerInfo done";
}

Remember:

  1. do not do this:mSocket.shutdownOutput().The code will make socket add a FIN ACK package which close the connect to remote.
  2. send command need use UTF-8 format.
  3. use Thread receive message and another to send command or print file.