I'm experiencing a strange behavior of bluetooth socket (in my opinion), and I would like know if anybody can clarify it to me.
The situation:
I have two Android applications connected together by a Bluetooth socket:
The first makes a simple write(byte[] message) on the output stream.
The second makes a simple read(byte[] buffer) on the input stream.
On the reader side I use a buffer of 1024 bytes. The sender send a message a little bit larger than the receiver buffer size: 1024 + 108 bytes (always the same message).
Ok now the behavior:
On the reader app I receive the most often a first chunk of 1024 bytes which fills up the buffer (as expected) and then a second one of 108 bytes.
But really often (maybe 40% of the time) I receive a first chunk of 1008 bytes and then a second one of 124 bytes.
I really would like to understand this because I'm affraid to miss an important bluetooth concept. At first I was thinking to compare the count of byte read with the buffer size to know if the entire message had been received but this experimentation shows that it's maybe not a good idea.
Is anybody can explain to me this behavior?
Thanks in advance.
For the record, I now use Google Guava methods for read/write on streams and all works fine.
I'm finding the same thing- it seems to be because Bluetooth sends data over as a stream instead of packets.
So if I send 4 500 byte packets, it might end up sending a 1600 byte one and a 400 byte one, or the way I sent it. Over stack overflow questions say to use some random value in the byte array to tell when a message is finished (How to read all bytes together via Bluetooth?).
There should be a better way, but I plan to use a very unlikely character set to try to find the end of the message- and pad it onto the end of each of my messages going out. Some of the other stack overflow questions suggest using '\n', but I might end up using several to make it more unlikely, such as: "\t~\t"- something that should never be typed in my game (or hopefully not extracted from the enormous amount of other stuff going on).
Hope that helps!
Related
I'm using Delphi XE7 for developing mobile application. And I'm using TIdtcpClient component to interact with the Server application. And I need to know for Android mobile & iOs mobile app, what is maximum size of data which I can send at a time to server. Or it depends on the speed of the internet. Please help me in this
TCP sockets are data streams, the length of the transmitted data is unlimited. For data with fixed length, client and server have to know when the stream ends, either by sending length information first before sending the actual data, or by using a end-of-data symbol / terminator sequence. You can also send an 'endless' stream, for example live audio / video data, which continues until one side disconnects.
There is no theoretical size limit to data that you can sent. Limitations are because of system resources/processing power, bandwidth availability and of course time that it takes to send.
System resources in the case of mobile devices will be memory, cpu power and data availability (cost per data) as it will most probably be for other platforms as well. Another resource that influences performance is the developer; the worst he writes the app the worst it will perform.
Bandwidth availability will determine how fast that chunk of data can be sent which directly influences the time it takes. Who wants to wait forever, right?
One more thing that is important, is the recipient. How patient the recipient is and how much resources he has also influences how much data you can send him.
So if you have plenty of time and resources then you will be able to send large amounts of data.
The Indy suite which TidTCPClient is part of, uses TidBytes as a memory data container into which an array of bytes is stored (the bytes that make up your data). Those TidBytes arrays are used to hold the data that you send or the data that you receive. They are handed to TidTCPClient when sending or receiving. The size of TidBytes arrays are once again limited by resources of the sender/receiver. If that causes an issue then you can break the data into smaller chunks then send them one-after-the-other. As long as you indicate to the recipient how big each chunk is, as mentioned by mjm and in the case of segmented sends you must also indicate which segment goes where in the complete data stream. A way of indicating to the recipient is to prefix the size of the data as either a byte, word or integer to the start of the entire package that you will send and as long as the server knows to either read the first byte, word or integer he will know how much data will follow that indicator and thus know how much data to expect as actual usable data.
Seeing that you might not know how much resources the recipient has it is wise to always break large amounts of data up into smaller chunks. This unfortunately is something that you will have to test to figure out how large. Also keep in mind the technology that will be used to send it across. For example Ethernet has certain packet sizes and if data is broken up into too small sizes it might cause too much overhead. The trick is to try and find the balance. Do not worry about that too much but do read up on it.
I am working on a group project where we are sending serial data over Bluetooth from Arduino to Android. We are all fairly new at both Arduino and Android.
Hardware used include Arduino Uno R3 and HC-05 bluetooth module.
I am sending dummy data for a 3 axis accelerometer packet and successfully read the packet data from Android.
However, we have this blob of data (about 50+ bytes usually and has ranged up to 512 bytes) that always gets sent to the app in the beginning. Its a randomly sized chunk of bytes, which we can't interpret because it doesn't seem to match the packet format we set up for our data. We managed to avoid looking at this byte chunk by checking to see if the packet size is small enough. But this adds a lot of overhead (4 - 5 seconds), so we'd like to figure out what this blob of data is. So, does the HC-05 send some proprietary Bluetooth related data first or is there some thing wrong with my script that's causing the unexpected data to be sent?
This is the Arduino code.
#include <SoftwareSerial.h>
SoftwareSerial bluetooth(10,11);
void setup(){
bluetooth.begin(9600);
}
void loop() {
int x = random(360);
int y = random(360);
int z = random(360);
formAccelerometerPacket(x, y, z);
delay(5000); // wait 5 sec
}
void formAccelerometerPacket(int xVal, int yVal, int zVal) {
printSensorVal('A', xVal);
printSensorVal(':', yVal);
printSensorVal(':', zVal);
}
void printSensorVal(char flag, int sensorVal) {
bluetooth.print(flag);
bluetooth.print(sensorVal);
}
I've looked at it with a Bluetooth terminal app but nothing looks wrong from there. Its LogCat from the app that shows this content received from the app, but I can't interpret it as I said earlier, which is what I need to solve.
I've tried to look at other SO questions but none others could help me.
I don't have the code for the Android app as it is with another teammate, but I know that they followed the BluetoothChat example closely.
The only thought I had was that since Arduino loops the data, if the app starts after the Arduino starts, it might start reading some data part way from what was going on in the serial port before. But it doesn't explain the size difference in the blob of bytes.
Edit on 08/21/2014 at 10:33AM PST
Here is a screenshot of the LogCat. What we did was ran the Android app first and then I started the Arduino to make sure the board didn't have old data. Looking at this makes me think it might be a pairing issue as some one suggested. I am working on trying that fix.
Try Bluetooth SPP on Google Play, then connect to the HC-05. Check the output and then once you get clean data reset the arduino and see what happens. That's how I usually go about checking the output from my HC-05. And no there is nothing sent by the HC-05 when it starts up. I couldn't comment so had to post an answer, sorry.
I am not sure that is your case but may be it's usefull. When you send a data from HC-05(FC-114) to a Slave(HC-06) the first byte(or the first three/four) is sent immediatly and the rest with a delay of 5/10ms. I don't know why, but i see it using oscilloscope. If well managed, you can fix the problem when receive the packet of byte waiting for a while, otherwise, you can get crazy for understand what is happening.
I'm working on an Android Bluetooth project to send and receive data from a custom made hardware. I used Bluetooth Chat Sample in SDK as basis.
I am sending data from one device to another (LG Nexus 4). All is ok until I reach a length of 1004 bytes (it is the audio data). At that point it splits it into 2 messages of 990 and 14 bytes in most of cases. but is strange sometimes its sending 1004 without splitting (approx. 4 times in 100).
I am sending this packet of 1004 bytes, in which there is 4 bytes is my header and rest of 1000 bytes is actual data which I want to use as per command in header, now if packets are splitting as per above mentioned way than I cannot handle the flow.
So, please let me know why packets are splitting in such way and how can I stop this splitting or, if I cannot do this, than please suggest me any alternative way to do this.
Thanks.
Data sent via Bluetooth socket is abstracted as a stream. Here the transport layer is broken into packets, where packet has a maximum size of almost 1KB(1000 bytes). So you can devise a mechanism in which you can send the message length info in the header, then on receiving side you will have to make subsequent read() calls; each returning data for one packet.
I need some help finding the documentation of .read(). I know this is easy, but I can't find it. I've search and searched, and this page on the android side is the closest I could find - http://developer.android.com/guide/topics/usb/accessory.html.
Here is the arduino code splice I am trying to interpret. I need to know how to modify the read() part for my needs. Thanks
AndroidAccessory acc("Manufacturer",
"Model",
"Description",
"1.0",
"hey.now.what",
"0000000012345678");
acc.read(msgIn, sizeof(msgIn), 1)
I was looking the same thing as you did. After googling around and trying it by myself, I managed to build up something like this:
Declaration:
int AndroidAccessory::read(void *buff, int len, unsigned int nakLimit);
Reads data from the Android device into the array pointed to by buff. It reads len number of bytes. Reading is stopped when len bytes is read or nakLimit number of NAKs is received from the USB controller. In case of Full Speed USB a NAK will be generated every 1ms. (according to the second source link).
The return value is the number of bytes available, not the number of bytes read. If you read less bytes than there are available, those extra bytes seem to be ignored.
In my experiments I found out that NAK interval is much smaller. With my Arduino Mega ADK, I found out that one second wait equals roughly nakLimit of 14000.
Sources:
http://developer.android.com/guide/topics/usb/adk.html (end of the page)
What is Nak Limit?
To read data from an opened USB connection one uses UsbDeviceConnection bulkTransfer method.
I have the situation that after sending a request the routine should read all incoming data, which can be just 8 bytes or even 300+ bytes.
The problem is that bulkTransfer does not read all the bytes for some reason - it just returns with some bytes while there could be more to come.
Is it better to write a loop around bulkTransfer until there is no more data, or increase the timeout, or possibly there is another approach.
What would be the best way to handle this?
I tried the loop approach and I am surprised that it only reads about 10-20 bytes each time with a timeout of even 1second. I am sure there is more data already available, don't know why it does not read more at a time.
Does it matter which buffersize one uses - many examples have 4096 but how does changing this influence the reading of data?
Many thanks
If the device sends 10 bytes at a time and does so repeatedly to finish the 300+ bytes, you still only get these 10-byte chunks each time you read with bulk transfer.
In other words, the method does not wait to fill up your buffer. It returns as soon as there is something. So if you really want to collect the entire 300+ byte response, you do need to loop.