AndroidでBLE(Bluetooth Low Energy)を使用する †1.BLE(Bluetooth Low Energy)について †Bluetooth Low Energyの略でBluetooth 4.0規格の一部です。 特徴: 2.BLEの通信についての基礎知識 †BLEはGATT(Generic Attribute Profile)と呼ばれるクライアントサーバモデルで行われます。 プロファイル †GATT(Generic Attribute Profile) GATTはサービス、キャラクタリスティック、ディスクリプタと呼ばれる3つの要素から構成されています。 サービス †サービスはプロファイルの機能を表します。 キャラクタリスティック †単一の値を持った属性を表します。 ディスクリプタ †ディスクリプタはキャラクタリスティックに付加情報が必要な際に用いられる属性値を表します。 3.AndroidでのBLE †Androidは4.3(API Level 18)から対応しています。 Bluetooth パッケージ †android.bluetooth.* BluetoothManager †Bluetoothの機能管理を行います。 BluetoothAdapter †端末のBluetoothを制御します。 BluetoothGatt †GATTプロファイルを操作します。 BluetoothDevice †BluetoothAdapterのスキャン結果として受け取ります。 BluetoothGattService †(GATT)サービス情報です。 BluetoothGattCharacteristic †キャラクタリスティック情報です。 BluetoothGattDescriptor †ディスクリプタ情報です。 4.アプリの実装 †パーミッション †マニフェスト(AndroidManifest.xml)に以下の記述を追加します。 パーミッション設定 <uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> アプリがBLE対応端末のみに対応していることを宣言するには以下を追加します。 <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/> 初期化 †BluetoothManager bluetoothManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE); mBluetoothAdapter = bluetoothManager.getAdapter(); BLEの有効化 †実行時にBluetoothが利用可能かどうかをチェックし、無効になっている場合はBluetoothを有効にする為の確認ダイアログを表示します。 BluetoothManager bluetoothManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE); BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter(); if (mBluetoothAdapter == null) { return false; } // Bluetooth機能が有効になっているかのチェック。無効の場合はダイアログを表示します。 if (mBluetoothAdapter.isEnabled()) { // Bluetoothが利用可 } else { // Bluetoothが利用不可。確認ダイアログを表示 Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); activity.startActivityForResult(enableBtIntent, 1); } スキャン †// 10秒後にスキャンを停止 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; ... // デバイススキャン後のコールバック関数 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);} }); } }; デバイスとの接続 †onLeScan()で返されるBluetoothDevice#connectGatt()を呼び出して接続します。 BluetoothDevice: BluetoothGatt connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback) BluetoothGattCallbackの実装 †private final BluetoothGattCallback callback = new BluetoothGattCallback() { // 接続状態が変更されたときに実行される @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { // 接続された if (newState == BluetoothProfile.STATE_CONNECTED) { Log.i(TAG, "Connected to GATT server."); // サービスを検索する Log.i(TAG, "Attempting to start service discovery:" + mBluetoothGatt.discoverServices()); // 切断された } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { Log.i(TAG, "Disconnected from GATT server."); } } @Override // サービスの検索結果を返す public void onServicesDiscovered(BluetoothGatt gatt, int status) { // 成功 if (status == BluetoothGatt.GATT_SUCCESS) { // サービスのリストを取得 List<BluetoothGattService> gattService = getSupportedGattServices(address); for(BluetoothGattService service : gattService) { UUID uuid = service.getUuid(); // サービスからCharacteristicsのリストを取得 List<BluetoothGattCharacteristic> charastics = service.getCharacteristics(); // Characteristic に Notification の受信要求を設定 for(BluetoothGattCharacteristic charastic : charastics) { // gatt.setCharacteristicNotification(charastic, true); } } } else { Log.w(TAG, "onServicesDiscovered received: " + status); } } // 読み込み通知 @Override public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { // Characteristicの読込成功 } } // 書き込み通知 @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { // Characteristicの書込成功 } ... }; 読込 †読込は非同期の為、読込要求と読込通知とからなります。 BluetoothGatt#readCharacteristic()を実行します。 読込要求 †mBluetoothGatt.readCharacteristic(characteristic); 読込通知 †public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { // Characteristicの読込成功 } } 書込 †書込は非同期の為、書込要求と書込通知とからなります。 BluetoothGatt#writeCharacteristic()を実行します。 書込要求 †mBluetoothGatt.writeCharacteristic(characteristic); 書込通知 †public void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { // Characteristicの書込成功 } } 接続の解除 †BluetoothGatt#close()を実行します。 複数のデバイスを接続する †複数のデバイスを接続する場合、同時に接続処理を行うのではなく、順次接続を行うことが必要です。 [ケース] †デバイスA,B,Cを接続するケース [処理手順] †1.デバイスAの接続 Embedded Technology 2015のデモについて †Android端末(Nexus7 2013)で6台のBLEデバイスに接続し、操作を行うデモを展示しました。 同時接続 †BLEデバイスを複数接続 LED照明 †明るさを6段階で変更 スイッチ †3個のリレーを搭載し、個別/同時にON/OFF操作 LED電球 †LED電球(RGB)の色を操作 YASHIRO Masayuki
|