UNPKG

react-native-ble-nitro

Version:

High-performance React Native BLE library built on Nitro Modules - drop-in replacement for react-native-ble-plx

373 lines (337 loc) 12.1 kB
/** * BleManager Compatibility Factory * * Creates BleManager instances with full react-native-ble-plx compatibility * by wrapping the Nitro implementation with compatibility shims */ import { createBleManager } from './BleManagerFactory'; import type { BleManager as BleManagerInterface } from './specs/BleManager.nitro'; import type { BleManagerOptions, UUID, DeviceId, TransactionId, ConnectionPriority, ConnectionOptions, ScanOptions, NativeDevice, NativeService, NativeCharacteristic, NativeDescriptor, LogLevel, State, Subscription } from './specs/types'; import { DeviceWrapper } from './compatibility/deviceWrapper'; import { stateToString, stringToState, logLevelToString, stringToLogLevel, normalizeLogLevel, normalizeCharacteristicSubscriptionType, characteristicSubscriptionTypeToString } from './compatibility/enums'; import { serviceDataMapToArray } from './compatibility/serviceData'; /** * BleManager wrapper that provides react-native-ble-plx compatibility */ export class BleManagerCompat { private bleManager: BleManagerInterface; constructor(options?: BleManagerOptions) { this.bleManager = createBleManager(options); } // Lifecycle async destroy(): Promise<void> { return await this.bleManager.destroy(); } // Common operations with compatibility async setLogLevel(logLevel: LogLevel | string): Promise<string> { const normalizedLogLevel = normalizeLogLevel(logLevel); const result = await this.bleManager.setLogLevel(normalizedLogLevel); return logLevelToString(result); } async logLevel(): Promise<string> { const result = await this.bleManager.logLevel(); return logLevelToString(result); } async cancelTransaction(transactionId: TransactionId): Promise<void> { return await this.bleManager.cancelTransaction(transactionId); } // State management with string conversion async enable(transactionId?: TransactionId): Promise<BleManagerCompat> { await this.bleManager.enable(transactionId); return this; } async disable(transactionId?: TransactionId): Promise<BleManagerCompat> { await this.bleManager.disable(transactionId); return this; } async state(): Promise<string> { const result = await this.bleManager.state(); return stateToString(result); } onStateChange( listener: (newState: string) => void, emitCurrentState?: boolean ): Subscription { return this.bleManager.onStateChange((state) => { listener(stateToString(state)); }, emitCurrentState); } // Device scanning with compatibility wrappers async startDeviceScan( uuids: UUID[] | null, options: ScanOptions | null, listener: (error: any | null, scannedDevice: DeviceWrapper | null) => void ): Promise<void> { return await this.bleManager.startDeviceScan(uuids, options, (error, device) => { listener(error, device ? new DeviceWrapper(this.createDeviceFromNative(device)) : null); }); } async stopDeviceScan(): Promise<void> { return await this.bleManager.stopDeviceScan(); } // Connection management async connectToDevice( deviceIdentifier: DeviceId, options?: Partial<ConnectionOptions> ): Promise<DeviceWrapper> { // Provide defaults for Nitro's required fields const connectionOptions: ConnectionOptions = { autoConnect: options?.autoConnect ?? false, requestMTU: options?.requestMTU ?? 23, timeout: options?.timeout ?? 0, }; const result = await this.bleManager.connectToDevice(deviceIdentifier, connectionOptions); return new DeviceWrapper(this.createDeviceFromNative(result)); } async cancelDeviceConnection(deviceIdentifier: DeviceId): Promise<DeviceWrapper> { const result = await this.bleManager.cancelDeviceConnection(deviceIdentifier); return new DeviceWrapper(this.createDeviceFromNative(result)); } async isDeviceConnected(deviceIdentifier: DeviceId): Promise<boolean> { return await this.bleManager.isDeviceConnected(deviceIdentifier); } onDeviceDisconnected( deviceIdentifier: DeviceId, listener: (error: any | null, device: DeviceWrapper | null) => void ): Subscription { return this.bleManager.onDeviceDisconnected(deviceIdentifier, (error, device) => { listener(error, device ? new DeviceWrapper(this.createDeviceFromNative(device)) : null); }); } // Device discovery async devices(deviceIdentifiers: DeviceId[]): Promise<DeviceWrapper[]> { const result = await this.bleManager.devices(deviceIdentifiers); return result.map(device => new DeviceWrapper(this.createDeviceFromNative(device))); } async connectedDevices(serviceUUIDs: UUID[]): Promise<DeviceWrapper[]> { const result = await this.bleManager.connectedDevices(serviceUUIDs); return result.map(device => new DeviceWrapper(this.createDeviceFromNative(device))); } // RSSI and MTU operations async readRSSIForDevice( deviceIdentifier: DeviceId, transactionId?: TransactionId ): Promise<DeviceWrapper> { const result = await this.bleManager.readRSSIForDevice(deviceIdentifier, transactionId); return new DeviceWrapper(this.createDeviceFromNative(result)); } async requestMTUForDevice( deviceIdentifier: DeviceId, mtu: number, transactionId?: TransactionId ): Promise<DeviceWrapper> { const result = await this.bleManager.requestMTUForDevice(deviceIdentifier, mtu, transactionId); return new DeviceWrapper(this.createDeviceFromNative(result)); } async requestConnectionPriorityForDevice( deviceIdentifier: DeviceId, connectionPriority: ConnectionPriority, transactionId?: TransactionId ): Promise<DeviceWrapper> { const result = await this.bleManager.requestConnectionPriorityForDevice( deviceIdentifier, connectionPriority, transactionId ); return new DeviceWrapper(this.createDeviceFromNative(result)); } // Service discovery async discoverAllServicesAndCharacteristicsForDevice( deviceIdentifier: DeviceId, transactionId?: TransactionId ): Promise<DeviceWrapper> { const result = await this.bleManager.discoverAllServicesAndCharacteristicsForDevice( deviceIdentifier, transactionId ); return new DeviceWrapper(this.createDeviceFromNative(result)); } // Service operations async servicesForDevice(deviceIdentifier: DeviceId): Promise<NativeService[]> { return await this.bleManager.servicesForDevice(deviceIdentifier); } // Characteristic operations async characteristicsForDevice( deviceIdentifier: DeviceId, serviceUUID: UUID ): Promise<NativeCharacteristic[]> { return await this.bleManager.characteristicsForDevice(deviceIdentifier, serviceUUID); } async readCharacteristicForDevice( deviceIdentifier: DeviceId, serviceUUID: UUID, characteristicUUID: UUID, transactionId?: TransactionId ): Promise<NativeCharacteristic> { return await this.bleManager.readCharacteristicForDevice( deviceIdentifier, serviceUUID, characteristicUUID, transactionId ); } async writeCharacteristicWithResponseForDevice( deviceIdentifier: DeviceId, serviceUUID: UUID, characteristicUUID: UUID, base64Value: string, transactionId?: TransactionId ): Promise<NativeCharacteristic> { return await this.bleManager.writeCharacteristicWithResponseForDevice( deviceIdentifier, serviceUUID, characteristicUUID, base64Value, transactionId ); } async writeCharacteristicWithoutResponseForDevice( deviceIdentifier: DeviceId, serviceUUID: UUID, characteristicUUID: UUID, base64Value: string, transactionId?: TransactionId ): Promise<NativeCharacteristic> { return await this.bleManager.writeCharacteristicWithoutResponseForDevice( deviceIdentifier, serviceUUID, characteristicUUID, base64Value, transactionId ); } monitorCharacteristicForDevice( deviceIdentifier: DeviceId, serviceUUID: UUID, characteristicUUID: UUID, listener: (error: any | null, characteristic: NativeCharacteristic | null) => void, transactionId?: TransactionId, subscriptionType?: 'notification' | 'indication' ): Subscription { const nitroSubscriptionType = subscriptionType ? normalizeCharacteristicSubscriptionType(subscriptionType) : undefined; return this.bleManager.monitorCharacteristicForDevice( deviceIdentifier, serviceUUID, characteristicUUID, listener, transactionId, nitroSubscriptionType ); } // Descriptor operations async descriptorsForDevice( deviceIdentifier: DeviceId, serviceUUID: UUID, characteristicUUID: UUID ): Promise<NativeDescriptor[]> { return await this.bleManager.descriptorsForDevice( deviceIdentifier, serviceUUID, characteristicUUID ); } async readDescriptorForDevice( deviceIdentifier: DeviceId, serviceUUID: UUID, characteristicUUID: UUID, descriptorUUID: UUID, transactionId?: TransactionId ): Promise<NativeDescriptor> { return await this.bleManager.readDescriptorForDevice( deviceIdentifier, serviceUUID, characteristicUUID, descriptorUUID, transactionId ); } async writeDescriptorForDevice( deviceIdentifier: DeviceId, serviceUUID: UUID, characteristicUUID: UUID, descriptorUUID: UUID, valueBase64: string, transactionId?: TransactionId ): Promise<NativeDescriptor> { return await this.bleManager.writeDescriptorForDevice( deviceIdentifier, serviceUUID, characteristicUUID, descriptorUUID, valueBase64, transactionId ); } /** * Helper method to create a Device wrapper from NativeDevice data * This is a temporary method until we have proper Device Nitro objects */ private createDeviceFromNative(nativeDevice: NativeDevice): any { // This is a placeholder - in the actual implementation, we'd need to create // proper Nitro Device objects, but for now we'll work with the native data return { id: nativeDevice.id, deviceName: nativeDevice.name, rssi: nativeDevice.rssi, mtu: nativeDevice.mtu, manufacturerData: nativeDevice.manufacturerData, rawScanRecord: nativeDevice.rawScanRecord, serviceData: nativeDevice.serviceData, serviceUUIDs: nativeDevice.serviceUUIDs, localName: nativeDevice.localName, txPowerLevel: nativeDevice.txPowerLevel, solicitedServiceUUIDs: nativeDevice.solicitedServiceUUIDs, isConnectable: nativeDevice.isConnectable, overflowServiceUUIDs: nativeDevice.overflowServiceUUIDs, // Add placeholder methods - these would be implemented in the actual Device class requestConnectionPriority: async () => this.createDeviceFromNative(nativeDevice), readRSSI: async () => this.createDeviceFromNative(nativeDevice), requestMTU: async () => this.createDeviceFromNative(nativeDevice), connect: async () => this.createDeviceFromNative(nativeDevice), cancelConnection: async () => this.createDeviceFromNative(nativeDevice), isConnected: async () => false, onDisconnected: () => ({ remove: () => {} }), discoverAllServicesAndCharacteristics: async () => this.createDeviceFromNative(nativeDevice), services: async () => [], characteristicsForService: async () => [], readCharacteristicForService: async () => ({}), writeCharacteristicWithResponseForService: async () => ({}), writeCharacteristicWithoutResponseForService: async () => ({}), monitorCharacteristicForService: () => ({ remove: () => {} }), descriptorsForService: async () => [], readDescriptorForService: async () => ({}), writeDescriptorForService: async () => ({}), }; } } /** * Factory function to create a compatibility BleManager */ export function createBleManagerCompat(options?: BleManagerOptions): BleManagerCompat { return new BleManagerCompat(options); }