react-native-sdk-ble-middleware-v2 0.1.0

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.
Files changed (39) hide show
  1. package/LICENSE +20 -0
  2. package/Middleware.podspec +21 -0
  3. package/README.md +187 -0
  4. package/android/build.gradle +77 -0
  5. package/android/gradle.properties +5 -0
  6. package/android/src/main/AndroidManifest.xml +2 -0
  7. package/android/src/main/java/com/middleware/MiddlewareModule.kt +23 -0
  8. package/android/src/main/java/com/middleware/MiddlewarePackage.kt +33 -0
  9. package/ios/Middleware.h +5 -0
  10. package/ios/Middleware.mm +21 -0
  11. package/lib/module/NativeMiddleware.js +3 -0
  12. package/lib/module/NativeMiddleware.js.map +1 -0
  13. package/lib/module/context/BLEContext.js +390 -0
  14. package/lib/module/context/BLEContext.js.map +1 -0
  15. package/lib/module/hooks/index.js +2 -0
  16. package/lib/module/hooks/index.js.map +1 -0
  17. package/lib/module/hooks/useBLE.js +167 -0
  18. package/lib/module/hooks/useBLE.js.map +1 -0
  19. package/lib/module/index.js +12 -0
  20. package/lib/module/index.js.map +1 -0
  21. package/lib/module/services/BLEMiddleware.js +252 -0
  22. package/lib/module/services/BLEMiddleware.js.map +1 -0
  23. package/lib/module/services/MockBLEManager.js +94 -0
  24. package/lib/module/services/MockBLEManager.js.map +1 -0
  25. package/lib/module/services/index.js +2 -0
  26. package/lib/module/services/index.js.map +1 -0
  27. package/lib/module/types/index.js +44 -0
  28. package/lib/module/types/index.js.map +1 -0
  29. package/package.json +179 -0
  30. package/react-native.config.js +8 -0
  31. package/src/NativeMiddleware.ts +7 -0
  32. package/src/context/BLEContext.tsx +487 -0
  33. package/src/hooks/index.ts +1 -0
  34. package/src/hooks/useBLE.ts +190 -0
  35. package/src/index.tsx +21 -0
  36. package/src/services/BLEMiddleware.ts +291 -0
  37. package/src/services/MockBLEManager.ts +96 -0
  38. package/src/services/index.ts +1 -0
  39. package/src/types/index.ts +97 -0
