munim-bluetooth 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +769 -15
- package/android/src/main/AndroidManifest.xml +18 -0
- package/android/src/main/java/com/munimbluetooth/HybridMunimBluetooth.kt +700 -3
- package/ios/HybridMunimBluetooth.swift +622 -3
- package/lib/commonjs/index.js +247 -2
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/index.js +227 -1
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/index.d.ts +161 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/specs/munim-bluetooth.nitro.d.ts +193 -1
- package/lib/typescript/src/specs/munim-bluetooth.nitro.d.ts.map +1 -1
- package/package.json +5 -2
- package/src/index.ts +287 -3
- package/src/specs/munim-bluetooth.nitro.ts +266 -3
package/README.md
CHANGED
|
@@ -1,29 +1,783 @@
|
|
|
1
|
-
|
|
1
|
+
<!-- Banner Image -->
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<p align="center">
|
|
4
|
+
<a href="https://github.com/munimtechnologies/munim-bluetooth">
|
|
5
|
+
<img alt="Munim Technologies Bluetooth" height="128" src="./.github/resources/banner.png?v=3">
|
|
6
|
+
<h1 align="center">munim-bluetooth</h1>
|
|
7
|
+
</a>
|
|
8
|
+
</p>
|
|
4
9
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
10
|
+
<p align="center">
|
|
11
|
+
<a aria-label="Package version" href="https://www.npmjs.com/package/munim-bluetooth" target="_blank">
|
|
12
|
+
<img alt="Package version" src="https://img.shields.io/npm/v/munim-bluetooth.svg?style=flat-square&label=Version&labelColor=000000&color=0066CC" />
|
|
13
|
+
</a>
|
|
14
|
+
<a aria-label="Package is free to use" href="https://github.com/munimtechnologies/munim-bluetooth/blob/main/LICENSE" target="_blank">
|
|
15
|
+
<img alt="License: MIT" src="https://img.shields.io/badge/License-MIT-success.svg?style=flat-square&color=33CC12" target="_blank" />
|
|
16
|
+
</a>
|
|
17
|
+
<a aria-label="package downloads" href="https://www.npmtrends.com/munim-bluetooth" target="_blank">
|
|
18
|
+
<img alt="Downloads" src="https://img.shields.io/npm/dm/munim-bluetooth.svg?style=flat-square&labelColor=gray&color=33CC12&label=Downloads" />
|
|
19
|
+
</a>
|
|
20
|
+
<a aria-label="total package downloads" href="https://www.npmjs.com/package/munim-bluetooth" target="_blank">
|
|
21
|
+
<img alt="Total Downloads" src="https://img.shields.io/npm/dt/munim-bluetooth.svg?style=flat-square&labelColor=gray&color=0066CC&label=Total%20Downloads" />
|
|
22
|
+
</a>
|
|
23
|
+
</p>
|
|
8
24
|
|
|
9
|
-
|
|
25
|
+
<p align="center">
|
|
26
|
+
<a aria-label="try with expo" href="https://docs.expo.dev/"><b>Works with Expo</b></a>
|
|
27
|
+
 • 
|
|
28
|
+
<a aria-label="documentation" href="https://github.com/munimtechnologies/munim-bluetooth#readme">Read the Documentation</a>
|
|
29
|
+
 • 
