React Native BLE PLXを使ったBLEデバイスの接続と通信ガイド


Summary

このガイドでは、React Native BLE PLXを使用したBLEデバイスとの接続と通信について詳しく探ります。特に初心者でもわかりやすいように、必要な手順や注意点を解説し、実際の開発に役立つ情報を提供します。 Key Points:

  • AndroidManifest.xmlへのBluetooth関連権限の追加が不可欠で、特にAPI 31以降は`BLUETOOTH_SCAN`と`BLUETOOTH_CONNECT`が必須です。
  • 位置情報権限はBLEスキャンに必要ですが、バックグラウンド動作を希望する場合は複雑な設定が求められます。
  • iOS環境でも適切な設定が必要で、プラットフォーム間の差異を理解しておくことが重要です。
この記事から得られる最も重要なポイントは、BLEデバイスとの接続には正しい設定とエラーハンドリングが不可欠であるということです。

React Native BLE PLXとは何か

現代の相互接続された世界では、Bluetooth Low Energy(BLE)デバイスが医療からスマートホームシステムに至るまで、さまざまなアプリケーションで重要な役割を果たしています。React Nativeはクロスプラットフォームのモバイルアプリケーションを構築するための人気フレームワークであり、BLE機能をシームレスに統合する柔軟性を開発者に提供します。このガイドでは、React Native BLE PLXという強力なライブラリを使用してBLEデバイスと接続する方法について探ります。

**React Native BLE PLXの紹介**
React Native BLE PLXは、React Nativeアプリケーション内でBLE周辺機器とやり取りするプロセスを簡素化する包括的なライブラリです。このライブラリは、BLEデバイスのスキャンや接続、通信に関する堅牢なAPIセットを提供しており、多様なBluetooth対応デバイスの能力を活かした魅力的なアプリケーションの構築が可能です。

プロジェクトへのReact Native BLE PLXの設定方法

**React Native BLE PLXのプロジェクトへの設定方法**
まず、npmまたはyarnを使用してReact Native BLE PLXをインストールします:
npm i react-native-ble-plx  

または
yarn add react-native-ble-plx  


