使用 JSSC 时如何从串行连接读取(所有可用的)数据?

How to read (all available) data from serial connection when using JSSC?

我正在尝试与 JSSC 合作。 我根据这个 link:

构建了我的应用程序

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 个单独的 byte[] 并且我需要在一个 (byte[]) 中没有复制功能的工作。

  1. 可能吗?

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

  1. 有没有更好的 JSSC 替代方案?

谢谢

你不能依赖任何图书馆一次给你所有你需要的内容,因为:

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

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

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

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] == '[=10=]')
                        {
                            m_bReceptionActive = true;
                            m_nReceptionPosition = 1;
                        }
                    }
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                }
                break;
            default:
                break;
        }
    }
}

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

试试这个:

将数据写入串行端口(使用 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 串行打印机通信。