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

时间:2015-01-11 05:34:20

标签: java jssc

我试图与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个字节,我得到48和52个字节,2个分隔调用) - 另一方发给我不同长度的信息 - 在我工作的ICD中,有一个字段告诉我们消息的长度。 (从字节#10到字节#13) - 我读不到14个字节:

 (serialPort.readBytes(14);, 

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

 (serialPort.readBytes(messageLength-14);

但如果我会这样做,我将不会有一次消息(我将有2个分隔byte []并且我需要它在一个部分(byte [])而没有复制功能的工作。

  1. 有可能吗?
  2. 使用以太网(SocketChannel)时,我们可以使用ByteBuffer读取数据。但是使用JSSC我们不能。

    1. JSSC有替代品吗?
    2. 由于

3 个答案:

答案 0 :(得分: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;
        }
    }
}

答案 1 :(得分:0)

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

后刷新数据

答案 2 :(得分: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();
        }

使用返回的字节数组执行所需的操作;就我而言,我只是将其显示以进行测试。

我发现,如果您一次读取一个字节(使用100ms超时),则它工作正常,当超时时,您已读取缓冲区中的所有数据。

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