Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

Everything About Bluetooth (淺談藍牙 4.0) - Periphe...

Johnny Sung
February 04, 2016
92

Everything About Bluetooth (淺談藍牙 4.0) - Peripheral 篇

2016.01.22 @ Android Taipei
講解 Bluetooth 的 GATT 的概念,並以 Android 實作
Example code:
Peripheral - BLE CPU Temp
https://github.com/j796160836/Ble-CPUTemp-Android
Central - BLE Temperature Receiver
https://github.com/j796160836/BleTemperatureReceiver-Android

Johnny Sung

February 04, 2016
Tweet

More Decks by Johnny Sung

Transcript

  1. • Heart Rate Service • Heart Rate Measurement • Data

    • Descriptor 00002A37-0000-1000-8000-00805F9B34FB GATT Heart Rate Monitor 0000180D-0000-1000-8000-00805F9B34FB Property: Notify
  2. Property: Indicate • Health Thermometer • Temperature Measurement • Data

    • Descriptor GATT Health Thermometer 00001809-0000-1000-8000-00805F9B34FB 00002A1C-0000-1000-8000-00805F9B34FB
  3. • an indicate operation is identical to a notify operation

    except that indications are acknowledged, while notifications are not. Notify vs Indicate http://mbientlab.com/blog/bluetooth-low-energy-introduction/
  4. Property: Indicate • Health Thermometer • Temperature Measurement • Data

    • Descriptor GATT Health Thermometer 00001809-0000-1000-8000-00805F9B34FB 00002A1C-0000-1000-8000-00805F9B34FB
  5. • Central • Android 4.3 (API Level 18) • Peripheral

    • Android 5.0 (API Level 21) • Specific BLE chip Requirement in Android
  6. BluetoothQFSNJTTJPOT $IFDLTZTUFNGFBUVSF getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE) @Override
 public void onActivityResult(int requestCode , int

    resultCode, Intent data) {
 if (requestCode == REQUEST_ENABLE_BT) {
 if (resultCode == Activity.RESULT_OK) {
 // Bluetooth has turned on
 } else {
 // User did not enable Bluetooth or an error occurred
 }
 }
 } Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
 startActivityForResult(enableIntent, REQUEST_ENABLE_BT); 3FRVFTUUPFOBCMF#MVFUPPUI
  7. BluetoothGattService hrmService = new BluetoothGattService(SERVICE_HEALTH_THERMOMETER_UUID,
 BluetoothGattService.SERVICE_TYPE_PRIMARY); BluetoothGattCharacteristic tempChar =
 new

    BluetoothGattCharacteristic(CHAR_TEMP_UUID, BluetoothGattCharacteristic.PROPERTY_INDICATE, BluetoothGattCharacteristic.PERMISSION_READ); tempChar.addDescriptor(new BluetoothGattDescriptor(
 UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"),
 (BluetoothGattDescriptor.PERMISSION_READ | BluetoothGattDescriptor.PERMISSION_WRITE))); 
 hrmService.addCharacteristic(tempChar); 1SFQBSFTFSWJDFTUSVDUVSF Health Thermometer 2A1C 1809
  8. AdvertiseData.Builder datas = new AdvertiseData.Builder();
 AdvertiseSettings.Builder settings = new AdvertiseSettings.Builder();


    
 datas.addServiceUuid(new ParcelUuid(hrmService.getUuid()));
 BluetoothLeAdvertiser advertiser = adapter.getBluetoothLeAdvertiser();
 advertiser.startAdvertising(settings.build(), datas.build(), advertiseCallback); BluetoothManager manager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
 BluetoothAdapter adapter = bluetoothManager.getAdapter(); BluetoothGattServer gattServer = manager.openGattServer(context, gattServerCallback); gattServer.addService(hrmService); 0QFOTFSWFS "EWFSUJTFUPPUIFST
  9. AdvertiseCallback advertiseCallback = new AdvertiseCallback() {
 @Override
 public void onStartSuccess(AdvertiseSettings

    settingsInEffect) {
 // ...
 }
 
 @Override
 public void onStartFailure(int errorCode) {
 // ...
 }
 }; "EWFSUJTFDBMMCBDL
  10. private HashSet<BluetoothDevice> bleDevices = new HashSet<>(); 
 private final BluetoothGattServerCallback

    gattServerCallback = new BluetoothGattServerCallback() {
 @Override
 public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
 super.onConnectionStateChange(device, status, newState);
 if (status == BluetoothGatt.GATT_SUCCESS) {
 if (newState == BluetoothGatt.STATE_CONNECTED) {
 // Connect
 bleDevices.add(device);
 } else if (newState == BluetoothGatt.STATE_DISCONNECTED) {
 // Disconnect
 bleDevices.remove(device);
 }
 } else {
 // Disconnect with error
 bleDevices.remove(device);
 }
 }
 // ... (略)
 }; )BOEMFEFWJDFDPOOFDU
  11. private final BluetoothGattServerCallback gattServerCallback = new BluetoothGattServerCallback() { 
 //

    ... (略)
 
 @Override
 public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
 // ... gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS,
 offset, characteristic.getValue());
 }
 
 // ... (略)
 }; 3FBEJOH$IBSBDUFSJTUJD
  12. 8SJUJOH$IBSBDUFSJTUJD http://developer.android.com/reference/android/bluetooth/ BluetoothGattServerCallback.html#onCharacteristicWriteRequest(android.bluetooth.BluetoothDevice, int, android.bluetooth.BluetoothGattCharacteristic, boolean, boolean, int, byte[]) private

    final BluetoothGattServerCallback gattServerCallback = new BluetoothGattServerCallback() {
 // ... (略)
 @Override
 public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded,
 int offset, byte[] value) {
 // ...
 ByteBuffer buffer = ByteBuffer.wrap(value);
 buffer.order(ByteOrder.LITTLE_ENDIAN); 
 characteristic.setValue(buffer.getInt(),
 BluetoothGattCharacteristic.FORMAT_UINT16, 0);
 
 if (responseNeeded) {
 gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, null);
 }
 } // ... (略)
 };
  13. private final BluetoothGattServerCallback mGattServerCallback = new BluetoothGattServerCallback() {
 // ...

    (略)
 @Override
 public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded,
 int offset, byte[] value) { 
 super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, responseNeeded, offset, value);
 if (responseNeeded) {
 gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, null);
 }
 } // ... (略)
 }; 8SJUJOH%FTDSJQUPS
  14. public void sendNotificationToDevices( BluetoothGattCharacteristic characteristic) {
 boolean indicate = (characteristic.getProperties()


    & BluetoothGattCharacteristic.PROPERTY_INDICATE)
 == BluetoothGattCharacteristic.PROPERTY_INDICATE;
 for (BluetoothDevice device : bleDevices) {
 gattServer.notifyCharacteristicChanged(device, characteristic, indicate);
 }
 } 4FOE$IBSBDUFSJTUJD/PUJGZ
  15. Q&A

  16. We introduced BLE peripheral mode in Android 5.0 Lollipop. Nexus

    6 and Nexus 9 are the first two production Nexus devices that support BLE peripheral mode. Due to hardware chipset dependency, older Nexus devices (4/5/7) will not have access to the feature on Lollipop. #52 Won’t Fix