When I try to receive and transmit BLE beacons at the same time Android device (5.0, 5.1, 6.0) transmits beacons only and doesn't scan. How can I do it at the same time. Please, give me simple code example. With only receiving or only transmitting there are not problems. I use android-beacon-library-2.11.
Is not possible to receive and send data through BLE at the same time: you need to implement some kind of read/write operations list and execute them sequentially, one by one.
Related
I am working on a BLE app. I am through to establishing communication between Mobile app (CENTRAL - BluetoothGattClient) and PERIPHERAL (GATT SERVER) albeit not neatly.
PERIPHERAL has one service which in turn has single characteristic on which CENTRAL has enabled notification. Read/Write from both sides happen through this characteristic
Here is the complete flow of communication from CENTRAL (Mobile) side
Problem 1
Sometime while receiving multiple packets from PERIPHERAL, I receive read notification - 'onCharcteristicChanged()' before I finish writing ACK (STEP 9) i.e. onCharcteristicChanged() is called before onCharctristicWrite().
In this scenario though I issue bleGatt.readCharacteristic(charac) but onCharactristicRead() never gets called. CENTRAL gets stuck. It is unable to read while waiting.
Problem 2
Sometime, while sending ACK, after issuing bleGatt.writeCharactristic(charac), onChactristicWrite() is not called hence ACK is not received by PERIPHERAL and communication stops.
Problem 3
Overall communication is very slow. It takes > 400ms to write one chunk (<=20 bytes) of data.
Is there any better strategy to sync Read/Write properly? I tried to do it by using BluetoothGattCallbacks but as explained it is not working properly.
What can be done to increase the speed of communication?
Both READ and WRITE is happening in same thread.
I have tested this on Moto E (Marshmallow), Moto G5 (Nougat) and Samsung S6 (Lollipop). The behaviour is consistent across devices.
My PERIPHERAL device is nRF52840.
Thanks
The easiest way to make sure your GATT communication works correctly is to use a queue for the BluetoothGatt object, since only one GATT operation can run at a time. That's why it doesn't work when you for example call readCharacteristic before the onCharacteristicWrite is called by the system.
The reason you get the notification before the write response is because the peripheral sends the notification before the write response.
What you can do to speed up the communication is to use Write Without Response instead of Write With Response. That way multiple packets can be sent in one round trip. The onCharacteristicWrite will then be called immediately (as long as the internal buffers are not filled up). Just be aware of https://issuetracker.google.com/issues/37121017.
I am trying to send 10 bytes of data, every 30milisecond,s between 2 android devices using bluetooth low enegry notifications. The goal is to achieve low latency communication and there is no interest in low energy.
You can check the results in the Delay graph(Y field = delta time between packets). The first 10seconds the communication is being perfomed good enough. (The interval between the packets is max 30-40ms). However after the 10th second, the intervals are either extremly high or extremely low.
This is probably happenning due to non strict connection interval parameters. You can check a sample of hci_events that shows clearly the slow down is caused by the hci_events.
I have tried to configure the parameters of the connection, calling from the master the function
requestConnectionPriority
However, it didn't change anything on the result graph. I also check the packets using wireshark and findout that the master didn't even send a request for configuring the connection interval. I also tried another configuration request with
requestMtu
with exactly the same results, no update packets was send from the master.
So, there are 2 questions that show up from this observations.
Has ble a timeout in the 10th second in order to ensure low energy consumption? If so, how can I disable it?
Is some thing wrong calling requestConnectionPriority, from the android 6.0.1 with the role of the central(master)? Can you give me a simple example on how is being called properly?
Note that requestConnectionPriority is called right after the connection being establish in the onConnectionStateChange of the BluetoothGattCallback.
The device that has role of a slave(server) is running (Android 5.1.1) and the master(client) is running (Android 6.0.1).
Thanks a lot!
IMPORTANT UPDATE: It's crucial to mention the way the connection is being initiated between the devices.
The central device calls device.connectGatt, where device is BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address). Address is a hardcoded string, the peripheral's public mac address. You can check logcat logs and also hci logs.
I have also tried connecting with the legit method (peripheral advertising and connect to scanned random address), but I get an error 'initiate direct connection fail, topology limitation'. You can check logcat logs and also hci logs.
Has ble a timeout in the 10th second in order to ensure low energy consumption? If so, how can I disable it?
No
Is some thing wrong calling requestConnectionPriority, from the android 6.0.1 with the role of the central(master)? Can you give me a simple example on how is being called properly?
I'm not aware of any bugs regarding requestConnectionPriority. But you could try to execute that method after the onServicesDiscovered callback. Android temporarily changes connection interval to 7.5 ms during the GATT service discovery so it might be confused if you don't wait until the service discovery is completed.
Regarding requestMtu, make sure you execute that method while there are no other GATT operations pending (otherwise it won't work).
One additional tip is to use an air sniffer and not only look at the hci logs.
I don't have enough devices to test and can't find this answer anywhere, how many devices can a single BLE scan be found at a time?
Say I have 20 devices in range, will the scan be able to handle the advertising packet of all of them or only seven?
It will handle all incoming advertisement packets while the scan is turned on. There is no limitation. Of course packets can be missed due to radio conditions.
One Scan is a loose terminology. Scan has a Scan Window parameter which tells the duration of the scan, i.e. the time the radio is in RX on a given advertisement channel. From host point of view, a scan period is a group of scan windows.
Scan waits for Advertisement Packets from Peripherals, which are retransmitted periodically, every Advertisement Interval (+ another parameter to randomize the interval a little).
Last, but not least, as there is no Carrier Sensing in BLE, Advertisement Packets from multiple peripherals may collision. They will be lost for receiver, and you'll need to wait for next packet from each of them.
So, here are some parameters needed to answer your question:
How long does your android phone listen for during one scan ?
How often does your peripherals send their advertisement packets ?
Is your radio environment busy / do you consider collision as probable ?
You can have a look at Vol3, Part C, Appendix A of BLE spec to see recommended timings of scan and advertising. Most are not mandatory, though.
An embedded device will send data through BLE. I developed an Android application to receive data, but have the following problem:
When the device connects to mobile BLEit will send data immediately but I am not able to read data, if I give a delay the app starts reading characteristics but will not be collecting data.
So when device BLE connects to mobile BLE how many milliseconds will it take to show the services? So I can match delay and receive data.
Instead of manually setting delays, you can use onConnectionStateChange, and onServicesDiscovered callbacks to execute your code based on the connection stage.
I am currently developing Android BLE, and encounters a lot of problems with the Android BLE stacks..
My development tool is Samsung Galaxy J with Android 4.3.
I want to know how can I read a characteristics from the BLE and the write the characteristics (is like i verify what data I have received, and then I send another data using the BLE)
and I have serious problem understanding how the Android BLE callbacks works,
I dont understand these 5 functions...and the manual is not clear, can anyone good soul explain in simple form???
onCharacteristicWrite
onCharacteristicRead
onCharacteristicChanged
onDescriptorRead
onDescriptorWrite
My current situation is, I managed to read the data in onCharacteristicChanged() callback and then I verified the received the data I try to send the data by using
characteristics.setValue(data)
gatt.writeCharacteristic(characteristics)
But, the Android BLE stack is not calling onCharacteristicsWrite() and in fact, Android just hangs there..
I try to google about Android BLE, there is not much information and only bunch of complains on how unstable the BLE stacks is......
Each of the callback from the Android BLE has its functions;
onDescriptorRead and onDescriptorWrite
This is used to write/read the configuration settings for the BLE device, some manufactures might require to send some data to the BLE device and acknowledge it by reading, before you can connect to the BLE device
onCharacteristicWrite
This is used to send data to the BLE device, usually in data mode for the BLE device.
This callback is called when you type
gatt.writeCharacteristic(characteristics);
onCharacteristicRead
This is used to read data from the BLE device
The callback is called when you write this code
gatt.readCharacteristic(characteristics);
onCharacteristicChanged
This callback is called when you are trying to send data using writeCharacteristic(characteristics) and the BLE device responds with some value.
Usually a BLE device has few characteristics, to make it simple, I name a few characteristics
WRITE - write Characteristics
READ - read Characteristics
To make it clear, when you send data, you will need to use WRITE characteristics and then when the BLE device responds Android app will call READ characteristics
A very important point to note is Android BLE stack allows you to write characteristics one at a time only!!
Example: IF you try to call write characteristics twice at a same time
gatt.writeCharacteristic(characteristics);
gatt.writeCharacteristic(characteristics);
The Android BLE stack will not issue the 2nd write characteristics!
Before setValue:characteristics.setValue(data) you should use gatt.setCharacteristicNotification(Char,true) to setNotification.