meverest
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.
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.
>> int length = input.read();
Check the value of length there:
if ( length < 0 )
throw new IOException ( "Can't read data" ) ;
Check the value of length there:
if ( length < 0 )
throw new IOException ( "Can't read data" ) ;
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.
(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 () ;
Try result = new String ( data ) ; instead of data.toString () ;
>> return new String( result );
Not needed, make it return result ;
Not needed, make it return result ;
ASKER
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.
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.
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.
ASKER
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.
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.
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.
ASKER
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.
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
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.
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.
ASKER
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!
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.
>> if( result == "OK" )
Should be if ( result.equals ( "OK" ) )