Android Bluetooth: Slow data rates calculated from BluetoothSocket - android

Using: HTC Legend and HTC Salsa
I'm calculating the speed using:
while(true)
{
try
{
int num = in.read(buffer);
if(reading == false)
{
prevTime = SystemClock.uptimeMillis();
reading = true;
}
else
{
//Calculate KB/s
count += num;
Long deltaTime = SystemClock.uptimeMillis()- prevTime;
if(deltaTime >= 1000)
{
Float speed = (float)count/deltaTime;
Log.d(TAG,"Data: " + speed + "KB/s");
count = 0;
prevTime = SystemClock.uptimeMillis();
}
}
} catch (IOException e) {
}
}
And writing some test data using
out.writeUTF("ababababababababababababababababbabababaababababababababababababababababbabababaababababababababababababababababbabababa" +
"ababababababababababababababababbabababaababababababababababababababababbabababaababababababababababababababababbabababa" +
"ababababababababababababababababbabababaababababababababababababababababbabababaababababababababababababababababbabababa" +
"ababababababababababababababababbabababaababababababababababababababababbabababaababababababababababababababababbabababa");
out.flush();
The writes are within another threads while(true) also.
I'm getting the following results.
02-13 18:17:16.897: D/krazyTag(3432): Data: 31.554672KB/s
02-13 18:17:17.927: D/krazyTag(3432): Data: 29.854227KB/s
02-13 18:17:18.977: D/krazyTag(3432): Data: 29.285034KB/s
02-13 18:17:20.067: D/krazyTag(3432): Data: 38.446888KB/s
02-13 18:17:21.097: D/krazyTag(3432): Data: 35.89484KB/s
02-13 18:17:22.127: D/krazyTag(3432): Data: 33.67118KB/s
02-13 18:17:23.227: D/krazyTag(3432): Data: 33.512726KB/s
02-13 18:17:24.307: D/krazyTag(3432): Data: 33.277622KB/s
Which is confusing me since the phones specs state they use Bluetooth® 2.1 with EDR
Which is capable of 260KB/S but I'm not even getting the old standard 90KB/s
I'm not sure if it's my stream and read/write calls (I'm using a buffered datainputstream)
Or if I'm calculating things wrong or have the wrong information?

I think the speed depends on your implementation of the Send and Receive threads, since you connects 2 Android devices with your own applications. Could you post your implementation?
I got the same problem also.
I am using ACER TAB A500 to communicate with a Bluetooth stick connected to PC and I got even slower result 12,3KB/s for sending data only.
That's why I did some experiments. I sent a message for 10000times and I got that the data rate depends on the length of the message.
For 1KB message, the data rate is 232KB/s. For 40Byte message, the
data rate is 18KB/s. For 1Byte message, the data rate is
0.48KB/s.
Here is my code:
// Get the BluetoothDevice object.
while(true){
driverBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
driverBluetoothDevice = driverBluetoothAdapter.getRemoteDevice("XX:XX:XX:XX:XX:XX");
if (driverBluetoothDevice == null){
break;
}
Method insecureMethod = driverBluetoothDevice.getClass().getMethod("createInsecureRfcommSocket", new Class[] { int.class });
byte portNumber = 5; // The SPP in port 5.
driverBluetoothSocket = (BluetoothSocket) insecureMethod.invoke(driverBluetoothDevice, portNumber);
// Try to connect to the Bluetooth device.
try {
driverBluetoothSocket.connect();
} catch (IOException e1) {
// Failed to connect to the device
break;
}
// Open input and output stream.
try {
driverInputStream = driverBluetoothSocket.getInputStream();
} catch (IOException e) {
break;
}
try {
driverOutputStream = driverBluetoothSocket.getOutputStream();
} catch (IOException e) {
break;
}
byte[] message = new byte[3000];
Random randomGenerator = new Random();
for (int i = 0; i < message.length; i++){
message[i] = (byte) randomGenerator.nextInt(100);
}
Date TimeValue = new Date();
long TimeStamp1 = TimeValue.getTime();
for (int i = 0; i < 10000; i++){
try {
driverOutputStream.write(message, 0, message.length);
} catch (IOException e) {
break;
}
}
TimeValue = new Date();
long TimeStamp2 = TimeValue.getTime();
long TimeDifference = TimeStamp2 - TimeStamp1;
TimeDifference = 0;
break;
}

Not sure if this helps with your speed problem and I could have overlooked this detail in your code snippet but are you reading and writing on the same thread? The documentation suggests you don't,
First and foremost, you should use a dedicated thread for all stream reading and writing. This is important because both read(byte[]) and write(byte[]) methods are blocking calls.
Bluetooth Android Developer

Related

Android TCP connection receiving packets out of order

I have a Particle Photon microcontroller sending TCP packets over a hotspot WiFi network to an Android Phone. The microcontroller is acting as server, the phone as client.
The phone however is receiving some (but not all) of the packets out of order, despite the information being transmitted via tcp. It was my understanding that this would not happen - am i wrong, or is there something i can do to correct this?
Microcontroller Code:
// This #include statement was automatically added by the Particle IDE.
#include "databuffer5.h"
// This #include statement was automatically added by the Particle IDE.
#include "databuffer7.h"
const unsigned int localPort = 10000;
IPAddress remoteIP(a, b, c, d);
// An TCP instance to let us send and receive packets over wifi
TCPServer server = TCPServer(localPort);
TCPClient client;
// UDP Port used for two way communication
short msg_count = 0;
const int adcPin = A0;
int byteBuffer;
unsigned long loopTimer;
const int packetSize = 40; //number of bytes in packet - 10 ints with 4 bytes each
byte buffer[packetSize];
int j = 0;
int dataCount = 0; //dummy data that increments every loop point, to measure packet contiuity
//(creates a line with slope 1 as data)
void setup() {
// start the UDP
server.begin();
// Print your device IP Address via serial
Serial.begin(9600);
Serial.println(WiFi.localIP());
//Serial.println(System.ticksPerMicrosecond()); //returns 120, ie 120MHz
}
void loop()
{
if (client.connected())
{
loopTimer = millis(); //mark start time of loop
for (int i = 0; i < 10; i++)
{
//for testing connection
byteBuffer = i+j*10;
buffer[i*4] = ( (byteBuffer >> 24) & 0xFF); //take upper 8 bits
buffer[i*4+1] = ( (byteBuffer >> 16) & 0xFF); //take middle upper 8 bits
buffer[i*4+2] = ( (byteBuffer >> 8 ) & 0xFF); //take middle lower 8 bits
buffer[i*4+3] = ( byteBuffer & 0xFF); //take lower 8 bits
dataCount++;
if (i != 9)
{
while(millis() < (loopTimer+10*(i+1))); //ie do nothing for 10 ms (time is in ms, want to delay by exactly 10ms for each loop)
//goal here is to sample every 10ms, by delaying for the remaining time
//dont delay here for the last sample, as the udp packet will take time
//delay after instead
}
}
server.write(buffer, sizeof(buffer)); //using sizeof on a byte array so dont need to scale (ie scaling factor is 1)
j++;
if (j < 0){j = 0;}
while(millis() < (loopTimer+10*10)); //delay till 100ms after loops started
}
else
{
client = server.available();
}
}
Android (client) code:
async_udp = new AsyncTask<Void, int[], Void>() {
#Override
protected Void doInBackground(Void... params) {
byte b1[];
b1 = new byte[100];
while (serverActive) {
Socket socket = null; //previously this was DatagramSocket (UDP) - no Socket (TCP)
try {
//DatagramSocket s = new DatagramSocket(server_port, server_ip);
socket = new Socket(server_ip, server_port);
socket.setPerformancePreferences(1, 2, 2);
InputStream socketStream = socket.getInputStream();
DatagramPacket p1 = new DatagramPacket(b1, b1.length);
ByteBuffer wrapped;
int data[] = new int[10+1]; //first number for message data, second is for the message number
while (serverActive) //TODO include shutdown function
{
while (socketStream.available() < 39){}
socketStream.read(b1, 0, 40);
//packet structure is a char containing message number, and 10 shorts (2 bytes) containing data points (between 0 and 4096)
wrapped = ByteBuffer.wrap(Arrays.copyOfRange(b1, 0, 40)); // extract 40 bytes to convert to 10 ints
for (int i = 0; i < 10; i++) {
data[i] = wrapped.getInt();
}
String str = data.toString();
server_port = p1.getPort();
server_ip = p1.getAddress();
String str_msg = "RECEIVED FROM CLIENT IP =" + server_ip + " port=" + server_port + " message no = " + b1[0] +
" data=" + str; //first character is message number
statusText = str_msg;
publishProgress(data);
}
socketStream.close();
socket.close();
} catch (SocketException e) {
if (socket != null) {}
//status.append("Error creating socket");
statusText = (" Error creating socket"); //this doesn't work!
} catch (IOException e) {
//status.append("Error recieving packet");
statusText = (" Error receiving packet"); //this doesn't work!
}
try{
Thread.sleep(100, 0); //sleep for 10ms if no wifi lock is found, to stop battery being silly
} catch(Exception e){
e.printStackTrace();
}
}
return null;
}
protected void onProgressUpdate(int[]... data1)
{
super.onProgressUpdate(data1);
int data[] = data1[0];
//send data to graph
for (int i = 0; i < 9; i++)
{
series.appendData(new DataPoint(lastDataX++, data[i]), false, graphPointsMax);
//append 9 points to graph, but only redraw the grpah on the 10th
}
series.appendData(new DataPoint(lastDataX++, data[9]), true, graphPointsMax);
}
};
if (Build.VERSION.SDK_INT >= 11)
{
async_udp.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
else
{
async_udp.execute();
}
What is guaranteed by TCP, is that when you send a message - it will come in the right order, even if split by the TCP stack along the way (see TCP Segment Number, which serves as an indication which split message part belongs together with which, and in what order). So, in your case, all you are sending using:
server.write(buffer, sizeof(buffer));
no meter how big is the buffer (within the limits of TCP protocol, of course) is guaranteed to arrive in the right order and complete.
Sending several buffers one-by-one over TCP will provide you guaranteed delivery, or error notification (if any), but not the order of the messages sent. Down to the protocol level, these packets will contain different Sequence Numbers, and therefore will be treated by the TCP stack of the receiver separately, in the order the stack prefers.
I see two relatively simple things that could be done here:
try to put all you can in one buffer (not really practical approach, though)
Introduce the counter and increment each time you are sending the buffer out. Put the counter along with the buffer and check the precedence on the receiving side (phone, in your case).

Sending continuous data from arduino to Android App using HC-05

I've been struggling with the problem of sending continuous data from arduino to Android.
What I want to do is get analog read convert it to 0-5V information, and send that information to Android app.
My arduino code is just simply:
//(...)defining pins and levels
SoftwareSerial BTSerial(rxPin, txPin);
void setup()
{
pinMode(getData, INPUT);
digitalWrite(keyPin, LOW);
BTSerial.begin(9600);
}
void loop()
{
contact = digitalRead(getData);
if (contact == HIGH) {
sensorValue = analogRead(sensorPin);
double voltage = sensorValue * (5.0 / 1023.0);
if (BTSerial.available()) {
Serial.write(BTSerial.read());
}
BTSerial.println(voltage, 3);
BTSerial.write("\r");
if (Serial.available()) {
BTSerial.write(Serial.read());
}
}
delay(5);
}
I need to send data informing about measurment with ~200Hz frequency.
After sending the data to application it seems that part of data is lost.
I tried higher bound rates but the problem still occurs. Is there a way to send continuous data from arduino using serial port without loosing some % of that data?
I think the problem is in the design of the receiver. I Solved BTL communication in .net Xamarin, but the principle should be the same. In Android reading from InputStream must be quick and can not use sleep. You need to use an endless cycle and there quick read data into temp buffer. Immediately a dune bytes to an auxiliary large buffer (use read / write cursor) and then, for example, in timer treat the data (I suppose you are using some packet protocol)
public override void Run()
{
WriteLogInfoToLog("ConnectedThread.Run() - before");
while (true)
{
try
{
int readBytes = 0;
lock (InternaldataReadLock)
{
readBytes = clientSocketInStream.Read(InternaldataRead, 0, InternaldataRead.Length);
Array.Copy(InternaldataRead, TempdataRead, readBytes);
}
if (readBytes > 0)
{
lock (dataReadLock)
{
dataRead = new byte[readBytes];
for (int i = 0; i < readBytes; i++)
{
dataRead[i] = TempdataRead[i];
}
}
}
}
catch (System.Exception e)
{
btlManager.btlState = BTLService.BTLState.Nothing;//Spadlo spojeni, musi spustit cele od zacatku
WriteLogInfoToLog("ConnectedThread.Run() - EXCEPTION " + e.Message + ", " + e.HResult + ", " + e.StackTrace + ", " + e.InnerException);
if (e is Java.IO.IOException)
{
}
else
{
}
break;
}
}
WriteLogInfoToLog("ConnectedThread.Run() - after");
}

Different internet speed when testing by my own code

I am facing a problem in checking of internet speed. Actually I am developing an android app which can test your internet speed on your cell phone. I make an sample to test the speed and its show write speed such as 7.3 Mbps as I am getting from my ISP. But in this test I am using below code.
long startCon = System.currentTimeMillis();
Log.i("mymobilespeedtest", "start conn = " + startCon);
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(imageURL);
HttpResponse response = null;
try {
response = httpClient.execute(httpGet);
Log.i("SketchEffect","Executing http connection to download selected image.");
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
Log.i("FBAlbum", e.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
Log.i("FBAlbum", e.toString());
}
long endCon = System.currentTimeMillis();
Log.i("mymobilespeedtest", "endCon = " + endCon);
Now I want to show progress as of internet speed by using a handler and using different method download a file.'
In this method I am using below code
String downloadFileUrl = "http://www.gregbugaj.com/wp-content/uploads/2009/03/dummy.txt";
URL url1 = new URL(downloadFileUrl);
URLConnection con1 = url1.openConnection();
con1.setUseCaches(false); stream1 = con1.getInputStream();
Message msgUpdateConnection = Message.obtain(mHandler,
MSG_UPDATE_CONNECTION_TIME);
msgUpdateConnection.arg1 = (int) connectionLatency;
mHandler.sendMessage(msgUpdateConnection);
long start = System.currentTimeMillis();
int currentByte = 0;
long updateStart = System.currentTimeMillis();
long updateDelta = 0;
int bytesInThreshold = 0;
int bytesIn = 0;
while (true) {
if ((currentByte = stream1.read()) == -1) {
break;
} else {
bytesIn++;
bytesInThreshold++;
baf.append((byte) currentByte);
if (updateDelta >= UPDATE_THRESHOLD) {
int progress = (int) ((bytesIn / (double) EXPECTED_SIZE_IN_BYTES) * 100);
Message msg = Message.obtain(mHandler,
MSG_UPDATE_STATUS,
calculate(updateDelta, bytesInThreshold));
msg.arg1 = progress;
msg.arg2 = bytesIn;
mHandler.sendMessage(msg);
// Reset
updateStart = System.currentTimeMillis();
bytesInThreshold = 0;
}
updateDelta = System.currentTimeMillis() - updateStart;
}
} if (downloadTime == 0) {
downloadTime = 1;
}
Message msg = Message.obtain(mHandler, MSG_COMPLETE_STATUS,
calculate(downloadTime, bytesIn));
msg.arg1 = bytesIn;
mHandler.sendMessage(msg);
By above code I am getting only .8 or 1.o Mbps speed (In mega bit per secons not bytes)
i'm trying to do the same thing, using a HTTP GET to measure Internet Speed (download), but there is a problem. When you do this: response = httpClient.execute(httpGet); you are not measuring only the time that takes for you to receive the answer, you are measuring the time that takes to make the entire request, that means that you are measuring the overhead of the entire protocol like establishing the TCP connection between server and client.
Check this: http://tinypic.com/r/15u6og/8
The useful data that you want are the PDU's, the rest is just overhead. But you are measuring the entire thing. As you can see establishing the TCP connection takes a lot of time.
That's why you are getting a wrong value.
I know this is a little late, but have you resolved this yet?

Android communication, what is sent is not what is received

Moved from Android forums
Im at a loss here. It want to send some serial data from arduino to android but what I send is not what is received. For example, If I put Serial.write(5), on the android side I get 48. If I put Serial.write(6) I get 1. The same problem happens when I send characters. If I send a 't', on android I get a T with 2 points on top(as if its a character from another language). ??????? What's happening?
Arduino
int count = 5;
const unsigned int BAUD_RATE = 115200;
void setup() {
Serial.begin(BAUD_RATE);
delay(10000);
}
void loop() {
//Serial.print(count, DEC);
//Serial.print(count, HEX);
Serial.print(count, OCT);
//Serial.println(count, BIN);
//Serial.write(temp);
//Serial.write("t");
Serial.write(count);
count++;
delay(2000);
}
Android
RFComm: UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
byte[] buffer = new byte[255];
Handler myHandler1 = new Handler();
Runnable receiveValues = new Runnable() {
public void run() {
try {
while (connected) {
while (in.available() > 0) {
Log.v("Note",
"For value: " + String.valueOf(in.read(buffer)));
for (int x = 0; x < buffer.length; x++)
Log.v("Note", "A " + buffer[x]);
}
Thread.sleep(50);
}
} catch (Exception e) {
connected = false;
e.printStackTrace();
}
}
};
The timing is right, every two seconds something gets sent but still I get the wrong value. As you can also see, I tried other ways to write to the serial port on the arduino but none of them work. Another thing, the end of line(when I do Serial.println()) is consistently received as a 0 on android.
Running on android 2.3.7 where min sdk = 8 (android 2.2)
Answer is really simple... Forgot about int ranges(-32768 to +32767) or in this case unsigned int(0 - 65534) and when I directly entered the baud rate, it worked well.
Serial.begin(115200);

Reading from multiple Bluetooth devices in Android?

Just to make it short. I want to connect to three devices and read the data from all the three at the same time. I know how to connect to one and i can read the data from that But What i want is to connect the other two and read from them.Any suggestions , or other example i can follow.
Here is part of the code which is similar to mine but shorter . This code can connect to one device using the mac. So How to modify this to connect to three devices at the same time and display the data they are sending?
Please help i really need it cause am stuck at this part of my project. Thanks for the help.
private boolean connected = false;
private BluetoothSocket sock;
private InputStream in;
public void test() throws Exception {
if (connected) {
return;
}
BluetoothDevice zee = BluetoothAdapter.getDefaultAdapter().
getRemoteDevice("00:14:C5:A1:02:67");
Method m = zee.getClass().getMethod("createRfcommSocket",
new Class[] { int.class });
sock = (BluetoothSocket)m.invoke(zee, Integer.valueOf(1));
devicecon.setText("Connecting......");
sock.connect();
devicecon.setText("Connected");
in = sock.getInputStream();
byte[] buffer = new byte[50];
int read = 0;
Log.d("ZeeTest", "++++ Listening...");
try {
while (true) {
read = in.read(buffer);
connected = true;
StringBuilder buf = new StringBuilder();
for (int i = 0; i < read; i++) {
int b = buffer[i] & 0xff;
if (b < 0x10) {
buf.append("0");
}
buf.append(Integer.toHexString(b)).append(" ");
}
Log.d("ZeeTest", "++++ Read "+ read +" bytes: "+ buf.toString());
}
} catch (IOException e) {}
Log.d("ZeeTest", "++++ Done: test()");
All you need to do is create a new thread (I suggest using an instance of AsyncTask for this rather than an actual Thread) for each device and call the connection code snippet
BluetoothDevice zee = BluetoothAdapter.getDefaultAdapter().
getRemoteDevice("00:14:C5:A1:02:67");
Method m = zee.getClass().getMethod("createRfcommSocket",
new Class[] { int.class });
sock = (BluetoothSocket)m.invoke(zee, Integer.valueOf(1));
devicecon.setText("Connecting......");
sock.connect();
from inside that new thread.

Categories

Resources