[labs.beatcraft.com]]~ [[labs.beatcraft.com]]~ [[Android]]~ #contents *1. About BLE (Bluetooth Low Energy) [#y7765074] > BLE is the abbreviation of Bluetooth Low Energy and a part of Bluetooth 4.0 standard.~ ~ Technical Overview:~ - Ultra-low power consumption (being capable of operating more than a year in a button battery.) ~ - No compatibility with the previous version of Bluetooth (Classic Bluetooth)~ - Communication distance is 2.5m to 10m.~ - A single BLE unit does not have restrictions on the number of concurrent connections. (Classic Bluetooth allows a single unit to connect with 7 units at most.)~ *2. Basic knowledges of BLE communication [#adc02a2b] > In the communication of BLE, GATT (Generic Attribute Profile), a client-server model, is employed.~ A device (server) consists of Profile (GATT), Service, Characteristic, and Descriptor. The diagram below describes the design of model.~ ~ &ref(./gatt.png); ** Profile [#n3183b5b] > GATT (Generic Attribute Profile) is a theoretical design for data communication between BLE devices.~ This handles to read the data structure, to write data, and to notify the change in data.~ ~ GATT consists of three elements, such as Service, Characteristic, and Descriptor.~ Profile does have more than one Service.~ ** Service [#l6a76675] > Service shows the functions of Profile.~ Service consists of several nesting Services and several Characteristics.~ ** Characteristic [#tc5d1590] > Characteristic does have a single value, which indicate its attribute.~ It consists of own value, property, which defines how to access the value, and several Descriptors.~ ** Descriptor [#f831458a] > Descriptor shows the attribute value, which is used when a characteristic needs the additional information.~ Some Characteristics do NOT contain any Descriptors.~ * 3. BLE on Android [#fb8170f3] Android 4.3 or above (API Level 18 or greater) supports BLE.~ ** Bluetooth Package [#nf593f39] > android.bluetooth.* **BluetoothManager [#fb739711] > It manages the functions of Bluetooth.~ It acquires BluetoothAdapter from BluetoothAdapter.~ **BluetoothAdapter [#g5f81df8] > It controls Bluetooth set at a mobile device.~ It scans Bluetooth devices. **BluetoothGatt [#ibcf03c2] > It operates GATT profile.~ It manages the search for Services, and the configuration of Descriptor.~ **BluetoothDevice [#e336bbd3] > It receives the scanning results of BluetoothAdapter.~ It is the information of Bluet device.~ **BluetoothGattService [#f2608ca1] > It is the information of (GATT) Services. It holds Characteristic (BluetoothGattCharacteristic). **BluetoothGattCharacteristic [#kc93d4f6] > It is the information of Characteristic.~ It holds Descriptor (BluetoothGattDescriptor). Some Characteristics do NOT have Descriptors.~ **BluetoothGattDescriptor [#dc84db56] > The information of Descriptor. * 4. Implementation of BLE on App [#a44fe1c4] ** Permission [#lc3905b5] > Please add these tags listed below to Manifest (AndroidManifest.xml) for making BLE effective.~ Configuration for Permission~ <uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> ~ Please add the tag to Manifest for making sure that the API only work with Android devices, which support BLE.~ <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/> ** Initializing [#u1b9a40c] > BluetoothManager bluetoothManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE); mBluetoothAdapter = bluetoothManager.getAdapter(); ~ **Making BLE effective [#b671573e] > As the app is executed, this checks whether Bluetooth function is available or not, If BLE is not effective, a dialog appears for confirmation to make BLE effective.~ BluetoothManager bluetoothManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE); BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter(); if (mBluetoothAdapter == null) { return false; } // Checking Bluetooth function effective or not. If it is not effective, a dialog appears for confirmation to enable BLE if (mBluetoothAdapter.isEnabled()) { // Bluetooth is effective } else { // Bluetooth is NOT enabled, and the confirmation dialog appears. Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); activity.startActivityForResult(enableBtIntent, 1); } ** Scanning [#g85c27f1] > // Stop scanning 10 seconds later. private static final long SCAN_PERIOD = 10000; ... private void scanLeDevice(final boolean enable) { if (enable) { // Stops scanning after a pre-defined scan period. mHandler.postDelayed(new Runnable() { @Override public void run() { mScanning = false; mBluetoothAdapter.stopLeScan(mLeScanCallback); } }, SCAN_PERIOD); mScanning = true; mBluetoothAdapter.startLeScan(mLeScanCallback); } else { mScanning = false; mBluetoothAdapter.stopLeScan(mLeScanCallback); } ... } private LeDeviceListAdapter mLeDeviceListAdapter; ... // The callback function after device scanning is completed private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) { runOnUiThread(new Runnable() { @Override public void run() { String msg = "name =" + device.getName() + ", bondstate = " + device.getBondState() + ", address = " + device.getAddress() + ", type" + device.getType() + ", uuid = " + device.getUuid().toString(); Log.d("Scan", msg);} }); } }; ** Connecting with a device [#k7158f57] > Call BluetoothDevice$connectGatt(), which is returned form onLeScan(), and connect with a device.~ ~ BluetoothDevice: BluetoothGatt connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback) ** Implementation of BluetoothGattCallback [#j35c7555] > private final BluetoothGattCallback callback = new BluetoothGattCallback() { // This is executed when the status of connection is changed. @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { // It is connected if (newState == BluetoothProfile.STATE_CONNECTED) { Log.i(TAG, "Connected to GATT server."); // Searching for Services Log.i(TAG, "Attempting to start service discovery:" + mBluetoothGatt.discoverServices()); // It is disconnected. } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { Log.i(TAG, "Disconnected from GATT server."); } } @Override // Return the search results of Services public void onServicesDiscovered(BluetoothGatt gatt, int status) { // Success if (status == BluetoothGatt.GATT_SUCCESS) { // Acquire the list of Services. List<BluetoothGattService> gattService = getSupportedGattServices(address); for(BluetoothGattService service : gattService) { UUID uuid = service.getUuid(); // Acquire the list of Characteristics from Services. List<BluetoothGattCharacteristic> charastics = service.getCharacteristics(); // Set up Characteristic for a reception request of Notification for(BluetoothGattCharacteristic charastic : charastics) { // gatt.setCharacteristicNotification(charastic, true); } } } else { Log.w(TAG, "onServicesDiscovered received: " + status); } } // Notification for reading @Override public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { // Characteristic is successfully read. } } // Notification for writing @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { // Characteristic is successfully written. } ... }; ** Reading [#c30fa84b] > Since reading is asynchronous, the reading process requires reading request and reading notification.~ ~ Execute BluetoothGatt#readCharacteristic().~ The results are returned to BluetoothGattCallBack#onCharacteristicRead().~ *** Reading request [#e1dcd1a3] > mBluetoothGatt.readCharacteristic(characteristic); *** Reading notification [#p354aad6] > public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { // Characteristic is successfully read. } } ** Writing [#w78a8d9a] > Since writing is asynchronous, the writing process requires writing request and writing notification.~ ~ Execute BluetoothGatt#writeCharacteristic()~ The results are returned to BluetoothGattCallBack#onCharacteristicWrite().~ *** Writing request [#a68e81f3] > mBluetoothGatt.writeCharacteristic(characteristic); *** Writing notification [#q71f3ab3] > public void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { // Characteristic is successfully written. } } ** Releasing the connection [#y33a1d42] > Execute BluetoothGatt#close(). * Connecting multiple devices [#k0d7c1cf] > To connect multiple devices, do not connect them simultaneously but connect them one by one.~ If the new connection attempt is started before the current connection attempt has been completed, the operation of device becomes unstable.~ If the new connection attempt is started before the scanning process is ended, the operation of device also becomes unstable.~ ** Case (Example) [#k352aecc] > Connect with Device A, B, and C. ** Processing procedure [#k41fe845] > 1. Connect to Device A~ BluetoothDevice#connectGatt()~ 2. Wait for the results of connection to Device A~ BluetoothGattCallback#onConnectionStateChange()~ 3. Connect to Device B~ BluetoothDevice#connectGatt()~ 4. Wait for the results of connection to Device B~ BluetoothGattCallback#onConnectionStateChange()~ 5. Connect to Device C~ BluetoothDevice#connectGatt()~ 6. Wait for the results of connection to Device C~ BluetoothGattCallback#onConnectionStateChange()~ * About demonstration at Embedded Technology 2015 [#h168d52c] > Exhibiting a single Android device is connected to 6 BLE devices, demonstrate how to handle these 6 devices with BLE connection. ***Multiple device connection [#p893dfd2] > Multiple BLE devices are connected.~ 6 devices are connected one by one.~ #youtube(FCtvmpk3XSE); *** LED light [#sc24d6fb] > There are three LED lights, and each light is capable of shifting six different brightness.~ The brightness of LED lights is changed individually or collectively.~ #youtube(e8rH0BX88Nc); ***Switch [#j748179f] > Employing three relays, turn on/off LED lights. It manages LEDs individually or collectively.~ #youtube(115ipQ69tik); ***LED color light valve [#sab94637] > It controls the color (RGB) of LED color light valve.~ #youtube(u_36gwa3jsE); * Revision History [#w5a8e891] > - 2016-02-19 This article is initially released.