Android BLE, read and write characteristics - android

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.

Related

What are the possible reasons for an android app failing to receive BLE notifications from a BLE device it's connected to?

I have posted several questions which are basically the same question over and over again because I honestly can't find the problem.
I need to receive notifications from a BLE device on a particular characteristic. I use the BGX Silicon Labs Bluetooth kit which is connected to a Processor board that we send and receive data from. The documentation states that two characteristics RX and TX are used for data exchange. Rx for sending and TX for receiving.
Here is the link as well:https://docs.silabs.com/gecko-os/1/bgx/latest/ble-services
Now I tried following the guide from PunchThrough that helps build a starter BLE app for android. I pretty much did everything they did. Now when I enable notifications for the RX characteristic when sending, the onCharacteristicChanged override function gets called as it should be. But when I send a request using that characteristic and expect a response based on that request sent in the form of a notification. Our team seems to manage fine using the software developed for the Desktop version, the android version I am working on however seems to succeed only in Writing data but not receiving. My question is simple, why does the onCharacteristicChanged function never get called when I enable notifications on the Tx characteristic?
The code has a queuing mechanism, and it writes to the descriptor and has notifications enabled on the TX characteristic but I get nothing, nothing at all. I can provide parts of the code if you wish but first I wanted to discuss what possible reason notifications are not received.

Does Android app needs to perform Central and Peripheral roles at same time to send and receive data over BLE?

Currently, I am developing an app which is communicating with one BLE Hardware which is receiving commands and responding back the command response. To Simulate hardware, We have developed one iOS Simulator app, which is working in Peripheral and responding back on requested command. But Somehow, As and when I try to write to the write characteristics, I got the status = BluetoothGatt .GATT_REQUEST_NOT_SUPPORTED in the onCharacteristicWrite callback. But somehow, I came to know that we need to implement the Central and Peripheral roles into Android app.
But I am still not sure, Do we need to implement Peripheral role as well to send and receive data in multiple packets.
I am developing the app using following nice blog post:
- https://medium.com/#avigezerit/bluetooth-low-energy-on-android-22bc7310387a
- https://android.jlelse.eu/android-bluetooth-low-energy-communication-simplified-d4fc67d3d26e
- https://www.bignerdranch.com/blog/bluetooth-low-energy-on-android-part-2/
And using following repo as learning point of view:
- https://github.com/bignerdranch/android-bluetooth-testbed/tree/a/android-ble-part-3
Thanks in advance!
Typically your phone app is the central and it communicates with a peripheral device over Bluetooth. If you want to send data to the peripheral, you can write a characteristic in the phone app, given writing is enabled for that characteristic. Your central can get data from the peripheral in 2 ways: it can either read a characteristic (if it's enabled) from the peripheral or receive notifications from the peripheral (if it's enabled). So if all you have is a central (phone app) and a peripheral (some kind of Bluetooth device) and you want to send data back and forth, you don't need to have both central and peripheral roles in the phone app. If you have some special stuff going on, it might be different for you, I don't know. I'm talking about a typical setup.
If you want to send commands to the peripheral, you could write those commands to a characteristic. The peripheral could in turn respond with notifications. This is basically the way I develop a Bluetooth solution, but it can be different depending what you want to achieve.
It takes two devices to communicate with each other.
Device A:
It will be Peripheral device which will be advertising the data. i.e.: Beacons, BLE Hardware
Device B:
It will be Central device which will send request for read,write. i.e.: Mobile
Setup for Device A:
If you don't have Peripheral, there is a way to make your android mobile to act like a Peripheral if your device is supporting that advance feature.
So before beginning, you may simply check that by using following app:
https://play.google.com/store/apps/details?id=com.kyriakosalexandrou.bluetoothsupportcheck
To make your device act like Peripheral, you may install following app which simply simulates the GATT and advertising:
https://play.google.com/store/apps/details?id=com.ble.peripheral.sim
Important: Setup service and characteristics based on your requirements, make sure characteristic is write enabled if you want write data on it.

How to sync communication between BLE Central (Mobile) and Peripheral?

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.

Get descriptor value from a BLE node

I am a newbie to Android app coding and I am currently writing an Android app to scan BLE beacons nearby and get the data inside the beacon. Currently I am using LightBlue Explorer which is an iOS app as a BLE beacon for broadcasting data.
I want my app to receive data broadcasted by the beacon. First of all, should I use 'descriptor' as a place for putting the data? (Since I can set the characteristic user description and descriptor value inside LightBlue Explorer) If so, how can I get the value of a descriptor in my app? For now, I can get the service and the characteristics of that beacon. Thanks a lot!
I am not familiar with beacons, but i have worked on BLE devices. SO i might say you a thing or two to start conversation thread.
BLE devices around you gives out broadcast information regarding the device itself necessary for establishing the connection with device itself.
So you cant directly access the data within the device without prior connection.
This is called Generic Access Profile (GAP)
Once after establishing the connection with the device and the app(Mobile) you have to use Generic Attribute Profile (GATT) to get data necessary for the device.
You can receive data after connection by two ways.
1) Write & Notify
2) Write & Read
1) In this you have to write necessary command on the specified write characteristic for specific service on the device and device will push the necessary data on the specific Notify characteristic. Make sure the notify characteristic is enabled
2) In this you have to write necessary command on the specified write characteristic for specific service on the device and then you have to request read to the device from the app, then from the read port you can get the data given by the device.
I hope you get kinda of idea about BLE working. I have worked on BLE devices on Android side.
If any doubts just reply to thread.
To others if any correction you feel is needed, please reply.
Thank You.

Can I bond a Bluetooth Low Energy device?

I want to pair my Android cellphone with a BLE device using createBond
and setPin
as in this StackOverflow question.
I'm using a TI SensorTag, and I am able to get it to connect, but I want to get it to bond so that I don't have to scan for it later.
Unfortunately, when I use createBond (or when I try to pair through Android Bluetooth Settings), my phone wants a PIN. I have not been able to find the PIN online, and some people I've asked say that BLE devices can't bond (that they only use the Just Works method). Does anyone know the SensorTag PIN, where to find it, or whether I'm just completely off base?
Android notwithstanding, BLE is a branch of Bluetooth 4.0 and, as such, should supporting pairing and bonding.
Technically, the "Just Works" method still implies bonding. However, in my experience it isn't necessary for both Android and iOS devices to connect and read from BLE devices that have authentication disabled.
My experience with the TI SensorTag data using Android is that it does not bond. The TI SensorTag uses the Just Works BLE method.
This is the sequence I use to communicate with the TI SensorTag, based on the information in http://developer.android.com/guide/topics/connectivity/bluetooth-le.html
press the button on the SensorTag. This will cause it to listen for Scan requests.
call startLeScan(). Wait for callback.
in your onLeScan() callback, save the device of the discovered TISensorTag.
On the UI thread, call device.connectGatt() and wait for callback.
In your onConnectionStateChange(), call discoverServices() and wait for callback.
In your onServicesDiscovered(), notify your UI thread that you are connected.
In your UI thread, start a read of a GATT Characteristic with readCharacteristic(). Wait for callback.
In your onCharacteristicRead(), call one of the getValue() methods.
Call BluetoothGatt.close(). This call is important. If your app exits without calling close(), the Bluetooth Stack may become unusable and you will need to reboot your phone.
I make my phone bonded to 2540 peripheral, and the PIN is 00000000,eight 0s;I am not sure if it works on TI sensor Tag, you can try.
And I also have a question, how I use A bonded device.
I was able to bond the SensorTag with 000000 as PIN.

Categories

Resources