import type { BleDevice, BleOptions, BleConnectionState, BleConnectionStateChangeCallback } from '../interface.uts' import type { BleConnectOptionsExt } from '../interface.uts' import type { ScanDevicesOptions } from '../interface.uts'; import Context from "android.content.Context"; import BluetoothAdapter from "android.bluetooth.BluetoothAdapter"; import BluetoothManager from "android.bluetooth.BluetoothManager"; import BluetoothDevice from "android.bluetooth.BluetoothDevice"; import BluetoothGatt from "android.bluetooth.BluetoothGatt"; import BluetoothGattCallback from "android.bluetooth.BluetoothGattCallback"; import ScanCallback from "android.bluetooth.le.ScanCallback"; import ScanResult from "android.bluetooth.le.ScanResult"; import ScanSettings from "android.bluetooth.le.ScanSettings"; import Handler from "android.os.Handler"; import Looper from "android.os.Looper"; import ContextCompat from "androidx.core.content.ContextCompat"; import PackageManager from "android.content.pm.PackageManager"; // 定义 PendingConnect 类型和实现类 interface PendingConnect { resolve: () => void; reject: (err?: any) => void; // Changed to make err optional timer?: number; } class PendingConnectImpl implements PendingConnect { resolve: () => void; reject: (err?: any) => void; // Changed to make err optional timer?: number; constructor(resolve: () => void, reject: (err?: any) => void, timer?: number) { this.resolve = resolve; this.reject = reject; this.timer = timer; } } // 引入全局回调管理 import { gattCallback } from './service_manager.uts' const pendingConnects = new Map(); const STATE_DISCONNECTED = 0; const STATE_CONNECTING = 1; const STATE_CONNECTED = 2; const STATE_DISCONNECTING = 3; export class DeviceManager { private static instance: DeviceManager | null = null; private devices = new Map(); private connectionStates = new Map(); private connectionStateChangeListeners: BleConnectionStateChangeCallback[] = [] private gattMap = new Map(); private scanCallback: ScanCallback | null = null private isScanning: boolean = false private constructor() {} static getInstance(): DeviceManager { if (DeviceManager.instance == null) { DeviceManager.instance = new DeviceManager(); } return DeviceManager.instance!; } startScan(options: ScanDevicesOptions): void { console.log('ak startscan now') const adapter = this.getBluetoothAdapter(); if (adapter == null) { throw new Error('未找到蓝牙适配器'); } if (!adapter.isEnabled) { // 尝试请求用户开启蓝牙 try { adapter.enable(); // 直接调用,无需可选链和括号 } catch (e) { // 某些设备可能不支持 enable } setTimeout(() => { if (!adapter.isEnabled) { throw new Error('蓝牙未开启'); } }, 1500); throw new Error('正在开启蓝牙,请重试'); } const foundDevices = this.devices; // 直接用全局 devices class MyScanCallback extends ScanCallback { private foundDevices: Map; private onDeviceFound: (device: BleDevice) => void; constructor(foundDevices: Map, onDeviceFound: (device: BleDevice) => void) { super(); this.foundDevices = foundDevices; this.onDeviceFound = onDeviceFound; } override onScanResult(callbackType: Int, result: ScanResult): void { const device = result.getDevice(); if (device != null) { const deviceId = device.getAddress(); let bleDevice = foundDevices.get(deviceId); if (bleDevice == null) { bleDevice = { deviceId, name: device.getName() ?? 'Unknown', rssi: result.getRssi(), lastSeen: Date.now() }; foundDevices.set(deviceId, bleDevice); this.onDeviceFound(bleDevice); } else { // 更新属性(已确保 bleDevice 非空) bleDevice.rssi = result.getRssi(); bleDevice.name = device.getName() ?? bleDevice.name; bleDevice.lastSeen = Date.now(); } } } override onScanFailed(errorCode: Int): void { console.log('ak scan fail') } } this.scanCallback = new MyScanCallback(foundDevices, options.onDeviceFound ?? (() => {})); const scanner = adapter.getBluetoothLeScanner(); if (scanner == null) { throw new Error('无法获取扫描器'); } const scanSettings = new ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) .build(); scanner.startScan(null, scanSettings, this.scanCallback); this.isScanning = true; // 默认10秒后停止扫描 new Handler(Looper.getMainLooper()).postDelayed(() => { if (this.isScanning && this.scanCallback != null) { scanner.stopScan(this.scanCallback); this.isScanning = false; // this.devices = foundDevices; if (options.onScanFinished != null) options.onScanFinished?.invoke(); } }, 40000); } async connectDevice(deviceId: string, options?: BleConnectOptionsExt): Promise { console.log('[AKBLE] connectDevice called, deviceId:', deviceId, 'options:', options, 'connectionStates:') const adapter = this.getBluetoothAdapter(); if (adapter == null) { console.error('[AKBLE] connectDevice failed: 蓝牙适配器不可用') throw new Error('蓝牙适配器不可用'); } const device = adapter.getRemoteDevice(deviceId); if (device == null) { console.error('[AKBLE] connectDevice failed: 未找到设备', deviceId) throw new Error('未找到设备'); } this.connectionStates.set(deviceId, STATE_CONNECTING); console.log('[AKBLE] connectDevice set STATE_CONNECTING, deviceId:', deviceId, 'connectionStates:') this.emitConnectionStateChange(deviceId, STATE_CONNECTING); const activity = UTSAndroid.getUniActivity(); const timeout = options?.timeout ?? 15000; const key = `${deviceId}|connect`; return new Promise((resolve, reject) => { const timer = setTimeout(() => { console.error('[AKBLE] connectDevice 超时:', deviceId) pendingConnects.delete(key); this.connectionStates.set(deviceId, STATE_DISCONNECTED); this.gattMap.set(deviceId, null); this.emitConnectionStateChange(deviceId, STATE_DISCONNECTED); reject(new Error('连接超时')); }, timeout); // 创建一个适配器函数来匹配类型签名 const resolveAdapter = () => { console.log('[AKBLE] connectDevice resolveAdapter:', deviceId) resolve(); }; const rejectAdapter = (err?: any) => { console.error('[AKBLE] connectDevice rejectAdapter:', deviceId, err) reject(err); }; pendingConnects.set(key, new PendingConnectImpl(resolveAdapter, rejectAdapter, timer)); try { console.log('[AKBLE] connectGatt 调用前:', deviceId) const gatt = device.connectGatt(activity, false, gattCallback); this.gattMap.set(deviceId, gatt); console.log('[AKBLE] connectGatt 调用后:', deviceId, gatt) } catch (e) { console.error('[AKBLE] connectGatt 异常:', deviceId, e) clearTimeout(timer); pendingConnects.delete(key); this.connectionStates.set(deviceId, STATE_DISCONNECTED); this.gattMap.set(deviceId, null); this.emitConnectionStateChange(deviceId, STATE_DISCONNECTED); reject(e); } }); } // 统一分发连接回调(应在 gattCallback.onConnectionStateChange 内调用) static handleConnectionStateChange(deviceId: string, newState: number, error?: any) { console.log('[AKBLE] handleConnectionStateChange:', deviceId, 'newState:', newState, 'error:', error, 'pendingConnects:') const key = `${deviceId}|connect`; const cb = pendingConnects.get(key); if (cb != null) { // 修复 timer 的空安全问题,使用临时变量 const timerValue = cb.timer; if (timerValue != null) { clearTimeout(timerValue); } // 修复 error 处理 if (newState === STATE_CONNECTED) { console.log('[AKBLE] handleConnectionStateChange: 连接成功', deviceId) cb.resolve(); } else { // 正确处理可空值 const errorToUse = error != null ? error : new Error('连接断开'); console.error('[AKBLE] handleConnectionStateChange: 连接失败', deviceId, errorToUse) cb.reject(errorToUse); } pendingConnects.delete(key); } else { console.warn('[AKBLE] handleConnectionStateChange: 未找到 pendingConnects', deviceId, newState) } } async disconnectDevice(deviceId: string, isActive: boolean = true): Promise { console.log('[AKBLE] disconnectDevice called, deviceId:', deviceId, 'isActive:', isActive) let gatt = this.gattMap.get(deviceId); if (gatt != null) { gatt.disconnect(); gatt.close(); // gatt=null; this.gattMap.set(deviceId, null); this.connectionStates.set(deviceId, STATE_DISCONNECTED); console.log('[AKBLE] disconnectDevice set STATE_DISCONNECTED, deviceId:', deviceId, 'connectionStates:') this.emitConnectionStateChange(deviceId, STATE_DISCONNECTED); return; } else { console.log('[AKBLE] disconnectDevice: gatt is null, deviceId:', deviceId) return; } } async reconnectDevice(deviceId: string, options?: BleConnectOptionsExt): Promise { let attempts = 0; const maxAttempts = options?.maxAttempts ?? 3; const interval = options?.interval ?? 3000; while (attempts < maxAttempts) { try { await this.disconnectDevice(deviceId, false); await this.connectDevice(deviceId, options); return; } catch (e) { attempts++; if (attempts >= maxAttempts) throw new Error('重连失败'); // 修复 setTimeout 问题,使用旧式 Promise + setTimeout 解决 await new Promise((resolve) => { setTimeout(() => { resolve(); }, interval); }); } } } getConnectedDevices(): BleDevice[] { // 创建一个空数组来存储结果 const result: BleDevice[] = []; // 遍历 devices Map 并检查连接状态 this.devices.forEach((device, deviceId) => { if (this.connectionStates.get(deviceId) === STATE_CONNECTED) { result.push(device); } }); return result; } onConnectionStateChange(listener: BleConnectionStateChangeCallback) { console.log('[AKBLE][LOG] onConnectionStateChange 注册, 当前监听数:', this.connectionStateChangeListeners.length + 1, listener) this.connectionStateChangeListeners.push(listener) } protected emitConnectionStateChange(deviceId: string, state: BleConnectionState) { console.log('[AKBLE][LOG] emitConnectionStateChange', deviceId, state, 'listeners:', this.connectionStateChangeListeners.length, 'connectionStates:', this.connectionStates) for (const listener of this.connectionStateChangeListeners) { try { console.log('[AKBLE][LOG] emitConnectionStateChange 调用 listener', listener) listener(deviceId, state) } catch (e) { console.error('[AKBLE][LOG] emitConnectionStateChange listener error', e) } } } getGattInstance(deviceId: string): BluetoothGatt | null { return this.gattMap.get(deviceId) ?? null; } private getBluetoothAdapter(): BluetoothAdapter | null { const context = UTSAndroid.getAppContext(); if (context == null) return null; const manager = context?.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager; return manager.getAdapter(); } /** * 获取指定ID的设备(如果存在) */ public getDevice(deviceId: string): BleDevice | null { console.log(deviceId,this.devices) return this.devices.get(deviceId) ?? null; } }