WellNuo/services/ble/index.ts
Sergei b5ab28aa3e Add bulk sensor operations API
Implemented comprehensive bulk operations for BLE sensor management to improve
efficiency when working with multiple sensors simultaneously.

Features Added:
- bulkDisconnect: Disconnect multiple sensors at once
- bulkReboot: Reboot multiple sensors sequentially
- bulkSetWiFi: Configure WiFi for multiple sensors with progress tracking

Implementation Details:
- Added BulkOperationResult and BulkWiFiResult types to track operation outcomes
- Implemented bulk operations in both RealBLEManager and MockBLEManager
- Exposed bulk operations through BLEContext for easy UI integration
- Sequential processing ensures reliable operation completion
- Progress callbacks for real-time UI updates during bulk operations

Testing:
- Added comprehensive test suite with 14 test cases
- Tests cover success scenarios, error handling, and edge cases
- All tests passing with appropriate timeout configurations
- Verified both individual and sequential bulk operations

Technical Notes:
- Bulk operations maintain device connection state consistency
- Error handling allows graceful continuation despite individual failures
- MockBLEManager includes realistic delays for testing
- Integration with existing BLE service architecture preserved

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-31 16:40:36 -08:00

57 lines
2.7 KiB
TypeScript

// BLE Service entry point
import * as Device from 'expo-device';
import { IBLEManager } from './types';
// Determine if BLE is available (real device vs simulator)
export const isBLEAvailable = Device.isDevice;
// Lazy singleton - only create BLEManager when first accessed
let _bleManager: IBLEManager | null = null;
function getBLEManager(): IBLEManager {
if (!_bleManager) {
// Dynamic import to prevent crash on Android startup
if (isBLEAvailable) {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { RealBLEManager } = require('./BLEManager');
_bleManager = new RealBLEManager();
} else {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { MockBLEManager } = require('./MockBLEManager');
_bleManager = new MockBLEManager();
}
}
return _bleManager!; // Non-null assertion - we just assigned it above
}
// Proxy object that lazily initializes the real manager
export const bleManager: IBLEManager = {
scanDevices: () => getBLEManager().scanDevices(),
stopScan: () => getBLEManager().stopScan(),
connectDevice: (deviceId: string) => getBLEManager().connectDevice(deviceId),
disconnectDevice: (deviceId: string) => getBLEManager().disconnectDevice(deviceId),
isDeviceConnected: (deviceId: string) => getBLEManager().isDeviceConnected(deviceId),
getConnectionState: (deviceId: string) => getBLEManager().getConnectionState(deviceId),
getAllConnections: () => getBLEManager().getAllConnections(),
addEventListener: (listener) => getBLEManager().addEventListener(listener),
removeEventListener: (listener) => getBLEManager().removeEventListener(listener),
sendCommand: (deviceId: string, command: string) => getBLEManager().sendCommand(deviceId, command),
getWiFiList: (deviceId: string) => getBLEManager().getWiFiList(deviceId),
setWiFi: (deviceId: string, ssid: string, password: string) => getBLEManager().setWiFi(deviceId, ssid, password),
getCurrentWiFi: (deviceId: string) => getBLEManager().getCurrentWiFi(deviceId),
rebootDevice: (deviceId: string) => getBLEManager().rebootDevice(deviceId),
cleanup: () => getBLEManager().cleanup(),
getSensorHealth: (wellId: number, mac: string) => getBLEManager().getSensorHealth(wellId, mac),
getAllSensorHealth: () => getBLEManager().getAllSensorHealth(),
bulkDisconnect: (deviceIds: string[]) => getBLEManager().bulkDisconnect(deviceIds),
bulkReboot: (deviceIds: string[]) => getBLEManager().bulkReboot(deviceIds),
bulkSetWiFi: (devices, ssid, password, onProgress) => getBLEManager().bulkSetWiFi(devices, ssid, password, onProgress),
};
// Re-export types
export * from './types';
// Re-export permission utilities
export * from './permissions';