|
|
30
|
+
<a aria-label="report issues" href="https://github.com/munimtechnologies/munim-bluetooth/issues">Report Issues</a>
|
|
31
|
+
</p>
|
|
10
32
|
|
|
11
|
-
|
|
12
|
-
|
|
33
|
+
<h6 align="center">Follow Munim Technologies</h6>
|
|
34
|
+
<p align="center">
|
|
35
|
+
<a aria-label="Follow Munim Technologies on GitHub" href="https://github.com/munimtechnologies" target="_blank">
|
|
36
|
+
<img alt="Munim Technologies on GitHub" src="https://img.shields.io/badge/GitHub-222222?style=for-the-badge&logo=github&logoColor=white" target="_blank" />
|
|
37
|
+
</a>
|
|
38
|
+
<a aria-label="Follow Munim Technologies on LinkedIn" href="https://linkedin.com/in/sheehanmunim" target="_blank">
|
|
39
|
+
<img alt="Munim Technologies on LinkedIn" src="https://img.shields.io/badge/LinkedIn-0077B5?style=for-the-badge&logo=linkedin&logoColor=white" target="_blank" />
|
|
40
|
+
</a>
|
|
41
|
+
<a aria-label="Visit Munim Technologies Website" href="https://munimtech.com" target="_blank">
|
|
42
|
+
<img alt="Munim Technologies Website" src="https://img.shields.io/badge/Website-0066CC?style=for-the-badge&logo=globe&logoColor=white" target="_blank" />
|
|
43
|
+
</a>
|
|
44
|
+
</p>
|
|
13
45
|
|
|
14
|
-
|
|
15
|
-
> To Support `Nitro Views` you need to install React Native version v0.78.0 or higher.
|
|
46
|
+
## Introduction
|
|
16
47
|
|
|
17
|
-
|
|
48
|
+
**munim-bluetooth** is a comprehensive React Native library for all your Bluetooth Low Energy (BLE) needs, supporting both peripheral and central roles. This library allows your React Native app to act as a BLE peripheral (advertising services and characteristics) or as a BLE central (scanning, connecting, and communicating with devices).
|
|
49
|
+
|
|
50
|
+
**Fully compatible with Expo!** Works seamlessly with both Expo managed and bare workflows.
|
|
51
|
+
|
|
52
|
+
**Built with React Native's Nitro modules architecture** for high performance and reliability.
|
|
53
|
+
|
|
54
|
+
**Note**: This library focuses on reliability and platform compatibility. It supports the core BLE features that work consistently across both Android and iOS platforms.
|
|
55
|
+
|
|
56
|
+
## Table of contents
|
|
57
|
+
|
|
58
|
+
- [📚 Documentation](#-documentation)
|
|
59
|
+
- [🚀 Features](#-features)
|
|
60
|
+
- [📦 Installation](#-installation)
|
|
61
|
+
- [⚡ Quick Start](#-quick-start)
|
|
62
|
+
- [🔧 API Reference](#-api-reference)
|
|
63
|
+
- [📖 Usage Examples](#-usage-examples)
|
|
64
|
+
- [🔍 Troubleshooting](#-troubleshooting)
|
|
65
|
+
- [👏 Contributing](#-contributing)
|
|
66
|
+
- [📄 License](#-license)
|
|
67
|
+
|
|
68
|
+
## 📚 Documentation
|
|
69
|
+
|
|
70
|
+
<p>Learn about building BLE apps <a aria-label="documentation" href="https://github.com/munimtechnologies/munim-bluetooth#readme">in our documentation!</a></p>
|
|
71
|
+
|
|
72
|
+
- [Getting Started](#-installation)
|
|
73
|
+
- [API Reference](#-api-reference)
|
|
74
|
+
- [Usage Examples](#-usage-examples)
|
|
75
|
+
- [Troubleshooting](#-troubleshooting)
|
|
76
|
+
|
|
77
|
+
## 🚀 Features
|
|
78
|
+
|
|
79
|
+
### Peripheral Mode
|
|
80
|
+
|
|
81
|
+
- 🔵 **BLE Peripheral Mode**: Transform your React Native app into a BLE peripheral device
|
|
82
|
+
- 📡 **Service Advertising**: Advertise custom GATT services with multiple characteristics
|
|
83
|
+
- 🔄 **Real-time Communication**: Support for read, write, and notify operations
|
|
84
|
+
- ✅ **Platform-Supported BLE Advertising**: Support for core BLE advertising data types that work reliably on both platforms
|
|
85
|
+
- 🔧 **Dynamic Updates**: Update advertising data while advertising is active
|
|
86
|
+
|
|
87
|
+
### Central Mode
|
|
88
|
+
|
|
89
|
+
- 🔍 **Device Scanning**: Scan for BLE devices with filtering options
|
|
90
|
+
- 🔗 **Device Connection**: Connect and disconnect from BLE devices
|
|
91
|
+
- 📊 **GATT Operations**: Discover services, read/write characteristics
|
|
92
|
+
- 🔔 **Notifications**: Subscribe to characteristic notifications/indications
|
|
93
|
+
- 📶 **RSSI Monitoring**: Read signal strength for connected devices
|
|
94
|
+
|
|
95
|
+
### Additional Features
|
|
96
|
+
|
|
97
|
+
- 📱 **Cross-platform**: Works on both iOS and Android
|
|
98
|
+
- 🎯 **TypeScript Support**: Full TypeScript definitions included
|
|
99
|
+
- ⚡ **High Performance**: Built with React Native's Nitro modules architecture
|
|
100
|
+
- 🚀 **Expo Compatible**: Works seamlessly with Expo managed and bare workflows
|
|
101
|
+
- 🔐 **Permission Handling**: Built-in permission request helpers
|
|
102
|
+
|
|
103
|
+
## 📦 Installation
|
|
104
|
+
|
|
105
|
+
### React Native CLI
|
|
18
106
|
|
|
19
107
|
```bash
|
|
20
108
|
npm install munim-bluetooth react-native-nitro-modules
|
|
109
|
+
# or
|
|
110
|
+
yarn add munim-bluetooth react-native-nitro-modules
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Expo
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
npx expo install munim-bluetooth react-native-nitro-modules
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
> **Note**: This library requires Expo SDK 50+ and works with both managed and bare workflows. To support Nitro modules, you need React Native version v0.78.0 or higher.
|
|
120
|
+
|
|
121
|
+
### iOS Setup
|
|
122
|
+
|
|
123
|
+
For iOS, the library is automatically linked. However, you need to add the following to your `Info.plist`:
|
|
124
|
+
|
|
125
|
+
```xml
|
|
126
|
+
<key>NSBluetoothAlwaysUsageDescription</key>
|
|
127
|
+
<string>This app uses Bluetooth for BLE communication</string>
|
|
128
|
+
<key>NSBluetoothPeripheralUsageDescription</key>
|
|
129
|
+
<string>This app uses Bluetooth to create a peripheral device</string>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**For Expo projects**, add these permissions to your `app.json`:
|
|
133
|
+
|
|
134
|
+
```json
|
|
135
|
+
{
|
|
136
|
+
"expo": {
|
|
137
|
+
"ios": {
|
|
138
|
+
"infoPlist": {
|
|
139
|
+
"NSBluetoothAlwaysUsageDescription": "This app uses Bluetooth for BLE communication",
|
|
140
|
+
"NSBluetoothPeripheralUsageDescription": "This app uses Bluetooth to create a peripheral device"
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
21
145
|
```
|
|
22
146
|
|
|
23
|
-
|
|
147
|
+
### Android Setup
|
|
148
|
+
|
|
149
|
+
For Android, add the following permissions to your `AndroidManifest.xml`:
|
|
150
|
+
|
|
151
|
+
```xml
|
|
152
|
+
<uses-permission android:name="android.permission.BLUETOOTH" />
|
|
153
|
+
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
|
154
|
+
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
|
155
|
+
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
|
156
|
+
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
|
157
|
+
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
|
158
|
+
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**For Expo projects**, add these permissions to your `app.json`:
|
|
162
|
+
|
|
163
|
+
```json
|
|
164
|
+
{
|
|
165
|
+
"expo": {
|
|
166
|
+
"android": {
|
|
167
|
+
"permissions": [
|
|
168
|
+
"android.permission.BLUETOOTH",
|
|
169
|
+
"android.permission.BLUETOOTH_ADMIN",
|
|
170
|
+
"android.permission.BLUETOOTH_ADVERTISE",
|
|
171
|
+
"android.permission.BLUETOOTH_SCAN",
|
|
172
|
+
"android.permission.BLUETOOTH_CONNECT",
|
|
173
|
+
"android.permission.ACCESS_FINE_LOCATION",
|
|
174
|
+
"android.permission.ACCESS_COARSE_LOCATION"
|
|
175
|
+
]
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## ⚡ Quick Start
|
|
182
|
+
|
|
183
|
+
### Basic Usage - Peripheral Mode
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
import { startAdvertising, stopAdvertising, setServices } from 'munim-bluetooth'
|
|
187
|
+
|
|
188
|
+
// Start advertising with basic options
|
|
189
|
+
startAdvertising({
|
|
190
|
+
serviceUUIDs: ['180D', '180F'],
|
|
191
|
+
localName: 'My Device',
|
|
192
|
+
manufacturerData: '0102030405',
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
// Set GATT services
|
|
196
|
+
setServices([
|
|
197
|
+
{
|
|
198
|
+
uuid: '180D',
|
|
199
|
+
characteristics: [
|
|
200
|
+
{
|
|
201
|
+
uuid: '2A37',
|
|
202
|
+
properties: ['read', 'notify'],
|
|
203
|
+
value: 'Hello World',
|
|
204
|
+
},
|
|
205
|
+
],
|
|
206
|
+
},
|
|
207
|
+
])
|
|
208
|
+
|
|
209
|
+
// Stop advertising
|
|
210
|
+
stopAdvertising()
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Basic Usage - Central Mode
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
import {
|
|
217
|
+
startScan,
|
|
218
|
+
stopScan,
|
|
219
|
+
connect,
|
|
220
|
+
discoverServices,
|
|
221
|
+
readCharacteristic,
|
|
222
|
+
subscribeToCharacteristic,
|
|
223
|
+
} from 'munim-bluetooth'
|
|
224
|
+
|
|
225
|
+
// Start scanning
|
|
226
|
+
startScan({
|
|
227
|
+
serviceUUIDs: ['180D'],
|
|
228
|
+
allowDuplicates: false,
|
|
229
|
+
scanMode: 'balanced',
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
// Connect to a device (deviceId from deviceFound event)
|
|
233
|
+
await connect('device-id-here')
|
|
234
|
+
|
|
235
|
+
// Discover services
|
|
236
|
+
const services = await discoverServices('device-id-here')
|
|
237
|
+
|
|
238
|
+
// Read a characteristic
|
|
239
|
+
const value = await readCharacteristic('device-id-here', '180D', '2A37')
|
|
240
|
+
|
|
241
|
+
// Subscribe to notifications
|
|
242
|
+
subscribeToCharacteristic('device-id-here', '180D', '2A37')
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Advanced Usage with Supported Advertising Data Types
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
import {
|
|
249
|
+
startAdvertising,
|
|
250
|
+
updateAdvertisingData,
|
|
251
|
+
getAdvertisingData,
|
|
252
|
+
type AdvertisingDataTypes,
|
|
253
|
+
} from 'munim-bluetooth'
|
|
254
|
+
|
|
255
|
+
// Platform-supported advertising data configuration
|
|
256
|
+
const advertisingData: AdvertisingDataTypes = {
|
|
257
|
+
// 0x01 - Flags (LE General Discoverable Mode, BR/EDR Not Supported)
|
|
258
|
+
flags: 0x06,
|
|
259
|
+
|
|
260
|
+
// 0x02-0x07 - Service UUIDs (fully supported)
|
|
261
|
+
completeServiceUUIDs16: ['180D', '180F'],
|
|
262
|
+
incompleteServiceUUIDs128: ['0000180D-0000-1000-8000-00805F9B34FB'],
|
|
263
|
+
|
|
264
|
+
// 0x08-0x09 - Local Name (fully supported)
|
|
265
|
+
completeLocalName: 'My Smart Device',
|
|
266
|
+
shortenedLocalName: 'SmartDev',
|
|
267
|
+
|
|
268
|
+
// 0x0A - Tx Power Level (fully supported)
|
|
269
|
+
txPowerLevel: -12,
|
|
270
|
+
|
|
271
|
+
// 0x14-0x15 - Service Solicitation (fully supported)
|
|
272
|
+
serviceSolicitationUUIDs16: ['180D'],
|
|
273
|
+
serviceSolicitationUUIDs128: ['0000180D-0000-1000-8000-00805F9B34FB'],
|
|
274
|
+
|
|
275
|
+
// 0x16, 0x20, 0x21 - Service Data (fully supported)
|
|
276
|
+
serviceData16: [
|
|
277
|
+
{ uuid: '180D', data: '0102030405' },
|
|
278
|
+
{ uuid: '180F', data: '060708090A' },
|
|
279
|
+
],
|
|
280
|
+
serviceData32: [
|
|
281
|
+
{ uuid: '0000180D-0000-1000-8000-00805F9B34FB', data: '0B0C0D0E0F' },
|
|
282
|
+
],
|
|
283
|
+
|
|
284
|
+
// 0x19 - Appearance (partial support)
|
|
285
|
+
appearance: 0x03c0, // Generic Watch
|
|
286
|
+
|
|
287
|
+
// 0x1F - Service Solicitation (32-bit) (fully supported)
|
|
288
|
+
serviceSolicitationUUIDs32: ['0000180D'],
|
|
289
|
+
|
|
290
|
+
// 0xFF - Manufacturer Specific Data (fully supported)
|
|
291
|
+
manufacturerData: '4C000215FDA50693A4E24FB1AFCFC6EB0764782500010001C5',
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Start advertising with supported data
|
|
295
|
+
startAdvertising({
|
|
296
|
+
serviceUUIDs: ['180D', '180F'],
|
|
297
|
+
advertisingData: advertisingData,
|
|
298
|
+
})
|
|
299
|
+
|
|
300
|
+
// Update advertising data dynamically
|
|
301
|
+
updateAdvertisingData({
|
|
302
|
+
flags: 0x04,
|
|
303
|
+
completeLocalName: 'Updated Device Name',
|
|
304
|
+
txPowerLevel: -8,
|
|
305
|
+
})
|
|
306
|
+
|
|
307
|
+
// Get current advertising data
|
|
308
|
+
const currentData = await getAdvertisingData()
|
|
309
|
+
console.log('Current advertising data:', currentData)
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## 🔧 API Reference
|
|
313
|
+
|
|
314
|
+
### Peripheral Functions
|
|
315
|
+
|
|
316
|
+
#### `startAdvertising(options)`
|
|
317
|
+
|
|
318
|
+
Starts BLE advertising with the specified options.
|
|
319
|
+
|
|
320
|
+
**Parameters:**
|
|
321
|
+
|
|
322
|
+
- `options` (object):
|
|
323
|
+
- `serviceUUIDs` (string[]): Array of service UUIDs to advertise
|
|
324
|
+
- `localName?` (string): Device name (legacy support)
|
|
325
|
+
- `manufacturerData?` (string): Manufacturer data in hex format (legacy support)
|
|
326
|
+
- `advertisingData?` (AdvertisingDataTypes): Platform-supported advertising data
|
|
327
|
+
|
|
328
|
+
#### `updateAdvertisingData(advertisingData)`
|
|
329
|
+
|
|
330
|
+
Updates the advertising data while advertising is active.
|
|
331
|
+
|
|
332
|
+
**Parameters:**
|
|
333
|
+
|
|
334
|
+
- `advertisingData` (AdvertisingDataTypes): New advertising data
|
|
335
|
+
|
|
336
|
+
#### `getAdvertisingData()`
|
|
337
|
+
|
|
338
|
+
Returns a Promise that resolves to the current advertising data.
|
|
339
|
+
|
|
340
|
+
**Returns:** Promise<AdvertisingDataTypes>
|
|
341
|
+
|
|
342
|
+
#### `stopAdvertising()`
|
|
343
|
+
|
|
344
|
+
Stops BLE advertising.
|
|
345
|
+
|
|
346
|
+
#### `setServices(services)`
|
|
347
|
+
|
|
348
|
+
Sets GATT services and characteristics.
|
|
349
|
+
|
|
350
|
+
**Parameters:**
|
|
351
|
+
|
|
352
|
+
- `services` (array): Array of service objects
|
|
353
|
+
|
|
354
|
+
### Central Functions
|
|
355
|
+
|
|
356
|
+
#### `isBluetoothEnabled()`
|
|
357
|
+
|
|
358
|
+
Checks if Bluetooth is enabled on the device.
|
|
359
|
+
|
|
360
|
+
**Returns:** Promise<boolean>
|
|
361
|
+
|
|
362
|
+
#### `requestBluetoothPermission()`
|
|
363
|
+
|
|
364
|
+
Requests Bluetooth permissions (Android) or checks authorization status (iOS).
|
|
365
|
+
|
|
366
|
+
**Returns:** Promise<boolean>
|
|
367
|
+
|
|
368
|
+
#### `startScan(options?)`
|
|
369
|
+
|
|
370
|
+
Starts scanning for BLE devices.
|
|
371
|
+
|
|
372
|
+
**Parameters:**
|
|
373
|
+
|
|
374
|
+
- `options?` (object):
|
|
375
|
+
- `serviceUUIDs?` (string[]): Filter by service UUIDs
|
|
376
|
+
- `allowDuplicates?` (boolean): Allow duplicate scan results
|
|
377
|
+
- `scanMode?` ('lowPower' | 'balanced' | 'lowLatency'): Scan mode
|
|
378
|
+
|
|
379
|
+
#### `stopScan()`
|
|
380
|
+
|
|
381
|
+
Stops scanning for BLE devices.
|
|
382
|
+
|
|
383
|
+
#### `connect(deviceId)`
|
|
384
|
+
|
|
385
|
+
Connects to a BLE device.
|
|
386
|
+
|
|
387
|
+
**Parameters:**
|
|
388
|
+
|
|
389
|
+
- `deviceId` (string): The unique identifier of the device
|
|
390
|
+
|
|
391
|
+
**Returns:** Promise<void>
|
|
392
|
+
|
|
393
|
+
#### `disconnect(deviceId)`
|
|
394
|
+
|
|
395
|
+
Disconnects from a BLE device.
|
|
396
|
+
|
|
397
|
+
**Parameters:**
|
|
398
|
+
|
|
399
|
+
- `deviceId` (string): The unique identifier of the device
|
|
400
|
+
|
|
401
|
+
#### `discoverServices(deviceId)`
|
|
402
|
+
|
|
403
|
+
Discovers GATT services for a connected device.
|
|
404
|
+
|
|
405
|
+
**Parameters:**
|
|
406
|
+
|
|
407
|
+
- `deviceId` (string): The unique identifier of the connected device
|
|
408
|
+
|
|
409
|
+
**Returns:** Promise<GATTService[]>
|
|
410
|
+
|
|
411
|
+
#### `readCharacteristic(deviceId, serviceUUID, characteristicUUID)`
|
|
412
|
+
|
|
413
|
+
Reads a characteristic value from a connected device.
|
|
414
|
+
|
|
415
|
+
**Parameters:**
|
|
416
|
+
|
|
417
|
+
- `deviceId` (string): The unique identifier of the connected device
|
|
418
|
+
- `serviceUUID` (string): The UUID of the service
|
|
419
|
+
- `characteristicUUID` (string): The UUID of the characteristic
|
|
420
|
+
|
|
421
|
+
**Returns:** Promise<CharacteristicValue>
|
|
422
|
+
|
|
423
|
+
#### `writeCharacteristic(deviceId, serviceUUID, characteristicUUID, value, writeType?)`
|
|
424
|
+
|
|
425
|
+
Writes a value to a characteristic on a connected device.
|
|
426
|
+
|
|
427
|
+
**Parameters:**
|
|
428
|
+
|
|
429
|
+
- `deviceId` (string): The unique identifier of the connected device
|
|
430
|
+
- `serviceUUID` (string): The UUID of the service
|
|
431
|
+
- `characteristicUUID` (string): The UUID of the characteristic
|
|
432
|
+
- `value` (string): The value to write (hex string)
|
|
433
|
+
- `writeType?` ('write' | 'writeWithoutResponse'): Write type
|
|
434
|
+
|
|
435
|
+
**Returns:** Promise<void>
|
|
436
|
+
|
|
437
|
+
#### `subscribeToCharacteristic(deviceId, serviceUUID, characteristicUUID)`
|
|
438
|
+
|
|
439
|
+
Subscribes to notifications/indications from a characteristic.
|
|
440
|
+
|
|
441
|
+
**Parameters:**
|
|
442
|
+
|
|
443
|
+
- `deviceId` (string): The unique identifier of the connected device
|
|
444
|
+
- `serviceUUID` (string): The UUID of the service
|
|
445
|
+
- `characteristicUUID` (string): The UUID of the characteristic
|
|
446
|
+
|
|
447
|
+
#### `unsubscribeFromCharacteristic(deviceId, serviceUUID, characteristicUUID)`
|
|
448
|
+
|
|
449
|
+
Unsubscribes from notifications/indications from a characteristic.
|
|
450
|
+
|
|
451
|
+
**Parameters:**
|
|
452
|
+
|
|
453
|
+
- `deviceId` (string): The unique identifier of the connected device
|
|
454
|
+
- `serviceUUID` (string): The UUID of the service
|
|
455
|
+
- `characteristicUUID` (string): The UUID of the characteristic
|
|
456
|
+
|
|
457
|
+
#### `getConnectedDevices()`
|
|
458
|
+
|
|
459
|
+
Gets list of currently connected devices.
|
|
460
|
+
|
|
461
|
+
**Returns:** Promise<string[]>
|
|
462
|
+
|
|
463
|
+
#### `readRSSI(deviceId)`
|
|
464
|
+
|
|
465
|
+
Reads RSSI (signal strength) for a connected device.
|
|
466
|
+
|
|
467
|
+
**Parameters:**
|
|
468
|
+
|
|
469
|
+
- `deviceId` (string): The unique identifier of the connected device
|
|
470
|
+
|
|
471
|
+
**Returns:** Promise<number>
|
|
472
|
+
|
|
473
|
+
### Types
|
|
474
|
+
|
|
475
|
+
#### `AdvertisingDataTypes`
|
|
476
|
+
|
|
477
|
+
Platform-supported interface for BLE advertising data types:
|
|
478
|
+
|
|
479
|
+
```typescript
|
|
480
|
+
interface AdvertisingDataTypes {
|
|
481
|
+
// 0x01 - Flags (partial support)
|
|
482
|
+
flags?: number
|
|
483
|
+
|
|
484
|
+
// 0x02-0x07 - Service UUIDs (fully supported)
|
|
485
|
+
incompleteServiceUUIDs16?: string[]
|
|
486
|
+
completeServiceUUIDs16?: string[]
|
|
487
|
+
incompleteServiceUUIDs32?: string[]
|
|
488
|
+
completeServiceUUIDs32?: string[]
|
|
489
|
+
incompleteServiceUUIDs128?: string[]
|
|
490
|
+
completeServiceUUIDs128?: string[]
|
|
491
|
+
|
|
492
|
+
// 0x08-0x09 - Local Name (fully supported)
|
|
493
|
+
shortenedLocalName?: string
|
|
494
|
+
completeLocalName?: string
|
|
495
|
+
|
|
496
|
+
// 0x0A - Tx Power Level (fully supported)
|
|
497
|
+
txPowerLevel?: number
|
|
498
|
+
|
|
499
|
+
// 0x14-0x15 - Service Solicitation (fully supported)
|
|
500
|
+
serviceSolicitationUUIDs16?: string[]
|
|
501
|
+
serviceSolicitationUUIDs128?: string[]
|
|
502
|
+
|
|
503
|
+
// 0x16, 0x20, 0x21 - Service Data (fully supported)
|
|
504
|
+
serviceData16?: Array<{
|
|
505
|
+
uuid: string
|
|
506
|
+
data: string
|
|
507
|
+
}>
|
|
508
|
+
serviceData32?: Array<{
|
|
509
|
+
uuid: string
|
|
510
|
+
data: string
|
|
511
|
+
}>
|
|
512
|
+
serviceData128?: Array<{
|
|
513
|
+
uuid: string
|
|
514
|
+
data: string
|
|
515
|
+
}>
|
|
516
|
+
|
|
517
|
+
// 0x19 - Appearance (partial support)
|
|
518
|
+
appearance?: number
|
|
519
|
+
|
|
520
|
+
// 0x1F - Service Solicitation (32-bit) (fully supported)
|
|
521
|
+
serviceSolicitationUUIDs32?: string[]
|
|
522
|
+
|
|
523
|
+
// 0xFF - Manufacturer Specific Data (fully supported)
|
|
524
|
+
manufacturerData?: string
|
|
525
|
+
}
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
## Supported BLE Advertising Data Types
|
|
529
|
+
|
|
530
|
+
| Hex | Type Name | Description | Support Level | Example |
|
|
531
|
+
| ---------------- | ----------------------------- | ------------------------------- | ------------- | ------------------------------------------------- |
|
|
532
|
+
| 0x01 | Flags | Basic device capabilities | Partial | `flags: 0x06` |
|
|
533
|
+
| 0x02-0x07 | Service UUIDs | Service UUIDs offered | Full | `completeServiceUUIDs16: ['180D']` |
|
|
534
|
+
| 0x08-0x09 | Local Name | Device name | Full | `completeLocalName: 'My Device'` |
|
|
535
|
+
| 0x0A | Tx Power Level | Transmit power in dBm | Full | `txPowerLevel: -12` |
|
|
536
|
+
| 0x14-0x15 | Service Solicitation | Services being sought | Full | `serviceSolicitationUUIDs16: ['180D']` |
|
|
537
|
+
| 0x16, 0x20, 0x21 | Service Data | Data associated with services | Full | `serviceData16: [{uuid: '180D', data: '010203'}]` |
|
|
538
|
+
| 0x19 | Appearance | Appearance category | Partial | `appearance: 0x03C0` |
|
|
539
|
+
| 0x1F | Service Solicitation (32-bit) | 32-bit services being solicited | Full | `serviceSolicitationUUIDs32: ['0000180D']` |
|
|
540
|
+
| 0xFF | Manufacturer Specific Data | Vendor-defined data | Full | `manufacturerData: '4748494A4B4C4D4E'` |
|
|
541
|
+
|
|
542
|
+
**Note**: This library focuses on reliability and platform compatibility. Advanced BLE features like mesh networking, LE Audio, indoor positioning, etc., are not supported due to platform limitations.
|
|
543
|
+
|
|
544
|
+
## 📖 Usage Examples
|
|
545
|
+
|
|
546
|
+
### Health Device Example
|
|
547
|
+
|
|
548
|
+
```typescript
|
|
549
|
+
import { startAdvertising, setServices } from 'munim-bluetooth'
|
|
550
|
+
|
|
551
|
+
// Health device advertising
|
|
552
|
+
startAdvertising({
|
|
553
|
+
serviceUUIDs: ['180D', '180F'], // Heart Rate, Battery Service
|
|
554
|
+
advertisingData: {
|
|
555
|
+
flags: 0x06, // LE General Discoverable Mode, BR/EDR Not Supported
|
|
556
|
+
completeLocalName: 'Health Monitor',
|
|
557
|
+
appearance: 0x03c0, // Generic Watch
|
|
558
|
+
txPowerLevel: -8,
|
|
559
|
+
manufacturerData: '0102030405', // Custom health data
|
|
560
|
+
serviceData16: [
|
|
561
|
+
{ uuid: '180D', data: '6400' }, // Heart rate: 100 bpm
|
|
562
|
+
{ uuid: '180F', data: '64' }, // Battery: 100%
|
|
563
|
+
],
|
|
564
|
+
},
|
|
565
|
+
})
|
|
566
|
+
|
|
567
|
+
// Set up GATT services
|
|
568
|
+
setServices([
|
|
569
|
+
{
|
|
570
|
+
uuid: '180D', // Heart Rate Service
|
|
571
|
+
characteristics: [
|
|
572
|
+
{
|
|
573
|
+
uuid: '2A37', // Heart Rate Measurement
|
|
574
|
+
properties: ['read', 'notify'],
|
|
575
|
+
value: '6400', // 100 bpm
|
|
576
|
+
},
|
|
577
|
+
],
|
|
578
|
+
},
|
|
579
|
+
{
|
|
580
|
+
uuid: '180F', // Battery Service
|
|
581
|
+
characteristics: [
|
|
582
|
+
{
|
|
583
|
+
uuid: '2A19', // Battery Level
|
|
584
|
+
properties: ['read', 'notify'],
|
|
585
|
+
value: '64', // 100%
|
|
586
|
+
},
|
|
587
|
+
],
|
|
588
|
+
},
|
|
589
|
+
])
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
### Smart Home Device Example
|
|
593
|
+
|
|
594
|
+
```typescript
|
|
595
|
+
import { startAdvertising, updateAdvertisingData } from 'munim-bluetooth'
|
|
596
|
+
|
|
597
|
+
// Smart home device
|
|
598
|
+
startAdvertising({
|
|
599
|
+
serviceUUIDs: ['1812', '180F'], // HID, Battery Service
|
|
600
|
+
advertisingData: {
|
|
601
|
+
flags: 0x04, // LE General Discoverable Mode
|
|
602
|
+
completeLocalName: 'Smart Light Bulb',
|
|
603
|
+
appearance: 0x03c1, // Generic Light Fixture
|
|
604
|
+
manufacturerData: '0102030405', // Custom light data
|
|
605
|
+
serviceData16: [
|
|
606
|
+
{ uuid: '1812', data: '01' }, // HID: Keyboard
|
|
607
|
+
{ uuid: '180F', data: '64' }, // Battery: 100%
|
|
608
|
+
],
|
|
609
|
+
},
|
|
610
|
+
})
|
|
611
|
+
|
|
612
|
+
// Update advertising data when light state changes
|
|
613
|
+
updateAdvertisingData({
|
|
614
|
+
manufacturerData: '0102030406', // Updated light data
|
|
615
|
+
serviceData16: [
|
|
616
|
+
{ uuid: '1812', data: '02' }, // HID: Mouse
|
|
617
|
+
{ uuid: '180F', data: '50' }, // Battery: 80%
|
|
618
|
+
],
|
|
619
|
+
})
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
### Basic Peripheral Setup
|
|
623
|
+
|
|
624
|
+
```js
|
|
625
|
+
import React, { useEffect } from 'react'
|
|
626
|
+
import {
|
|
627
|
+
startAdvertising,
|
|
628
|
+
stopAdvertising,
|
|
629
|
+
setServices,
|
|
630
|
+
addListener,
|
|
631
|
+
removeListeners,
|
|
632
|
+
} from 'munim-bluetooth'
|
|
633
|
+
|
|
634
|
+
const MyPeripheral = () => {
|
|
635
|
+
useEffect(() => {
|
|
636
|
+
// Configure services
|
|
637
|
+
setServices([
|
|
638
|
+
{
|
|
639
|
+
uuid: '1800', // Generic Access Service
|
|
640
|
+
characteristics: [
|
|
641
|
+
{
|
|
642
|
+
uuid: '2a00', // Device Name
|
|
643
|
+
properties: ['read'],
|
|
644
|
+
value: 'MyDevice',
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
uuid: '2a01', // Appearance
|
|
648
|
+
properties: ['read'],
|
|
649
|
+
value: '0x03C0', // Generic Computer
|
|
650
|
+
},
|
|
651
|
+
],
|
|
652
|
+
},
|
|
653
|
+
{
|
|
654
|
+
uuid: '1801', // Generic Attribute Service
|
|
655
|
+
characteristics: [
|
|
656
|
+
{
|
|
657
|
+
uuid: '2a05', // Service Changed
|
|
658
|
+
properties: ['indicate'],
|
|
659
|
+
},
|
|
660
|
+
],
|
|
661
|
+
},
|
|
662
|
+
])
|
|
663
|
+
|
|
664
|
+
// Start advertising
|
|
665
|
+
startAdvertising({
|
|
666
|
+
serviceUUIDs: ['1800', '1801'],
|
|
667
|
+
localName: 'MyReactNativePeripheral',
|
|
668
|
+
})
|
|
669
|
+
|
|
670
|
+
// Cleanup on unmount
|
|
671
|
+
return () => {
|
|
672
|
+
stopAdvertising()
|
|
673
|
+
removeListeners('connectionStateChanged')
|
|
674
|
+
}
|
|
675
|
+
}, [])
|
|
676
|
+
|
|
677
|
+
return <Text>Peripheral is running...</Text>
|
|
678
|
+
}
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
### Device Scanner Example
|
|
682
|
+
|
|
683
|
+
```js
|
|
684
|
+
import React, { useState, useEffect } from 'react'
|
|
685
|
+
import {
|
|
686
|
+
startScan,
|
|
687
|
+
stopScan,
|
|
688
|
+
connect,
|
|
689
|
+
discoverServices,
|
|
690
|
+
readCharacteristic,
|
|
691
|
+
subscribeToCharacteristic,
|
|
692
|
+
addListener,
|
|
693
|
+
} from 'munim-bluetooth'
|
|
694
|
+
|
|
695
|
+
const DeviceScanner = () => {
|
|
696
|
+
const [devices, setDevices] = useState([])
|
|
697
|
+
const [connectedDevice, setConnectedDevice] = useState(null)
|
|
698
|
+
|
|
699
|
+
useEffect(() => {
|
|
700
|
+
// Start scanning
|
|
701
|
+
startScan({
|
|
702
|
+
serviceUUIDs: ['180D'], // Filter by Heart Rate service
|
|
703
|
+
allowDuplicates: false,
|
|
704
|
+
scanMode: 'balanced',
|
|
705
|
+
})
|
|
706
|
+
|
|
707
|
+
// Listen for discovered devices
|
|
708
|
+
addListener('deviceFound')
|
|
709
|
+
// Handle deviceFound events to update devices state
|
|
710
|
+
|
|
711
|
+
// Cleanup
|
|
712
|
+
return () => {
|
|
713
|
+
stopScan()
|
|
714
|
+
if (connectedDevice) {
|
|
715
|
+
disconnect(connectedDevice)
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
}, [])
|
|
719
|
+
|
|
720
|
+
const handleConnect = async (deviceId) => {
|
|
721
|
+
await connect(deviceId)
|
|
722
|
+
setConnectedDevice(deviceId)
|
|
723
|
+
|
|
724
|
+
// Discover services
|
|
725
|
+
const services = await discoverServices(deviceId)
|
|
726
|
+
console.log('Services:', services)
|
|
727
|
+
|
|
728
|
+
// Read a characteristic
|
|
729
|
+
const value = await readCharacteristic(deviceId, '180D', '2A37')
|
|
730
|
+
console.log('Heart Rate:', value)
|
|
731
|
+
|
|
732
|
+
// Subscribe to notifications
|
|
733
|
+
subscribeToCharacteristic(deviceId, '180D', '2A37')
|
|
734
|
+
|
|
735
|
+
// Listen for value changes
|
|
736
|
+
addListener('characteristicValueChanged')
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
return (
|
|
740
|
+
<View>
|
|
741
|
+
<Text>Found {devices.length} devices</Text>
|
|
742
|
+
{/* Render device list */}
|
|
743
|
+
</View>
|
|
744
|
+
)
|
|
745
|
+
}
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
## 🔍 Troubleshooting
|
|
749
|
+
|
|
750
|
+
### Common Issues
|
|
751
|
+
|
|
752
|
+
1. **Permission Denied**: Ensure you have the necessary Bluetooth permissions in your app
|
|
753
|
+
2. **Advertising Not Starting**: Check that Bluetooth is enabled on the device
|
|
754
|
+
3. **Services Not Visible**: Verify that your service UUIDs are properly formatted
|
|
755
|
+
4. **Scanning Not Working**: On Android 6.0+, ensure location permissions are granted
|
|
756
|
+
5. **Connection Fails**: Verify the device is in range and advertising
|
|
757
|
+
|
|
758
|
+
### Expo-Specific Issues
|
|
759
|
+
|
|
760
|
+
1. **Development Build Required**: This library requires a development build in Expo. Use `npx expo run:ios` or `npx expo run:android`
|
|
761
|
+
2. **Permissions Not Working**: Make sure you've added the permissions to your `app.json` as shown in the setup section
|
|
762
|
+
3. **Build Errors**: Ensure you're using Expo SDK 50+ and have the latest Expo CLI
|
|
763
|
+
4. **Nitro Modules**: Make sure you have `react-native-nitro-modules` installed and configured
|
|
764
|
+
|
|
765
|
+
### Debug Mode
|
|
766
|
+
|
|
767
|
+
Enable debug logging by setting the following environment variable:
|
|
768
|
+
|
|
769
|
+
```bash
|
|
770
|
+
export REACT_NATIVE_BLUETOOTH_DEBUG=1
|
|
771
|
+
```
|
|
772
|
+
|
|
773
|
+
## 👏 Contributing
|
|
774
|
+
|
|
775
|
+
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details on how to submit pull requests, report issues, and contribute to the project.
|
|
776
|
+
|
|
777
|
+
## 📄 License
|
|
24
778
|
|
|
25
|
-
|
|
779
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
26
780
|
|
|
27
|
-
|
|
781
|
+
---
|
|
28
782
|
|
|
29
|
-
|
|
783
|
+
<img alt="Star the Munim Technologies repo on GitHub to support the project" src="https://user-images.githubusercontent.com/9664363/185428788-d762fd5d-97b3-4f59-8db7-f72405be9677.gif" width="50%">
|