react-native-ble-plxを使ってみた

React Nativeのbluetoothライブラリreact-native-ble-plxを使ってみました

connect

RxBluetoothKit, RxAndroidBleを使ったことがあれば特につまづくことなくconnectまで実装できると思います。

作者が同じなので実装方法がだいぶ似ています。

検証用デバイスとしてtoio core cubeを使用しています。iosでコントローラアプリをリリースしているので買った際にはぜひ!!

import { BleManager } from 'react-native-ble-plx';

...省略..

    componentDidMount(){
      this.manager = new BleManager();
      //UUIDを指定しない場合全てのデバイスをスキャン
      this.manager.startDeviceScan(['10B20100-5B3B-4571-9508-CF3EFCD7BBAE'], {
            allowDuplicates: false
          }, (error, device) => {
            if (error) {
            console.error(`エラー: ${error}`);
            return
            }
            //検証用デバイスとしてtoioを使うので名前で絞っています。
            if (device.name === 'toio Core Cube') {
                console.log('cubeを検出したよ');
                this.peripheral = device;
                device.connect();
            }
        })
    }

Write

デバイスにwriteする値をBase64型で渡す必要があるのでキャストようにbufferを使います。以下のコマンドからインストールしてください。

npm install buffer

以下のように書き込むbyteの配列をキャストします。

const uint8Array = Uint8Array.from([0x01, 0x02, 0x03]);
const writeData = Util.uit8ArrayToBase64(uint8Array)

実際にデバイスへ書き込む際のコードはこんな感じです。

Writeのメソッドが複数用意されているので使用するデバイスのcharacteristicの属性によってどのメソッドを使うかが変わります。

async soundEffect(device){
        //書き込むデータのキャスト
        const uint8Array = Uint8Array.from([0x02, 0x09, 0xFF]);
        const writeData = Util.uit8ArrayToBase64(uint8Array)

        const characteristics = await device.characteristicsForService('10B20100-5B3B-4571-9508-CF3EFCD7BBAE');
        const control = await characteristics.filter((c) => {
            return c.uuid === '10b20104-5b3b-4571-9508-cf3efcd7bbae';
          })[0];
        await control.writeWithResponse(writeData);
    }

コード一覧

ConnectとWriteでボタンを2つ用意しているだけのコードです。

例外処理は行ってないので結構ガバガバですがwriteまでの道のりの参考になれば幸いです。

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Button,
  Text,
  View,
} from 'react-native';
import { Buffer } from 'buffer';
import { BleManager } from 'react-native-ble-plx';

export class PlxTest extends React.Component {

    constructor(){
        super();
        this.peripheral = null;
    }
    componentDidMount(){
      this.manager = new BleManager();
    }

    onPressStart(){
        this.manager.startDeviceScan(['10B20100-5B3B-4571-9508-CF3EFCD7BBAE'], {
            allowDuplicates: false
          }, (error, device) => {
            if (error) {
            console.error(`エラー: ${error}`);
            return
            }
            if (device.name === 'toio Core Cube') {
                if (device.id != "FD:E6:8E:2A:F0:48") return
                    if (this.peripheral) {
                        this.manager.stopDeviceScan()
                        return
                    }
                    device.connect()
                    .then((device)=> {
               //こいつを呼び出さないとwriteできません!
                        device.discoverAllServicesAndCharacteristics()
                    });
                    this.peripheral = device;
            }
        })
    }
    onPressSoundEffect() {
        if (!this.peripheral) return
		
        this.soundEffect(this.peripheral).then(() => {
            console.log('soundEffect success')
          }).catch((err) => {
            console.log(`soundEffect error = ${err}`);
          });
  
    }

    async soundEffect(device){
        //書き込むデータのキャスト
        const uint8Array = Uint8Array.from([0x02, 0x09, 0xFF]);
        const writeData = Util.uit8ArrayToBase64(uint8Array)

        const characteristics = await device.characteristicsForService('10B20100-5B3B-4571-9508-CF3EFCD7BBAE');
        const control = await characteristics.filter((c) => {
            return c.uuid === '10b20104-5b3b-4571-9508-cf3efcd7bbae';
          })[0];
        await control.writeWithResponse(writeData);
    }
    
    render() {
        return (
        <View style={styles.container}>
            <View style={styles.buttonContainer}>
                <Button
                    onPress={this.onPressStart.bind(this)}
                    title="Start"
                    color="#841584"
                />
            </View>

            <View style={styles.buttonContainer}>
                <Button
                    onPress={this.onPressSoundEffect.bind(this)}
                    title="WriteValue"
                    color="#841584"
                />
            </View>
            <Text style={styles.welcome}>
            Hello ble-plx
            </Text>
        </View>
        );
    }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  buttonContainer: {
    width: 200,
    padding:5,
    backgroundColor:'#8f1f8f',
    margin: 5
  },
  welcome: {
    fontSize: 40,
    textAlign: 'center',
    margin: 10,
  },
});

参考文献

react-native-ble-plx