Is there a way to communicate reliably via Bluetooth? - android

I have to exchange data between two bluetooth devices, one of them will be an Android device. For simplicity's sake you can assume the other device will be a generic linux device running bluez producing data similar to the data a fitness tracker would produce.
The scenario seems a straightforward use case for Bluetooth Low Energy. The problem i am currently running into comes from the fact that communication has to be reliable (reliable in the way TCP is reliable). This means:
no losses
no corruption of data
order needs to be preserved
no duplicates
no phantom packets
While losses are prevented at link layer level, the order for instance seems not to be explicitly preserved when working with Low Energy (using indications would probably achieve this).
Not having done a lot of work with Bluetooth I am currently overwhelmed quite a bit with the amount of options while at the same time no option seems to fit the bill nicely.
Is there a "best-practice" for setting up reliable communication between two bluetooth devices? A Bluetooth Low Energy solution would be preferable, but is not mandatory.

Once your Bluetooth connection is setup its reliable. So you don't have to be worried about data loss or corruption.
So the things you're worried about can be easily handled in your side. You'll get proper connection and disconnection callback while setting up a BroadcastReceiver for your BluetoothAdapter.
In case of any disconnection you may have to restart the procedure for connection again and once its established properly you may resend the data.
I don't know about your purpose yet, but one thing I need to mention here is, I would not recommend Bluetooth communication if you're holding the connection for long time. Some devices disconnects the connection automatically after some time if there's no continuos transmission.

Android has Bluetooth support, but it only allow to send ot receive data from stream. There is a very good sample project from Google: https://github.com/googlesamples/android-BluetoothChat . The only drawback of this sample is that it use Handler to nitify about Bluetooth events. I changed it a bit so it use another Thread and from it calls methods of interface you set, take a look at project: https://github.com/AlexShutov/LEDLights . This is ordinary Bluetooth, not BLE, hope it will help

Android's BLE stack is as good as the link layer specification. So you can use "write without response" in one direction and notifications for the other direction. Just make sure your peripheral side does not drop incoming writes.

BLE uses 24-bit CRC. for the amount of data transmitted using BLE the CRC is quite robust and the possibility of corruption is very low ( note that TCP CRC is 16bit and the Ethernet CRC is 32bit, please see http://www.evanjones.ca/tcp-and-ethernet-checksums-fail.html).
The ordering issues in wired network is a result of routing packets through different routes to the same destination ( plese see If TCP is connection oriented why do packets follow different paths?) . This is partially due to the use of sliding window acknowledgement protocol, which allows a number of packets to be transmitted before being acknowledged.In BLE there is no routing and the acknowledgement scheme is a variation of stop and wait ARQ scheme(2-bit lazy acknowledgement), this means that it is not possible to send a new packet without being acknowledged. These two factors makes the possibility of having an out of order transmission highly unlikely.

Related

How can I speed up Nearby Connections API discovery?

I am attempting to connect two Android devices close-range without a 3rd party service to transfer two small json payloads back and forth before closing the connection. Think adding nearby contacts.
I am using the P2P_POINT_TO_POINT Strategy and have both devices advertising and discovering using the code found here: https://developers.google.com/nearby/connections/android/get-started. It consistently works, however it repeatedly takes 10-15 seconds to find the connection and prompt to accept the connection.
Ideally I could get this below 10 seconds.
I read that having one dedicated to advertising another dedicated to discovering helps but it does not work for my use case.
Is there a way to improve the connection rate?
Unfortunately, the best you can do is to try to connect in one direction. That should lower the connection latency to 2~7 seconds. When both devices connect to each other at the same time, that causes thrashing and while we do our best to handle it gracefully, it will cause increased latency.
Stopping discovery before calling request connection would help too, but not by much. We already do it internally during the most sensitive operations.
Our advertising and discovery stack is based off of Bluetooth, and we've experimented with other technologies to compliment it. But they typically have harsher limitations than Bluetooth does (needs a router, needs a very recent Android phone, can't handle simultaneous connections, can't advertise and discover at the same time). Of all the technologies I know of, only mDNS would be faster while still allowing bi-directional connection attempts, and that requires both phones to be connected to the same router (and that the router hasn't disabled mDNS). Typically this means it only works at home. If that's a reasonable limitation for you, then I can pass that on to the team.

