react-native-sdk-ble-middleware-v2 0.1.2 → 0.1.3

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.
@@ -146,7 +146,7 @@ export const BLEProvider = ({
146
146
 
147
147
  // Characteristic changed event
148
148
  bleMiddleware.on('characteristicChanged', event => {
149
- console.log('Characteristic Changed Event:', event);
149
+ console.log('📡 Characteristic Changed Event:', event);
150
150
  const {
151
151
  characteristicUuid,
152
152
  deviceId
@@ -165,6 +165,7 @@ export const BLEProvider = ({
165
165
  updatedState.notifications.ff01 = event;
166
166
  } else if (uuidUpper === '0000FF21-0000-1000-8000-00805F9B34FB') {
167
167
  updatedState.notifications.ff21 = event;
168
+ console.log('✅ FF21 notification stored in device state');
168
169
  } else if (uuidUpper === '0000FF31-0000-1000-8000-00805F9B34FB') {
169
170
  updatedState.notifications.ff31 = event;
170
171
  } else if (uuidUpper === '0000FF41-0000-1000-8000-00805F9B34FB') {
@@ -177,22 +178,32 @@ export const BLEProvider = ({
177
178
  return newMap;
178
179
  });
179
180
 
180
- // Legacy: Update global notifications for primary device
181
- if (deviceId === connectedDeviceId) {
182
- if (uuidUpper === '0000FF01-0000-1000-8000-00805F9B34FB') {
183
- setFF01Notification(event);
184
- } else if (uuidUpper === '0000FF21-0000-1000-8000-00805F9B34FB') {
185
- setFF21Notification(event);
186
- } else if (uuidUpper === '0000FF31-0000-1000-8000-00805F9B34FB') {
187
- setFF31Notification(event);
188
- } else if (uuidUpper === '0000FF41-0000-1000-8000-00805F9B34FB') {
189
- setFF41Notification(event);
190
- } else if (uuidUpper === '0000FF02-0000-1000-8000-00805F9B34FB') {
191
- setFF02Notification(event);
181
+ // Legacy: Update global notifications using functional update to avoid stale closure
182
+ setConnectedDeviceId(currentPrimaryDeviceId => {
183
+ console.log(`🔍 Comparing deviceId: ${deviceId} with primary: ${currentPrimaryDeviceId}`);
184
+
185
+ // Check if this event is for the primary device
186
+ if (deviceId === currentPrimaryDeviceId) {
187
+ console.log('✅ This is the primary device, updating global notifications');
188
+ if (uuidUpper === '0000FF01-0000-1000-8000-00805F9B34FB') {
189
+ setFF01Notification(event);
190
+ } else if (uuidUpper === '0000FF21-0000-1000-8000-00805F9B34FB') {
191
+ setFF21Notification(event);
192
+ console.log('✅ FF21 global notification updated!');
193
+ } else if (uuidUpper === '0000FF31-0000-1000-8000-00805F9B34FB') {
194
+ setFF31Notification(event);
195
+ } else if (uuidUpper === '0000FF41-0000-1000-8000-00805F9B34FB') {
196
+ setFF41Notification(event);
197
+ } else if (uuidUpper === '0000FF02-0000-1000-8000-00805F9B34FB') {
198
+ setFF02Notification(event);
199
+ } else {
200
+ console.log('⚠️ Unhandled characteristic:', characteristicUuid);
201
+ }
192
202
  } else {
193
- console.log('⚠️ Unhandled characteristic:', characteristicUuid);
203
+ console.log(`⚠️ Not primary device - skipping global update`);
194
204
  }
195
- }
205
+ return currentPrimaryDeviceId; // Return unchanged
206
+ });
196
207
  });
197
208
  };
198
209
  const startScan = async () => {
@@ -1 +1 @@
1
- {"version":3,"names":["React","createContext","useContext","useState","useEffect","bleMiddleware","BLEContext","undefined","BLEProvider","children","bluetoothEnabled","setBluetoothEnabled","isScanning","setIsScanning","discoveredDevices","setDiscoveredDevices","connectedDevices","setConnectedDevices","Map","connectedDeviceId","setConnectedDeviceId","ff01Notification","setFF01Notification","ff21Notification","setFF21Notification","ff31Notification","setFF31Notification","ff41Notification","setFF41Notification","ff02Notification","setFF02Notification","isInfusionRunning","setIsInfusionRunning","initialize","waitForInitialization","setupBLE","setupEventListeners","removeAllListeners","requestPermissions","enabled","isBluetoothEnabled","error","console","on","device","prev","exists","find","d","id","map","deviceId","newMap","set","isConnected","infusionLevel","notifications","ff01","ff21","ff31","ff41","ff02","log","delete","remaining","Array","from","keys","filter","newPrimary","state","event","characteristicUuid","uuidUpper","toUpperCase","deviceState","get","updatedState","startScan","timeout","allowDuplicates","stopScan","connectToDevice","connect","disconnectDevice","disconnect","getDeviceState","isDeviceConnected","has","getConnectedDeviceIds","startInfusion","stopInfusion","setInfusionLevel","level","readCharacteristic","serviceUuid","writeCharacteristic","data","options","setUserRole","role","getUserRole","value","createElement","Provider","useBLEContext","context","Error"],"sources":["BLEContext.tsx"],"sourcesContent":["import React, { createContext, useContext, useState, useEffect } from 'react';\nimport type {\n BLEDevice,\n CharacteristicNotification,\n DeviceConnectionState,\n UserRole,\n} from '../types';\nimport bleMiddleware from '../services/BLEMiddleware';\n\n/**\n * BLE Context State\n */\ninterface BLEContextState {\n // Connection state\n bluetoothEnabled: boolean;\n isScanning: boolean;\n discoveredDevices: BLEDevice[];\n connectedDevices: Map<string, DeviceConnectionState>;\n\n // Legacy single device support (for backward compatibility)\n connectedDeviceId: string | null;\n isInfusionRunning: boolean;\n ff01Notification: CharacteristicNotification | null;\n ff21Notification: CharacteristicNotification | null;\n ff31Notification: CharacteristicNotification | null;\n ff41Notification: CharacteristicNotification | null;\n ff02Notification: CharacteristicNotification | null;\n\n // Actions\n startScan: () => Promise<void>;\n stopScan: () => Promise<void>;\n connectToDevice: (device: BLEDevice) => Promise<void>;\n disconnectDevice: (deviceId: string) => Promise<void>;\n requestPermissions: () => Promise<void>;\n\n // Multi-device queries\n getDeviceState: (deviceId: string) => DeviceConnectionState | undefined;\n isDeviceConnected: (deviceId: string) => boolean;\n getConnectedDeviceIds: () => string[];\n\n // Infusion actions\n startInfusion: (deviceId: string) => Promise<void>;\n stopInfusion: (deviceId: string) => Promise<void>;\n setInfusionLevel: (deviceId: string, level: number) => Promise<void>;\n\n // Characteristic operations\n readCharacteristic: (\n deviceId: string,\n serviceUuid: string,\n characteristicUuid: string\n ) => Promise<any>;\n writeCharacteristic: (\n deviceId: string,\n serviceUuid: string,\n characteristicUuid: string,\n data: string,\n options?: { withResponse?: boolean }\n ) => Promise<void>;\n\n // User role management\n setUserRole: (role: UserRole) => void;\n getUserRole: () => UserRole;\n}\n\nconst BLEContext = createContext<BLEContextState | undefined>(undefined);\n\n/**\n * BLE Provider Component\n * Manages all BLE state and operations\n */\nexport const BLEProvider: React.FC<{ children: React.ReactNode }> = ({\n children,\n}) => {\n const [bluetoothEnabled, setBluetoothEnabled] = useState(false);\n const [isScanning, setIsScanning] = useState(false);\n const [discoveredDevices, setDiscoveredDevices] = useState<BLEDevice[]>([]);\n const [connectedDevices, setConnectedDevices] = useState<\n Map<string, DeviceConnectionState>\n >(new Map());\n\n // Legacy single device support (tracks the first/primary connected device)\n const [connectedDeviceId, setConnectedDeviceId] = useState<string | null>(\n null\n );\n\n // Legacy notification states (for the primary device)\n const [ff01Notification, setFF01Notification] =\n useState<CharacteristicNotification | null>(null);\n const [ff21Notification, setFF21Notification] =\n useState<CharacteristicNotification | null>(null);\n const [ff31Notification, setFF31Notification] =\n useState<CharacteristicNotification | null>(null);\n const [ff41Notification, setFF41Notification] =\n useState<CharacteristicNotification | null>(null);\n const [ff02Notification, setFF02Notification] =\n useState<CharacteristicNotification | null>(null);\n\n // Legacy infusion state (for the primary device)\n const [isInfusionRunning, setIsInfusionRunning] = useState(false);\n\n useEffect(() => {\n const initialize = async () => {\n // Wait for BLE middleware to initialize first\n await bleMiddleware.waitForInitialization();\n\n // Then setup BLE and event listeners\n await setupBLE();\n setupEventListeners();\n };\n\n initialize();\n\n return () => {\n bleMiddleware.removeAllListeners();\n };\n }, []);\n\n const setupBLE = async () => {\n try {\n await requestPermissions();\n const enabled = await bleMiddleware.isBluetoothEnabled();\n setBluetoothEnabled(enabled);\n } catch (error) {\n console.error('Failed to setup BLE:', error);\n }\n };\n\n const requestPermissions = async () => {\n try {\n await bleMiddleware.requestPermissions();\n } catch (error) {\n console.error('Failed to request permissions:', error);\n }\n };\n\n const setupEventListeners = () => {\n // Scan result event\n bleMiddleware.on('scanResult', ({ device }: any) => {\n setDiscoveredDevices((prev) => {\n const exists = prev.find((d) => d.id === device.id);\n if (exists) {\n return prev.map((d) => (d.id === device.id ? device : d));\n }\n return [...prev, device];\n });\n });\n\n // Connected event\n bleMiddleware.on('connected', ({ deviceId }: any) => {\n setConnectedDevices((prev) => {\n const newMap = new Map(prev);\n newMap.set(deviceId, {\n deviceId,\n isConnected: true,\n isInfusionRunning: false,\n infusionLevel: null,\n notifications: {\n ff01: null,\n ff21: null,\n ff31: null,\n ff41: null,\n ff02: null,\n },\n });\n return newMap;\n });\n\n // Legacy: Set first connected device as primary\n setConnectedDeviceId((prev) => prev || deviceId);\n console.log('✅ Device connected:', deviceId);\n });\n\n // Disconnected event\n bleMiddleware.on('disconnected', ({ deviceId }: any) => {\n setConnectedDevices((prev) => {\n const newMap = new Map(prev);\n newMap.delete(deviceId);\n return newMap;\n });\n\n // Legacy: Update primary device\n setConnectedDeviceId((prev) => {\n if (prev === deviceId) {\n // If primary device disconnected, set new primary or null\n const remaining = Array.from(connectedDevices.keys()).filter(\n (id) => id !== deviceId\n );\n const newPrimary = remaining[0] || null;\n // Update legacy infusion state\n if (!newPrimary) {\n setIsInfusionRunning(false);\n }\n return newPrimary;\n }\n return prev;\n });\n\n console.log('❌ Device disconnected:', deviceId);\n });\n\n // Scan failed event\n bleMiddleware.on('BleManagerScanFailed', ({ error }: any) => {\n console.error('BLE Scan Failed:', error);\n setIsScanning(false);\n });\n\n // Bluetooth state changed event\n bleMiddleware.on('bluetoothStateChanged', ({ state }: any) => {\n setBluetoothEnabled(state === 'poweredOn');\n });\n\n // Characteristic changed event\n bleMiddleware.on('characteristicChanged', (event: any) => {\n console.log('Characteristic Changed Event:', event);\n const { characteristicUuid, deviceId } = event;\n const uuidUpper = characteristicUuid?.toUpperCase();\n\n // Update device-specific notifications\n setConnectedDevices((prev) => {\n const newMap = new Map(prev);\n const deviceState = newMap.get(deviceId);\n if (deviceState) {\n const updatedState = { ...deviceState };\n if (uuidUpper === '0000FF01-0000-1000-8000-00805F9B34FB') {\n updatedState.notifications.ff01 = event;\n } else if (uuidUpper === '0000FF21-0000-1000-8000-00805F9B34FB') {\n updatedState.notifications.ff21 = event;\n } else if (uuidUpper === '0000FF31-0000-1000-8000-00805F9B34FB') {\n updatedState.notifications.ff31 = event;\n } else if (uuidUpper === '0000FF41-0000-1000-8000-00805F9B34FB') {\n updatedState.notifications.ff41 = event;\n } else if (uuidUpper === '0000FF02-0000-1000-8000-00805F9B34FB') {\n updatedState.notifications.ff02 = event;\n }\n newMap.set(deviceId, updatedState);\n }\n return newMap;\n });\n\n // Legacy: Update global notifications for primary device\n if (deviceId === connectedDeviceId) {\n if (uuidUpper === '0000FF01-0000-1000-8000-00805F9B34FB') {\n setFF01Notification(event);\n } else if (uuidUpper === '0000FF21-0000-1000-8000-00805F9B34FB') {\n setFF21Notification(event);\n } else if (uuidUpper === '0000FF31-0000-1000-8000-00805F9B34FB') {\n setFF31Notification(event);\n } else if (uuidUpper === '0000FF41-0000-1000-8000-00805F9B34FB') {\n setFF41Notification(event);\n } else if (uuidUpper === '0000FF02-0000-1000-8000-00805F9B34FB') {\n setFF02Notification(event);\n } else {\n console.log('⚠️ Unhandled characteristic:', characteristicUuid);\n }\n }\n });\n };\n\n const startScan = async () => {\n console.log('Starting device scan...');\n try {\n setDiscoveredDevices([]);\n setIsScanning(true);\n await bleMiddleware.startScan({ timeout: 10000, allowDuplicates: false });\n } catch (error) {\n console.error('Failed to start scan:', error);\n setIsScanning(false);\n }\n };\n\n const stopScan = async () => {\n try {\n await bleMiddleware.stopScan();\n setIsScanning(false);\n } catch (error) {\n console.error('Failed to stop scan:', error);\n }\n };\n\n const connectToDevice = async (device: BLEDevice) => {\n console.log('Connecting to device:', device);\n try {\n await bleMiddleware.connect(device.id);\n console.log('Connected successfully');\n } catch (error) {\n console.error('Failed to connect:', error);\n }\n };\n\n const disconnectDevice = async (deviceId: string) => {\n try {\n await bleMiddleware.disconnect(deviceId);\n // State will be updated in the 'disconnected' event handler\n console.log('Disconnected from device:', deviceId);\n } catch (error) {\n console.error('Failed to disconnect:', error);\n }\n };\n\n // Multi-device query helpers\n const getDeviceState = (\n deviceId: string\n ): DeviceConnectionState | undefined => {\n return connectedDevices.get(deviceId);\n };\n\n const isDeviceConnected = (deviceId: string): boolean => {\n return connectedDevices.has(deviceId);\n };\n\n const getConnectedDeviceIds = (): string[] => {\n return Array.from(connectedDevices.keys());\n };\n\n const startInfusion = async (deviceId: string) => {\n try {\n await bleMiddleware.startInfusion(deviceId);\n\n // Update device-specific state\n setConnectedDevices((prev) => {\n const newMap = new Map(prev);\n const deviceState = newMap.get(deviceId);\n if (deviceState) {\n newMap.set(deviceId, {\n ...deviceState,\n isInfusionRunning: true,\n });\n }\n return newMap;\n });\n\n // Legacy: Update global state if this is the primary device\n if (deviceId === connectedDeviceId) {\n setIsInfusionRunning(true);\n }\n\n console.log('✅ Infusion started successfully for device:', deviceId);\n } catch (error) {\n console.error('Failed to start infusion:', error);\n throw error;\n }\n };\n\n const stopInfusion = async (deviceId: string) => {\n try {\n await bleMiddleware.stopInfusion(deviceId);\n\n // Update device-specific state\n setConnectedDevices((prev) => {\n const newMap = new Map(prev);\n const deviceState = newMap.get(deviceId);\n if (deviceState) {\n newMap.set(deviceId, {\n ...deviceState,\n isInfusionRunning: false,\n });\n }\n return newMap;\n });\n\n // Legacy: Update global state if this is the primary device\n if (deviceId === connectedDeviceId) {\n setIsInfusionRunning(false);\n }\n\n console.log('✅ Infusion stopped successfully for device:', deviceId);\n } catch (error) {\n console.error('Failed to stop infusion:', error);\n throw error;\n }\n };\n\n const setInfusionLevel = async (deviceId: string, level: number) => {\n try {\n await bleMiddleware.setInfusionLevel(deviceId, level);\n\n // Update device-specific state\n setConnectedDevices((prev) => {\n const newMap = new Map(prev);\n const deviceState = newMap.get(deviceId);\n if (deviceState) {\n newMap.set(deviceId, {\n ...deviceState,\n infusionLevel: level,\n });\n }\n return newMap;\n });\n\n console.log(\n `✅ Infusion level set to ${level} successfully for device:`,\n deviceId\n );\n } catch (error) {\n console.error('Failed to set infusion level:', error);\n throw error;\n }\n };\n\n const readCharacteristic = async (\n deviceId: string,\n serviceUuid: string,\n characteristicUuid: string\n ) => {\n try {\n return await bleMiddleware.readCharacteristic(\n deviceId,\n serviceUuid,\n characteristicUuid\n );\n } catch (error) {\n console.error('Failed to read characteristic:', error);\n throw error;\n }\n };\n\n const writeCharacteristic = async (\n deviceId: string,\n serviceUuid: string,\n characteristicUuid: string,\n data: string,\n options?: { withResponse?: boolean }\n ) => {\n try {\n await bleMiddleware.writeCharacteristic(\n deviceId,\n serviceUuid,\n characteristicUuid,\n data,\n options\n );\n } catch (error) {\n console.error('Failed to write characteristic:', error);\n throw error;\n }\n };\n\n const setUserRole = (role: UserRole) => {\n bleMiddleware.setUserRole(role);\n };\n\n const getUserRole = (): UserRole => {\n return bleMiddleware.getUserRole();\n };\n\n const value: BLEContextState = {\n bluetoothEnabled,\n isScanning,\n discoveredDevices,\n connectedDevices,\n connectedDeviceId,\n isInfusionRunning,\n ff01Notification,\n ff21Notification,\n ff31Notification,\n ff41Notification,\n ff02Notification,\n startScan,\n stopScan,\n connectToDevice,\n disconnectDevice,\n requestPermissions,\n getDeviceState,\n isDeviceConnected,\n getConnectedDeviceIds,\n startInfusion,\n stopInfusion,\n setInfusionLevel,\n readCharacteristic,\n writeCharacteristic,\n setUserRole,\n getUserRole,\n };\n\n return <BLEContext.Provider value={value}>{children}</BLEContext.Provider>;\n};\n\n/**\n * Hook to access BLE context\n */\nexport const useBLEContext = (): BLEContextState => {\n const context = useContext(BLEContext);\n if (!context) {\n throw new Error('useBLEContext must be used within a BLEProvider');\n }\n return context;\n};\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["React","createContext","useContext","useState","useEffect","bleMiddleware","BLEContext","undefined","BLEProvider","children","bluetoothEnabled","setBluetoothEnabled","isScanning","setIsScanning","discoveredDevices","setDiscoveredDevices","connectedDevices","setConnectedDevices","Map","connectedDeviceId","setConnectedDeviceId","ff01Notification","setFF01Notification","ff21Notification","setFF21Notification","ff31Notification","setFF31Notification","ff41Notification","setFF41Notification","ff02Notification","setFF02Notification","isInfusionRunning","setIsInfusionRunning","initialize","waitForInitialization","setupBLE","setupEventListeners","removeAllListeners","requestPermissions","enabled","isBluetoothEnabled","error","console","on","device","prev","exists","find","d","id","map","deviceId","newMap","set","isConnected","infusionLevel","notifications","ff01","ff21","ff31","ff41","ff02","log","delete","remaining","Array","from","keys","filter","newPrimary","state","event","characteristicUuid","uuidUpper","toUpperCase","deviceState","get","updatedState","currentPrimaryDeviceId","startScan","timeout","allowDuplicates","stopScan","connectToDevice","connect","disconnectDevice","disconnect","getDeviceState","isDeviceConnected","has","getConnectedDeviceIds","startInfusion","stopInfusion","setInfusionLevel","level","readCharacteristic","serviceUuid","writeCharacteristic","data","options","setUserRole","role","getUserRole","value","createElement","Provider","useBLEContext","context","Error"],"sources":["BLEContext.tsx"],"sourcesContent":["import React, { createContext, useContext, useState, useEffect } from 'react';\nimport type {\n BLEDevice,\n CharacteristicNotification,\n DeviceConnectionState,\n UserRole,\n} from '../types';\nimport bleMiddleware from '../services/BLEMiddleware';\n\n/**\n * BLE Context State\n */\ninterface BLEContextState {\n // Connection state\n bluetoothEnabled: boolean;\n isScanning: boolean;\n discoveredDevices: BLEDevice[];\n connectedDevices: Map<string, DeviceConnectionState>;\n\n // Legacy single device support (for backward compatibility)\n connectedDeviceId: string | null;\n isInfusionRunning: boolean;\n ff01Notification: CharacteristicNotification | null;\n ff21Notification: CharacteristicNotification | null;\n ff31Notification: CharacteristicNotification | null;\n ff41Notification: CharacteristicNotification | null;\n ff02Notification: CharacteristicNotification | null;\n\n // Actions\n startScan: () => Promise<void>;\n stopScan: () => Promise<void>;\n connectToDevice: (device: BLEDevice) => Promise<void>;\n disconnectDevice: (deviceId: string) => Promise<void>;\n requestPermissions: () => Promise<void>;\n\n // Multi-device queries\n getDeviceState: (deviceId: string) => DeviceConnectionState | undefined;\n isDeviceConnected: (deviceId: string) => boolean;\n getConnectedDeviceIds: () => string[];\n\n // Infusion actions\n startInfusion: (deviceId: string) => Promise<void>;\n stopInfusion: (deviceId: string) => Promise<void>;\n setInfusionLevel: (deviceId: string, level: number) => Promise<void>;\n\n // Characteristic operations\n readCharacteristic: (\n deviceId: string,\n serviceUuid: string,\n characteristicUuid: string\n ) => Promise<any>;\n writeCharacteristic: (\n deviceId: string,\n serviceUuid: string,\n characteristicUuid: string,\n data: string,\n options?: { withResponse?: boolean }\n ) => Promise<void>;\n\n // User role management\n setUserRole: (role: UserRole) => void;\n getUserRole: () => UserRole;\n}\n\nconst BLEContext = createContext<BLEContextState | undefined>(undefined);\n\n/**\n * BLE Provider Component\n * Manages all BLE state and operations\n */\nexport const BLEProvider: React.FC<{ children: React.ReactNode }> = ({\n children,\n}) => {\n const [bluetoothEnabled, setBluetoothEnabled] = useState(false);\n const [isScanning, setIsScanning] = useState(false);\n const [discoveredDevices, setDiscoveredDevices] = useState<BLEDevice[]>([]);\n const [connectedDevices, setConnectedDevices] = useState<\n Map<string, DeviceConnectionState>\n >(new Map());\n\n // Legacy single device support (tracks the first/primary connected device)\n const [connectedDeviceId, setConnectedDeviceId] = useState<string | null>(\n null\n );\n\n // Legacy notification states (for the primary device)\n const [ff01Notification, setFF01Notification] =\n useState<CharacteristicNotification | null>(null);\n const [ff21Notification, setFF21Notification] =\n useState<CharacteristicNotification | null>(null);\n const [ff31Notification, setFF31Notification] =\n useState<CharacteristicNotification | null>(null);\n const [ff41Notification, setFF41Notification] =\n useState<CharacteristicNotification | null>(null);\n const [ff02Notification, setFF02Notification] =\n useState<CharacteristicNotification | null>(null);\n\n // Legacy infusion state (for the primary device)\n const [isInfusionRunning, setIsInfusionRunning] = useState(false);\n\n useEffect(() => {\n const initialize = async () => {\n // Wait for BLE middleware to initialize first\n await bleMiddleware.waitForInitialization();\n\n // Then setup BLE and event listeners\n await setupBLE();\n setupEventListeners();\n };\n\n initialize();\n\n return () => {\n bleMiddleware.removeAllListeners();\n };\n }, []);\n\n const setupBLE = async () => {\n try {\n await requestPermissions();\n const enabled = await bleMiddleware.isBluetoothEnabled();\n setBluetoothEnabled(enabled);\n } catch (error) {\n console.error('Failed to setup BLE:', error);\n }\n };\n\n const requestPermissions = async () => {\n try {\n await bleMiddleware.requestPermissions();\n } catch (error) {\n console.error('Failed to request permissions:', error);\n }\n };\n\n const setupEventListeners = () => {\n // Scan result event\n bleMiddleware.on('scanResult', ({ device }: any) => {\n setDiscoveredDevices((prev) => {\n const exists = prev.find((d) => d.id === device.id);\n if (exists) {\n return prev.map((d) => (d.id === device.id ? device : d));\n }\n return [...prev, device];\n });\n });\n\n // Connected event\n bleMiddleware.on('connected', ({ deviceId }: any) => {\n setConnectedDevices((prev) => {\n const newMap = new Map(prev);\n newMap.set(deviceId, {\n deviceId,\n isConnected: true,\n isInfusionRunning: false,\n infusionLevel: null,\n notifications: {\n ff01: null,\n ff21: null,\n ff31: null,\n ff41: null,\n ff02: null,\n },\n });\n return newMap;\n });\n\n // Legacy: Set first connected device as primary\n setConnectedDeviceId((prev) => prev || deviceId);\n console.log('✅ Device connected:', deviceId);\n });\n\n // Disconnected event\n bleMiddleware.on('disconnected', ({ deviceId }: any) => {\n setConnectedDevices((prev) => {\n const newMap = new Map(prev);\n newMap.delete(deviceId);\n return newMap;\n });\n\n // Legacy: Update primary device\n setConnectedDeviceId((prev) => {\n if (prev === deviceId) {\n // If primary device disconnected, set new primary or null\n const remaining = Array.from(connectedDevices.keys()).filter(\n (id) => id !== deviceId\n );\n const newPrimary = remaining[0] || null;\n // Update legacy infusion state\n if (!newPrimary) {\n setIsInfusionRunning(false);\n }\n return newPrimary;\n }\n return prev;\n });\n\n console.log('❌ Device disconnected:', deviceId);\n });\n\n // Scan failed event\n bleMiddleware.on('BleManagerScanFailed', ({ error }: any) => {\n console.error('BLE Scan Failed:', error);\n setIsScanning(false);\n });\n\n // Bluetooth state changed event\n bleMiddleware.on('bluetoothStateChanged', ({ state }: any) => {\n setBluetoothEnabled(state === 'poweredOn');\n });\n\n // Characteristic changed event\n bleMiddleware.on('characteristicChanged', (event: any) => {\n console.log('📡 Characteristic Changed Event:', event);\n const { characteristicUuid, deviceId } = event;\n const uuidUpper = characteristicUuid?.toUpperCase();\n\n // Update device-specific notifications\n setConnectedDevices((prev) => {\n const newMap = new Map(prev);\n const deviceState = newMap.get(deviceId);\n if (deviceState) {\n const updatedState = { ...deviceState };\n if (uuidUpper === '0000FF01-0000-1000-8000-00805F9B34FB') {\n updatedState.notifications.ff01 = event;\n } else if (uuidUpper === '0000FF21-0000-1000-8000-00805F9B34FB') {\n updatedState.notifications.ff21 = event;\n console.log('✅ FF21 notification stored in device state');\n } else if (uuidUpper === '0000FF31-0000-1000-8000-00805F9B34FB') {\n updatedState.notifications.ff31 = event;\n } else if (uuidUpper === '0000FF41-0000-1000-8000-00805F9B34FB') {\n updatedState.notifications.ff41 = event;\n } else if (uuidUpper === '0000FF02-0000-1000-8000-00805F9B34FB') {\n updatedState.notifications.ff02 = event;\n }\n newMap.set(deviceId, updatedState);\n }\n return newMap;\n });\n\n // Legacy: Update global notifications using functional update to avoid stale closure\n setConnectedDeviceId((currentPrimaryDeviceId) => {\n console.log(\n `🔍 Comparing deviceId: ${deviceId} with primary: ${currentPrimaryDeviceId}`\n );\n\n // Check if this event is for the primary device\n if (deviceId === currentPrimaryDeviceId) {\n console.log(\n '✅ This is the primary device, updating global notifications'\n );\n\n if (uuidUpper === '0000FF01-0000-1000-8000-00805F9B34FB') {\n setFF01Notification(event);\n } else if (uuidUpper === '0000FF21-0000-1000-8000-00805F9B34FB') {\n setFF21Notification(event);\n console.log('✅ FF21 global notification updated!');\n } else if (uuidUpper === '0000FF31-0000-1000-8000-00805F9B34FB') {\n setFF31Notification(event);\n } else if (uuidUpper === '0000FF41-0000-1000-8000-00805F9B34FB') {\n setFF41Notification(event);\n } else if (uuidUpper === '0000FF02-0000-1000-8000-00805F9B34FB') {\n setFF02Notification(event);\n } else {\n console.log('⚠️ Unhandled characteristic:', characteristicUuid);\n }\n } else {\n console.log(`⚠️ Not primary device - skipping global update`);\n }\n\n return currentPrimaryDeviceId; // Return unchanged\n });\n });\n };\n\n const startScan = async () => {\n console.log('Starting device scan...');\n try {\n setDiscoveredDevices([]);\n setIsScanning(true);\n await bleMiddleware.startScan({ timeout: 10000, allowDuplicates: false });\n } catch (error) {\n console.error('Failed to start scan:', error);\n setIsScanning(false);\n }\n };\n\n const stopScan = async () => {\n try {\n await bleMiddleware.stopScan();\n setIsScanning(false);\n } catch (error) {\n console.error('Failed to stop scan:', error);\n }\n };\n\n const connectToDevice = async (device: BLEDevice) => {\n console.log('Connecting to device:', device);\n try {\n await bleMiddleware.connect(device.id);\n console.log('Connected successfully');\n } catch (error) {\n console.error('Failed to connect:', error);\n }\n };\n\n const disconnectDevice = async (deviceId: string) => {\n try {\n await bleMiddleware.disconnect(deviceId);\n // State will be updated in the 'disconnected' event handler\n console.log('Disconnected from device:', deviceId);\n } catch (error) {\n console.error('Failed to disconnect:', error);\n }\n };\n\n // Multi-device query helpers\n const getDeviceState = (\n deviceId: string\n ): DeviceConnectionState | undefined => {\n return connectedDevices.get(deviceId);\n };\n\n const isDeviceConnected = (deviceId: string): boolean => {\n return connectedDevices.has(deviceId);\n };\n\n const getConnectedDeviceIds = (): string[] => {\n return Array.from(connectedDevices.keys());\n };\n\n const startInfusion = async (deviceId: string) => {\n try {\n await bleMiddleware.startInfusion(deviceId);\n\n // Update device-specific state\n setConnectedDevices((prev) => {\n const newMap = new Map(prev);\n const deviceState = newMap.get(deviceId);\n if (deviceState) {\n newMap.set(deviceId, {\n ...deviceState,\n isInfusionRunning: true,\n });\n }\n return newMap;\n });\n\n // Legacy: Update global state if this is the primary device\n if (deviceId === connectedDeviceId) {\n setIsInfusionRunning(true);\n }\n\n console.log('✅ Infusion started successfully for device:', deviceId);\n } catch (error) {\n console.error('Failed to start infusion:', error);\n throw error;\n }\n };\n\n const stopInfusion = async (deviceId: string) => {\n try {\n await bleMiddleware.stopInfusion(deviceId);\n\n // Update device-specific state\n setConnectedDevices((prev) => {\n const newMap = new Map(prev);\n const deviceState = newMap.get(deviceId);\n if (deviceState) {\n newMap.set(deviceId, {\n ...deviceState,\n isInfusionRunning: false,\n });\n }\n return newMap;\n });\n\n // Legacy: Update global state if this is the primary device\n if (deviceId === connectedDeviceId) {\n setIsInfusionRunning(false);\n }\n\n console.log('✅ Infusion stopped successfully for device:', deviceId);\n } catch (error) {\n console.error('Failed to stop infusion:', error);\n throw error;\n }\n };\n\n const setInfusionLevel = async (deviceId: string, level: number) => {\n try {\n await bleMiddleware.setInfusionLevel(deviceId, level);\n\n // Update device-specific state\n setConnectedDevices((prev) => {\n const newMap = new Map(prev);\n const deviceState = newMap.get(deviceId);\n if (deviceState) {\n newMap.set(deviceId, {\n ...deviceState,\n infusionLevel: level,\n });\n }\n return newMap;\n });\n\n console.log(\n `✅ Infusion level set to ${level} successfully for device:`,\n deviceId\n );\n } catch (error) {\n console.error('Failed to set infusion level:', error);\n throw error;\n }\n };\n\n const readCharacteristic = async (\n deviceId: string,\n serviceUuid: string,\n characteristicUuid: string\n ) => {\n try {\n return await bleMiddleware.readCharacteristic(\n deviceId,\n serviceUuid,\n characteristicUuid\n );\n } catch (error) {\n console.error('Failed to read characteristic:', error);\n throw error;\n }\n };\n\n const writeCharacteristic = async (\n deviceId: string,\n serviceUuid: string,\n characteristicUuid: string,\n data: string,\n options?: { withResponse?: boolean }\n ) => {\n try {\n await bleMiddleware.writeCharacteristic(\n deviceId,\n serviceUuid,\n characteristicUuid,\n data,\n options\n );\n } catch (error) {\n console.error('Failed to write characteristic:', error);\n throw error;\n }\n };\n\n const setUserRole = (role: UserRole) => {\n bleMiddleware.setUserRole(role);\n };\n\n const getUserRole = (): UserRole => {\n return bleMiddleware.getUserRole();\n };\n\n const value: BLEContextState = {\n bluetoothEnabled,\n isScanning,\n discoveredDevices,\n connectedDevices,\n connectedDeviceId,\n isInfusionRunning,\n ff01Notification,\n ff21Notification,\n ff31Notification,\n ff41Notification,\n ff02Notification,\n startScan,\n stopScan,\n connectToDevice,\n disconnectDevice,\n requestPermissions,\n getDeviceState,\n isDeviceConnected,\n getConnectedDeviceIds,\n startInfusion,\n stopInfusion,\n setInfusionLevel,\n readCharacteristic,\n writeCharacteristic,\n setUserRole,\n getUserRole,\n };\n\n return <BLEContext.Provider value={value}>{children}</BLEContext.Provider>;\n};\n\n/**\n * Hook to access BLE context\n */\nexport const useBLEContext = (): BLEContextState => {\n const context = useContext(BLEContext);\n if (!context) {\n throw new Error('useBLEContext must be used within a BLEProvider');\n }\n return context;\n};\n"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,aAAa,EAAEC,UAAU,EAAEC,QAAQ,EAAEC,SAAS,QAAQ,OAAO;AAO7E,OAAOC,aAAa,MAAM,2BAA2B;;AAErD;AACA;AACA;;AAqDA,MAAMC,UAAU,gBAAGL,aAAa,CAA8BM,SAAS,CAAC;;AAExE;AACA;AACA;AACA;AACA,OAAO,MAAMC,WAAoD,GAAGA,CAAC;EACnEC;AACF,CAAC,KAAK;EACJ,MAAM,CAACC,gBAAgB,EAAEC,mBAAmB,CAAC,GAAGR,QAAQ,CAAC,KAAK,CAAC;EAC/D,MAAM,CAACS,UAAU,EAAEC,aAAa,CAAC,GAAGV,QAAQ,CAAC,KAAK,CAAC;EACnD,MAAM,CAACW,iBAAiB,EAAEC,oBAAoB,CAAC,GAAGZ,QAAQ,CAAc,EAAE,CAAC;EAC3E,MAAM,CAACa,gBAAgB,EAAEC,mBAAmB,CAAC,GAAGd,QAAQ,CAEtD,IAAIe,GAAG,CAAC,CAAC,CAAC;;EAEZ;EACA,MAAM,CAACC,iBAAiB,EAAEC,oBAAoB,CAAC,GAAGjB,QAAQ,CACxD,IACF,CAAC;;EAED;EACA,MAAM,CAACkB,gBAAgB,EAAEC,mBAAmB,CAAC,GAC3CnB,QAAQ,CAAoC,IAAI,CAAC;EACnD,MAAM,CAACoB,gBAAgB,EAAEC,mBAAmB,CAAC,GAC3CrB,QAAQ,CAAoC,IAAI,CAAC;EACnD,MAAM,CAACsB,gBAAgB,EAAEC,mBAAmB,CAAC,GAC3CvB,QAAQ,CAAoC,IAAI,CAAC;EACnD,MAAM,CAACwB,gBAAgB,EAAEC,mBAAmB,CAAC,GAC3CzB,QAAQ,CAAoC,IAAI,CAAC;EACnD,MAAM,CAAC0B,gBAAgB,EAAEC,mBAAmB,CAAC,GAC3C3B,QAAQ,CAAoC,IAAI,CAAC;;EAEnD;EACA,MAAM,CAAC4B,iBAAiB,EAAEC,oBAAoB,CAAC,GAAG7B,QAAQ,CAAC,KAAK,CAAC;EAEjEC,SAAS,CAAC,MAAM;IACd,MAAM6B,UAAU,GAAG,MAAAA,CAAA,KAAY;MAC7B;MACA,MAAM5B,aAAa,CAAC6B,qBAAqB,CAAC,CAAC;;MAE3C;MACA,MAAMC,QAAQ,CAAC,CAAC;MAChBC,mBAAmB,CAAC,CAAC;IACvB,CAAC;IAEDH,UAAU,CAAC,CAAC;IAEZ,OAAO,MAAM;MACX5B,aAAa,CAACgC,kBAAkB,CAAC,CAAC;IACpC,CAAC;EACH,CAAC,EAAE,EAAE,CAAC;EAEN,MAAMF,QAAQ,GAAG,MAAAA,CAAA,KAAY;IAC3B,IAAI;MACF,MAAMG,kBAAkB,CAAC,CAAC;MAC1B,MAAMC,OAAO,GAAG,MAAMlC,aAAa,CAACmC,kBAAkB,CAAC,CAAC;MACxD7B,mBAAmB,CAAC4B,OAAO,CAAC;IAC9B,CAAC,CAAC,OAAOE,KAAK,EAAE;MACdC,OAAO,CAACD,KAAK,CAAC,sBAAsB,EAAEA,KAAK,CAAC;IAC9C;EACF,CAAC;EAED,MAAMH,kBAAkB,GAAG,MAAAA,CAAA,KAAY;IACrC,IAAI;MACF,MAAMjC,aAAa,CAACiC,kBAAkB,CAAC,CAAC;IAC1C,CAAC,CAAC,OAAOG,KAAK,EAAE;MACdC,OAAO,CAACD,KAAK,CAAC,gCAAgC,EAAEA,KAAK,CAAC;IACxD;EACF,CAAC;EAED,MAAML,mBAAmB,GAAGA,CAAA,KAAM;IAChC;IACA/B,aAAa,CAACsC,EAAE,CAAC,YAAY,EAAE,CAAC;MAAEC;IAAY,CAAC,KAAK;MAClD7B,oBAAoB,CAAE8B,IAAI,IAAK;QAC7B,MAAMC,MAAM,GAAGD,IAAI,CAACE,IAAI,CAAEC,CAAC,IAAKA,CAAC,CAACC,EAAE,KAAKL,MAAM,CAACK,EAAE,CAAC;QACnD,IAAIH,MAAM,EAAE;UACV,OAAOD,IAAI,CAACK,GAAG,CAAEF,CAAC,IAAMA,CAAC,CAACC,EAAE,KAAKL,MAAM,CAACK,EAAE,GAAGL,MAAM,GAAGI,CAAE,CAAC;QAC3D;QACA,OAAO,CAAC,GAAGH,IAAI,EAAED,MAAM,CAAC;MAC1B,CAAC,CAAC;IACJ,CAAC,CAAC;;IAEF;IACAvC,aAAa,CAACsC,EAAE,CAAC,WAAW,EAAE,CAAC;MAAEQ;IAAc,CAAC,KAAK;MACnDlC,mBAAmB,CAAE4B,IAAI,IAAK;QAC5B,MAAMO,MAAM,GAAG,IAAIlC,GAAG,CAAC2B,IAAI,CAAC;QAC5BO,MAAM,CAACC,GAAG,CAACF,QAAQ,EAAE;UACnBA,QAAQ;UACRG,WAAW,EAAE,IAAI;UACjBvB,iBAAiB,EAAE,KAAK;UACxBwB,aAAa,EAAE,IAAI;UACnBC,aAAa,EAAE;YACbC,IAAI,EAAE,IAAI;YACVC,IAAI,EAAE,IAAI;YACVC,IAAI,EAAE,IAAI;YACVC,IAAI,EAAE,IAAI;YACVC,IAAI,EAAE;UACR;QACF,CAAC,CAAC;QACF,OAAOT,MAAM;MACf,CAAC,CAAC;;MAEF;MACAhC,oBAAoB,CAAEyB,IAAI,IAAKA,IAAI,IAAIM,QAAQ,CAAC;MAChDT,OAAO,CAACoB,GAAG,CAAC,qBAAqB,EAAEX,QAAQ,CAAC;IAC9C,CAAC,CAAC;;IAEF;IACA9C,aAAa,CAACsC,EAAE,CAAC,cAAc,EAAE,CAAC;MAAEQ;IAAc,CAAC,KAAK;MACtDlC,mBAAmB,CAAE4B,IAAI,IAAK;QAC5B,MAAMO,MAAM,GAAG,IAAIlC,GAAG,CAAC2B,IAAI,CAAC;QAC5BO,MAAM,CAACW,MAAM,CAACZ,QAAQ,CAAC;QACvB,OAAOC,MAAM;MACf,CAAC,CAAC;;MAEF;MACAhC,oBAAoB,CAAEyB,IAAI,IAAK;QAC7B,IAAIA,IAAI,KAAKM,QAAQ,EAAE;UACrB;UACA,MAAMa,SAAS,GAAGC,KAAK,CAACC,IAAI,CAAClD,gBAAgB,CAACmD,IAAI,CAAC,CAAC,CAAC,CAACC,MAAM,CACzDnB,EAAE,IAAKA,EAAE,KAAKE,QACjB,CAAC;UACD,MAAMkB,UAAU,GAAGL,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI;UACvC;UACA,IAAI,CAACK,UAAU,EAAE;YACfrC,oBAAoB,CAAC,KAAK,CAAC;UAC7B;UACA,OAAOqC,UAAU;QACnB;QACA,OAAOxB,IAAI;MACb,CAAC,CAAC;MAEFH,OAAO,CAACoB,GAAG,CAAC,wBAAwB,EAAEX,QAAQ,CAAC;IACjD,CAAC,CAAC;;IAEF;IACA9C,aAAa,CAACsC,EAAE,CAAC,sBAAsB,EAAE,CAAC;MAAEF;IAAW,CAAC,KAAK;MAC3DC,OAAO,CAACD,KAAK,CAAC,kBAAkB,EAAEA,KAAK,CAAC;MACxC5B,aAAa,CAAC,KAAK,CAAC;IACtB,CAAC,CAAC;;IAEF;IACAR,aAAa,CAACsC,EAAE,CAAC,uBAAuB,EAAE,CAAC;MAAE2B;IAAW,CAAC,KAAK;MAC5D3D,mBAAmB,CAAC2D,KAAK,KAAK,WAAW,CAAC;IAC5C,CAAC,CAAC;;IAEF;IACAjE,aAAa,CAACsC,EAAE,CAAC,uBAAuB,EAAG4B,KAAU,IAAK;MACxD7B,OAAO,CAACoB,GAAG,CAAC,kCAAkC,EAAES,KAAK,CAAC;MACtD,MAAM;QAAEC,kBAAkB;QAAErB;MAAS,CAAC,GAAGoB,KAAK;MAC9C,MAAME,SAAS,GAAGD,kBAAkB,aAAlBA,kBAAkB,uBAAlBA,kBAAkB,CAAEE,WAAW,CAAC,CAAC;;MAEnD;MACAzD,mBAAmB,CAAE4B,IAAI,IAAK;QAC5B,MAAMO,MAAM,GAAG,IAAIlC,GAAG,CAAC2B,IAAI,CAAC;QAC5B,MAAM8B,WAAW,GAAGvB,MAAM,CAACwB,GAAG,CAACzB,QAAQ,CAAC;QACxC,IAAIwB,WAAW,EAAE;UACf,MAAME,YAAY,GAAG;YAAE,GAAGF;UAAY,CAAC;UACvC,IAAIF,SAAS,KAAK,sCAAsC,EAAE;YACxDI,YAAY,CAACrB,aAAa,CAACC,IAAI,GAAGc,KAAK;UACzC,CAAC,MAAM,IAAIE,SAAS,KAAK,sCAAsC,EAAE;YAC/DI,YAAY,CAACrB,aAAa,CAACE,IAAI,GAAGa,KAAK;YACvC7B,OAAO,CAACoB,GAAG,CAAC,4CAA4C,CAAC;UAC3D,CAAC,MAAM,IAAIW,SAAS,KAAK,sCAAsC,EAAE;YAC/DI,YAAY,CAACrB,aAAa,CAACG,IAAI,GAAGY,KAAK;UACzC,CAAC,MAAM,IAAIE,SAAS,KAAK,sCAAsC,EAAE;YAC/DI,YAAY,CAACrB,aAAa,CAACI,IAAI,GAAGW,KAAK;UACzC,CAAC,MAAM,IAAIE,SAAS,KAAK,sCAAsC,EAAE;YAC/DI,YAAY,CAACrB,aAAa,CAACK,IAAI,GAAGU,KAAK;UACzC;UACAnB,MAAM,CAACC,GAAG,CAACF,QAAQ,EAAE0B,YAAY,CAAC;QACpC;QACA,OAAOzB,MAAM;MACf,CAAC,CAAC;;MAEF;MACAhC,oBAAoB,CAAE0D,sBAAsB,IAAK;QAC/CpC,OAAO,CAACoB,GAAG,CACT,0BAA0BX,QAAQ,kBAAkB2B,sBAAsB,EAC5E,CAAC;;QAED;QACA,IAAI3B,QAAQ,KAAK2B,sBAAsB,EAAE;UACvCpC,OAAO,CAACoB,GAAG,CACT,6DACF,CAAC;UAED,IAAIW,SAAS,KAAK,sCAAsC,EAAE;YACxDnD,mBAAmB,CAACiD,KAAK,CAAC;UAC5B,CAAC,MAAM,IAAIE,SAAS,KAAK,sCAAsC,EAAE;YAC/DjD,mBAAmB,CAAC+C,KAAK,CAAC;YAC1B7B,OAAO,CAACoB,GAAG,CAAC,qCAAqC,CAAC;UACpD,CAAC,MAAM,IAAIW,SAAS,KAAK,sCAAsC,EAAE;YAC/D/C,mBAAmB,CAAC6C,KAAK,CAAC;UAC5B,CAAC,MAAM,IAAIE,SAAS,KAAK,sCAAsC,EAAE;YAC/D7C,mBAAmB,CAAC2C,KAAK,CAAC;UAC5B,CAAC,MAAM,IAAIE,SAAS,KAAK,sCAAsC,EAAE;YAC/D3C,mBAAmB,CAACyC,KAAK,CAAC;UAC5B,CAAC,MAAM;YACL7B,OAAO,CAACoB,GAAG,CAAC,8BAA8B,EAAEU,kBAAkB,CAAC;UACjE;QACF,CAAC,MAAM;UACL9B,OAAO,CAACoB,GAAG,CAAC,gDAAgD,CAAC;QAC/D;QAEA,OAAOgB,sBAAsB,CAAC,CAAC;MACjC,CAAC,CAAC;IACJ,CAAC,CAAC;EACJ,CAAC;EAED,MAAMC,SAAS,GAAG,MAAAA,CAAA,KAAY;IAC5BrC,OAAO,CAACoB,GAAG,CAAC,yBAAyB,CAAC;IACtC,IAAI;MACF/C,oBAAoB,CAAC,EAAE,CAAC;MACxBF,aAAa,CAAC,IAAI,CAAC;MACnB,MAAMR,aAAa,CAAC0E,SAAS,CAAC;QAAEC,OAAO,EAAE,KAAK;QAAEC,eAAe,EAAE;MAAM,CAAC,CAAC;IAC3E,CAAC,CAAC,OAAOxC,KAAK,EAAE;MACdC,OAAO,CAACD,KAAK,CAAC,uBAAuB,EAAEA,KAAK,CAAC;MAC7C5B,aAAa,CAAC,KAAK,CAAC;IACtB;EACF,CAAC;EAED,MAAMqE,QAAQ,GAAG,MAAAA,CAAA,KAAY;IAC3B,IAAI;MACF,MAAM7E,aAAa,CAAC6E,QAAQ,CAAC,CAAC;MAC9BrE,aAAa,CAAC,KAAK,CAAC;IACtB,CAAC,CAAC,OAAO4B,KAAK,EAAE;MACdC,OAAO,CAACD,KAAK,CAAC,sBAAsB,EAAEA,KAAK,CAAC;IAC9C;EACF,CAAC;EAED,MAAM0C,eAAe,GAAG,MAAOvC,MAAiB,IAAK;IACnDF,OAAO,CAACoB,GAAG,CAAC,uBAAuB,EAAElB,MAAM,CAAC;IAC5C,IAAI;MACF,MAAMvC,aAAa,CAAC+E,OAAO,CAACxC,MAAM,CAACK,EAAE,CAAC;MACtCP,OAAO,CAACoB,GAAG,CAAC,wBAAwB,CAAC;IACvC,CAAC,CAAC,OAAOrB,KAAK,EAAE;MACdC,OAAO,CAACD,KAAK,CAAC,oBAAoB,EAAEA,KAAK,CAAC;IAC5C;EACF,CAAC;EAED,MAAM4C,gBAAgB,GAAG,MAAOlC,QAAgB,IAAK;IACnD,IAAI;MACF,MAAM9C,aAAa,CAACiF,UAAU,CAACnC,QAAQ,CAAC;MACxC;MACAT,OAAO,CAACoB,GAAG,CAAC,2BAA2B,EAAEX,QAAQ,CAAC;IACpD,CAAC,CAAC,OAAOV,KAAK,EAAE;MACdC,OAAO,CAACD,KAAK,CAAC,uBAAuB,EAAEA,KAAK,CAAC;IAC/C;EACF,CAAC;;EAED;EACA,MAAM8C,cAAc,GAClBpC,QAAgB,IACsB;IACtC,OAAOnC,gBAAgB,CAAC4D,GAAG,CAACzB,QAAQ,CAAC;EACvC,CAAC;EAED,MAAMqC,iBAAiB,GAAIrC,QAAgB,IAAc;IACvD,OAAOnC,gBAAgB,CAACyE,GAAG,CAACtC,QAAQ,CAAC;EACvC,CAAC;EAED,MAAMuC,qBAAqB,GAAGA,CAAA,KAAgB;IAC5C,OAAOzB,KAAK,CAACC,IAAI,CAAClD,gBAAgB,CAACmD,IAAI,CAAC,CAAC,CAAC;EAC5C,CAAC;EAED,MAAMwB,aAAa,GAAG,MAAOxC,QAAgB,IAAK;IAChD,IAAI;MACF,MAAM9C,aAAa,CAACsF,aAAa,CAACxC,QAAQ,CAAC;;MAE3C;MACAlC,mBAAmB,CAAE4B,IAAI,IAAK;QAC5B,MAAMO,MAAM,GAAG,IAAIlC,GAAG,CAAC2B,IAAI,CAAC;QAC5B,MAAM8B,WAAW,GAAGvB,MAAM,CAACwB,GAAG,CAACzB,QAAQ,CAAC;QACxC,IAAIwB,WAAW,EAAE;UACfvB,MAAM,CAACC,GAAG,CAACF,QAAQ,EAAE;YACnB,GAAGwB,WAAW;YACd5C,iBAAiB,EAAE;UACrB,CAAC,CAAC;QACJ;QACA,OAAOqB,MAAM;MACf,CAAC,CAAC;;MAEF;MACA,IAAID,QAAQ,KAAKhC,iBAAiB,EAAE;QAClCa,oBAAoB,CAAC,IAAI,CAAC;MAC5B;MAEAU,OAAO,CAACoB,GAAG,CAAC,6CAA6C,EAAEX,QAAQ,CAAC;IACtE,CAAC,CAAC,OAAOV,KAAK,EAAE;MACdC,OAAO,CAACD,KAAK,CAAC,2BAA2B,EAAEA,KAAK,CAAC;MACjD,MAAMA,KAAK;IACb;EACF,CAAC;EAED,MAAMmD,YAAY,GAAG,MAAOzC,QAAgB,IAAK;IAC/C,IAAI;MACF,MAAM9C,aAAa,CAACuF,YAAY,CAACzC,QAAQ,CAAC;;MAE1C;MACAlC,mBAAmB,CAAE4B,IAAI,IAAK;QAC5B,MAAMO,MAAM,GAAG,IAAIlC,GAAG,CAAC2B,IAAI,CAAC;QAC5B,MAAM8B,WAAW,GAAGvB,MAAM,CAACwB,GAAG,CAACzB,QAAQ,CAAC;QACxC,IAAIwB,WAAW,EAAE;UACfvB,MAAM,CAACC,GAAG,CAACF,QAAQ,EAAE;YACnB,GAAGwB,WAAW;YACd5C,iBAAiB,EAAE;UACrB,CAAC,CAAC;QACJ;QACA,OAAOqB,MAAM;MACf,CAAC,CAAC;;MAEF;MACA,IAAID,QAAQ,KAAKhC,iBAAiB,EAAE;QAClCa,oBAAoB,CAAC,KAAK,CAAC;MAC7B;MAEAU,OAAO,CAACoB,GAAG,CAAC,6CAA6C,EAAEX,QAAQ,CAAC;IACtE,CAAC,CAAC,OAAOV,KAAK,EAAE;MACdC,OAAO,CAACD,KAAK,CAAC,0BAA0B,EAAEA,KAAK,CAAC;MAChD,MAAMA,KAAK;IACb;EACF,CAAC;EAED,MAAMoD,gBAAgB,GAAG,MAAAA,CAAO1C,QAAgB,EAAE2C,KAAa,KAAK;IAClE,IAAI;MACF,MAAMzF,aAAa,CAACwF,gBAAgB,CAAC1C,QAAQ,EAAE2C,KAAK,CAAC;;MAErD;MACA7E,mBAAmB,CAAE4B,IAAI,IAAK;QAC5B,MAAMO,MAAM,GAAG,IAAIlC,GAAG,CAAC2B,IAAI,CAAC;QAC5B,MAAM8B,WAAW,GAAGvB,MAAM,CAACwB,GAAG,CAACzB,QAAQ,CAAC;QACxC,IAAIwB,WAAW,EAAE;UACfvB,MAAM,CAACC,GAAG,CAACF,QAAQ,EAAE;YACnB,GAAGwB,WAAW;YACdpB,aAAa,EAAEuC;UACjB,CAAC,CAAC;QACJ;QACA,OAAO1C,MAAM;MACf,CAAC,CAAC;MAEFV,OAAO,CAACoB,GAAG,CACT,2BAA2BgC,KAAK,2BAA2B,EAC3D3C,QACF,CAAC;IACH,CAAC,CAAC,OAAOV,KAAK,EAAE;MACdC,OAAO,CAACD,KAAK,CAAC,+BAA+B,EAAEA,KAAK,CAAC;MACrD,MAAMA,KAAK;IACb;EACF,CAAC;EAED,MAAMsD,kBAAkB,GAAG,MAAAA,CACzB5C,QAAgB,EAChB6C,WAAmB,EACnBxB,kBAA0B,KACvB;IACH,IAAI;MACF,OAAO,MAAMnE,aAAa,CAAC0F,kBAAkB,CAC3C5C,QAAQ,EACR6C,WAAW,EACXxB,kBACF,CAAC;IACH,CAAC,CAAC,OAAO/B,KAAK,EAAE;MACdC,OAAO,CAACD,KAAK,CAAC,gCAAgC,EAAEA,KAAK,CAAC;MACtD,MAAMA,KAAK;IACb;EACF,CAAC;EAED,MAAMwD,mBAAmB,GAAG,MAAAA,CAC1B9C,QAAgB,EAChB6C,WAAmB,EACnBxB,kBAA0B,EAC1B0B,IAAY,EACZC,OAAoC,KACjC;IACH,IAAI;MACF,MAAM9F,aAAa,CAAC4F,mBAAmB,CACrC9C,QAAQ,EACR6C,WAAW,EACXxB,kBAAkB,EAClB0B,IAAI,EACJC,OACF,CAAC;IACH,CAAC,CAAC,OAAO1D,KAAK,EAAE;MACdC,OAAO,CAACD,KAAK,CAAC,iCAAiC,EAAEA,KAAK,CAAC;MACvD,MAAMA,KAAK;IACb;EACF,CAAC;EAED,MAAM2D,WAAW,GAAIC,IAAc,IAAK;IACtChG,aAAa,CAAC+F,WAAW,CAACC,IAAI,CAAC;EACjC,CAAC;EAED,MAAMC,WAAW,GAAGA,CAAA,KAAgB;IAClC,OAAOjG,aAAa,CAACiG,WAAW,CAAC,CAAC;EACpC,CAAC;EAED,MAAMC,KAAsB,GAAG;IAC7B7F,gBAAgB;IAChBE,UAAU;IACVE,iBAAiB;IACjBE,gBAAgB;IAChBG,iBAAiB;IACjBY,iBAAiB;IACjBV,gBAAgB;IAChBE,gBAAgB;IAChBE,gBAAgB;IAChBE,gBAAgB;IAChBE,gBAAgB;IAChBkD,SAAS;IACTG,QAAQ;IACRC,eAAe;IACfE,gBAAgB;IAChB/C,kBAAkB;IAClBiD,cAAc;IACdC,iBAAiB;IACjBE,qBAAqB;IACrBC,aAAa;IACbC,YAAY;IACZC,gBAAgB;IAChBE,kBAAkB;IAClBE,mBAAmB;IACnBG,WAAW;IACXE;EACF,CAAC;EAED,oBAAOtG,KAAA,CAAAwG,aAAA,CAAClG,UAAU,CAACmG,QAAQ;IAACF,KAAK,EAAEA;EAAM,GAAE9F,QAA8B,CAAC;AAC5E,CAAC;;AAED;AACA;AACA;AACA,OAAO,MAAMiG,aAAa,GAAGA,CAAA,KAAuB;EAClD,MAAMC,OAAO,GAAGzG,UAAU,CAACI,UAAU,CAAC;EACtC,IAAI,CAACqG,OAAO,EAAE;IACZ,MAAM,IAAIC,KAAK,CAAC,iDAAiD,CAAC;EACpE;EACA,OAAOD,OAAO;AAChB,CAAC","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-sdk-ble-middleware-v2",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "A React Native middleware library for simplified BLE (Bluetooth Low Energy) operations with context-based API",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./src/index.tsx",
@@ -211,7 +211,7 @@ export const BLEProvider: React.FC<{ children: React.ReactNode }> = ({
211
211
 
212
212
  // Characteristic changed event
213
213
  bleMiddleware.on('characteristicChanged', (event: any) => {
214
- console.log('Characteristic Changed Event:', event);
214
+ console.log('📡 Characteristic Changed Event:', event);
215
215
  const { characteristicUuid, deviceId } = event;
216
216
  const uuidUpper = characteristicUuid?.toUpperCase();
217
217
 
@@ -225,6 +225,7 @@ export const BLEProvider: React.FC<{ children: React.ReactNode }> = ({
225
225
  updatedState.notifications.ff01 = event;
226
226
  } else if (uuidUpper === '0000FF21-0000-1000-8000-00805F9B34FB') {
227
227
  updatedState.notifications.ff21 = event;
228
+ console.log('✅ FF21 notification stored in device state');
228
229
  } else if (uuidUpper === '0000FF31-0000-1000-8000-00805F9B34FB') {
229
230
  updatedState.notifications.ff31 = event;
230
231
  } else if (uuidUpper === '0000FF41-0000-1000-8000-00805F9B34FB') {
@@ -237,22 +238,38 @@ export const BLEProvider: React.FC<{ children: React.ReactNode }> = ({
237
238
  return newMap;
238
239
  });
239
240
 
240
- // Legacy: Update global notifications for primary device
241
- if (deviceId === connectedDeviceId) {
242
- if (uuidUpper === '0000FF01-0000-1000-8000-00805F9B34FB') {
243
- setFF01Notification(event);
244
- } else if (uuidUpper === '0000FF21-0000-1000-8000-00805F9B34FB') {
245
- setFF21Notification(event);
246
- } else if (uuidUpper === '0000FF31-0000-1000-8000-00805F9B34FB') {
247
- setFF31Notification(event);
248
- } else if (uuidUpper === '0000FF41-0000-1000-8000-00805F9B34FB') {
249
- setFF41Notification(event);
250
- } else if (uuidUpper === '0000FF02-0000-1000-8000-00805F9B34FB') {
251
- setFF02Notification(event);
241
+ // Legacy: Update global notifications using functional update to avoid stale closure
242
+ setConnectedDeviceId((currentPrimaryDeviceId) => {
243
+ console.log(
244
+ `🔍 Comparing deviceId: ${deviceId} with primary: ${currentPrimaryDeviceId}`
245
+ );
246
+
247
+ // Check if this event is for the primary device
248
+ if (deviceId === currentPrimaryDeviceId) {
249
+ console.log(
250
+ '✅ This is the primary device, updating global notifications'
251
+ );
252
+
253
+ if (uuidUpper === '0000FF01-0000-1000-8000-00805F9B34FB') {
254
+ setFF01Notification(event);
255
+ } else if (uuidUpper === '0000FF21-0000-1000-8000-00805F9B34FB') {
256
+ setFF21Notification(event);
257
+ console.log('✅ FF21 global notification updated!');
258
+ } else if (uuidUpper === '0000FF31-0000-1000-8000-00805F9B34FB') {
259
+ setFF31Notification(event);
260
+ } else if (uuidUpper === '0000FF41-0000-1000-8000-00805F9B34FB') {
261
+ setFF41Notification(event);
262
+ } else if (uuidUpper === '0000FF02-0000-1000-8000-00805F9B34FB') {
263
+ setFF02Notification(event);
264
+ } else {
265
+ console.log('⚠️ Unhandled characteristic:', characteristicUuid);
266
+ }
252
267
  } else {
253
- console.log('⚠️ Unhandled characteristic:', characteristicUuid);
268
+ console.log(`⚠️ Not primary device - skipping global update`);
254
269
  }
255
- }
270
+
271
+ return currentPrimaryDeviceId; // Return unchanged
272
+ });
256
273
  });
257
274
  };
258
275