Demystifying Android's Bluetooth Low Energy at MCE^3 Conf

Preview:

Citation preview

DEMYSTIFYING ANDROID'S BLUETOOTH LOW ENERGY

Paweł UrbanSenior Software Engineer

Dariusz SewerynSenior Software Engineer

BLUETOOTH LOW ENERGY

BLUETOOTH LOW ENERGY

ANDROID’S NATIVE SUPPORT

BLUETOOTH LOW ENERGY

ANDROID’S NATIVE SUPPORT

YOUR SECRET WEAPON

WHY SHOULD I CARE ABOUT BLE?

The Internet of Things – infographic The Connectivist based on Cisco data

2006

2006 2010

2006 2010 2013

A DEVELOPER PERSPECTIVE

Jelly Bean

BACKWARD SUPPORT

BACKWARD SUPPORT

BACKWARD SUPPORTBETA

BACKWARD SUPPORTBETA

LOW ENERGY

GAP (GENERIC ACCESS PROFILE)

PERIPHERAL

PERIPHERAL CENTRAL

PERIPHERAL CENTRAL

ADVERTISE PRESENCE

PERIPHERAL CENTRAL

ADVERTISE PRESENCECONNECTION HANDSHAKE

CLIENT

PERIPHERAL CENTRAL

ADVERTISE PRESENCECONNECTION HANDSHAKE

SERVER

CLIENT

PERIPHERAL CENTRAL

ADVERTISE PRESENCECONNECTION HANDSHAKE

SERVER

READ/WRITE DATA REQ

RESPOND WITH DATA

GATT (Generic Attribute Profile)

Texas Instruments SensorTAG

Peripheral device

Service A

Characteristic 1 Characteristic 2

DEVICE

Peripheral deviceDEVICE

SENSOR

Service A

Characteristic 1 Characteristic 2

Peripheral deviceDEVICE

SENSOR

36.6°C SENSOR VALUE

Service A

Characteristic 1 Characteristic 2

Peripheral deviceDEVICE

SENSOR

36.6°C SENSOR VALUE

Service A

Characteristic 1 Characteristic 2

SENSOR CONFIGURATION

Peripheral deviceDEVICE

SENSOR

36.6°C SENSOR VALUE

Service A

Characteristic 1 Characteristic 2

SENSOR CONFIGURATION

READ WRITE NOTIFY

Peripheral device

Service A

Characteristic 1 Characteristic 2

Service B

Characteristic 3 Characteristic 4

Service C

Characteristic 5 Characteristic 6

DISCOVERY

UUID