BLE: Why are Write Commands slower than Notifications?

In the context of BLE (Bluetooth Low Energy), Write Commands can be used to write from a Client to the Server, and Notifications to write from the Server to the Client. In my setup, the Client is a Central device (Android phone), and the Server is a Peripheral (dev board).
After performing several data throughput tests with multiple phones, I noticed that the throughput varies greatly with the phone, which is expected because a great deal of the BLE lower layers implementation is up to the manufacturer to figure out. But what caught my attention was that Write Command always achieve a much lower throughput that Notifications, independently from the phone. Why is that?
They should have the same throughput. Multiple write commands and notifications can be sent during one connection event. They are treated the same.
You could use an air sniffer to see if you find any problems.
How long the connection event should be open can be suggested when the connection is created and with connection parameter updates. Sadly, Android's BLE stack hard codes this to the default value, which means no recommendation. That will in practice mean you are limited to 3 or 4 packets per connection event.

Ping in Android to detect device failing/departure

I've read this tutorial about data transfer in a battery efficient way.
All the lessons are based on one, simple concept: polling the server is Android is battery inefficient. For this reason, Google Cloud Messaging is introduced in order to send messages from the server to the device only when needed.
There is only one problem: I'm trying to implement a "mobile cloud", so a cloud composed by mobile devices, where each device can join/leave the network with high frequency. So I need some mechanism to detect when a device is not reachable anymore. Until now, in all the works that I've seen on the topic, the only solution was to periodically ping the main server to say "Hey, I'm still alive!" from the mobile device. Obviously this solution is battery killing, but until now I've not seen/found any better solution.
Do you know any battery efficient solution for this problem?
There's no reason why pinging the server periodically (heartbeat) is necessarily wasteful of the battery/inefficient. That depends upon how frequently you need to ping, and whether your ping needs to initiate its own transmission vs piggy backing on some other transmission.
Let me explain. Battery inefficiency depends upon whether or not you are increasing the frequency or duration of the transceiver being in an active state. If the transceiver is continually active anyway, such as it is continuously exchanging data or audio, then a heartbeat adds no additional burden. If it is not active, then there will be additional energy usage but that depends upon the frequency of your heartbeat compared to how long a ping will cause the transceiver to be powered. Even then, it's probably irrelevant to your application as I suspect "cloud" means the devices are active and connected.
Let's assume that your heartbeat is such that it will increase the duration of your transceiver being active. There are still techniques you can use to decrease this impact, such as caching your beat and sending it only when it can piggy back on another transmission. Of course, such solutions depend upon whether your heartbeat is implemented in an application, OS or kernel.
I suggest you do actual tests to see if there is truly an impact on your devices.
PS I'm not saying the tutorial is wrong. It isn't. But it is addressing a broader and more general problem then what you have.

Bluetooth Android RFCOMM / SPP error handling suggestions

I am planning a communication protocol to be used between an Android device and a custom sensor that would use a commercial Bluetooth module. I would use the SPP profile that is said to "provide a simple reliable data stream to the user, similar to TCP."
I am not so familiar with the Bluetooth technology and have some questions about designing such a protocol.
First of all it is not clear to me if I have to worry corrupted data being transferred or not. Will the underlying protocoll stack guarantee me that the bytes I read from the InputStream Android gives are the same that the UART receives on the sensor side? Do I have to define my own data packages protected with CRC or stuff or would it be overkill?
It is not clear to me from the Android Bluetooth documentation what happens in my application if the signal is weak and is lost for a while. Do I get IOException at once or the platform provides me some hidden error handling and recovery that would make such short outages invisible to me?
Thanks for any advice.
You need not worry about data corruption over SPP , Bluetooth provides 2 levels of CRC , one at the baseband and then one at the L2CAP level,
Both have retransmission mechanism for any detected corruptions - thus applications will receive only good packets.
About the second question - Yes on the Socket streams that you are connected on you will receive IOExceptions if the underlying Bluetooth connections get disconnected, Android cannot handle automatic restore - typically applications need to detect the reason for disconnection and try re-connect as applicable.
So if you want to continue your data exchange from the point you last successfully received / sent then for it your application should maintain some sort of sequence number and light protocol to achieve a resume.
The other option is to simply start from the beaning of data exchange upon a re-connect (So it depends on your usecase)

