This discussion is archived
13 Replies Latest reply: Feb 8, 2007 6:58 PM by 807597 RSS

URGENT: Capturing data through serial port

807596 Newbie
Currently Being Moderated
Hi,

My problem is with the use of javax.comm API. I have an RFID tag reader connected to
the serial port. It is a handheld reader and reads tags when its trigger is pulled. The
data that is read is sent to the serial port. This is what I want to capture.

I tried to test the reading operation by running the SimpleRead sample. What I see is
that I pull the trigger once to read 1 tag, but that generates 3 DATA_AVAILABLE events.
The tag ID that is read is 16 bytes, preceded by a 3 byte AIM Identifier (that declares
the following data was read from an RFID tag, and not a barcode which has different
AIM Identifiers for the different symbologies - but I digress.) By inserting some println's,
I was able to see that the 19 bytes of data are read 8 bytes at a time. The first 8 bytes
are read on the first DATA_AVAILABLE event, the next 8 are read on the second event
and the last 3 bytes are read on the 3rd DATA_AVAILABLE event.

This is strange & not good for me. How can my application know that the data read in
these 3 separate DATA_AVAILABLE events is to be concatenated to form a single
tag ID? Why is the single trigger-pull & tag read operation broken up into chunks of
8 bytes? Is there some configuration setting that will give me the behavior I want?
(I cannot rely on the length of the tag ID being 16 bytes always, because the same
reader will also be reading barcodes where the data may have varying length)

