Files
czzj-app/src/pages/add-device/scan/use-scan-device.ts
2026-10-10 11:11:44 +08:00

123 lines
3.0 KiB
TypeScript

import { onMounted, onUnmounted, ref } from 'vue'
import {
ensureBluetoothReady,
getBluetoothErrorMessage,
getDiscoveredBluetoothDevices,
isBluetoothApiSupported,
startBluetoothDiscovery,
stopBluetoothDiscovery,
subscribeBluetoothDevicesFound,
} from '@/utils/bluetooth'
import { buildBindDeviceQuery } from '../add-device.types'
import type { ScannedDeviceItem } from './scan.types'
import { mapBluetoothDevice } from './scan.utils'
const SCAN_SECONDS = 20
export function useScanDevice() {
const currentStep = 2
const devices = ref<ScannedDeviceItem[]>([])
const selectedId = ref('')
const secondsLeft = ref(SCAN_SECONDS)
const scanning = ref(true)
const scanError = ref('')
let unsubscribeFound: (() => void) | undefined
function upsertDevice(item: ScannedDeviceItem) {
const idx = devices.value.findIndex((d) => d.id === item.id)
if (idx >= 0) {
devices.value[idx] = item
return
}
devices.value.push(item)
if (!selectedId.value) selectedId.value = item.id
}
function ingestBluetoothDevices(found: UniApp.BluetoothDeviceInfo[]) {
for (const device of found) {
upsertDevice(mapBluetoothDevice(device))
}
}
async function beginDiscovery() {
if (!isBluetoothApiSupported()) {
scanning.value = false
scanError.value = '当前环境不支持蓝牙扫描,请使用 App 或微信小程序'
return
}
try {
await ensureBluetoothReady()
unsubscribeFound = subscribeBluetoothDevicesFound((found) => {
ingestBluetoothDevices(found)
})
const existing = await getDiscoveredBluetoothDevices()
ingestBluetoothDevices(existing)
await startBluetoothDiscovery()
} catch (err) {
scanning.value = false
scanError.value = getBluetoothErrorMessage(err)
uni.showToast({ title: scanError.value, icon: 'none' })
}
}
onMounted(() => {
void beginDiscovery()
})
const timer = setInterval(() => {
if (secondsLeft.value <= 0) {
scanning.value = false
return
}
secondsLeft.value -= 1
if (secondsLeft.value === 0) {
scanning.value = false
void stopBluetoothDiscovery().catch(() => {})
}
}, 1000)
onUnmounted(() => {
clearInterval(timer)
unsubscribeFound?.()
void stopBluetoothDiscovery().catch(() => {})
})
function onSelectDevice(id: string) {
selectedId.value = id
}
function onDeviceAction(device: ScannedDeviceItem) {
selectedId.value = device.id
if (!device.canAdd) {
uni.showToast({ title: '暂无法添加该设备', icon: 'none' })
return
}
const q = buildBindDeviceQuery({
deviceNo: device.deviceNo,
name: device.name,
serialMasked: device.serialMasked,
productId: device.productId,
model: device.model,
imei: device.imei,
mac: device.mac,
})
uni.navigateTo({ url: `/pages/add-device/pair/index?${q}` })
}
return {
currentStep,
devices,
selectedId,
secondsLeft,
scanning,
scanError,
onSelectDevice,
onDeviceAction,
}
}