Android Bluetooth Chat sample app - multiple connections

Is it possible to set up the Android Bluetooth Chat sample app to connect more than one person at a time, and have a mini chat room? What would that entail?
tl;dr version: Bluetooth sucks for this, don't use it, use wifi instead, probably backed by a web backend.
I have investigated this issue thoroughly throughout the years in the interests of a social wireless network research project. My general advice is: it doesn't work with more than two / three people. Bluetooth just isn't designed with wireless peer to peer networks in mind.
In general, it seems that the cheap Bluetooth controllers included on Android devices (especially HTC's devices, iirc) don't really handle any more than two or three connections at a time. I'm unsure if this is a hardware or firmware problem, but I can recount some basic anecdotes. I was working to implement this idea at the SDK level (i.e., without firmware modifications) around the beginning of 2011, and was able to get a peer to get two additional connections (i.e., three devices, each connecting to the other two) to work for a period of a few minutes to an hour before the connections would suddenly die and the socket would become unusable, requiring reconnection. Unfortunately, 20 minutes was an upper bound, and generally it was impossible to get connections to more than one other device at all reliably.
The goal of the project was to support multiple people interacting with each other silently in the background, but this never materialized, instead we ditched Bluetooth and went with wifi instead, which worked much much better. In the abstract, I think people view Bluetooth as a possible medium for reliable peer to peer communication, but it wasn't really designed that way: it's more of a medium used for short range communication between small devices (think headsets).
Be aware that if you want to do this, the maximum number of devices to which you can connect is fixed, because as per the Bluetooth spec, a piconet supports a maximum of seven devices. (See the wikipedia article.)
The required change is simple: you use a different UUID for each device. This can be implemented a number of ways, using an out of band exchange mechanism, or simple scheme where you assign UUIDs in an increasing fashion and when connecting to the network, try each in succession.
Here are some relevant Google groups threads:
Bluetooth peer to peer networks
Multiple connections on Android Bluetooth
I remember posting a more elaborate one detailing how to do this (with code) that I might dig up as well.., if I can find it. It should be from late 2010 or early 2011.
So the answer is, in the abstract, yes, you can try to do this, by using multiple UUIDs (after you use one, that's it, and you have to try another using some assignment protocol). However, in practice, after a lot of trial and error, this doesn't really work for what you probably want to use it for, and it's a lot better to go with an internet backend instead. By the way, this is also good for another reason, most users don't really like to turn on their Bluetooth for fear of their battery being drained..
Leaving this here, in case it helps someone else.
I was able to make my custom chat room following official bluetooth tutorial and modifying it a little.
Unfortunately, I cannot provide most of my code, but main idea is:
Every device is acts both as server and as a client. When Chat is started, device starts its server thread. Server thread is the same as official but doesn't ends when accept connection. It just keep listening.
Client thread is identical as in tutorial.
Both server and client thread manages connection same. I created separated threads for accepting messages following this tutorial and one for sending them.
private void manageConnectedSocket(BluetoothSocket socket) {
//create thread responsible for sending messages.
SendingThread w = new SendingThread(socket);
MainActivity.addSendingThread(w);
//Creates listener for messages to accept.
MainActivity.addListener(socket);
}
Now in main activity always when user click send button, for each worker (sending thread) send message to remote device. Listening is running asynchronously.
IMPORTANT:
You need to handle exceptions when message send fails and remove sending and recieving thread for device when you detect it is disconected. In my case I used well known UUID "00001101-0000-1000-8000-00805f9b34fb". For every device.
You need to wait 3 second between atempts to connect as client because some devices has weak bluetooth hardware and it is refusing connect as client.
Bt connection is supporting up to 7 -10 connections. So you will be limited in that range. I think it is designed for extensions of main device and not for random comunication
Source: search "bluetooth programming" on google

Categories

Resources