Thanks for any help. This is really urgent.
- Ajoy
  • 1. Re: URGENT: Capturing data through serial port
    807596 Newbie
    Currently Being Moderated
    Hmmm.... I did some tinkering around and find that, if I enable Receive Threshold
    and set it at 12 (i.e. > 8 but < number of bytes on the tag read), then in the
    processing of the DATA_AVAILABLE event, calling inputStream.available()
    still returns 8 (where inputStream is the return value of serialPort.getInputStream()).
    However, when inputStream.read(byte[] buf) is called on the next line, all the
    bits that arrive on the port are read at once. And there is no further DATA_AVAILABLE
    event until the reader reads another tag.

    My problem is that, if I set the receive threshold below 8, then only 8 bits are
    read with multiple DATA_AVAILABLE events (as before). So, I set it to 12 (not
    too high, else read may block even after a tag is read). But, now, if a barcode
    is read with the same scanner (which is possible), the data length on the
    barcode may be < 8 and that means that just 1 scan of the barcode is not
    enough to make the read method return.

    - Ajoy
  • 2. Re: URGENT: Capturing data through serial port
    807596 Newbie
    Currently Being Moderated
    please post your code, your SerialEvent code where your captureing the DATA_Available event, and also your code of InStream.read() code.

  • 3. Re: URGENT: Capturing data through serial port
    807596 Newbie
    Currently Being Moderated
    Thanks for replying, wew64. I took the sample standalone SimpleRead
    Java app at: <JAVAX_COMM_ROOT>/samples/Simple/SimpleRead.java
    and enabled receive threshold, setting it at 12. Also, put in some print
    statements. The entire changed code is given below (along with Sun's
    copyright notice & license statement, as required :-)

    I think I forgot to mention that I'm getting the behavior I want with receive threshold
    set at 12 for all barcodes & tags I have, all of which have > 12 bytes of data.
    I'm only concerned about reading a barcode that may have < 12 bytes of data.

    /*
    * @(#)SimpleRead.java     1.12 98/06/25 SMI
    *
    * Copyright (c) 1998 Sun Microsystems, Inc. All Rights Reserved.
    *
    * Sun grants you ("Licensee") a non-exclusive, royalty free, license
    * to use, modify and redistribute this software in source and binary
    * code form, provided that i) this copyright notice and license appear
    * on all copies of the software; and ii) Licensee does not utilize the
    * software in a manner which is disparaging to Sun.
    *
    * This software is provided "AS IS," without a warranty of any kind.
    * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
    * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
    * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND
    * ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
    * LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE
    * SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS
    * BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
    * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES,
    * HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING
    * OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN
    * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
    *
    * This software is not designed or intended for use in on-line control
    * of aircraft, air traffic, aircraft navigation or aircraft
    * communications; or in the design, construction, operation or
    * maintenance of any nuclear facility. Licensee represents and
    * warrants that it will not use or redistribute the Software for such
    * purposes.
    */

    import java.io.*;
    import java.util.*;
    import javax.comm.*;

    public class SimpleRead implements Runnable, SerialPortEventListener {
    static CommPortIdentifier portId;
    static Enumeration portList;

    InputStream inputStream;
    SerialPort serialPort;
    Thread readThread;

    public static void main(String[] args) {
    portList = CommPortIdentifier.getPortIdentifiers();

    try
    {
    portId = CommPortIdentifier.getPortIdentifier("COM1");
    SimpleRead reader = new SimpleRead();
    }
    catch (NoSuchPortException nspe)
    {
    System.out.println("No port named COM1 found");
    }
    catch (UnsupportedCommOperationException ucoe)
    {
    System.out.println("Could not enable receive threshold.");
    }

    }

    public SimpleRead() throws UnsupportedCommOperationException {
    try {
    serialPort = (SerialPort) portId.open("SimpleReadApp", 2000);
    } catch (PortInUseException e) {}
    try {
    serialPort.enableReceiveThreshold(12);
    System.out.println("Port '" + serialPort.getName() + "' settings:");
    System.out.println("\tInput Buffer Size: " + serialPort.getInputBufferSize());
    System.out.println("\tReceive Framing Enabled? " + serialPort.isReceiveFramingEnabled());
    System.out.println("\tReceive Framing Byte: " + serialPort.getReceiveFramingByte());
    System.out.println("\tReceive Threshold Enabled? " + serialPort.isReceiveThresholdEnabled());
    System.out.println("\tReceive Threshold: " + serialPort.getReceiveThreshold());
    System.out.println("\tReceive Timeout Enabled? " + serialPort.isReceiveTimeoutEnabled());
    System.out.println("\tReceive Timeout: " + serialPort.getReceiveTimeout());
    inputStream = serialPort.getInputStream();
    } catch (IOException e) {}

         try {
    serialPort.addEventListener(this);
         } catch (TooManyListenersException e) {}
    serialPort.notifyOnDataAvailable(true);
    try {
    serialPort.setSerialPortParams(19200,
    SerialPort.DATABITS_7,
    SerialPort.STOPBITS_2,
    SerialPort.PARITY_NONE);
    } catch (UnsupportedCommOperationException e) {}
    readThread = new Thread(this);
    readThread.start();
    }

    public void run() {
    try {
    Thread.sleep(20000);
    } catch (InterruptedException e) {}
    }

    public void serialEvent(SerialPortEvent event) {
    System.out.println("Entered method serialEvent()");
    switch(event.getEventType()) {
    case SerialPortEvent.BI:
    case SerialPortEvent.OE:
    case SerialPortEvent.FE:
    case SerialPortEvent.PE:
    case SerialPortEvent.CD:
    case SerialPortEvent.CTS:
    case SerialPortEvent.DSR:
    case SerialPortEvent.RI:
    case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
    break;
    case SerialPortEvent.DATA_AVAILABLE:
    byte[] readBuffer = new byte[4096];

    try {
    while (inputStream.available() > 0) {
    System.out.println("Available bytes: " + inputStream.available());
    int numBytes = inputStream.read(readBuffer);
    System.out.println("Number of bytes read: " + numBytes);
    }
    System.out.println("\"" + new String(readBuffer).trim() + "\"");
    } catch (IOException e) {}
    break;
    }
    }
    }
  • 4. Re: URGENT: Capturing data through serial port
    807596 Newbie
    Currently Being Moderated
    please use the [ code ]and [code ] tags for code.

    I don't think you have a problem with the code, it's more like understanding how to make it work.
    to make the read method return.
    You do not have a read() method.

    The code is behaving as it should.

    You need to use the SimpleRead class as a thread, add and remove the Serial port listener as needed.
    You read all data available, then send it to a method to parse the buffer.
    You can count how much data was read so you know how much to parse.

    I never used receive threshhold.


    Here is example (sample)of my serial port reader
    //SerialIO
       public void serialEvent(SerialPortEvent event) {
            switch(event.getEventType()) {
                  case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
                break;
            case SerialPortEvent.DATA_AVAILABLE:
                this.dataManager.readData();
    
        }
    //DataManager
    public void readData() {
         String str;
         int     bytes = 0;
         long endTime, now;
    
         try {
              while (this.owner.isComPortOpen
                   && (SerialIO.inStream.available() > 0)) {
                             
                   bytes = SerilIO.inStream.read(this.buffer);
                   if (bytes > 0) {
                   if (bytes > this.buffer.length) {
                        System.out.println( ": Input buffer overflow!");
                   }
         /**
         **Here is where you parse your buffer
         */
                   sendDataToParser(bytes, buffer);
                             
                    }
              }
                             
              } catch (IOException ex) {
                   System.out.println( ": Cannot read input stream");
              }
         }
    
    /**
          * Stops the serialEvent listener
          */
         protected void stopSerialEvent() {
    
              SerialIO.serialPort.removeEventListener();
              try {
                   Thread.sleep(2000);
                   flushInputStream();
              } catch (InterruptedException e1) {
                   // TODO Auto-generated catch block
                   e1.printStackTrace();
              }
              
         }
    /**
          * Starts the Serial event listener
          */
         protected void startSerialEvent() {
              // TODO Auto-generated method stub
              try {
                   SerialIO.serialPort.addEventListener(SerialIO);
              } catch (TooManyListenersException e) {
                   // TODO Auto-generated catch block
                   //System.out.println("startSerialEvent in dataManager");
                   e.printStackTrace();
              }
         }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
  • 5. Re: URGENT: Capturing data through serial port
    807596 Newbie
    Currently Being Moderated
    I had some problems understanding your reply. Perhaps, you did not read the code correctly
    due to the poor formatting. I'm sorry about that. I list responses to a couple of your comments
    below. Also, could you send the complete code including a main method, to read the serial
    input on a DATA_AVAILABLE event and print the read data to System.out, using your approach?
    You have only sent some pieces of illustrative code, I guess. I tried to construct an executable
    class out of the code you sent but could not. I'm sorry if this sounds too dumb a request. :-)

    1. You say that I do not have a read() method; but in the serial event handler method "public void serialEvent(SerialEvent event)",
    I have the following code to handle the DATA_AVAILABLE event. (Note the call to inputStream.read(readBuffer) within the while loop):
    byte[] readBuffer = new byte[4096];
    
    try
    {
        while (inputStream.available() > 0)
        {
            System.out.println("Available bytes: " + inputStream.available());
            int numBytes = inputStream.read(readBuffer);
            System.out.println("Number of bytes read: " + numBytes);
        }
        System.out.println("\"" + new String(readBuffer).trim() + "\"");
    }
    catch (IOException e)
    { e.printStackTrace(); }
    2. You also say that I "need to use the SimpleRead class as a thread, add and remove the Serial port listener as needed"; but the main method instantiates a SimpleRead object using the SimpleRead no-arg constructor, which has the following code
    readThread = new Thread(this);
    readThread.start();
    and SimpleRead class has the following run method:
    public void run()
    {
        try
        {
            Thread.sleep(20000);
        }
        catch (InterruptedException e) {}
    }
    Thanks...
    - Ajoy
  • 6. Re: URGENT: Capturing data through serial port
    807596 Newbie
    Currently Being Moderated
    Ok, back to the original question
    1 tag, but that generates 3 DATA_AVAILABLE events.
    are you sure its 3 events, and not just looping in your while( data.available() ) ???

    Does this really matter?? just create a buffer that puts the chunks together, then parse it later.

    What is the time intervals your Hardware( scanner) sends data at??
    Does it send the first chunk as 8 , then wait some millisecs, then send the second, wait some millisecs, then send the last chunk???


    I used the SerialDemo sample program to verify data being sent to and from device.
    Give it a try, or try BlackBox, it will give you a byte count.
  • 7. Re: URGENT: Capturing data through serial port
    807596 Newbie
    Currently Being Moderated
    I'm sure it's 3 events because if you look at the following code:
    try
    {
        while (inputStream.available() > 0)
        {
            System.out.println("Available bytes: " + inputStream.available());
            int numBytes = inputStream.read(readBuffer);
            System.out.println("Number of bytes read: " + numBytes);
        }
        System.out.println("\"" + new String(readBuffer).trim() + "\"");
    }
    catch (IOException e)
    { e.printStackTrace(); }
    The buffer contents are printed out outside the while loop. If it was looping within the while
    loop while data available, the "Available bytes" and "Number of bytes read" would be
    printed out 3 times, but the buffer contents would just be printed once. However, I see
    the buffer contents also printed 3 times, each time with the next 8 bytes. The only way
    that the last println (outside the while loop) could execute 3 times is if the DATA_AVAILABLE
    event is generated 3 times.

    The port settings are 19200, 7, N, 2 (baud rate, data bits, parity, stop bits). I cannot keep
    the chunks in a buffer and then concatenate them later because the data on the barcodes
    is not of a fixed length. So, if it is being read in chunks of 8 bytes, I wouldn't know how many
    of those chunks to put together to get the data on 1 barcode i.e. where does the data on
    one barcode end and the data on the next barcode scanned begin?

    It could be that it's just due to the hardware. As you said, it might be sending data with
    some small delay between every 8 bytes. But then, if that was so, then with a receive
    threshold of 12 bytes, the first 8 bytes would be read. The read operation would then
    block for those few msec and read the next 8 bytes. Now there are 16 bytes (> 12) in
    the buffer, so read would just return with 16 bytes. But I see that on an RF tag with 21
    bytes in its ID, all 21 bytes are read at once. If the small interval broke up the data without
    the threshold, then with the threshold, too, the data should be broken up after the
    threshold number of bytes have been read.

    Oh well, I'll just work with this setting until the 1st demo Oct.-beginning. Will check the
    hardware specs and see if this workaround can be eliminated later.

    Thanks for your help. I'll give you the Duke points for your effort. :-)

    - Ajoy
  • 8. Re: URGENT: Capturing data through serial port
    807596 Newbie
    Currently Being Moderated
    where does the data on one barcode end and the data on the next barcode scanned begin?
    I don't think my barcode data has a header (start bit).
    The data ends with a carrage return key press.Others may be different.

    I worked with a different serial data stream last year, the data length was variable, header started with 01100110 and then the next three bits would be the number of bytes to follow, 20 - 60 bytes long.

    well, I'll just work with this setting until the 1st demo Oct.-beginning.
    At least you have it working, and later, once you have more working, you can optimize the serial port reader later.

    Good luck
    '

  • 9. Re: URGENT: Capturing data through serial port
    807596 Newbie
    Currently Being Moderated
    Hi Ajoy,
    I was reading the messages you posted in the discussion forum. I m having almost the same problem. I would be grateful if you could help me out.
    If it's ok with you could you please share the piece of the code to read the reader of RFID?
    I appreciate it.
    Thank you
  • 10. Re: URGENT: Capturing data through serial port
    807596 Newbie
    Currently Being Moderated
    Hi folks,

    try to use

    serialPort.disableReceiveFraming();
    serialPort.disableReceiveTimeout();
    serialPort.enableReceiveThreshold(length);

    with lenght as the preferred size of the dataset. (e.g. 16 bytes instead of 8)

    Have fun!

    Regards, Tom.
  • 11. Re: URGENT: Capturing data through serial port
    807596 Newbie
    Currently Being Moderated
    Now that I get a byte array with the correct length I have another problem. There's a shift in the datagram that varies every time I start my program. :(

    Any idea how I can get this to work synchronously?

    Regards, Tom.
  • 12. Re: URGENT:  Capturing data through serial port
    807596 Newbie
    Currently Being Moderated
    If I want to send character "o" through serial port by use javax.comm. what should I do?
    please, help me.
  • 13. Re: URGENT: Capturing data through serial port
    807597 Newbie
    Currently Being Moderated
    Hi All,

    I am also getting the same problem when i try to read the data from a serial port.

    Tom, It would be really great if you give some ideas to read the exact byte data.

    Thanks in advance.
    Jose.