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([]) 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, } }