LoginSignup
4
2

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