1 TEMPERATURE(„4E99FFF1-4B3E-11E5-9D65-0002A5D5C51B"); 2 HUMIDITY(„4E99FFF2-4B3E-11E5-9D65-0002A5D5C51B"); 3 TIME(„5E99FFC1-4B3E-11E5-9D65-0002A5D5C51B"); 4 DEVICE_NAME(„00002a26-0000-1000-8000-00805f9b34fb”);

UUID

1 TEMPERATURE(„4E99FFF1-4B3E-11E5-9D65-0002A5D5C51B"); 2 HUMIDITY(„4E99FFF2-4B3E-11E5-9D65-0002A5D5C51B"); 3 TIME(„5E99FFC1-4B3E-11E5-9D65-0002A5D5C51B"); 4 DEVICE_NAME(„00002a26-0000-1000-8000-00805f9b34fb”);

128-bit

UUID

1 TEMPERATURE(„4E99FFF1-4B3E-11E5-9D65-0002A5D5C51B"); 2 HUMIDITY(„4E99FFF2-4B3E-11E5-9D65-0002A5D5C51B"); 3 TIME(„5E99FFC1-4B3E-11E5-9D65-0002A5D5C51B"); 4 DEVICE_NAME(„00002a26-0000-1000-8000-00805f9b34fb”);

16-bit

THE SCARY PART

BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();final boolean startLeScan = bluetoothAdapter.startLeScan(leScanCallback);

BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { // processing results }};

bluetoothAdapter.stopLeScan(leScanCallback);

SCAN

BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();final boolean startLeScan = bluetoothAdapter.startLeScan(leScanCallback);

BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { // processing results }};

bluetoothAdapter.stopLeScan(leScanCallback);

SCAN

BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();final boolean startLeScan = bluetoothAdapter.startLeScan(leScanCallback);

BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { // processing results }};

bluetoothAdapter.stopLeScan(leScanCallback);

SCAN

BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();final boolean startLeScan = bluetoothAdapter.startLeScan(leScanCallback);

BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { // processing results }};

bluetoothAdapter.stopLeScan(leScanCallback);

SCAN

BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();final boolean startLeScan = bluetoothAdapter.startLeScan(

new UUID[]{ UUID.fromString(…) }, leScanCallback);

BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { // processing results }};

bluetoothAdapter.stopLeScan(leScanCallback);

SCAN

BluetoothDevice remoteDevice = bluetoothAdapter.getRemoteDevice(getEnteredMacAddress());BluetoothGatt bluetoothGatt = remoteDevice.connectGatt(context, false, callback);BluetoothGattCallback callback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

if (status == BluetoothGatt.GATT_SUCCESS) { if (newState == BluetoothProfile.STATE_CONNECTED) { // You are connected! } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { // Disconnected bluetoothGatt.close(); } } else { // Maybe disconnected? onDisconnectRequested(); } }};

CONNECTION

BluetoothDevice remoteDevice = bluetoothAdapter.getRemoteDevice(getEnteredMacAddress());BluetoothGatt bluetoothGatt = remoteDevice.connectGatt(context, false, callback);BluetoothGattCallback callback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

if (status == BluetoothGatt.GATT_SUCCESS) { if (newState == BluetoothProfile.STATE_CONNECTED) { // You are connected! } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { // Disconnected bluetoothGatt.close(); } } else { // Maybe disconnected? onDisconnectRequested(); } }};

CONNECTION

BluetoothDevice remoteDevice = bluetoothAdapter.getRemoteDevice(getEnteredMacAddress());BluetoothGatt bluetoothGatt = remoteDevice.connectGatt(context, false, callback);BluetoothGattCallback callback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

if (status == BluetoothGatt.GATT_SUCCESS) { if (newState == BluetoothProfile.STATE_CONNECTED) { // You are connected! } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { // Disconnected bluetoothGatt.close(); } } else { // Maybe disconnected? onDisconnectRequested(); } }};

CONNECTION

BluetoothDevice remoteDevice = bluetoothAdapter.getRemoteDevice(getEnteredMacAddress());BluetoothGatt bluetoothGatt = remoteDevice.connectGatt(context, false, callback);BluetoothGattCallback callback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

if (status == BluetoothGatt.GATT_SUCCESS) { if (newState == BluetoothProfile.STATE_CONNECTED) { // You are connected! } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { // Disconnected bluetoothGatt.close(); } } else { // Maybe disconnected? onDisconnectRequested(); } }};

CONNECTION

BluetoothDevice remoteDevice = bluetoothAdapter.getRemoteDevice(getEnteredMacAddress());BluetoothGatt bluetoothGatt = remoteDevice.connectGatt(context, false, callback);BluetoothGattCallback callback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

if (status == BluetoothGatt.GATT_SUCCESS) { if (newState == BluetoothProfile.STATE_CONNECTED) { // You are connected! } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { // Disconnected bluetoothGatt.close(); } } else { // Maybe disconnected? onDisconnectRequested(); } }};

CONNECTION

boolean startedDiscovering = bluetoothGatt.discoverServices();

@Overridepublic void onServicesDiscovered(BluetoothGatt gatt, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { BluetoothGattService service = gatt.getService(serviceUUID); BluetoothGattCharacteristic characteristic = service.getCharacteristic(characteristicUUID); boolean startedReadOperation = gatt.readCharacteristic(characteristic); // ... } else { // ... }}

@Overridepublic void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { byte[] characteristicValue = characteristic.getValue(); } else { // ... }}

READING DATA

boolean startedDiscovering = bluetoothGatt.discoverServices();

@Overridepublic void onServicesDiscovered(BluetoothGatt gatt, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { BluetoothGattService service = gatt.getService(serviceUUID); BluetoothGattCharacteristic characteristic = service.getCharacteristic(characteristicUUID); boolean startedReadOperation = gatt.readCharacteristic(characteristic); // ... } else { // ... }}

@Overridepublic void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { byte[] characteristicValue = characteristic.getValue(); } else { // ... }}

READING DATA

boolean startedDiscovering = bluetoothGatt.discoverServices();

@Overridepublic void onServicesDiscovered(BluetoothGatt gatt, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { BluetoothGattService service = gatt.getService(serviceUUID); BluetoothGattCharacteristic characteristic = service.getCharacteristic(characteristicUUID); boolean startedReadOperation = gatt.readCharacteristic(characteristic); // ... } else { // ... }}

@Overridepublic void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { byte[] characteristicValue = characteristic.getValue(); } else { // ... }}

READING DATA

boolean startedDiscovering = bluetoothGatt.discoverServices();

@Overridepublic void onServicesDiscovered(BluetoothGatt gatt, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { BluetoothGattService service = gatt.getService(serviceUUID); BluetoothGattCharacteristic characteristic = service.getCharacteristic(characteristicUUID); boolean startedReadOperation = gatt.readCharacteristic(characteristic); // ... } else { // ... }}

@Overridepublic void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { byte[] characteristicValue = characteristic.getValue(); } else { // ... }}

READING DATA

@Override void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)@Overridevoid onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status)@Overridevoid onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status)@Overridevoid onConnectionStateChange(BluetoothGatt gatt, int status, int newState)@Overridevoid onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status)@Overridevoid onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status)@Overridevoid onServicesDiscovered(BluetoothGatt gatt, int status)@Overridevoid onMtuChanged(BluetoothGatt gatt, int mtu, int status)@Overridevoid onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status)@Overridevoid onReliableWriteCompleted(BluetoothGatt gatt, int status)

DOES IT HAVE TO BE HARD?

RxAndroidBLENo! Just use

RXJAVA

OBSERVABLE

RXJAVA

Device Scanning

OBSERVABLE

Device Scanning

Scanned device

Device Scanning

Scanned device

Device Scanning

Scanned device

Device Scanning

Device Scanning

Establish Connection

Device Scanning

Connecting to deviceEstablish Connection

Device Scanning

Connecting to deviceEstablish Connection

Read Characteristic

Device Scanning

Connecting to deviceEstablish Connection

Device Scanning

Connecting to device

Reading Characteristic ValueRead Characteristic

Establish Connection

Device Scanning

Connecting to device

Reading Characteristic ValueRead Characteristic

Establish Connection

Declaration of what we want to achieve

Device Scanning

Connecting to device

Reading Characteristic ValueRead Characteristic

Establish Connection

Device Scanning

Connecting to device

Reading Characteristic ValueRead Characteristic

Establish Connection

Device Scanning

Connecting to device

Some action

Do something

Establish Connection

Device Scanning

Connecting to device

Some action

Do something

Establish Connection

Device Scanning

Connecting to device

Some action

Do something

Establish Connection

THE DEMO

SAY THAT AGAIN?

Q&As?

LET’S CHAT!

@DSeweryn

+PawełUrban

https://git.io/vw8PM

Thank You!@DSeweryn +PawełUrban

https://git.io/vw8PM

Recommended