SEC_Warehouse/src/ble/hooks/useBle.ts

55 lines
1.9 KiB
TypeScript

import { useEffect, useRef, useState } from 'react'
import { createBluetoothDiscovery } from '../discovery'
// 工厂回调 → React state 的映射产物
export interface BleUiState {
searching: boolean
connected: boolean
deviceList: Array<{ deviceId: string; name?: string; RSSI?: number }>
profileId: string
stage: string
deviceInfo: Record<string, unknown> | null
authResult: unknown
}
export function useBle() {
const [state, setState] = useState<BleUiState>({
searching: false,
connected: false,
deviceList: [],
profileId: 'UNKNOWN',
stage: 'IDLE',
deviceInfo: null,
authResult: null
})
// discovery 实例在整个组件生命周期内只创建一次;
// 回调里读最新 state 用 setState 函数式更新,不闭包旧值
const discoveryRef = useRef<ReturnType<typeof createBluetoothDiscovery> | null>(null)
if (discoveryRef.current === null) {
discoveryRef.current = createBluetoothDiscovery({
onSearchingChange: (searching) => setState((s) => ({ ...s, searching })),
onConnectedChange: (connected) => setState((s) => ({ ...s, connected })),
onDeviceListChange: (deviceList) => setState((s) => ({ ...s, deviceList })),
onProfileChange: (profileId) => setState((s) => ({ ...s, profileId })),
onStageChange: (stage) => setState((s) => ({ ...s, stage })),
onDeviceInfoChange: (deviceInfo) => setState((s) => ({ ...s, deviceInfo })),
onAuthChange: (authResult) => setState((s) => ({ ...s, authResult }))
// onError / onRadarData / onProtocolState / onProtocolMsg 按页面需要接入
})
}
// 卸载时统一清理(停扫描、断连接、解绑事件)
useEffect(() => {
const discovery = discoveryRef.current
return () => {
discovery?.cleanupDiscovery()
discoveryRef.current = null
}
}, [])
const discovery = discoveryRef.current!
return { state, discovery }
}