はじめに
本記事では、ボタン押下でESP32というマイクロコンピュータにBLE(Bluetooth Low Energy)通信での接続をするAndroidスマホアプリケーションを作成していきます。
ReactNativeを用いたBLE通信機能であったり、Arduino言語を用いたESP32側の受信機能であったりの最小構成をまとめているつもりなので、そういった分野に興味がある方は是非読んでみてください。
目次
- はじめに
- 1. 前提条件
- 2. プロジェクトを作成する
- 3. パーミッションの設定
- 4. スマホアプリの画面作成
- 5. BLE接続処理作成
- 6. ESP32側のBLE通信処理作成
- 7. 動作確認
- おわりに
1. 前提条件
以下では、今回の開発で必要とするPC環境・ソフトウェア・電子部品等について記載しています。
ソフトウェアのインストールがまだ済んでいない場合や必要な機材が足りていない場合は、適宜ソフトのインストールや機材の購入をして対応しましょう。
1-1. 開発環境
本記事の開発を行う上で必要としている環境は以下の通りです。
項目 | 内容 |
---|---|
OS | Windows 10 / 11 |
スマホアプリ用エディタ | Visual Studio Code(以下、VSCode) |
ESP32用エディタ | ArduinoIDE |
スマホアプリ用実行環境 | Node.js |
スマホアプリ開発用クライアント | expo-dev-client |
スマホ実機 | スマートフォン(Android) |
まだ開発エディタや実行環境をPCにインストールしていない方は、以前私が書いたインストール手順の記事がありますので、以下を参考にインストールとセットアップを済ましてください。
なお、Expo Goでは動かないのでdev client必須になりますのでご注意ください。
- WindowsでVisual Studio Code(VSCode)のインストールと初期設定を行う手順
- WindowsにNode.jsをインストールする手順
- expo-dev-clientでReact Native(TypeScript)アプリをスマホ実機(Android)に表示する手順【Windows/Node.js/VSCode】
- マイコンESP32にArduinoIDEでプログラムを書き込んで実行するまでの手順
1-2. 使用機材
私が使用しているESP32とESP32をPCに接続するためのUSBケーブルは以下のものです。
項目 | 内容 | リンク |
---|---|---|
ESP32 | ESP32-DevKitC-32E ESP32-WROOM-32E開発ボード 4MB | リンク(秋月電子通商) |
通信用USBケーブル | Lumen microUSBケーブル | リンク(Amazon) |
購入サイトのリンクも載せていますが、これじゃないといけないというわけではありません。
ただし、USBケーブルに関しては充電用ではなく通信用の物を使わないとArduinoIDEがESP32を認識できないことがあるので注意です。
2. プロジェクトを作成する
それでは、ソースコードの製造を進めていきます。
まずはVSCodeでプロジェクトを作成しましょう。
今回は、「BLE-Connect-Demo」という名前のプロジェクトを作成しようと思います。
ここのプロジェクト名はなんでも良いので、皆さんのセンスで好きに決めていただいても大丈夫です。
なお、プロジェクトの作成方法については、「expo-dev-clientでReact Native(TypeScript)アプリをスマホ実機(Android)に表示する手順【Windows/Node.js/VSCode】」の「2-2.プロジェクトを作成する」を参考にしてみてください。
下記のようなプロジェクトをエクスプローラーに作成することができればOKです。
なお、本記事では、
expo-router
構成を用いたNavigation (TypeScript)
テンプレートを元に開発を進めますので、expo-router
構成に慣れていない方はexpo-router
のディレクトリ構成について調べてみるといいかもです。
3. パーミッションの設定
React Native(Expo)でBLE通信を行うには、Android側のパーミッション設定を明示的に行う必要があります。
以下ではパーミッションの設定の必要性と設定のやり方について解説していきます。
3-1. なぜパーミッションが必要なのか?
AndroidではBLE通信を行うために、OSのバージョンに応じて必要な権限(パーミッション)が異なります。
これらの権限を付与しないと、BLEスキャンや接続ができなかったり、アプリがクラッシュすることもあります。
3-2. Androidのバージョンごとの必要パーミッション一覧
使用するAndroidOSのバージョンによって、必要なパーミッションが変わってくるので、以下を参考にしましょう。
Androidバージョン | 必要なパーミッション |
---|---|
Android 11以下 |
BLUETOOTH , BLUETOOTH_ADMIN , ACCESS_FINE_LOCATION
|
Android 12以降 |
BLUETOOTH_SCAN , BLUETOOTH_CONNECT , ACCESS_FINE_LOCATION
|
3-3. パーミッションリクエスト処理の実装
Android 6.0以降では、アプリ起動中にパーミッションを動的にリクエストする必要があります。
パーミッションのリクエストはアプリの起動時に1度だけ行えばよいので、expo-router
構成の場合、アプリ全体の共通レイアウト・処理を定義しているapp/_layout.tsx
ファイルのRootLayout
関数にuseEffect
を用いて下記のようにソースコードを書きましょう。
// app/_layout.tsx
import { useEffect } from "react"; // import文追加(テンプレートに存在する場合は追記必要なし)
import { PermissionsAndroid, Platform } from "react-native"; // import文追加
/* ---他のテンプレートimport文省略--- */
/*
* Android端末においてBLE通信を行うために必要なパーミッションをリクエストする非同期関数
*/
async function requestBLEPermissions() {
if (Platform.OS === "android") {
try {
await PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
]);
} catch (err) {
console.warn("BLE permission error:", err);
}
}
}
/*
* アプリ全体に適用される共通処理を定義するレイアウトコンポーネント
* - 初回起動時にBLEのパーミッションをリクエストする
* @returns <Stack>ナビゲーションコンポーネントをラップした要素
*/
export default function RootLayout() {
/* ---他のテンプレート処理省略--- */
// 初回レンダリング時にBLEパーミッションをリクエストする
useEffect(() => {
requestBLEPermissions();
}, []);
return <RootLayoutNav />;
}
3-4. ソースコードの解説
「3-3. パーミッションリクエスト処理の実装」で記載したソースコードについて各処理ごとに解説します。
分かっているよという方は、読み飛ばして大丈夫です。
async function requestBLEPermissions() {
}
上記のように書くことで、BLEパーミッションをリクエストする非同期関数を定義しています。よくあるTypeScriptの書き方ですが、async
を使うことで非同期関数にしていることに注目です。
BLEの権限取得をする際、Androidがユーザーに「このアプリにBluetoothを使わせていい?」と確認し、ユーザがOKまたは拒否の操作をするまで待つことになります。
ユーザーの操作待ちの時間が発生するため、async
で非同期関数としているというわけです。
if (Platform.OS === "android") {
}
上記の処理では、アプリを実行している環境がAndroidかどうかのチェックをしています。
パーミッションのリクエスト処理はiOSでは不要な処理となっておりますので、Androidに限定しています。
今回はAndroid限定の解説ですが、iOSでもBLEを使う場合は NSBluetoothAlwaysUsageDescription を infoPlist に追加する必要があります。
await PermissionsAndroid.requestMultiple([
]);
上記の処理では、Androidパーミッション関連のAPIをまとめたオブジェクトであるPermissionsAndroid
モジュールのrequestMultiple
関数を使用することで、複数のパーミッションをまとめてリクエストします。
await
を使うことで、すべての権限のリクエストが完了するまで、パーミッションのリクエスト処理を待つようにしています。
PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
上記の処理では、リクエストするパーミッションを定義しています。
各パーミッションの内容については以下の通りです。
パーミッション名 | 説明 | 対象バージョン | 主な用途 |
---|---|---|---|
BLUETOOTH_SCAN |
周囲のBLEデバイスをスキャンするための権限 | Android 12(API 31)以降 | デバイス検索(スキャン) |
BLUETOOTH_CONNECT |
BLEデバイスと接続・通信するための権限 | Android 12(API 31)以降 | デバイスへの接続・読み書き |
ACCESS_FINE_LOCATION |
BLEスキャン時に位置情報を使うための権限(間接的) | Android 6.0(API 23)以降 | BLEスキャンに位置情報が必要な場合に要求される(11以前は必須) |
Android 11以前では、BLUETOOTH
/ BLUETOOTH_ADMIN
と ACCESS_FINE_LOCATION
があればBLE通信ができたが、Android 12からは「スキャン」「接続」が別々のパーミッションとして分かれたため、両方必要となっています。
ACCESS_FINE_LOCATION
は BLEスキャンに位置情報を使う関係で必要とされます(BLEがロケーション情報に使われるため)。
useEffect(() => {
requestBLEPermissions();
}, []);
上記のように、React
のuseEffect
関数を使うことで、アプリのレンダリング時の処理を定義しています。第二引数に[]
を指定することで、初回レンダリング時に1度だけ処理を行うようにしています。
そして、useEffectの処理の中でrequestBLEPermissions関数を呼び出すことで、初回レンダリング時に1度だけBLE権限のリクエストを行う処理が実装できます。
なお、フック順序の関係で、RootLayout
メソッドの開始すぐにこの処理を配置するようにしないとエラーになりますので、ご注意ください。
4. スマホアプリの画面作成
次にスマホアプリの画面を作成していきます。
画面を作成するにあたって主に使用するコンポーネントは、ReactNative
のSwitch
コンポーネントになります。スイッチをONにするとBLE通信が開始する仕組みを作っていきたいと思います。
4-1. Switchコンポーネント実装
それでは、ソースコードを書いていきましょう。
expo-router
構成では、エクスプローラーのapp/(tabs)/index.tsx
のファイルが、アプリを開いたとき最初に描画される画面のソースコードとなりますので、app/(tabs)/index.tsx
にSwitch
コンポーネントを書いていきましょう。
下記のようにソースコードを書いてみてください。
// app/(tabs)/index.tsx
// useStateフックをReactからインポート(状態管理用)
import { useState } from 'react';
// StyleSheet: スタイル定義, Switch: ON/OFFスイッチUI部品
import { StyleSheet, Switch } from 'react-native';
// Text, View を Themed コンポーネントからインポート(テーマ対応のUI)
import { Text, View } from '@/components/Themed';
// この画面コンポーネントをエクスポート
export default function TabOneScreen() {
// スイッチの状態を保持する変数(初期値: false = OFF)
const [isEnabled, setIsEnabled] = useState(false);
// スイッチが切り替わったときに呼ばれる関数
const handleSwitchChange = async (value: boolean) => {
// 新しい状態(true/false)を反映
setIsEnabled(value);
// ONになった場合の処理
if (value) {
try {
console.log("BLE接続処理を実装予定");
// ここでBLE接続処理を呼び出す予定
} catch (error) {
console.error("接続失敗:", error);
// 接続失敗時はスイッチをOFFに戻す
setIsEnabled(false);
}
} else {
console.log("BLE切断処理を実装予定");
// ここでBLE切断処理を呼び出す予定
}
};
// 実際に描画するUI
return (
<View style={styles.container}>
{/* ラベルテキスト */}
<Text style={styles.label}>BLE接続スイッチ</Text>
{/* 拡大したスイッチ */}
<Switch
value={isEnabled} // 現在のスイッチ状態
onValueChange={handleSwitchChange} // 切り替え時に呼ぶ関数
style={styles.switch} // スタイル(サイズ調整など)
/>
</View>
);
}
// スタイル定義
const styles = StyleSheet.create({
// 画面全体を中央寄せ
container: {
flex: 1,
alignItems: 'center', // 横方向中央
justifyContent: 'center', // 縦方向中央
},
// ラベル文字のスタイル
label: {
fontSize: 20, // 文字サイズ
marginBottom: 20, // 下に余白
},
// スイッチのスタイル(拡大表示)
switch: {
transform: [{ scale: 2 }], // 2倍に拡大
},
});
JSX(JavaScript XML)をreturnするところでSwitch
コンポーネントを記述しております。
Switch
のOn/Offの状態については、React
のuseState
フックで管理しています。
また、Switch
のonValueChange
プロパティでスイッチをON/OFFした際の処理を呼び出しおり、それがhandleSwitchChange
関数となります。
handleSwitchChange
関数内では、「BLE接続処理を実装予定」や「BLE切断処理を実装予定」と記述している箇所がありますが、BLE接続・切断処理については、次項以降で別途処理を作成して実装・解説していきます。
4-2. 画面表示してみる
それでは、「4-1. Switchコンポーネント実装」で実装したアプリ画面をお手元のAndroidスマホ実機で表示してみましょう。
アプリをビルド~Androidスマホにアプリをインストール~スマホ実機にアプリ表示する手順については、私が以前書いた「expo-dev-clientでReact Native(TypeScript)アプリをスマホ実機(Android)に表示する手順【Windows/Node.js/VSCode】」の記事を参考にしてみてください。
下記のようにアプリ画面が表示されれば成功です。
画面中央部にBLE接続スイッチの文字列とスイッチコンポーネントが表示されますが、まだスイッチをON/OFFしてもBLE接続機能は実装していないので何も起きません。
なので、次項以降でESP32にBLE接続する機能を実装していきたいと思います。
5. BLE接続処理作成
画面の作成が完了したら、次にスイッチをON/OFFした際のBLE接続・切断機能を作成していきたいと思います。
5-1. react-native-ble-plxのインストール
React Nativeアプリで Bluetooth Low Energy(BLE)通信を行うための部品として、react-native-ble-plx
というライブラリがあります。
まずは、VSCode
のターミナルでBLE-Connect-Demoプロジェクトファイルに移動した状態で、下記のコマンドを実行し、react-native-ble-plx
をインストールしましょう。
npx expo install react-native-ble-plx
5-2. libフォルダを作成する
BLE通信の処理についてもappフォルダ内のソースに記述していたら、1つのファイルのソースコード量が長くなってしまうので、今回はわかりやすいようにBLE通信処理を格納するlibフォルダを新規作成しようと思います。
下記画像のように、BLE-Connect-Demo
プロジェクトフォルダを右クリックし、新しいフォルダーを押下しましょう。
そうすると、新規作成するフォルダの名称を入力できるので、「lib」と入力してlibフォルダを新規作成しましょう。
なお、フォルダ名は変えても問題ないので、もしこだわりがあれば「lib」じゃなくてもいいです。
5-3. Ble.tsファイルをlibフォルダ下に作成する
libフォルダができたら、次にlibフォルダの中に今回BLE処理を作成するファイルを新規作成しましょう。
下記画像のように、libフォルダを右クリックし、新しいファイルをクリックしましょう。
新しいファイルをクリックすると、新規ファイルを作成し、ファイル名を入力できるようになりますので「Ble.ts」と入力しましょう。
なお、拡張子の「ts」は
TypeScript
で書かれたソースコードファイルのことを指します。今回はTypeScriptでソースコードを書いていきますので、拡張子より前は任意のファイル名でも問題ないですが、拡張子は必ず「.ts」にしてください。
5-4. BLE接続・切断処理を実装
それでは作成したBle.tsファイルにBLE接続・切断処理のソースコードを書いていきたいと思います。
下記のように書いてみてください。
// react-native-ble-plx から BLE 管理クラスとデバイス型をインポート
import { BleManager, Device } from 'react-native-ble-plx';
// BLE 接続やスキャンを管理するためのインスタンスを作成
const manager = new BleManager();
// 接続対象のデバイス名やUUIDを定義(ESP32 を想定)
const TARGET_DEVICE_NAME = 'ESP32'; // デバイス名
// 現在接続中のデバイスを保持する変数(接続していない場合は null)
let connectedDevice: Device | null = null;
/**
* BLE デバイスをスキャンして接続する処理
*/
export async function connectToDevice(): Promise<void> {
// Promise を返して、接続成功/失敗を外部で await できるようにする
return new Promise((resolve, reject) => {
// デバイススキャン開始(フィルタなし)
manager.startDeviceScan(null, null, async (error, device) => {
// エラー発生時の処理
if (error) {
manager.stopDeviceScan(); // スキャンを停止
reject(error); // 呼び出し元にエラーを返す
return;
}
// デバイス情報が取得できなかった場合はスキップ
if (!device) return;
// デバイス名が指定のものと一致するか確認
if (device.name === TARGET_DEVICE_NAME) {
manager.stopDeviceScan(); // 対象が見つかったらスキャン終了
try {
// デバイスに接続
const connected = await device.connect();
// 接続中デバイスとして保持
connectedDevice = connected;
// 接続成功ログ
console.log('接続成功:', connected.name);
// 成功として resolve を呼び出す
resolve();
} catch (err) {
// 接続やサービス取得に失敗した場合は reject
reject(err);
}
}
});
});
}
/**
* 現在接続中の BLE デバイスを切断する処理
*/
export async function disconnectDevice(): Promise<void> {
// 接続中デバイスがある場合
if (connectedDevice) {
try {
// 接続をキャンセル
await connectedDevice.cancelConnection();
console.log('切断完了');
// 接続中デバイスをクリア
connectedDevice = null;
} catch (error) {
// 切断失敗時のエラー表示
console.error('切断失敗:', error);
}
} else {
// そもそも接続されていない場合
console.log('切断対象デバイスなし');
}
}
5-5. BLE接続・切断処理のソースコード解説
それでは、BLE接続・切断処理のソースコードの構成について簡単に解説します。
解説するとはいっても、基本的に処理の内容としては、ソースコードに書いているコメント通りです。
react-native-ble-plx
ライブラリを用いてBLE通信を行う場合、react-native-ble-plx
ライブラリが提供するBleManager
というクラスを使用します。
BleManager
クラスは、スマホ側からBLEデバイス(例:ESP32)をスキャン・接続・通信するための操作窓口のような役割を持つreact-native-ble-plx
ライブラリの中心的クラスとなっており、本ソースコード上でも頻繁にBleManager
クラスのメソッドを使用しています。
// BLEデバイススキャン
manager.startDeviceScan(null, null, async (error, device) => {
}
本ソースコードの処理の流れとしては、connectToDevice
関数内の上記構文で、BleManager
クラスのstartDeviceScan
メソッドを用いて、周囲に存在するBLEデバイスの信号をスキャンしています。
スキャンして信号を発信するBLEデバイスが見つかった場合、第3引数のdevice
にBLEデバイス情報を格納する処理の流れとなっております。
// デバイス名が指定のものと一致するか確認
if (device.name === TARGET_DEVICE_NAME) {
manager.stopDeviceScan(); // 対象が見つかったらスキャン終了
try {
// デバイスに接続
const connected = await device.connect();
// 接続中デバイスとして保持
connectedDevice = connected;
/* 以下略 */
}
そして、見つかったBLEデバイス情報の名前が、TARGET_DEVICE_NAME
で指定したデバイス名である「ESP32」と等しい場合、BleManager
クラスのstopDeviceScan
メソッドでデバイススキャン処理を終了し、Deviceクラスのconnect
メソッドを用いてESP32に向けてBLE接続を開始しています。
なお、BleManager
クラスのstopDeviceScan
メソッドでデバイススキャン処理を終了しないと、デバイススキャンがずっと続いてしまう点には要注意です。
また、接続したBLEデバイス情報は、切断処理で使う用にconnectedDevice
変数にグローバルで保持します。
export async function disconnectDevice(): Promise<void> {
if (connectedDevice) {
try {
await connectedDevice.cancelConnection();
/* 以下略 */
disconnectDevice
関数の方では、connectToDevice
関数でキャッシュした接続BLEデバイス情報(ESP32のデバイス情報)が存在するかチェックし、存在した場合、cancelConnection
メソッドを用いて切断処理を行っています。
そして、これらの処理を画面側のSwitch切り替え時に呼び出す処理を次項で実装していきます。
5-6. 画面側からBLE接続・切断の呼び出し処理を実装
BLE接続・切断処理の作成が完了したら、今度はapp/(tabs)/index.tsx
ファイルを編集して、画面側からBLE接続・切断処理を呼び出す処理を書いていきましょう。
下記のように、SwitchのOn/Off切り替え時に実行されるhandleSwitchChange
関数内で、ONになった場合はconnectToDevice
メソッド、Offになった場合はdisconnectDevice
メソッドを呼び出せばOKです。
// app/(tabs)/index.tsx
import { connectToDevice, disconnectDevice } from '@/lib/Ble'; // 追記するimport文
const handleSwitchChange = async (value: boolean) => {
setIsEnabled(value);
if (value) {
try {
await connectToDevice(); // 追記する呼び出し処理
} catch (error) {
console.error("接続失敗:", error);
setIsEnabled(false);
}
} else {
await disconnectDevice(); // 追記する呼び出し処理
}
};
/* 以下略 */
6. ESP32側のBLE通信処理作成
それでは次に、ESP32側のBLE通信処理の作成をしていこうと思います。
ESP32にプログラムを書き込むためには、ArduinoIDEを使います。
ArduinoIDEのセットアップやプログラムを書き込み・コンパイル等については、以前私が書いた下記の記事を参考にしてみてください。
6-1. BLE通信処理実装(ESP32側)
それでは、ESP32に書き込むプログラムを作っていきましょう。
ArduinoIDEを開き、下記のようにスケッチを作成しましょう。
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
// ====== 設定 ======
static const char* DEVICE_NAME = "ESP32"; // React Native側と一致させる
// ====== グローバル ======
BLEServer* pServer = nullptr;
// 接続/切断のコールバック
class ServerCallbacks : public BLEServerCallbacks {
void onConnect(BLEServer* pServer) override {
Serial.println("Central connected.");
}
void onDisconnect(BLEServer* pServer) override {
Serial.println("Central disconnected. Restart advertising...");
// 切断時に再アドバタイズ
pServer->getAdvertising()->start();
}
};
void setup() {
Serial.begin(115200);
delay(200);
// BLE初期化
BLEDevice::init(DEVICE_NAME);
// サーバ作成 & コールバック設定
pServer = BLEDevice::createServer();
pServer->setCallbacks(new ServerCallbacks());
// アドバタイズ設定
BLEAdvertising* pAdvertising = BLEDevice::getAdvertising();
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06); // 接続性向上のための推奨設定
pAdvertising->setMinPreferred(0x12);
BLEDevice::startAdvertising();
Serial.println("Advertising started. Waiting for central...");
}
void loop() {
// 特にやることが無ければ空でOK
// 必要なら接続監視やタイムアウト処理などをここに追加
}
6-2. ソースコード解説
それでは、ESP32側のソースコードについて解説していきたいと思います。
まず、setup
関数がESP32のプログラム実行時の最初に実行される処理となります。
Serial.begin(115200);
上記のSerial
クラスは、Arduino(ESP32含む)環境でマイコンとPCとの間でシリアル通信を行うためのクラスとなっており、主にUSBケーブル経由でPCのシリアルモニタにデータを送る/受け取るのに使います。
今回はbegin
メソッドを用いて、シリアル通信を開始する形となっております。
なお、引数で指定している115200の数字は通信速度(ボーレート)となっておりまして、このボーレートはArduino IDEのシリアルモニタの設定と一致させる必要があります。
ボーレートの数値の目安はいくつかありますが、115200がArduinoやESP32でよく使う、高速で安定した通信速度となっております。
// BLE初期化
BLEDevice::init(DEVICE_NAME);
上記の処理でBLE機能の初期化とデバイス名の設定をしています。
デバイス名については、下記のようにグローバル変数で設定しています。
// ====== 設定 ======
static const char* DEVICE_NAME = "ESP32"; // React Native側と一致させる
コメントにも書いてありますが、デバイス名については、Androidアプリ側でBLEデバイスのスキャンを行う際に使用していますので、Androidアプリ側とESP32側でデバイス名を一致させる必要があります。
なお、今回はわかりやすくデバイス名を「ESP32」としておりますが、ここのデバイス名については任意で変更していただいても問題ないです。
// サーバ作成
pServer = BLEDevice::createServer();
上記の処理で、ESP32 をBLEサーバーとして動作させるためのインスタンスを作成しています。
このBLEサーバーは、サービスやキャラクタリスティックを持ってCentral(スマホなど)からの接続要求を受け付ける役割を持ちますので、必須処理となります。
// コールバック設定
pServer->setCallbacks(new ServerCallbacks());
上記の処理で、BLEサーバーとスマホ間でのBLE接続/切断などのイベント発生時に呼び出すクラスを設定しています。
呼び出すクラスは、ソースコード上部に記述している下記のServerCallbacks
クラスです。
// 接続/切断のコールバック
class ServerCallbacks : public BLEServerCallbacks {
void onConnect(BLEServer* pServer) override {
Serial.println("Central connected.");
}
void onDisconnect(BLEServer* pServer) override {
Serial.println("Central disconnected. Restart advertising...");
// 切断時に再アドバタイズ
pServer->getAdvertising()->start();
}
};
onConnect
メソッドは、スマホとのBLE接続時に実行される処理で、シリアルモニターに「Central connected.」という文字列を出力します。
onDisconnect
メソッドは、スマホとのBLE切断時に実行される処理で、シリアルモニターに「Central disconnected. Restart advertising...」という文字列を出力し、次に説明するアドバタイズと呼ばれる信号を再度発信します。
// アドバタイズ設定
BLEAdvertising* pAdvertising = BLEDevice::getAdvertising();
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06); // 接続性向上のための推奨設定
pAdvertising->setMinPreferred(0x12);
BLEDevice::startAdvertising();
ここでは、アドバタイズと呼ばれる、BLE通信における信号の広告を発信しています。
これを行うことで、スマホ側がBLEスキャン時に、ESP32をBLEデバイスとして認識することができるようになるので必須機能となります。
getAdvertising
でアドバタイズ設定用のオブジェクトを取得し、setScanResponse
でスキャン応答パケットを有効化、setMinPreferred
で接続パラメータの“希望値”を広告に載せるための設定をし、startAdvertising
で信号の広告の発信を開始しています。
なお、BLEのアドバタイズは基本的に接続されると自動で止まるので、BLE切断時に再度startAdvertising
を呼びなおすという処理の流れになっています。
7. 動作確認
ここまで実装できたら製造完了なので、動作確認をしていきましょう。
7-1. 再ビルドする
react-native-ble-plx
ライブラリを追加した後、easに再ビルドを行わないとBLE機能が動かないので、下記コマンドで再ビルドしてアプリをAndroidスマホにインストールしなおしましょう。
eas build -p android --profile development
7-2. BLE接続をする
ここまでできたら、実際にBLE接続を行っていきましょう。
「マイコンESP32にArduinoIDEでプログラムを書き込んで実行するまでの手順」の記事を参考にESP32のプログラムを実行し、ESP32を実行している状態でAndroidアプリを実行してSwitchをONに切り替えていきます。
まず、ESP32をPCに接続した状態でArduinoIDEにプログラムの書き込みを行うと、下記のようにアドバタイズの開始を示すログが表示されるかと思います。
Advertising started. Waiting for central...
アドバタイズの開始が確認出来たら、スマホアプリの方から下記のようにBLE接続スイッチをONに変更しましょう。
BLE接続スイッチをONにすると、下記のようにVSCodeのターミナル上に、ESP32にBLE接続したことを知らせるログが表示されるかと思います。
LOG 接続処理開始
LOG 接続成功: ESP32
ArduinoIDEのシリアルモニタの方も確認すると、下記のようにスマホとの接続の成功を知らせるログが表示されます。
Central connected.
ここまでできれば、BLE接続成功です。お疲れさまでした。
スイッチOFFにすると、切断したことを知らせるログも表示されますので、そちらも確認いただければと思います。
おわりに
いかがでしたでしょうか。
今回は、AndroidスマホからESP32にBLE通信で接続するまでの流れを1つの記事にまとめてみました。
VSCode側とArduinoIDE側とでソースコードを書く箇所が多いので大変かとは思いますが、最後まで読んでいただきありがとうございました。
みなさまの役に少しでも立ちましたら、いいね・コメント・フォロー等をいただけると幸いです。
ちなみに、本記事で使用したソースコードについては下記に格納しておりますので、よかったら参考にしてみてください。
次回は、接続時のモーダル制御とか状態制御とかタイムアウト制御とかの記事を書こうかな~とはなんとなく思ってますが、まだ決まってないです。
でも定期的に投稿はしていきたいなとは思ってます。
それでは、最後まで読んでいただきありがとうございました。