Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you get data from a Bluetooth LE device

I have a bluetooth barcode scanner that supports bluetooth LE and I am trying to get the barcode information from it when one is scanned.

I can connect to it fine onServicesDiscovered gets called in my BluetoothGattCallback but I am not sure what to do from there.

With a classic bluetooth connection you would get a InputStream from a BluetoothSocket and you would just wait for the read() to give you data but I am not sure how it works with Bluetooth LE. I tried looping through the BluetoothGattCharacteristic's checking the property and if its a read property I call gatt.readCharacteristic(characteristic); but that just gives me useless information and that's even before I attempt to scan something.

So how do I get the barcode data from the scanner?

this is the scanner I have https://www.zebra.com/us/en/support-downloads/scanners/ultra-rugged-scanners/li3608-li3678.html

like image 395
tyczj Avatar asked Aug 14 '17 14:08

tyczj


People also ask

How do I transfer data over BLE?

Once you have connected to a BLE GATT server, you can use the connection to find out what services are available on the device, query data from the device, and request notifications when a certain GATT characteristic changes.

How does Bluetooth LE work?

BLE devices are discovered through the broadcasting of advertising packets over 3 separate frequencies to reduce interference. A BLE device sends out a repetitive packet of information over one of three channels with random delays of up to 10 milliseconds.


1 Answers

The data provided by BLE devices is called Characteristics. These data packages are specially formed, tightly packed byte arrays that encode specific values for specific Services. You can check out the Services at the official Bluetooth website. Here you'll find the defined (authoritative) GATT services and the belonging characteristics.

For example, you have a BLE cycling computer that reports speed and cadence. You look up the Cycling Speed and Cadence item in the list. This entry contains the UUID (0x1816) of the service and a link to the data sheet that contains the characteristics. Now if you go to the Service Characteristics table, you'll find a couple entries. You want the speed and cadence, so you'll open CSC Measurement (the Type field of the entry) that takes you to the characteristic's data sheet. Here you'll see the Value Fields table that defines the specific values that can be read from the characteristic.

This was the Bluetooth LE part in general, now back to Android. Note, that you'll have to look up these fields in order to get the values from the characteristics. I'm just gonna assume that you already have the characteristic that you want to get the data from. Here's a quick sample that retrieves the wheel and crank revolutions (if available).

BluetoothGattCharacteristic characteristic = ... ;

int offset = 0; // we define the offset that is to be used when reading the next field

// FORMAT_* values are constants in BluetoothGattCharacteristic
// these represent the values you can find in the "Value Fields" table in the "Format" column
int flags = characteristic.getIntValue(FORMAT_UINT8, offset);

offset += 1; // UINT8 = 8 bits = 1 byte

// we have to check the flags' 0th bit to see if C1 field exists 
if ((flags & 1) != 0) {
    int cumulativeWheelRevolutions = characteristic.getIntValue(FORMAT_UINT32, offset);
    offset += 4; // UINT32 = 32 bits = 4 bytes

    int lastWheelEventTime = characteristic.getIntValue(FORMAT_UINT16, offset);
    offset += 2; // UINT16 = 16 bits = 2 bytes
}

// we have to check the flags' 1st bit to see if C2 field exists 
if ((flags & 2) != 0) {
    int cumulativeCrankRevolutions = characteristic.getIntValue(FORMAT_UINT16, offset);
    offset += 2;

    int lastCrankEventTime = characteristic.getIntValue(FORMAT_UINT16, offset);
    offset += 2;
}

The flags field needs to be checked for specific bits because it is possible that the device does not report every type of data, e.g. it doesn't count the wheel revolutions. The selected characteristic's sheet always contains the relevant information about this field (if exists).

It's also worth noting that the documentation says that

The CSC Measurement characteristic (CSC refers to Cycling Speed and Cadence) is a variable length structure containing a Flags field and, based on the contents of the Flags field, may contain one or more additional fields [...]

This is why you cannot assume that cumulative crank revolutions value is to be found at the 7 bytes (8 + 32 + 16 bits; 1 + 4 + 2 bytes respectively) offset and the offset should be counted as you progress along the fields.


This was an example for reading Cycling Speed and Cadence values from a BLE device. You'll have to look up these available fields and values for every device (or rather the service) you want to support in your application. If the device is a special one and it cannot be found in this GATT directory, you'll need to consult the device's manual, SDK, or vendor for more info.

like image 111
Gergely Kőrössy Avatar answered Oct 01 '22 09:10

Gergely Kőrössy