4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Raspberry Pi zero whのBLEとAndroidアプリ(react-native)で通信する

Posted at

Raspberry Pi zero whのBLEモジュールとAndroidアプリ(react-native)を繋げるのに少し苦労したので備忘録として書きます。

環境

ここでは、Raspberry Pi zero wh と Android(react-native) の間でBLEを使った通信をすることを想定しています。

なお、Raspberry Pi側のプログラムはgolangで書きます。

準備

BLE開発に必要な概念

これだけはまず知っておいた方がいい、という基礎知識です。

BLE概論系の記事には色々と難しい言葉が並んでいますが、まず覚える必要があるのは次の2つだけです。

  • サーバー(ペリフェラル)
  • クライアント(セントラル)

サーバー

サーバー(ペリフェラル)は、デバイス側を表します。つまりここではRaspberry Pi側です。

クライアント

クライアント(セントラル)はここではAndroid側です。

サーバーはRaspberry Pi、クライアントはAndroid。これだけ覚えておきましょう。

BLEのアプリケーションを識別するのに必要な値

BLEモジュールと通信するために、そのBLEモジュールを使っているアプリケーションを識別する値が必要になります。これが以下の二つです。

  • MACアドレス
  • UUID (service UUIDとcharacteristic UUIDの2種)

ここで、MACアドレスはBLEモジュールに固有の値で、 hciconfig などで確認することができます。
2種のUUIDはアプリケーション側で設定できる値で、任意の値を使うことができます。

MACアドレスの確認

ではまずBLEモジュールのMACアドレスを確認します。Raspberry Piで以下のコマンドを実行してください。

pi@raspberrypi:~ $ sudo hciconfig
hci0:        Type: Primary  Bus: UART
        BD Address: B8:26:EB:BA:3C:11  ACL MTU: 1021:8  SCO MTU: 64:1
        UP RUNNING PSCAN
        RX bytes:15221 acl:0 sco:0 events:530 errors:0
        TX bytes:17899 acl:18 sco:0 commands:722 errors:0

pi@raspberrypi:~ $

ここでのMACアドレスはB8:26:EB:BA:3C:11ですね。メモしておきましょう。

golangでBLEサーバーの作成

まずはただ動いて欲しいので、github.com/paypal/gattというライブラリのサンプルをそのまま使います。 https://github.com/paypal/gatt

こいつをビルドしてRaspberry Pi上で実行しましょう。(sudo を忘れないように)

pi@raspberrypi:~ $ sudo ./gatt_server_lnx
2018/04/07 09:48:34 dev: hci0 up
2018/04/07 09:48:34 dev: hci0 reset
2018/04/07 09:48:34 dev: hci0 down
2018/04/07 09:48:34 dev: hci0 opened
State: PoweredOn
2018/04/07 09:48:34 BD Addr: B8:26:EB:BA:3C:11
2018/04/07 09:48:34 Generating attribute table:
2018/04/07 09:48:34 handle	type	props	secure	pvt	value
2018/04/07 09:48:34 0x0001	0x2800	0x02	0x00	*gatt.Service	[ 00 18 ]
2018/04/07 09:48:34 0x0002	0x2803	0x02	0x00	*gatt.Characteristic	[ 02 03 00 00 2A ]
2018/04/07 09:48:34 0x0003	0x2a00	0x02	0x00	*gatt.Characteristic	[ 47 6F 70 68 65 72 ]
2018/04/07 09:48:34 0x0004	0x2803	0x02	0x00	*gatt.Characteristic	[ 02 05 00 01 2A ]
2018/04/07 09:48:34 0x0005	0x2a01	0x02	0x00	*gatt.Characteristic	[ 00 80 ]
2018/04/07 09:48:34 0x0006	0x2803	0x02	0x00	*gatt.Characteristic	[ 02 07 00 02 2A ]
2018/04/07 09:48:34 0x0007	0x2a02	0x02	0x00	*gatt.Characteristic	[ 00 ]
2018/04/07 09:48:34 0x0008	0x2803	0x02	0x00	*gatt.Characteristic	[ 02 09 00 03 2A ]
2018/04/07 09:48:34 0x0009	0x2a03	0x02	0x00	*gatt.Characteristic	[ 00 00 00 00 00 00 ]
2018/04/07 09:48:34 0x000A	0x2803	0x02	0x00	*gatt.Characteristic	[ 02 0B 00 04 2A ]
2018/04/07 09:48:34 0x000B	0x2a04	0x02	0x00	*gatt.Characteristic	[ 06 00 06 00 00 00 D0 07 ]
2018/04/07 09:48:34 Generating attribute table:
2018/04/07 09:48:34 handle	type	props	secure	pvt	value
2018/04/07 09:48:34 0x0001	0x2800	0x02	0x00	*gatt.Service	[ 00 18 ]
2018/04/07 09:48:34 0x0002	0x2803	0x02	0x00	*gatt.Characteristic	[ 02 03 00 00 2A ]
...略

react-native側

react-native側は、 https://github.com/innoveit/react-native-ble-manager というライブラリを使って通信します。

コード片で申し訳ないのですが、こんな感じのコードを書きます。

  startScan() {
    if (!this.state.scanning) {
      this.setState({peripherals: new Map()});
      BleManager.scan([], 3, true).then((results) => {
        console.log('Scanning...');
        this.setState({scanning: true});
        console.log(results)
      });
    }

    BleManager.getConnectedPeripherals([]).then((results) => {
      console.log(results);
      var peripherals = this.state.peripherals;
      for (var i = 0; i < results.length; i++) {
        var peripheral = results[i];
        peripheral.connected = true;
        peripherals.set(peripheral.id, peripheral);
        console.log(peripheral)
        this.setState({ peripherals });
      }
    });

    BleManager.connect("B8:26:EB:BA:3C:11").then(() => {
      console.log('Connected');
    }).catch((error) => {
      // Failure code
      console.log(error);
    })

    BleManager.retrieveServices("B8:26:EB:BA:3C:11").then((peripheralInfo) => {
      // Success code
      console.log('Peripheral info:', peripheralInfo);
    });

    const data = stringToBytes("piyo");
    console.log(data)
    BleManager.write("B8:26:EB:BA:3C:11", "09fc95c0-c111-11e3-9904-0002a5d5c51b", "16fe0d80-c111-11e3-b8c8-0002a5d5c51b", data).then(() => {
      // Success code
      console.log('Write: ' + data);
    }).catch((error) => {
      // Failure code
      console.log(error);
    });
  }

ここで大事な点が2点あります。まず1つ目は、 read, write, notifyの前には必ずBleManager.retrieveServices()を実行しなくてはいけない ことです。
普通にドキュメントに書いてあるのですが、忘れがちみたいです。
https://github.com/innoveit/react-native-ble-manager/issues/259

次に、2つのUUIDについてです。これらはpaypal/gattのexampleに書いてあります。

まず、serviceUUIDは https://github.com/paypal/gatt/blob/4ae819d591cfc94c496c45deb55928469542beec/examples/service/count.go#L13 です。

そして、characteristicUUIDは https://github.com/paypal/gatt/blob/4ae819d591cfc94c496c45deb55928469542beec/examples/service/count.go#L20 です。

雑に書きましたがこんな感じです。

4
2
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
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?