import { NativeEventEmitter, NativeModules } from 'react-native'; import SdkBle, { type BleDevice, type BleService, type BleCharacteristic, type BleScanOptions, type BleWriteOptions, type BleConnectionState, } from './NativeSdkBle'; // Event types export type BleEvent = | 'scanResult' | 'connected' | 'disconnected' | 'servicesDiscovered' | 'characteristicChanged' | 'error' | 'bluetoothStateChanged'; export interface BleScanResult { device: BleDevice; } export interface BleConnectedEvent { deviceId: string; } export interface BleDisconnectedEvent { deviceId: string; reason?: string; } export interface BleServicesDiscoveredEvent { deviceId: string; services: BleService[]; } export interface BleCharacteristicChangedEvent { deviceId: string; serviceUuid: string; characteristicUuid: string; value: string; } export interface BleErrorEvent { code: string; message: string; deviceId?: string; } export interface BleBluetoothStateChangedEvent { state: | 'unknown' | 'resetting' | 'unsupported' | 'unauthorized' | 'poweredOff' | 'poweredOn'; } export type BleEventData = { scanResult: BleScanResult; connected: BleConnectedEvent; disconnected: BleDisconnectedEvent; servicesDiscovered: BleServicesDiscoveredEvent; characteristicChanged: BleCharacteristicChangedEvent; error: BleErrorEvent; bluetoothStateChanged: BleBluetoothStateChangedEvent; }; class BleManager { private eventEmitter: NativeEventEmitter; private listeners: Map> = new Map(); constructor() { this.eventEmitter = new NativeEventEmitter(NativeModules.SdkBle); } // Event handling on( event: T, listener: (data: BleEventData[T]) => void ): void { if (!this.listeners.has(event)) { this.listeners.set(event, new Set()); } const listeners = this.listeners.get(event)!; listeners.add(listener); // Create a wrapper function to handle the native event data const wrappedListener = (data: any) => { listener(data as BleEventData[T]); }; this.eventEmitter.addListener(event, wrappedListener); } off( event: T, listener?: (data: BleEventData[T]) => void ): void { const listeners = this.listeners.get(event); if (!listeners) return; if (listener) { listeners.delete(listener); // For simplicity, remove all listeners and re-add the remaining ones this.eventEmitter.removeAllListeners(event); // Re-add remaining listeners for (const remainingListener of listeners) { const wrappedListener = (data: any) => { (remainingListener as any)(data); }; this.eventEmitter.addListener(event, wrappedListener); } } else { // Remove all listeners for this event listeners.clear(); this.eventEmitter.removeAllListeners(event); } // Clean up empty sets if (listeners.size === 0) { this.listeners.delete(event); } } // Scanning methods async startScan(options?: BleScanOptions): Promise { return SdkBle.startScan(options); } async stopScan(): Promise { return SdkBle.stopScan(); } // Connection methods async connect(deviceId: string): Promise { return SdkBle.connect(deviceId); } async disconnect(deviceId: string): Promise { return SdkBle.disconnect(deviceId); } async isConnected(deviceId: string): Promise { return SdkBle.isConnected(deviceId); } async getConnectedDevices(): Promise { return SdkBle.getConnectedDevices(); } // Service discovery async discoverServices(deviceId: string): Promise { return SdkBle.discoverServices(deviceId); } // Characteristic operations async readCharacteristic( deviceId: string, serviceUuid: string, characteristicUuid: string ): Promise { return SdkBle.readCharacteristic(deviceId, serviceUuid, characteristicUuid); } async writeCharacteristic( deviceId: string, serviceUuid: string, characteristicUuid: string, data: string, options?: BleWriteOptions ): Promise { return SdkBle.writeCharacteristic( deviceId, serviceUuid, characteristicUuid, data, options ); } async setNotify( deviceId: string, serviceUuid: string, characteristicUuid: string, enable: boolean ): Promise { return SdkBle.setNotify(deviceId, serviceUuid, characteristicUuid, enable); } // Permissions and Bluetooth state async requestPermissions(): Promise { return SdkBle.requestPermissions(); } async isBluetoothEnabled(): Promise { return SdkBle.isBluetoothEnabled(); } async enableBluetooth(): Promise { return SdkBle.enableBluetooth(); } // Utility methods removeAllListeners(): void { for (const event of this.listeners.keys()) { this.eventEmitter.removeAllListeners(event); } this.listeners.clear(); } // Infusion control methods async startInfusion(deviceId: string): Promise { return SdkBle.startInfusion(deviceId); } async stopInfusion(deviceId: string): Promise { return SdkBle.stopInfusion(deviceId); } async setInfusionLevel(deviceId: string, level: number): Promise { return SdkBle.setInfusionLevel(deviceId, level); } // User role method async setUserRole(role: 'patient' | 'nurse' | 'engineer'): Promise { return SdkBle.setUserRole(role); } } // Create singleton instance const bleManager = new BleManager(); export default bleManager; // Export types for external use export type { BleDevice, BleService, BleCharacteristic, BleScanOptions, BleWriteOptions, BleConnectionState, };