From da2e8601e45a6a4b65983c8ec5aab1d9b769b643 Mon Sep 17 00:00:00 2001 From: intent-kacper-cyranowski <143452571+intent-kacper-cyranowski@users.noreply.github.com> Date: Wed, 17 Jul 2024 10:44:03 +0200 Subject: [PATCH] Chore/add tutorials (#1221) * chore: add tutorials --- README.md | 3 +- INTRO.md => docs/GETTING_STARTED.md | 61 +++++++---- docs/TUTORIALS.md | 108 +++++++++++++++++++ docs/index.html | 157 ++++++++++++++++++++++++---- documentation.yml | 7 +- 5 files changed, 290 insertions(+), 46 deletions(-) rename INTRO.md => docs/GETTING_STARTED.md (74%) create mode 100644 docs/TUTORIALS.md diff --git a/README.md b/README.md index 68d7a55e..ac965350 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ It does NOT support: - bluetooth classic devices. - communicating between phones using BLE (Peripheral support) - [bonding peripherals](https://github.com/dotintent/react-native-ble-plx/wiki/Device-Bonding) +- [beacons](https://github.com/dotintent/react-native-ble-plx/wiki/=-FAQ:-Beacons) ## Table of Contents @@ -43,7 +44,7 @@ For old RN versions (<0.60) please check [old README](./docs/README_V1.md) (1.x) for the old instructions or [migration guide](./docs/MIGRATION_V1.md). | React Native | 3.1.2 | -|--------------| ------------------ | +| ------------ | ------------------ | | 0.74.1 | :white_check_mark: | | 0.69.6 | :white_check_mark: | | Expo 51 | :white_check_mark: | diff --git a/INTRO.md b/docs/GETTING_STARTED.md similarity index 74% rename from INTRO.md rename to docs/GETTING_STARTED.md index fcde8afc..c746f08a 100644 --- a/INTRO.md +++ b/docs/GETTING_STARTED.md @@ -1,31 +1,52 @@ -
This guide is an introduction to BLE stack and APIs exported by this library. All examples will be based on CC2541 SensorTag.
-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 keep it -as a static reference:
+In the case of Expo, you will need to prepare a plugin config, detailed information can be found here: https://github.com/dotintent/react-native-ble-plx?tab=readme-ov-file#expo-sdk-43 +In the case of react native CLI you need to configure two environments:
+ +First step is to create BleManager instance which is an entry point to all available APIs. It should be declared OUTSIDE the life cycle of React. Make sure to create it after application started its execution. We can keep it as a static reference by either creating our own abstraction (ex.1) or by simply creating a new instance (ex.2).
+import { BleManager } from 'react-native-ble-plx'
+
+// create your own singleton class
+class BLEServiceInstance {
+ manager: BleManage
+
+ constructor() {
+ this.manager = new BleManager()
+ }
+}
+
+export const BLEService = new BLEServiceInstance()
+import { BleManager } from 'react-native-ble-plx'
export const manager = new BleManager()
-Only one instance of BleManager is allowed. When you don't need any BLE functionality you
-can destroy created instance by calling manager.destroy()
function. You can then recreate
-BleManager
later on.
Note that you may experience undefined behaviour when calling a function on one BleManager
-and continuing with another instance. A frequently made error is to create a new instance
-of the manager for every re-render of a React Native Component.
Only one instance of BleManager is allowed. When you don't need any BLE functionality you can destroy created instance by calling manager.destroy()
function. You can then recreate BleManager
later on.
Note that you may experience undefined behavior when calling a function on one BleManager
and continuing with another instance. A frequently made error is to create a new instance of the manager for every re-render of a React Native Component.
Check if you requested following permissions
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:
React.useEffect(() => {
@@ -2040,7 +2065,7 @@ Waiting for Powered On state
}, true)
return () => subscription.remove()
}, [manager])
-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:
function scanAndConnect() {
@@ -2063,9 +2088,9 @@ Scanning devices
It is worth to note that scanning function may emit one device multiple times. However
when device is connected it won't broadcast and needs to be disconnected from central
to be scanned again. Only one scanning listener can be registered.
-Bluetooth 5 Advertisements in Android
+Bluetooth 5 Advertisements in Android
To see devices that use Bluetooth 5 Advertising Extension you have to set the legacyScan
variable to false
in Scan options when you are starting BleManager.startDeviceScan(),
-Connecting and discovering services and characteristics
+Connecting and discovering services and characteristics
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
@@ -2086,14 +2111,100 @@
Connecting and discovering services and characteristics
It can be a long process depending on number of characteristics and services available.
* Extremely rarely, when peripheral's service/characteristic set can change during a connection
an additional service discovery may be needed.
-Read, write and monitor values
+Read, write and monitor values
After successful discovery of services you can call
and other functions which are described in detail in documentation.
+and other functions which are described in detail in documentation. You can also check our example app which is available in the repository.
+ + +onDeviceDisconnected
method allows you to monitor the disconnection of a device, more about the method can be found BleManager.onDeviceDisconnected(). Using it you can implement your own logic to handle the disconnection event. For example, you can try to reconnect to the device or show a notification to the user.
Note: connection will be monitored only when app is in foreground.
+const setupOnDeviceDisconnected = (deviceIdToMonitor: String) => {
+ bleManagerInstance.onDeviceDisconnected(deviceIdToMonitor, disconnectedListener)
+}
+
+const disconnectedListener = (error: BleError | null, device: Device | null) => {
+ if (error) {
+ console.error(JSON.stringify(error, null, 4))
+ }
+ if (device) {
+ console.info(JSON.stringify(device, null, 4))
+
+ // reconnect to the device
+ device.connect()
+ }
+}
+The first thing you need to do is connect to your device. Once the connection is established you can only perform basic operations without the possibility of interacting with the services on the device. To be able to interact with the services on the device, so you need to call an additional command device.discoverAllServicesAndCharacteristics()
because even though you know what service and characteristics are on the device, they all must be visible to the GATT client, which handles all operations.
device
+ .connect()
+ .then(device => {
+ return device.discoverAllServicesAndCharacteristics()
+ })
+ .then(device => {
+ // A fully functional connection you can use, now you can read, write and monitor values
+ })
+ .catch(error => {
+ // Handle errors
+ })
+To read a value from a characteristic, you need to call the readCharacteristic
method on the device object. The method returns a promise that resolves to the characteristic value.
device
+ .readCharacteristicForService(serviceUUID, characteristicUUID)
+ .then(characteristic => {
+ console.log('Read characteristic value:', characteristic.value)
+ })
+ .catch(error => {
+ console.error('Read characteristic error:', error)
+ })
+To write a value to a characteristic, you need to call the writeCharacteristicWithResponse
or writeCharacteristicWithoutResponse
method on the device object. The method returns a promise that resolves when the write operation is completed.
device
+ .writeCharacteristicWithResponseForService(serviceUUID, characteristicUUID, value)
+ .then(() => {
+ console.log('Write characteristic success')
+ })
+ .catch(error => {
+ console.error('Write characteristic error:', error)
+ })
+If you want to connect to a device that isn't discoverable because it is already connected to the system, you can use the getConnectedDevices
method to get a list of connected devices. Then you can use the connect
method on the device object to connect to the device, after making sure that the device is not already connected.
bleManagerInstance
+ .getConnectedDevices([serviceUUIDs])
+ .then(devices => {
+ const device = devices.find(d => d.id === deviceIdWeWantToConnectTo)
+
+ if (device && !device.isConnected) {
+ device.connect()
+ }
+ })
+ .catch(error => {
+ console.error('Get connected devices error:', error)
+ })
+If you encounter any issues with the library, you can enable native logs to get more information about what is happening under the hood. To enable native logs, you need to set the logLevel
property on the BleManager instance to LogLevel.Verbose
.
bleManagerInstance.setLogLevel(LogLevel.Verbose)+
To collect native logs on Android, you can open the Logcat in Android Studio and set filters to package:mine (tag:BluetoothGatt | tag:ReactNativeJS | RxBle)
.
To collect native logs on iOS, you can open the Xcode console.