0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AndroidスマホからESP32(マイコン)にBLE通信で接続してみた

Posted at

はじめに

本記事では、ボタン押下でESP32というマイクロコンピュータにBLE(Bluetooth Low Energy)通信での接続をするAndroidスマホアプリケーションを作成していきます。
ReactNativeを用いたBLE通信機能であったり、Arduino言語を用いたESP32側の受信機能であったりの最小構成をまとめているつもりなので、そういった分野に興味がある方は是非読んでみてください。

目次

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必須になりますのでご注意ください。

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です。

BLE-Connect-Demo.png

なお、本記事では、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_ADMINACCESS_FINE_LOCATION があればBLE通信ができたが、Android 12からは「スキャン」「接続」が別々のパーミッションとして分かれたため、両方必要となっています。

ACCESS_FINE_LOCATION は BLEスキャンに位置情報を使う関係で必要とされます(BLEがロケーション情報に使われるため)。

useEffect(() => {
    requestBLEPermissions();
 }, []);

上記のように、ReactuseEffect関数を使うことで、アプリのレンダリング時の処理を定義しています。第二引数に[]を指定することで、初回レンダリング時に1度だけ処理を行うようにしています。

そして、useEffectの処理の中でrequestBLEPermissions関数を呼び出すことで、初回レンダリング時に1度だけBLE権限のリクエストを行う処理が実装できます。

なお、フック順序の関係で、RootLayoutメソッドの開始すぐにこの処理を配置するようにしないとエラーになりますので、ご注意ください。

4. スマホアプリの画面作成

次にスマホアプリの画面を作成していきます。

画面を作成するにあたって主に使用するコンポーネントは、ReactNativeSwitchコンポーネントになります。スイッチをONにするとBLE通信が開始する仕組みを作っていきたいと思います。

4-1. Switchコンポーネント実装

それでは、ソースコードを書いていきましょう。

expo-router構成では、エクスプローラーのapp/(tabs)/index.tsxのファイルが、アプリを開いたとき最初に描画される画面のソースコードとなりますので、app/(tabs)/index.tsxSwitchコンポーネントを書いていきましょう。

下記のようにソースコードを書いてみてください。

// 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の状態については、ReactuseStateフックで管理しています。

また、SwitchonValueChangeプロパティでスイッチを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】」の記事を参考にしてみてください。

下記のようにアプリ画面が表示されれば成功です。

アプリ画面.png

画面中央部に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プロジェクトフォルダを右クリックし、新しいフォルダーを押下しましょう。

新しいフォルダー.png

そうすると、新規作成するフォルダの名称を入力できるので、「lib」と入力してlibフォルダを新規作成しましょう。

libフォルダ.png

なお、フォルダ名は変えても問題ないので、もしこだわりがあれば「lib」じゃなくてもいいです。

5-3. Ble.tsファイルをlibフォルダ下に作成する

libフォルダができたら、次にlibフォルダの中に今回BLE処理を作成するファイルを新規作成しましょう。

下記画像のように、libフォルダを右クリックし、新しいファイルをクリックしましょう。

新しいファイル.png

新しいファイルをクリックすると、新規ファイルを作成し、ファイル名を入力できるようになりますので「Ble.ts」と入力しましょう。

Ble.ts.png

なお、拡張子の「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に変更しましょう。

SwitchON.png

BLE接続スイッチをONにすると、下記のようにVSCodeのターミナル上に、ESP32にBLE接続したことを知らせるログが表示されるかと思います。

 LOG  接続処理開始
 LOG  接続成功: ESP32

ArduinoIDEのシリアルモニタの方も確認すると、下記のようにスマホとの接続の成功を知らせるログが表示されます。

Central connected.

ここまでできれば、BLE接続成功です。お疲れさまでした。
スイッチOFFにすると、切断したことを知らせるログも表示されますので、そちらも確認いただければと思います。

おわりに

いかがでしたでしょうか。
今回は、AndroidスマホからESP32にBLE通信で接続するまでの流れを1つの記事にまとめてみました。
VSCode側とArduinoIDE側とでソースコードを書く箇所が多いので大変かとは思いますが、最後まで読んでいただきありがとうございました。
みなさまの役に少しでも立ちましたら、いいね・コメント・フォロー等をいただけると幸いです。

ちなみに、本記事で使用したソースコードについては下記に格納しておりますので、よかったら参考にしてみてください。

次回は、接続時のモーダル制御とか状態制御とかタイムアウト制御とかの記事を書こうかな~とはなんとなく思ってますが、まだ決まってないです。
でも定期的に投稿はしていきたいなとは思ってます。

それでは、最後まで読んでいただきありがとうございました。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?