[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 =&#12288;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.

Front page   Edit Diff Backup Upload Copy Rename Reload   New List of pages Search Recent changes   RSS of recent changes