Search code examples
javajssc

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


I'm trying to work with JSSC. I built my app according to this link:

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

My event handler looks like:

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);
                    }
                }
            }

        }
    }

The problem is that I'm always not getting the incoming data in one piece. (I the message has a length of 100 bytes, Im getting 48 and 52 bytes in 2 separates calls) - The other side send me messages in different lengths.
- In the ICD Im working with, there is a field which tell us the length of the message. (from byte #10 to byte #13) - I cant read 14 bytes:

 (serialPort.readBytes(14);, 

parse the message length and read the rest of the message:

 (serialPort.readBytes(messageLength-14);

But if I will do it, I will not have the message in once piece (I will have 2 separates byte[] and I need it in one piece (byte[]) without the work of copy function.

  1. Is it possible ?

When working with Ethernet (SocketChannel) we can read data using ByteBuffer. But with JSSC we cant.

  1. Is there a good alternative to JSSC ?

Thanks


Solution

  • You can't rely on any library to give you all the content you need at once because :

    • the library dont know how many data you need
    • the library will give you data as it comes and also depending on buffers, hardware, etc

    You must develop your own business logic to handle your packets reception. It will of course depend on how your packets are defined : are they always the same length, are they separated with same ending character, etc.

    Here is an example that should work with your system (note you should take this as a start, not a full solution, it doesn't include timeout for example) :

    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;
            }
        }
    }