I have looked on numerous topics on android BLE stack in various website. From what i gathered, the bluetooth stack in android is unreliable and not suitable for any fast and concurrent connection.
I am currently assigned to a project that uses BLE as their main business idea. The idea is to setup BLE devices on the top of each door to advertise to the phones using ibeacon frame (to support both iOS and Android). Whereas the android app will read the advertisement and connect to it via GATT and do a characteristic write. The biggest problem is that the project requires a fast write for each beacon it pass by (within 6s to connect and write characteristic) .
This means that scanning and writing must be done frequently for each door it pass by. I know for a fact that android 7 and above have a max of 5start/stop scan for each 30second. Therefore my logic uses a interval of 3second scan and then followed by a 3second write for each beacon it discovered. EG. During the 3s scan period, the app found 3 beacon, those 3 are added into a queue. Write period of 3second the queue is dequeued and proceed one by one to connect and write for each beacon found.
Scanning and writing are mutually excursive as i heard and encounted many problems when doing them together. Such as high failure rate when doing connecting ble -> write characteristic. However by making them mutually excursive, this means that i can only connect and write to a limited number of beacon if i walk pass through multiple doors with ble beacon.
My connect and write logic contains a default timeout of retry for 1.5s with max of 3 retry. Each gatt action such as .connect, .discovery contains a delay of 200ms.
I am wondering the following question
What is the average time required for ble connect then ble write characteristic (not including scanning). I have tried and seems that certain phones takes as slow as 500ms, whereas some other phone takes as long as 4.5s or just fail to establish connect and write .
Is the whole idea viable? The whole project requires at most 6s to connect and write characteristic to each door it pass by which has ble beaconattached on it.
Any improvement to be make?
Related
I am evaluating Google Nearby connections2.0 more specifically evaluating the synergy effect of it. For this I am evaluating it against Wifi, Bluetooth and BLE in totally offline scenario, without any router.
Scenario
One device is advertising, all others (8 devices in total) are discovering. On successful connection, I am sending simple Files of 20B, 200B and 33KB sizes for 30 secs straight to each connected device.
I am using android Samsung S6 SM-G920F devices with android version: 6.0.1 and playservices version 12.8.74
I have following issues/questions
Q1: First of all at max 3 to 4 devices could be connected simulatenously more than this results into disconnect event of other devices. Even if only 3 devices are connected, and I am continuously sending message for 30seconds, one of them disconnected ? In simpler words, cannot sustain connectivity with any device for more than 45 secs. usually disconnection occur between 25 - 45 secs
Q2: I cannot send message/file continuously for 30 seconds like we can do with the Wifi like this
While(30sec){
bluetoothSocket.outputStream.write(bytes)
}
Because if I try to do this then I got the exception of too much work.I have to wait for the the callback in onTransferPayLoadUpdate()
Q3: If I try to send the file of 1MB or more to other peers, peer received the file successfully in onPayloadReceived callback but server/sender receive the successful status after too much delay. In my case it's between 1 mins to 5 mins after client callback. And I cannot send new file until I got the success callback on server. If I try to send it before getting the callback, nothing happens. Literally nothing. So In essence I can only send file of 1MB once then I have to resent both the devices to send another file.
This should be broken up into 3 separate questions. It helps future developers search easier. So if you get the time to do that, let me know and I'll split up my answer as well. But anyway, let's get into it!
A1: Nearby Connections has 3 separate strategies. The more limited the strategy, the more types of mediums we can use. So with that in mind, and with no router involved, P2P_CLUSTER will only use Bluetooth. It's the most general strategy, so it has the fewest mediums available.
All Android devices use mobile Bluetooth chips, which are unfortunately weak (but small and power sensitive), and that causes them to have a theoretical 7 device limit but a practical 3~4 device limit. To make things worst, that limit is eaten up by smart watches and paired headphones as well. That's why you're running into problems.
P2P_STAR and P2P_POINT_TO_POINT are both much more limited, because you can't connect in any direction. You need to choose who the host is beforehand and have everyone scan for and connect to that host. But you get the added benefit of WiFi hotspots, which have higher bandwidth and a larger number of simultaneous devices supported. I've seen 7 devices happily connected to a Lollipop device.
If you want to go beyond that, into the 10s and 100s, and a router isn't available, you'll have to build a mesh network. I can link you to examples of how to do that if you're interested. We don't offer support for that within Connections, but others have built meshes on top of us so we can point you in the right direction.
A2: Can you include a stack trace of the error you're seeing? Payload.Type.STREAM was built for continuously sending data. The other payload types should also work too, baring some rare but potential issues like BYTE payloads filling up the phones RAM.
A3: Both devices need to wait for onPayloadTransferUpdate(SUCCESS). onPayloadReceived is only a header, and means that there's an incoming file or stream but that the data hasn't been received yet. For byte payloads, we actually send the full byte payload inside the header so that's the only time data is immediately available.
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.
can 5 or more ble modules (cc2241), each with an rgb led, be simultaneously controlled at same time from one app.I want to choose and control, at the same time,the rgb led blinking patterns from an ios/android app, so if i press a color on app, all the ble modules will respond at same time
At the exact same time is not possible: your central only has one radio PHY, it can only talk to one peripheral at the same time. Connection events with peripherals are scheduled by the Central PHY in a round-robin manner.
If you accept some delay between deliveries of updates to the 5 modules, this is doable.
Let's suppose the 5 modules are connected with equivalent connection parameters, when your application writes the characteristic for each device, phy actually has to wait for the next connection event to actually deliver the packet, in turn for each connection.
In an ideal environment, you could assume worst case latency is (ConnectionInterval * (SlaveLatency + 1)), with some packet loss, this can easily be multiplied by 2 to 5. ConnectionInterval and SlaveLatency are parameters set by your device.
Let's say all modules should be updated within 200ms allowing one connection event to be lost, you should have a connectionInterval under 100ms and slaveLatency = 0. This is reasonable.
It is possible if you are using Broadcast/Observer connectionless model.
This is exactly the same way how Apple iBeacon works.
In this mode all data is transmitted in advertisement packet of broadcasting device. If you take look on TI CC254x examples you will find few implementations that uses it.
Depending of your application this could be perfectly OK way to go.
I'm developing a Bluetooth low energy application to connect with a device which will be sending 20 byte long transmissions in notification mode in intervals of 6 milliseconds or more.
So far the application is working fine. It can scan, discover and then subscribe to the characteristic to receive data notifications. The issue is that for the first 2-4 seconds the data will be read nicely in a sequential order but after that the notification data starts to appear in bursts or as in chunks of data but not in consistent intervals between each transmission.
This doesn't happen when i check the data transmission with the Texas Instruments BLE evaluation kit, there my reader shows a perfect transfer with not bursts appearing. Only on android it's become visible.
Could this be an issue that can be configured to fix in android side?
Could this be a problem with the high transmission rate (~milliseconds intervals)?
Thank you..
So it sums up to that optimal throughput can be achieved with the proper configuration of connection parameters for the BLE connection. It is usually done at the peripherals end and may have to differ for the platform connecting to (i.e. IOS , Android may have different connection requirements..)
P.S. : Since i was looking at android found this method documented here https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#requestConnectionPriority(int) which is calling for a connection priority( CONNECTION_PRIORITY_BALANCED, CONNECTION_PRIORITY_HIGH or CONNECTION_PRIORITY_LOW_POWER) But I didn't test it.
You could try to enable Bluetooth HCI Snoop Log in Developer Options and then view the log file in WireShark. Look for connection update commands, these can be issued by either side of communication. This command change the transmission settings and slow down the transfer. Also look for GAPROLE_PARAM_UPDATE_ENABLE in your TI BLE app.
Yes Michael we use CC2650 and for our requirement BLE is sufficient bur I'm not sure if it really supports bluetooth classic (http://www.ti.com/product/CC2650/description) .
You can try playing around the BLE connection parameters to get the setup tuned, that's what we did other than trying to build the app giving priority to BLE operations.Take a look at this for more information on connection parameters.
https://devzone.nordicsemi.com/question/60/what-is-connection-parameters/
You can't configure the connection parameters on the phone but the peripheral(i.e. SensorTag) even so there's not guarantee that the given parameters will actually be accepted by the central device in case will settle with a set of parameters accepted by the central device. (Android and IOS have different policies in terms of these..)
In our case we are transmitting in intervals of 15ms and seems quite stable. But all these high frequent transfers at the cost of the low power consumption capabilities of BLE which is really what it is intended for. We could go even below that close to 7.5ms which is the minimum connection interval supported by Android. Our initial tests were stable but reliability of such a low latency is questionable.
I do have a Bluetooth LE remote controlled car. Therefore i need to write periodically to a drive characteristic on the car. My microcontroller (AtmelXMega128A1 # 32Mhz + nRF8001) should be able to handle up to 122 connections per second # 7,5ms connection interval.
My Android App is based on cordova and a bluetooth low energy plugin: https://github.com/randdusing/BluetoothLE
I am running this on a Nexus 5 with Android v4.4.4.
I have a timer which sends values for steering and acceleration to the car each 175ms. I would like to send each 50ms but that does not work. I cannot tell where the problem is but i guess it is the android implementation of GATT (I get the pending command error at some level).
If i write more than it can handle the car executes all commands in a row but time shifted. Some queue hickup obviously and this is not the Microcontroller as it operates much faster.
I am doing a timing change which seems to be successful. I tried turning WiFi off as i hoped it would help but nothing changed.
Is there any experience on periodical writings to a GATT characteristics on Android? Examples would be great.
First of all you should make a robust design. Data should be driven by callback from the Android BT Stack telling when it's ready to accept more data (when the previous transmission is done). Do not use a timer. There will always happen need for retransmissions on the lower stack level so you cannot rely on an exact transfer interval and throughput.
The 7.5ms is the shortest possible connection interval however the default is usually much slower (48.75ms on my Nexus 5 with Android L) So from your peripheral you should try to request a faster connection interval once connected. This will speed up your throughput and responsiveness.
Some Android BT stacks refuse if you try to force a very fast connection interval. You should be handling that intelligently. Like trying with 7.5ms (parameter = 6) and increase it if it failed. iOS design guideline say you must not use a lower value than 20 (*1.25ms) and the upper request value should be at least 20 higher than the lower. You will get a faster connection parameter though if you request values min=10, max=20 and end around 18ms or something.
For android it seems most will accept the 7.5ms (value 6) but again you should not force it because the stack might cancel the connection then.
I made experiments on Android L, requesting connection intervals from the peripheral side when connected. Android rounded off requests so only every 3rd step gave a difference.
6=7.5ms, 9=11.25ms, 12=15.0ms, ..., 39=48.75ms which seems to be the default value on Nexus 5 running Android L.
Bluetooth is a shared resource in the broadcom chipset most are using on the smartphone side. Wifi, BT Classic, BT Low Enegy and sometimes GPS shares bandwidth. You will see hiccups and must be tolerant about them. Make a robust design.
Something else you can try is to renegotiate MTU-SIZE if you need larger data packages than the default. This is by specification an optional BLE feature however Apple broke it completely in iOS7 where they use it as a mandatory thing to boost up throughput. This broke all BLE devices which didn't implement the response handler and so it crashed and could never be used with iOS devices until a SW update was made. Baaaaaad. For android this is not a problem though.