セットアップに関する問題が発生した場合は、以下のnpmパッケージリンクを参照してください。
[https://www.npmjs.com/package/react-native-ble-plx]

**必要な権限**
React NativeアプリケーションからBLEデバイスを検出するために、以下の権限がリクエストされているか確認してください。

**Android:**
- `PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION`
- `PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT`(API 31以上で必要)

AndroidManifest.xmlにはBluetoothの権限を追加し、
を更新します:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">     
...
<!-- Android >= 12 -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<!-- Android < 12 -->
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
<!-- 共通 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- アプリケーションが常にBLEを必要とする場合は、この行を追加します。詳細については、
https://developer.android.com/guide/topics/connectivity/bluetooth-le.html#permissions
を参照してください。-->
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
...
Extended Perspectives Comparison:
項目内容
ライブラリ名React Native BLE PLX
概要BLEデバイスとシームレスに接続し、通信を行うための包括的なAPIセットを提供するライブラリ。
必要な権限 (Android)ACCESS_FINE_LOCATION, BLUETOOTH_CONNECT, BLUETOOTH_SCAN, BLUETOOTH_ADMIN
必要な権限 (iOS)NSBluetoothAlwaysUsageDescription
主要機能デバイスのスキャン、接続、サービス・特性の発見、データの読み書き、通知の監視
注意点BLEデバイスへのアクセスには適切なUUIDが必要。Base64形式でのデータ取扱いに注意。

必要な権限の確認と設定

iOSでは、Info.plistファイルにNSBluetoothAlwaysUsageDescriptionを追加する必要があります。これはiOS 13以降の要件です。また、Androidでは位置情報やBluetooth、近接共有の権限を確認することも重要です。BLEマネージャーを起動する前に、位置情報とBluetoothが有効になっているかどうかをチェックしてください。

次に、BLEマネージャーのインスタンスを作成します。このインスタンスはすべての利用可能なAPIへの入り口となりますので、アプリケーションが実行される際に作成するようにしましょう。例えば、静的な参照として保持することができます:

import { BleManager } from 'react-native-ble-plx';
export const manager = new BleManager();


BleManagerは一度だけインスタンス化できるため、一つのインスタンスで全ての操作を行う必要があります。もしBLE機能が不要になった場合は、manager.destroy()メソッドを呼び出してインスタンスを破棄できます。

注意点として、新しいコンポーネントで再レンダリングごとに新しいBleManagerのインスタンスを作成すると、不具合が発生することがあります。同じBleManager上で関数を呼び出し続けないようにしましょう。

BLEマネージャーの作成方法

アプリケーションが起動すると、BLEスタックはすぐには利用できないため、その状態を確認する必要があります。現在のBluetoothの状態を検出し、Bluetoothの状態変化を追跡するために、`onStateChange()`関数を使用します。以下のように実装できます:

useEffect(() => {
const stateChangeListener = manager.onStateChange(state => {
console.log('onStateChange: ', state);
if (state === State.PoweredOn) {
scan();
}
});
return () => {
stateChangeListener?.remove();
};
}, [manager]);


次に、位置情報の状態変化を確認します。こちらも同様に`useEffect`フックを使って実装可能です:

useEffect(() => {
let locationSubscription: EmitterSubscription | null = null;

const addLocationListener = async () => {
try {
const subscription = await SystemSetting.addLocationListener(data => {
console.log('Location: ', data);
setIsLocationOn(data);
});
locationSubscription = subscription;
} catch (error) {
console.error('Error adding location listener:', error);
}
};

addLocationListener();
}, []);


このコードでは、Bluetoothがオンになったときや位置情報サービスが有効になったときに、それぞれ適切な処理を行うことができます。このようにしてデバイス間で円滑な通信を実現し、安全性やパフォーマンスにも配慮した設計となっています。


BLEマネージャーの作成方法 Free Images


Bluetoothと位置情報の状態確認方法

BLEデバイスをスキャンするためには、まずプロジェクトの設定が完了している必要があります。周囲のBLEデバイスを検出するために、スキャンを開始しましょう。接続する前に、デバイスをスキャンしなければなりません。以下は、検出されたデバイスを処理するために一つのコールバック関数のみを登録できるシンプルな関数です。

function scan() {
manager.startDeviceScan(null, null, (error, device) => {
if (error) {
// エラーが発生した場合は、スキャンが自動的に停止します。
return;
}

// 広告データや他の基準に基づいて探しているデバイスかどうか確認します。
if (device.name === 'TI BLE Sensor Tag' || device.name === 'SensorTag') {
// 一つのデバイスだけを探しているので、スキャンを停止します。
connect();
manager.stopDeviceScan();

// 接続処理へ進みます。
}
});
}


ここで注意すべき点は、スキャン中に同じデバイスが複数回通知されることがあるということです。ただし、一度接続すると、そのデバイスはもうブロードキャストされず、中央から切断しない限り再びスキャンできません。また、特定の時間経過後には必ずスキャンを停止させる必要があります。そのためには`setTimeout()`関数などを利用してスキャン停止プロセスを管理すると良いでしょう。

次に、BLEデバイスへの接続とサービス及び特性の探索についてですが、一旦デバイスが見つかっても、それはまだ切断状態です。そこで、そのデバイスに接続し、その中に含まれる全てのサービスと特性を発見する必要があります。サービスとは、それぞれ意味ごとに特性がグループ化されたコンテナとして理解できます。

BLEデバイスのスキャン方法

特性とは、値を保持するためのコンテナであり、利用可能な機能に基づいて読み取り、書き込み、および監視ができます。たとえば、接続は次のようになります:
connect = async () => {  try {  await manager.connectToDevice(deviceId).then(device=>{console.log('デバイスに接続しました:', device.name);  // 接続されたデバイスを扱うためのロジックを追加します。return device.discoverAllServicesAndCharacteristics();}).catch(error => {    // エラー処理  })} catch (error) {console.error('デバイスへの接続中にエラーが発生しました:', error);}}; 
- サービスと特性の発見は、一度の接続ごとに実行する必要があります。このプロセスは、利用可能な特性やサービスの数によって長くなる場合があります。

BLEデバイスへの接続とサービス・キャラクタリスティックの発見

接続が確立された後、BLEデバイスとのコミュニケーションを行うためには、その特性に対して読み取りや書き込みを実施する必要があります。場合によっては、接続中にデバイスのサービスやキャラクタリスティックセットが変更されることが非常に稀にあります。このような場合、追加のサービス探索が求められることがあります。接続したBLEデバイスと通信する際には、まずそのデバイスのサービスIDおよびキャラクタリスティックIDを確認することが重要です。

以下は特定のサービスUUIDとキャラクタリスティックUUIDを用いて値を読み取る例です。
// 特定の読み取りサービスUUIDとキャラクタリスティックUUIDを設定します。
const serviceUUID = 'YOUR_SERVICE_UUID';
const characteristicUUID = 'YOUR_CHARACTERISTIC_UUID';

// キャラクタリスティックから値を読み取る関数
const readCharacteristic = async () => {
const readData = await manager.ReadCharacteristicForDevice(deviceID, serviceUUID, characteristicUUID)
.then(readData => {
console.log("BLEデバイスから読み取ったデータ:", readData);
})
.catch(error => {
console.log("BLEデバイスからのデータ読み取り中にエラーが発生しました:", error);
});
};


このように、GATTプロトコルなど基本的なBLE通信の原理について理解しつつ、ペアリング方法や特定のUUIDによるサービス・キャラクタリスティックの識別についても把握しておくと良いでしょう。プラットフォームごとの具体的な実装例やエラーハンドリングも知識として加えることで、一層有益な情報となります。

BLEデバイスとの通信方法

デバイスから受信したデータはBase64形式ですので、必要に応じてデータを変換してください。**注意:** BLEデバイスのserviceUUIDおよびcharacteristicUUIDについて理解することが重要です。読み取るための特定の特性がない場合、そのデバイスからデータを読み取ることはできません。**例として、デバイスに値を書き込む方法:** 現在サポートされている2つの方法があります:- WriteWithResponse - WriteWithoutResponse // 具体的な書き込み用サービスUUIDと特性UUIDを仮定します const serviceUUID = 'YOUR_SERVICE_UUID'; const characteristicUUID = 'YOUR_CHARACTERISTIC_UUID'; // 応答ありで特性を書き込む関数```javascriptconst writeCharacteristic = async () => {await manager.writeCharacteristicWithResponseForDevice(deviceID, serviceUUID, characteristicUUID, valueBase64).then (value =>{console.log('書き込み成功: ', value);}).catch(error=>{console.log('書き込み失敗: ', error);})}]

通知機能を利用したデバイスからの応答取得法

デバイスに値を書き込む際、アプリケーションはペリフェラルからデータが正常に受信されたかの確認を期待します。ここで紹介する`writeWithoutResponse`関数は、応答なしで特性に書き込むためのものです。

const writeWithoutResponse = async () => {
await manager.writeCharacteristicWithoutResponseForDevice(deviceID, serviceUUID, characteristicUUID, valueBase64)
.then(value => {
console.log('書き込み成功: ', value);
})
.catch(error => {
console.log('書き込み失敗: ', error);
});
};


応答なしで値を書くことは通常より早く行えますが、ペリフェラルがデータを受信した保証はありませんので注意が必要です。**注記:** BLEデバイスに書き込むデータは必ずbase64形式である必要があります。このため、返答するデータもbase64フォーマットに変換してください。react-native-ble-plxではbase64形式のみをサポートしているためです。また、BLEデバイスのserviceUUIDとcharacteristicUUIDについて理解しておくことも重要です。もし書き込む特性が存在しない場合、そのデバイスにはデータを書き込むことができません。

さらに、BLEデバイスからの通知機能を活用すれば、通信の安定性や耐障害性について深い理解を得ることができます。このような情報を通じて、実装時の考慮点や具体的なプロファイルに基づいた応答取得方法も明確になるでしょう。

BLEデバイスからの切断手順

初めに、BLEデバイスと接続すると、そのデバイスがデータを送信することがあります。このデータを通知または監視するためには、`monitorCharacteristicForDevice`関数を使用します。**デバイスからの値を監視する例:**
// 特定の通知サービスUUIDおよび特性UUIDを仮定const serviceUUID = 'YOUR_SERVICE_UUID';const characteristicUUID = 'YOUR_CHARACTERISTIC_UUID';// デバイスからのデータを監視する関数const monitorCharateristicData= async () => {await manager.monitorCharacteristicForDevice(deviceID, serviceUUID, characteristicUUID).then(value =>{console.log('モニタリング成功: ', value);}).catch(error=>{console.log('モニタリング失敗: ', error);})}
- デバイスから受け取るデータはBase64形式であるため、必要に応じてそのデータを変換してください。**注意:** BLEデバイスのサービスUUIDと特性UUIDについて把握しておくことは重要です。通知用の特性がない場合、デバイスからの通知は行えません。**BLEデバイスとの切断:**- React NativeでBLEデバイスと正常に接続し、必要な操作が完了した後に切断機能を実装することで、接続管理や今後の操作への準備が整います。**切断するための例:**
// デバイスから切断する関数const disconnectFromDevice = async () => {await manager.cancelDeviceConnection(deviceID).then(device=>{console.log('切断成功: ', device);}).catch(error=>{console.log('切断失敗: ', error);})}
**注意:** 通信が完了した後には必ずこの切断関数を実行し、BLEデバイスとの接続を解除してください。

Reference Articles

React NativeアプリにおけるBLE通信を学ぶ #JavaScript

はじめにBLEの予備知識ゼロの状態からスタートして、BLE機器と通信するReact Nativeアプリを作るまでの道のり(経験談)を紹介します。

Source: Qiita

岡野 光夫 (Teruo Okano)

Expert

Related Discussions

❖ Related Articles