Connect, fetch and read data from BLE devices with React-Native

By StartxLabs
Date 03-11-20
Connect, fetch and read data from BLE devices with React-Native
" Connect, fetch and read data from BLE devices with React-Native"

Connect, fetch and read data from BLE devices with React-Native

First of all, we should go through the basic definition of BLE.

BLE is a relatively new Bluetooth standard defined by the Bluetooth Special Interest Group (SIG) with a focus on low energy. It has enabled device manufacturers to add a low power communications interface on existing solutions.

A common interaction pattern from a central device is as follows:

  • Scan for peripherals advertising defined BLE service types by UUID
  • Connect to a selected peripheral
  • Discover services on the connected peripheral
  • Discover characteristics on the services of interest on the peripheral
  • Read or write values to the characteristics of interest
  • Disconnect when connection no longer needed

Now, the next challenge is that how can we implement the required above milestones in react native.

We will be library named react-native-ble-plx. This library is very stable and below are the commands to install it.

npm install --save react-native-ble-plx

 

Instructions for iOS:

1. Open Xcode workspace located inside ios folder and add empty Swift file if you don't have at least one:

  • Select File/New/File…
  • Choose Swift file and click Next.
  • Name it however you want, select your application target and create it.
  • Accept to create Objective-C bridging header.
  •  

2. Update your ios/Podfile to contain (it may be already there):

pod 'react-native-ble-plx', :path => '../node_modules/react-native-ble-plx'

 

3. Open terminal and move to ios folder of project and run 

pod install

 

4. Open Xcode, and find info.plist. Right click and open as Source Code. Paste below key value pair. 

<key>NSBluetoothAlwaysUsageDescription</key>
<string>YOUR_DESCRIPTION_WHY_THIS_APP_REQUIRES_BLUETOOTH_ACCESS</string>

 

5. If you want to support background mode:

  • In your application target go to Capabilities tab and enable Uses Bluetooth LE Accessories in Background Modes section.
  • Pass restoreStateIdentifier and restoreStateFunction to BleManager constructor.

Instructions for Android.

1. In top level build.gradle make sure that min SDK version is at least 18:

buildscript {
    ext {
        ...
        minSdkVersion = 18
        ...

 

2. In build.gradle make sure to add jitpack repository to known repositories:

allprojects {
    repositories {
      ...
      maven { url 'https://www.jitpack.io' }
    }
}

 

3. In AndroidManifest.xml, add Bluetooth permissions and update <uses-sdk/>:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    <uses-permission android:name="android.permission.BLUETOOTH"/>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
    <uses-permission-sdk-23 android:name="android.permission.ACCESS_FINE_LOCATION"/>

    <!-- Add this line if your application always requires BLE. More info can be found on:
         https://developer.android.com/guide/topics/connectivity/bluetooth-le.html#permissions
      -->
    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

    ...

Next step is to manage/access Bluetooth permissions from user.

For iOS, the fourth step in installation procedure will show an alert to user for granting permissions for accessing bluetooth.

For Android, we need to add following permissions.

  • BLUETOOTH : Allows applications to connect to paired bluetooth devices.
  • BLUETOOTH_ADMIN: Allows applications to discover and pair bluetooth devices.
  • ACCESS_COARSE_LOCATION: Allows an app to access approximate location.

For enabling these permissions, add below code in androidmanfest.xml.

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

Regarding why we weed location permission, you can get further information from https://www.polidea.com/blog/a-curious-relationship-android-ble-and-location/ 

Lets move to implementation part of process.

First step is to create BleManager instance which is an entry point to all available APIs. Make sure to create it after application started its execution. For example we can do it in Component’s constructor:

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

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

 

When iOS application launches BLE stack is not immediately available and we need to check its status. To detect current state and following state changes we can use onStateChange() function:

componentWillMount() {
    const subscription = this.manager.onStateChange((state) => {
        if (state === 'PoweredOn') {
            this.scanAndConnect();
            subscription.remove();
        }
    }, true);
}

 

Devices needs to be scanned first to be able to connect to them. There is a simple function which allows only one callback to be registered to handle detected devices:

scanAndConnect() {
    this.manager.startDeviceScan(null, null, (error, device) => {
        if (error) {
            // Handle error (scanning will be stopped automatically)
            return
        }

        // Check if it is a device you are looking for based on advertisement data
        // or other criteria.
        if (device.name === 'TI BLE Sensor Tag' || 
            device.name === 'SensorTag') {
            
            // Stop scanning as it's not necessary if you are scanning for one device.
            this.manager.stopDeviceScan();

            // Proceed with connection.
        }
    });
}

 

Once device is scanned it is in disconnected state. We need to connect to it and discover all services and characteristics it contains. Services may be understood as containers grouping characteristics based on their meaning. Characteristic is a container for a value which can be read, written and monitored based on available capabilities. For example connection may look like this:

device.connect()
    .then((device) => {
        return device.discoverAllServicesAndCharacteristics()
    })
    .then((device) => {
       // Do work on device with services and characteristics
    })
    .catch((error) => {
        // Handle errors
    });

As the data we read from Ble device is encrypted so, we have to decode that using base64 decode.

For this, we will install another npm package named Buffer.

Run the following command to install Buffer in your project.

npm i buffer

 

You can use buffer package to decode data in following way.

import { Buffer } from 'buffer';
Buffer.from(VALUE_READ_FROM_BLE_DEVICE, 'Base-64')

 

Conclusion

Congratulations! You have successfully read the data from BLE devices. Now you can this data according to your application requirements.

 

For any questions, feedbacks, please e-mail us- [email protected]

Thank You.

subscribe to startxlabs

startxlabs