0

我正在尝试与 JSSC 合作。我根据此链接构建了我的应用程序:

https://code.google.com/p/java-simple-serial-connector/wiki/jSSC_examples

我的事件处理程序如下所示:

static class SerialPortReader implements SerialPortEventListener {

        public void serialEvent(SerialPortEvent event) {
            if(event.isRXCHAR()){//If data is available                                
                    try {
                        byte buffer[] = serialPort.readBytes();
                    }
                    catch (SerialPortException ex) {
                        System.out.println(ex);
                    }
                }
            }

        }
    }

问题是我总是无法将传入的数据一次性获取。(我的消息长度为 100 字节,我在 2 个单独的呼叫中分别获得 48 和 52 个字节) - 另一方向我发送不同长度的消息。
- 在我使用的 ICD 中,有一个字段告诉我们消息的长度。(从字节 #10 到字节 #13) - 我无法读取 14 个字节:

 (serialPort.readBytes(14);, 

解析消息长度并读取消息的其余部分:

 (serialPort.readBytes(messageLength-14);

但是如果我这样做,我将不会在一次中获得消息(我将有 2 个单独的字节 [],并且我需要它在一个片段(字节 [])中没有复制功能的工作。

  1. 可能吗 ?

使用以太网(SocketChannel)时,我们可以使用 ByteBuffer 读取数据。但是对于 JSSC,我们不能。

  1. JSSC 有什么好的替代品吗?

谢谢

4

3 回答 3

2

您不能依赖任何库一次为您提供所需的所有内容,因为:

  • 图书馆不知道你需要多少数据
  • 该库将根据缓冲区、硬件等为您提供数据

您必须开发自己的业务逻辑来处理数据包接收。这当然取决于您的数据包是如何定义的:它们是否总是相同的长度,它们是否用相同的结束字符分隔等等。

这是一个应该适用于您的系统的示例(请注意,您应该将此作为开始,而不是完整的解决方案,例如它不包括超时):

static class SerialPortReader implements SerialPortEventListener
{
    private int m_nReceptionPosition = 0;
    private boolean m_bReceptionActive = false;
    private byte[] m_aReceptionBuffer = new byte[2048];

    @Override
    public void serialEvent(SerialPortEvent p_oEvent)
    {
        byte[] aReceiveBuffer = new byte[2048];

        int nLength = 0;
        int nByte = 0;

        switch(p_oEvent.getEventType())
        {
            case SerialPortEvent.RXCHAR:
                try
                {
                    aReceiveBuffer = serialPort.readBytes();

                    for(nByte = 0;nByte < aReceiveBuffer.length;nByte++)
                    {
                        //System.out.print(String.format("%02X ",aReceiveBuffer[nByte]));

                        m_aReceptionBuffer[m_nReceptionPosition] = aReceiveBuffer[nByte];

                        // Buffer overflow protection
                        if(m_nReceptionPosition >= 2047)
                        {

                            // Reset for next packet
                            m_bReceptionActive = false;
                            m_nReceptionPosition = 0;
                        }
                        else if(m_bReceptionActive)
                        {
                            m_nReceptionPosition++;

                            // Receive at least the start of the packet including the length
                            if(m_nReceptionPosition >= 14)
                            {
                                nLength = (short)((short)m_aReceptionBuffer[10] & 0x000000FF);
                                nLength |= ((short)m_aReceptionBuffer[11] << 8) & 0x0000FF00;
                                nLength |= ((short)m_aReceptionBuffer[12] << 16) & 0x00FF0000;
                                nLength |= ((short)m_aReceptionBuffer[13] << 24) & 0xFF000000;

                                //nLength += ..; // Depending if the length in the packet include ALL bytes from the packet or only the content part

                                if(m_nReceptionPosition >= nLength)
                                {
                                    // You received at least all the content

                                    // Reset for next packet
                                    m_bReceptionActive = false;
                                    m_nReceptionPosition = 0;
                                }
                            }

                        }
                        // Start receiving only if this is a Start Of Header
                        else if(m_aReceptionBuffer[0] == '\0')
                        {
                            m_bReceptionActive = true;
                            m_nReceptionPosition = 1;
                        }
                    }
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                }
                break;
            default:
                break;
        }
    }
}
于 2015-01-12T20:26:49.177 回答
0

将数据写入串行端口后,需要刷新。检查时序,注意只有在另一端写完后才会读。读取大小只是读取系统调用的指示,不能保证。数据可能已经到达并缓存在串行端口硬件缓冲区中,但可能尚未传输到操作系统缓冲区,因此未传输到应用程序。考虑使用 scm 库,它在每次写入后刷新数据http://www.embeddedunveiled.com/

于 2015-04-01T05:43:11.940 回答
0

尝试这个:

将数据写入串行端口(使用 serialPort.writeBytes()),如果您期望得到响应,请使用以下命令:

    byte[] getData() throws SerialPortException, IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] b;

        try {
            while ((b = serialPort.readBytes(1, 100)) != null) {
                baos.write(b);
    //                System.out.println ("Wrote: " + b.length + " bytes");
                }
    //            System.out.println("Returning: " + Arrays.toString(baos.toByteArray()));
            } catch (SerialPortTimeoutException ex) {
                ;   //don't want to catch it, it just means there is no more data         to read
            }
            return baos.toByteArray();
        }

用返回的字节数组做你想做的事;就我而言,我只是将其显示以进行测试。

我发现如果你一次读取一个字节,使用 100 毫秒超时,它工作得很好,当它超时时,你已经读取了缓冲区中的所有数据。

资料来源:尝试使用 jssc 和 ESC/POS 与 Epson 串行打印机通信。

于 2019-01-10T12:27:33.643 回答