# react-native-ble-connect
[![npm version](https://img.shields.io/npm/v/react-native-ble-connect.svg?style=flat)](https://www.npmjs.com/package/react-native-ble-connect)
[![npm downloads](https://img.shields.io/npm/dm/react-native-ble-connect.svg?style=flat)](https://www.npmjs.com/package/react-native-ble-connect)
[![GitHub issues](https://img.shields.io/github/issues/petrykowskiM/react-native-ble-connect.svg?style=flat)](https://github.com/petrykowskim/react-native-ble-connect/issues)

This repsitory builds up on a fork of [react-native-ble-manager](https://github.com/innoveit/react-native-ble-manager) by innoveit.

##Requirements
RN 0.30+

##Supported Platforms
- iOS 8+
- Android (API 19+)

## Tips and Tricks for working with Bluetooth
You have to keep in mind that working with bluetooth is a pain in the a**. 
Here are some tips for your implementation that my lead to problems.

1. IOS and Android treat characteristic-ID's different according to their string case.
Android stores the characteristic strings in lower case, and IOS in upper case. Keep this in mind
when comparing characteristics.
2. Android and IOS have different abilities when it comes to the number of Bluetooth messages that can be send 
at the same time. To make sure that your app runs correctly on different devices try to only send one bluetooth
message at a time.

##Install
```shell
npm i --save react-native-ble-connect
```
####iOS
- Open the node_modules/react-native-ble-connect/ios folder and drag BleManager.xcodeproj into your Libraries group.
- Check the "Build Phases"of your project and add "libBleManager.a" in the "Link Binary With Libraries" section.

####Android
#####Update Gradle Settings

```gradle
// file: android/settings.gradle
...

include ':react-native-ble-connect'
project(':react-native-ble-connect').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-ble-connect/android')
```
#####Update Gradle Build

```gradle
// file: android/app/build.gradle
...

dependencies {
    ...
    compile project(':react-native-ble-connect')
}
```
#####Register React Package
```java
...
import it.innove.BleManagerPackage; // <--- import

public class MainApplication extends Application implements ReactApplication {

    ...

    @Override
    protected List<ReactPackage> getPackages() {
        return Arrays.<ReactPackage>asList(
            new MainReactPackage(),
            new BleManagerPackage() // <------ add the package
        );
    }

    ...
}
```
##Note
Android API >= 23 require the ACCESS_COARSE_LOCATION permission to scan for peripherals.
React Native >= 0.33 natively support PermissionsAndroid like in the example.

##Basic Example
```js
import React, { Component } from 'react';
import {
  AppRegistry,
  Text,
  View,
  TouchableHighlight,
  NativeAppEventEmitter,
  Platform,
  PermissionsAndroid
} from 'react-native';
import BleManager from 'react-native-ble-connect';

class BleExample extends Component {

    constructor(){
        super()

        this.state = {
            ble:null,
            scanning:false,
        }
    }

    componentDidMount() {
        BleManager.start({showAlert: false});
        this.handleDiscoverPeripheral = this.handleDiscoverPeripheral.bind(this);

        NativeAppEventEmitter
            .addListener('BleManagerDiscoverPeripheral', this.handleDiscoverPeripheral );
            
        if (Platform.OS === 'android' && Platform.Version >= 23) {
            PermissionsAndroid.checkPermission(PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION).then((result) => {
                if (result) {
                  console.log("Permission is OK");
                } else {
                  PermissionsAndroid.requestPermission(PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION).then((result) => {
                    if (result) {
                      console.log("User accept");
                    } else {
                      console.log("User refuse");
                    }
                  });
                }
          });
        }
    }

    handleScan() {
        BleManager.scan([], 30, true)
            .then((results) => {console.log('Scanning...'); });
    }

    toggleScanning(bool){
        if (bool) {
            this.setState({scanning:true})
            this.scanning = setInterval( ()=> this.handleScan(), 3000);
        } else{
            this.setState({scanning:false, ble: null})
            clearInterval(this.scanning);
        }
    }

    handleDiscoverPeripheral(data){
        console.log('Got ble data', data);
        this.setState({ ble: data })
    }

    render() {

        const container = {
            flex: 1,
            justifyContent: 'center',
            alignItems: 'center',
            backgroundColor: '#F5FCFF',
        }

        const bleList = this.state.ble
            ? <Text> Device found: {this.state.ble.name} </Text>
            : <Text>no devices nearby</Text>

        return (
            <View style={container}>
                <TouchableHighlight style={{padding:20, backgroundColor:'#ccc'}} onPress={() => this.toggleScanning(!this.state.scanning) }>
                    <Text>Scan Bluetooth ({this.state.scanning ? 'on' : 'off'})</Text>
                </TouchableHighlight>

                {bleList}
            </View>
        );
    }
}

AppRegistry.registerComponent('BleExample', () => BleExample);
```

##Methods

### start(options)
Init the module.
Returns a `Promise` object.

__Arguments__
- `options` - `JSON` 

The parameter is optional the configuration keys are:
- `showAlert` - `Boolean` - [iOS only] Show or hide the alert if the bluetooth is turned off during initialization

__Examples__
```js
BleManager.start({showAlert: false})
  .then(() => {
    // Success code
    console.log('Module initialized');
  });

```

### scan(serviceUUIDs, seconds)
Scan for availables peripherals.
Returns a `Promise` object.

__Arguments__
- `serviceUUIDs` - `Array of String` - the UUIDs of the services to looking for. On Android the filter works only for 5.0 or newer.
- `seconds` - `Integer` - the amount of seconds to scan. If 0 scan will last until stopped.
- `allowDuplicates` - `Boolean` - [iOS only] allow duplicates in device scanning

__Examples__
```js
BleManager.scan([], 5, true)
  .then(() => {
    // Success code
    console.log('Scan started');
  });

```

### stopScan()
Stop the scanning.
Returns a `Promise` object.

__Examples__
```js
BleManager.stopScan()
  .then(() => {
    // Success code
    console.log('Scan stopped');
  });

```

### connect(peripheralId)
Attempts to connect to a peripheral. In many case if you can't connect you have to scan for the peripheral before.
Returns a `Promise` object.

__Arguments__
- `peripheralId` - `String` - the id/mac address of the peripheral to connect, if succeeded contains the peripheral's services and characteristics infos.

__Examples__
```js
BleManager.connect('XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX')
  .then((peripheralInfo) => {
    // Success code
    console.log('Connected');
    console.log(peripheralInfo);
  })
  .catch((error) => {
    // Failure code
    console.log(error);
  });
```

### Pairing / Bonding
Pairing or also called Bonding of the mobile device with the bluetooth peripheral does not require an additional method. It works by accessing 
a secured characteristic of the peripheral after calling the connect name.

To sum it up. Perform following steps:

1. Call the connect function with the  peripheralId
2. Read a characteristic of the peripheral that is only accesible after bonding

Android performs the bonding process by itself, whereas ios asks the user whether to pair with the device. 

### disconnect(peripheralId)
Disconnect from a peripheral.
Returns a `Promise` object.

__Arguments__
- `peripheralId` - `String` - the id/mac address of the peripheral to disconnect.

__Examples__
```js
BleManager.disconnect('XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX')
  .then(() => {
    // Success code
    console.log('Disconnected');
  })
  .catch((error) => {
    // Failure code
    console.log(error);
  });
```

### enableBluetooth() [Android only]
Create the request to the user to activate the bluetooth.
Returns a `Promise` object.

__Examples__
```js
BleManager.enableBluetooth()
  .then(() => {
    // Success code
    console.log('The bluetooh is already enabled or the user confirm');
  })
  .catch((error) => {
    // Failure code
    console.log('The user refuse to enable bluetooth');
  });
```

### checkState()
Force the module to check the state of BLE and trigger a BleManagerDidUpdateState event.

__Examples__
```js
BleManager.checkState();
```

### startNotification(peripheralId, serviceUUID, characteristicUUID)
Start the notification on the specified characteristic.
Returns a `Promise` object.
Getting notifications with [NotificationEvent](#blemanagerdidupdatevalueforcharacteristic)

__Arguments__
- `peripheralId` - `String` - the id/mac address of the peripheral.
- `serviceUUID` - `String` - the UUID of the service.
- `characteristicUUID` - `String` - the UUID of the characteristic.

__Examples__
```js
BleManager.startNotification('XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX')
  .then(() => {
    // Success code
    console.log('Notification started');
  })
  .catch((error) => {
    // Failure code
    console.log(error);
  });
```

### stopNotification(peripheralId, serviceUUID, characteristicUUID)
Stop the notification on the specified characteristic.
Returns a `Promise` object.

__Arguments__
- `peripheralId` - `String` - the id/mac address of the peripheral.
- `serviceUUID` - `String` - the UUID of the service.
- `characteristicUUID` - `String` - the UUID of the characteristic.

### read(peripheralId, serviceUUID, characteristicUUID)
Read the current value of the specified characteristic.
Returns a `Promise` object.

__Arguments__
- `peripheralId` - `String` - the id/mac address of the peripheral.
- `serviceUUID` - `String` - the UUID of the service.
- `characteristicUUID` - `String` - the UUID of the characteristic.

__Examples__
```js
BleManager.read('XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX')
  .then((readData) => {
    // Success code
    console.log('Read: ' + readData);
  })
  .catch((error) => {
    // Failure code
    console.log(error);
  });
```


### write(peripheralId, serviceUUID, characteristicUUID, data, maxByteSize)
Write with response to the specified characteristic.
Returns a `Promise` object.

__Arguments__
- `peripheralId` - `String` - the id/mac address of the peripheral.
- `serviceUUID` - `String` - the UUID of the service.
- `characteristicUUID` - `String` - the UUID of the characteristic.
- `data` - `String` - the data to write in Base64 format.
- `maxByteSize` - `Integer` - specify the max byte size before splitting message

To get the `data` into base64 format, you will need a library like `base64-js`. Install `base64-js`:

`npm install base64-js --save`

To format the data before calling the write function:
```js
var base64 = require('base64-js');
var data = base64.fromByteArray(yourData);
```

__Examples__
```js
BleManager.write('XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', data)
  .then(() => {
    // Success code
    console.log('Write: ' + data);
  })
  .catch((error) => {
    // Failure code
    console.log(error);
  });
```

### writeWithoutResponse(peripheralId, serviceUUID, characteristicUUID, data, maxByteSize, queueSleepTime)
Write without response to the specified characteristic.
Returns a `Promise` object.

__Arguments__
- `peripheralId` - `String` - the id/mac address of the peripheral.
- `serviceUUID` - `String` - the UUID of the service.
- `characteristicUUID` - `String` - the UUID of the characteristic.
- `data` - `String` - the data to write in Base64 format.
- `maxByteSize` - `Integer` - (Optional) specify the max byte size
- `queueSleepTime` - `Integer` - (Optional) specify the wait time before each write if the data is greater than maxByteSize

To get the `data` into base64 format, you will need a library like `base64-js`. Install `base64-js`:

`npm install base64-js --save`

To format the data before calling the write function:
```js
var base64 = require('base64-js');
var data = base64.fromByteArray(yourData);
```

__Examples__
```js
BleManager.writeWithoutResponse('XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', data)
  .then(() => {
    // Success code
    console.log('Writed: ' + data);
  })
  .catch((error) => {
    // Failure code
    console.log(error);
  });
```

### getConnectedPeripherals(serviceUUIDs)
Return the connected peripherals.
Returns a `Promise` object.

__Arguments__
- `serviceUUIDs` - `Array of String` - the UUIDs of the services to looking for.

__Examples__
```js
BleManager.getConnectedPeripherals([])
  .then((peripheralsArray) => {
    // Success code
    console.log('Connected peripherals: ' + peripheralsArray.length);
  });

```

### getDiscoveredPeripherals()
Return the discovered peripherals after a scan.
Returns a `Promise` object.

__Examples__
```js
BleManager.getDiscoveredPeripherals([])
  .then((peripheralsArray) => {
    // Success code
    console.log('Discovered peripherals: ' + peripheralsArray.length);
  });

```

### isPeripheralConnected(peripheralId, serviceUUIDs)
Check whether a specific peripheral is connected and return `true` or `false`.
Returns a `Promise` object.

__Examples__
```js
BleManager.isPeripheralConnected('XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', [])
  .then((isConnected) => {
    if (isConnected) {
      console.log('Peripheral is connected!');
    } else {
      console.log('Peripheral is NOT connected!');
    }
  });

```

##Events
### BleManagerStopScan
The scanning for peripherals is ended.

__Arguments__
- `none`

__Examples__
```js
NativeAppEventEmitter.addListener(
    'BleManagerStopScan',
    () => {
        // Scanning is stopped
    }
);
```

###  BleManagerDidUpdateState
Gets fired on change of the device's Bluetooth state. 

__Arguments__
- `state` - `String` - the new BLE state ('on'/'off').

__Examples__
```js
NativeAppEventEmitter.addListener(
    'BleManagerDidUpdateState',
    (args) => {
        // The new state: args.state
    }
);
```

###  BleManagerDiscoverPeripheral
Will be fired after starting a scan and on every device found. It also fires multiple times for the same device if not configured differently when starting the scan.

__Arguments__
- `id` - `String` - the id of the peripheral
- `name` - `String` - the name of the peripheral

__Examples__
```js
NativeAppEventEmitter.addListener(
    'BleManagerDiscoverPeripheral',
    (newPeripheral) => {
        // The id: newPeripheral.id
        // The name: newPeripheral.name
    }
);
```

###  BleManagerDidUpdateValueForCharacteristic
A characteristic notify a new value.

__Arguments__
- `peripheral` - `String` - the id of the peripheral
- `characteristic` - `String` - the UUID of the characteristic
- `value` - `String` - the read value in Hex format

###  BleManagerConnectPeripheral
A peripheral was connected.

__Arguments__
- `peripheral` - `String` - the id of the peripheral

###  BleManagerDisconnectPeripheral
A peripheral was disconnected.

__Arguments__
- `peripheral` - `String` - the id of the peripheral