@@ -0,0 +1,291 @@
1
+ import { Platform, PermissionsAndroid } from 'react-native';
2
+ import type { ScanOptions, BLEEventType, UserRole } from '../types';
3
+
4
+ /**
5
+ * BLEMiddleware - Wrapper class for react-native-sdk-ble
6
+ * Handles all BLE operations and event management
7
+ */
8
+ class BLEMiddleware {
9
+ private bleManager: any = null;
10
+ private isInitialized: boolean = false;
11
+ private initializationPromise: Promise<void> | null = null;
12
+ private currentUserRole: UserRole = 'patient'; // Default role
13
+
14
+ constructor() {
15
+ // Start initialization immediately
16
+ this.initializationPromise = this.initializeBLEManager();
17
+ }
18
+
19
+ private async initializeBLEManager(): Promise<void> {
20
+ if (this.isInitialized) {
21
+ return;
22
+ }
23
+
24
+ try {
25
+ // Import the real BLE SDK
26
+ const BleModule = require('react-native-sdk-ble');
27
+ this.bleManager = BleModule.default || BleModule;
28
+ this.isInitialized = true;
29
+ console.log('✅ BLE Manager initialized successfully');
30
+ } catch (error) {
31
+ console.error('❌ Failed to initialize BLE Manager:', error);
32
+ console.error(
33
+ 'Make sure react-native-sdk-ble is installed in your app as a peer dependency'
34
+ );
35
+ console.error('Run: npm install react-native-sdk-ble');
36
+ this.isInitialized = false;
37
+ throw new Error(
38
+ 'react-native-sdk-ble is required but not installed. Please install it in your app: npm install react-native-sdk-ble'
39
+ );
40
+ }
41
+ }
42
+
43
+ private async ensureInitialized(): Promise<void> {
44
+ // Wait for initialization to complete
45
+ if (this.initializationPromise) {
46
+ await this.initializationPromise;
47
+ }
48
+
49
+ if (!this.isInitialized || !this.bleManager) {
50
+ throw new Error(
51
+ 'BLE Manager is not initialized. Please ensure react-native-sdk-ble is installed: npm install react-native-sdk-ble'
52
+ );
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Check if Bluetooth is enabled on the device
58
+ */
59
+ async isBluetoothEnabled(): Promise<boolean> {
60
+ await this.ensureInitialized();
61
+ return await this.bleManager.isBluetoothEnabled();
62
+ }
63
+
64
+ /**
65
+ * Request necessary permissions for BLE operations
66
+ */
67
+ async requestPermissions(): Promise<void> {
68
+ if (Platform.OS === 'android') {
69
+ const granted = await PermissionsAndroid.requestMultiple([
70
+ PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
71
+ PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
72
+ PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
73
+ ]);
74
+
75
+ const allGranted = Object.values(granted).every(
76
+ (status) => status === PermissionsAndroid.RESULTS.GRANTED
77
+ );
78
+
79
+ if (!allGranted) {
80
+ console.warn('Not all BLE permissions were granted');
81
+ }
82
+ }
83
+
84
+ await this.ensureInitialized();
85
+ await this.bleManager.requestPermissions();
86
+ }
87
+
88
+ /**
89
+ * Start scanning for BLE devices
90
+ */
91
+ async startScan(options: ScanOptions = {}): Promise<void> {
92
+ await this.ensureInitialized();
93
+ const defaultOptions = {
94
+ timeout: 10000,
95
+ allowDuplicates: false,
96
+ ...options,
97
+ };
98
+ await this.bleManager.startScan(defaultOptions);
99
+ }
100
+
101
+ /**
102
+ * Stop scanning for BLE devices
103
+ */
104
+ async stopScan(): Promise<void> {
105
+ await this.ensureInitialized();
106
+ await this.bleManager.stopScan();
107
+ }
108
+
109
+ /**
110
+ * Connect to a BLE device
111
+ */
112
+ async connect(deviceId: string): Promise<void> {
113
+ await this.ensureInitialized();
114
+ await this.bleManager.connect(deviceId);
115
+
116
+ // Automatically send user role command after connection
117
+ await this.sendUserRoleCommand();
118
+ }
119
+
120
+ /**
121
+ * Send user role command to device
122
+ * @private
123
+ */
124
+ private async sendUserRoleCommand(): Promise<void> {
125
+ try {
126
+ await this.ensureInitialized();
127
+ if (this.bleManager && this.bleManager.setUserRole) {
128
+ await this.bleManager.setUserRole(this.currentUserRole);
129
+ console.log(`✅ User role '${this.currentUserRole}' sent to device`);
130
+ } else {
131
+ console.warn('⚠️ setUserRole method not available in BLE SDK');
132
+ }
133
+ } catch (error) {
134
+ console.warn(`⚠️ Failed to send user role:`, error);
135
+ // Don't throw - allow connection to proceed even if role command fails
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Disconnect from a BLE device
141
+ */
142
+ async disconnect(deviceId: string): Promise<void> {
143
+ await this.ensureInitialized();
144
+ await this.bleManager.disconnect(deviceId);
145
+ }
146
+
147
+ /**
148
+ * Register event listener
149
+ */
150
+ on(event: BLEEventType, callback: (data: any) => void): void {
151
+ // For event listeners, we check synchronously but warn if not ready
152
+ if (!this.isInitialized || !this.bleManager) {
153
+ console.warn(
154
+ `BLE Manager not ready yet. Event listener for '${event}' will be registered once initialization completes.`
155
+ );
156
+ // Queue the event listener to be registered after initialization
157
+ this.initializationPromise?.then(() => {
158
+ if (this.isInitialized && this.bleManager) {
159
+ this.bleManager.on(event, callback);
160
+ }
161
+ });
162
+ return;
163
+ }
164
+ this.bleManager.on(event, callback);
165
+ }
166
+
167
+ /**
168
+ * Remove all event listeners
169
+ */
170
+ removeAllListeners(): void {
171
+ if (this.isInitialized && this.bleManager) {
172
+ this.bleManager.removeAllListeners();
173
+ }
174
+ }
175
+
176
+ /**
177
+ * Get the underlying BLE manager instance
178
+ * Use with caution - prefer using the wrapper methods
179
+ */
180
+ async getRawManager(): Promise<any> {
181
+ await this.ensureInitialized();
182
+ return this.bleManager;
183
+ }
184
+
185
+ /**
186
+ * Check if the BLE manager is ready
187
+ */
188
+ isReady(): boolean {
189
+ return this.isInitialized && this.bleManager !== null;
190
+ }
191
+
192
+ /**
193
+ * Wait for initialization to complete
194
+ */
195
+ async waitForInitialization(): Promise<void> {
196
+ if (this.initializationPromise) {
197
+ await this.initializationPromise;
198
+ }
199
+ }
200
+
201
+ /**
202
+ * Read characteristic value
203
+ */
204
+ async readCharacteristic(
205
+ deviceId: string,
206
+ serviceUuid: string,
207
+ characteristicUuid: string
208
+ ): Promise<any> {
209
+ await this.ensureInitialized();
210
+ return await this.bleManager.readCharacteristic(
211
+ deviceId,
212
+ serviceUuid,
213
+ characteristicUuid
214
+ );
215
+ }
216
+
217
+ /**
218
+ * Write characteristic value
219
+ */
220
+ async writeCharacteristic(
221
+ deviceId: string,
222
+ serviceUuid: string,
223
+ characteristicUuid: string,
224
+ data: string,
225
+ options?: { withResponse?: boolean }
226
+ ): Promise<void> {
227
+ await this.ensureInitialized();
228
+ await this.bleManager.writeCharacteristic(
229
+ deviceId,
230
+ serviceUuid,
231
+ characteristicUuid,
232
+ data,
233
+ options
234
+ );
235
+ }
236
+
237
+ /**
238
+ * Start infusion - Sends command A4 01 01
239
+ */
240
+ async startInfusion(deviceId: string): Promise<void> {
241
+ await this.ensureInitialized();
242
+ await this.bleManager.startInfusion(deviceId);
243
+ console.log('✅ Infusion started - Command A4 01 01 sent');
244
+ }
245
+
246
+ /**
247
+ * Stop infusion - Sends command A4 01 00
248
+ */
249
+ async stopInfusion(deviceId: string): Promise<void> {
250
+ await this.ensureInitialized();
251
+ await this.bleManager.stopInfusion(deviceId);
252
+ console.log('✅ Infusion stopped - Command A4 01 00 sent');
253
+ }
254
+
255
+ /**
256
+ * Set infusion level - Sends command A5 01 0{level}
257
+ * @param deviceId - The device ID to send the command to
258
+ * @param level - Infusion level (1-9)
259
+ */
260
+ async setInfusionLevel(deviceId: string, level: number): Promise<void> {
261
+ await this.ensureInitialized();
262
+ if (level < 1 || level > 5) {
263
+ throw new Error('Infusion level must be between 1 and 5');
264
+ }
265
+ await this.bleManager.setInfusionLevel(deviceId, level);
266
+ console.log(
267
+ `✅ Infusion level set to ${level} - Command A5 01 0${level} sent`
268
+ );
269
+ }
270
+
271
+ /**
272
+ * Set user role
273
+ * @param role - The user role to set ('patient', 'nurse', or 'engineer')
274
+ */
275
+ setUserRole(role: UserRole): void {
276
+ this.currentUserRole = role;
277
+ console.log(`✅ User role set to: ${role}`);
278
+ }
279
+
280
+ /**
281
+ * Get current user role
282
+ * @returns The current user role
283
+ */
284
+ getUserRole(): UserRole {
285
+ return this.currentUserRole;
286
+ }
287
+ }
288
+
289
+ // Export singleton instance
290
+ export const bleMiddleware = new BLEMiddleware();
291
+ export default bleMiddleware;
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Mock BLE Manager for development/testing
3
+ * Replace this with the actual react-native-sdk-ble package
4
+ */
5
+
6
+ class MockBLEManager {
7
+ private listeners: Map<string, Function[]> = new Map();
8
+
9
+ async isBluetoothEnabled(): Promise<boolean> {
10
+ console.log('📱 Mock: Checking Bluetooth status...');
11
+ return true;
12
+ }
13
+
14
+ async requestPermissions(): Promise<void> {
15
+ console.log('📱 Mock: Requesting permissions...');
16
+ return Promise.resolve();
17
+ }
18
+
19
+ async startScan(options: any): Promise<void> {
20
+ console.log('📱 Mock: Starting scan with options:', options);
21
+
22
+ // Simulate finding devices
23
+ setTimeout(() => {
24
+ this.emit('scanResult', {
25
+ device: {
26
+ id: 'mock-device-1',
27
+ name: 'Mock BLE Device 1',
28
+ rssi: -65,
29
+ },
30
+ });
31
+ }, 1000);
32
+
33
+ setTimeout(() => {
34
+ this.emit('scanResult', {
35
+ device: {
36
+ id: 'mock-device-2',
37
+ name: 'Mock BLE Device 2',
38
+ rssi: -75,
39
+ },
40
+ });
41
+ }, 2000);
42
+
43
+ return Promise.resolve();
44
+ }
45
+
46
+ async stopScan(): Promise<void> {
47
+ console.log('📱 Mock: Stopping scan...');
48
+ return Promise.resolve();
49
+ }
50
+
51
+ async connect(deviceId: string): Promise<void> {
52
+ console.log('📱 Mock: Connecting to device:', deviceId);
53
+ setTimeout(() => {
54
+ this.emit('connected', { deviceId });
55
+
56
+ // Simulate characteristic notifications
57
+ setTimeout(() => {
58
+ this.emit('characteristicChanged', {
59
+ deviceId,
60
+ serviceUuid: '0000FF00-0000-1000-8000-00805F9B34FB',
61
+ characteristicUuid: '0000FF21-0000-1000-8000-00805F9B34FB',
62
+ value: [1, 2, 3, 4],
63
+ });
64
+ }, 2000);
65
+ }, 500);
66
+ return Promise.resolve();
67
+ }
68
+
69
+ async disconnect(deviceId: string): Promise<void> {
70
+ console.log('📱 Mock: Disconnecting from device:', deviceId);
71
+ setTimeout(() => {
72
+ this.emit('disconnected', { deviceId });
73
+ }, 500);
74
+ return Promise.resolve();
75
+ }
76
+
77
+ on(event: string, callback: Function): void {
78
+ if (!this.listeners.has(event)) {
79
+ this.listeners.set(event, []);
80
+ }
81
+ this.listeners.get(event)!.push(callback);
82
+ console.log(`📱 Mock: Registered listener for '${event}'`);
83
+ }
84
+
85
+ removeAllListeners(): void {
86
+ console.log('📱 Mock: Removing all listeners');
87
+ this.listeners.clear();
88
+ }
89
+
90
+ private emit(event: string, data: any): void {
91
+ const callbacks = this.listeners.get(event) || [];
92
+ callbacks.forEach((callback) => callback(data));
93
+ }
94
+ }
95
+
96
+ export default new MockBLEManager();
@@ -0,0 +1 @@
1
+ export { default as bleMiddleware } from './BLEMiddleware';
@@ -0,0 +1,97 @@
1
+ /**
2
+ * BLE Device interface
3
+ */
4
+ export interface BLEDevice {
5
+ id: string;
6
+ name?: string;
7
+ rssi?: number;
8
+ [key: string]: any;
9
+ }
10
+
11
+ /**
12
+ * Scan configuration options
13
+ */
14
+ export interface ScanOptions {
15
+ timeout?: number;
16
+ allowDuplicates?: boolean;
17
+ }
18
+
19
+ /**
20
+ * User role types
21
+ */
22
+ export type UserRole = 'patient' | 'nurse' | 'engineer';
23
+
24
+ /**
25
+ * Characteristic notification event
26
+ */
27
+ export interface CharacteristicNotification {
28
+ deviceId: string;
29
+ serviceUuid: string;
30
+ characteristicUuid: string;
31
+ value: any;
32
+ }
33
+
34
+ /**
35
+ * Device connection state
36
+ */
37
+ export interface DeviceConnectionState {
38
+ deviceId: string;
39
+ isConnected: boolean;
40
+ isInfusionRunning: boolean;
41
+ infusionLevel: number | null;
42
+ notifications: {
43
+ ff01: CharacteristicNotification | null;
44
+ ff21: CharacteristicNotification | null;
45
+ ff31: CharacteristicNotification | null;
46
+ ff41: CharacteristicNotification | null;
47
+ ff02: CharacteristicNotification | null;
48
+ };
49
+ }
50
+
51
+ /**
52
+ * BLE event types
53
+ */
54
+ export type BLEEventType =
55
+ | 'scanResult'
56
+ | 'connected'
57
+ | 'disconnected'
58
+ | 'BleManagerScanFailed'
59
+ | 'bluetoothStateChanged'
60
+ | 'characteristicChanged';
61
+
62
+ /**
63
+ * BLE event payloads
64
+ */
65
+ export interface BLEEvents {
66
+ scanResult: { device: BLEDevice };
67
+ connected: { deviceId: string };
68
+ disconnected: { deviceId: string };
69
+ BleManagerScanFailed: { error: string };
70
+ bluetoothStateChanged: { state: string };
71
+ characteristicChanged: CharacteristicNotification;
72
+ }
73
+
74
+ /**
75
+ * Characteristic UUIDs for notifications
76
+ */
77
+ export enum CharacteristicUUID {
78
+ FF01 = '0000FF01-0000-1000-8000-00805F9B34FB',
79
+ FF21 = '0000FF21-0000-1000-8000-00805F9B34FB',
80
+ FF31 = '0000FF31-0000-1000-8000-00805F9B34FB',
81
+ FF41 = '0000FF41-0000-1000-8000-00805F9B34FB',
82
+ FF02 = '0000FF02-0000-1000-8000-00805F9B34FB',
83
+ }
84
+
85
+ /**
86
+ * BLE Manager interface
87
+ */
88
+ export interface IBLEManager {
89
+ isBluetoothEnabled(): Promise<boolean>;
90
+ requestPermissions(): Promise<void>;
91
+ startScan(options?: ScanOptions): Promise<void>;
92
+ stopScan(): Promise<void>;
93
+ connect(deviceId: string): Promise<void>;
94
+ disconnect(deviceId: string): Promise<void>;
95
+ on(event: BLEEventType, callback: (data: any) => void): void;
96
+ removeAllListeners(): void;
97
+ }