[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()
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.
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.
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.
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   New List of pages Search Recent changes   RSS of recent changes