0

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

Vasseurth
  • 6,354
  • 12
  • 53
  • 81
user3668129
  • 4,318
  • 6
  • 45
  • 87
  • You can't assume getting your full data in one peace, it will most likely never happen. If your message is always 100 bytes, you only need to keep comming data inside a variable and trigger your business code once you get 100 bytes, and reset your variable. If you have a specific SOH or ending character, you can trigger accordingly. – Alexandre Lavoie Jan 11 '15 at 05:37
  • How can I register to ending characters event ? – user3668129 Jan 11 '15 at 09:28

3 Answers3

2

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;
        }
    }
}
Alexandre Lavoie
  • 8,711
  • 3
  • 31
  • 72
0

After writing data to serial port it need to be flushed. Check the timing and pay attention to the fact that read should occur only after other end has written. read size is just an indication to read system call and is not guaranteed. The data may have arrived and is buffered in serial port hardware buffer but may not have been transferred to operating system buffer hence not to application. Consider using scm library, it flushes data after each write http://www.embeddedunveiled.com/

samuel05051980
  • 369
  • 2
  • 2
0

Try this:

Write your data to the serial port (using serialPort.writeBytes()) and if you are expecting a response, use this:

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

Do what you want with the returned byte array; in my case I just display it for testing.

I found it works just fine if you read one byte at a time, using a 100ms timeout, and when it does time out, you've read all data in the buffer.

Source: trying to talk to an Epson serial printer using jssc and ESC/POS.

John
  • 1