Link to home
Start Free TrialLog in
Avatar of meverest
meverestFlag for Australia

asked on

Bluetooth SPP reader problem

Hi Folks,

having an infuriating problem trying to read bluetooth serial port data in a midp application.  seems like the serial port is unreliable at best (although I assume that it is something to do with how I am handling it), but the upshot is that at the moment, I can't get any reliable data out of it at all.

Here is a function I use to try to get the data:

    public final static String readData(StreamConnection conn)
    {
   
        InputStream input = null;
        byte[] data = null;
        String result = "OK";
   
        try
        {
            input = conn.openInputStream();
     
            // Probably want to throw an exception if length is not greater then 0
            int length = input.read();
            data= new byte[length];
            length = 0;

            // Assemble data
            while (length != data.length)
            {
                int ch = input.read(data, length, data.length - length);
                if (ch == -1)
                {
                    throw new IOException("Can't read data");
                }
                length += ch;
            }
        }
        catch (IOException e)
        {
            result = e.toString();
        }
        finally
        {
            // close input stream      
            if (input != null)
            {
                try
                {
                    input.close();
                }
                catch (IOException e)
                {
                    result = e.toString();
                }
            }
        }
        if( result == "OK" ) result = data.toString();
        return new String( result );
    }  

I call it like:

        try
        {
            StreamConnection con = (StreamConnection) Connector.open(printerUrl);
            String cardData = readData( con );
            con .close();
        }

Right now, the function ALWAYS returns "Can't read data"

Any guidance on how I can get this thing working will be most appreciated!

Any suggestions at all, also very welcome :)

Regards,  Mike.
Avatar of Mayank S
Mayank S
Flag of India image

BTW:

>> if( result == "OK" )

Should be if ( result.equals ( "OK" ) )
>> int length = input.read();

Check the value of length there:

if ( length < 0 )
  throw new IOException ( "Can't read data" ) ;
Avatar of meverest

ASKER

Hi mayankeagle,

(thanks for the fast reply!)

I put:

if ( length < 0 )
  throw new IOException ( "length < 0" ) ;

but that seems to be never true.  Odd thing now is that sometimes i still get "Can't read data" returned as before, but ometimes, too, I get some data returned (but it is string representation of the bytes read, and not the ascii text that I expect to find)

I must be missing something serious....

Cheers.
 
>> but it is string representation of the bytes read

Try result = new String ( data ) ; instead of data.toString () ;
>> return new String( result );

Not needed, make it return result ;
Thanks mayankeagle!

Seems like I'm making some progress, and adding a few debug lines, I seem to be getting some indication that there is some problem with this:

            StreamConnection con = (StreamConnection) Connector.open(printerUrl);

Seems like maybe it doesn't close down properly sometimes - if I repeat the read process over and over, sometimes I get to the readData routine, other times it throws an exception at connector.open...

Unless you have some tips for me, I'll play with it a bit more and see what comes out.

Cheers.
Do you call this from multiple threads? If so, try to synchronize it, also close the connection in a finally block:

synchronized ( this )
{
  StreamConnection con = null ;
  try
  {
    con = ( StreamConnection ) Connector.open ( printerUrl ) ;
    String cardData = readData ( con ) ;
  }
  finally
  {
    if ( con != null )
          con .close () ; // end if
  }
}

I'm not a J2ME expert, so I can't give you more tips on this, but hope this would help. Otherwise wait for more experts to comment.
Thanks very much for your help so far, mayankeagle.

I am at least able to get data that I need out of the serial port, but it is still strangely unreliable.  Sometimes I get all the data, sometimes exceptions on connector.open(), sometimes I get that "Cant read data" exception - I made it into:

            while (length != data.length)
            {
                int ch = input.read(data, length, data.length - length);
                if (ch == -1)
                {
                    throw new IOException("Can't read data:" + length + "");
                }
                length += ch;
            }

and discover that length is invariably zero.

Haven't tried out that synchronisation concept yet.  It is not called from different places, but it is possible that the device has data stacked up in the output buffer before connecting - not sure what implication that might have though...

Regards,  Mike.
>> Haven't tried out that synchronisation concept yet.

Maybe try it once.

>> sometimes I get that "Cant read data" exception

Why not ignore that exception and instead just break out of the loop, to see what data is read:

if ( ch == -1 )
  break ; // end if

Then check what is there in result.
I'm getting highly variable results.

Sometimes 'length' comes back as zero, and thus no data is read.

Is there some way I can format the inputstream to flush anything that is there or keep a hold of it until i get data through - at the same time I need to make sure that there is some time-out capability so that I don't end up in a deadlock...

Cheers.
ASKER CERTIFIED SOLUTION
Avatar of Mayank S
Mayank S
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hello mayankeagle,

I think that I have almost got it.

It turns out that the client platform is too quick for the server, and only ever gets the first part of the whole data on first try.

Therefore, I have to make several shots at it to be sure to get it all:

                try
                {
                    input = swiperConn.openInputStream();
                     ByteArrayOutputStream buff = new ByteArrayOutputStream( );

                    // Probably want to throw an exception if length is not greater then 0
                    buff.write( input.read() );

                    while ( true )
                    {
                        cycle++;
                        int count = input.available();
                        if( count < 0 ) break;

                        for ( int i = 0; i < count; i++ )
                            buff.write( input.read() );

                        swipeData = buff.toString().trim();
                        parseData( swipeData );
                        if( swipeData.length() == length ) break;
                        length = swipeData.length();
                        if( cycle > 6 ) break;
                    }
                }
 
still not quite done, but at least I am getting more reliable results now.

I'll leave this open for just a bit longer, then I'll close it off and award the points - thanks!

Mike.

Try it in a do-while loop. First read, then check available () and re-loop.
Thanks for hanging in there with me.

Much appreciated! :)

Not sure what the advantage of do while instead of while(true) - i did it that way so that I can break it with more than one condition.

cheers!
do while will read first and then check the condition - so you make sure you wait for input to come to the input-stream instead of directly looping out.