import { useEffect, useState } from 'react'
import Taro from '@tarojs/taro'
import { View, Text } from '@tarojs/components'
import { Navbar } from '@/components/navbar'
import { useBle } from '@/ble/hooks/useBle'
import { navigateTo } from '@/utils/navigation'
import { ROUTES } from '@/constants/routes'
import { getErrorMessage } from '@/utils/error'
import { DEVICE_ACTION_KEYS, ACTION_REGISTRY, isEp832Device } from '@/constants/deviceActions'
import type { BleDevice } from '@/ble/hooks/useBle'
import styles from './ble-config.module.scss'
export default function DeviceBleConfig() {
const { state, discovery } = useBle()
const [preparingId, setPreparingId] = useState('')
// 页面隐藏/卸载时清理搜索(对齐旧版 onHide/onUnload),连接保持供配网页使用
useEffect(() => {
return () => {
if (discovery.getState().isSearching) {
discovery.stopSearch(false)
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
const startScan = async () => {
if (state.searching) {
await discovery.stopSearch()
return
}
// startSearch 内部自动完成:Android 定位权限检查 + 适配器初始化 +
// 服务 UUID 过滤扫描(00F4/F400/FFF4)+ 4s 无结果兜底全扫 + 30s 自动停止
try {
await discovery.startSearch()
} catch {
// startSearch 内部已 toast 具体错误码,此处不再重复提示
}
}
// 点击"网络配置":连接 → 发现服务特征 → 订阅 F301(厂家确认无需鉴权)→ 打开配网页
const openWifiPanel = async (deviceId: string) => {
if (preparingId) return
setPreparingId(deviceId)
Taro.showLoading({ title: '连接设备中', mask: true })
let prepError: unknown = null
try {
await discovery.prepareWifiConfig(deviceId)
navigateTo(ROUTES.DEVICE_CONFIG)
} catch (error) {
prepError = error
} finally {
setPreparingId('')
// showLoading 与 showToast 共用同一遮罩层,必须先 hideLoading 再弹提示
Taro.hideLoading()
}
if (prepError) {
// 连接/订阅失败用模态弹窗,需用户主动确认,确保错误诊断信息可见可读
Taro.showModal({
title: '设备连接失败',
content: getErrorMessage(prepError),
showCancel: false,
confirmText: '知道了'
})
}
}
const invokeAction = (key: string, deviceId: string) => {
if (key === 'WIFI') openWifiPanel(deviceId)
// PARAMS/SERVER 仅占位,后续接入
}
const isActionBusy = (key: string, deviceId: string) =>
key === 'WIFI' && preparingId === deviceId
const renderDevice = (device: BleDevice) => {
const actions = (DEVICE_ACTION_KEYS[isEp832Device(device) ? 'EP832' : 'DEFAULT'] ?? DEVICE_ACTION_KEYS.DEFAULT)
.map((key) => ({ key, ...ACTION_REGISTRY[key] }))
return (
{String(device.showName ?? device.deviceId)}
{device.hasTargetService ? (
00F4
) : device.matchedByName || device.matchedByPayload ? (
名称匹配
) : null}
{String(device.deviceId)}
{actions.map((action) => {
const busy = isActionBusy(action.key, device.deviceId)
return (
!busy && invokeAction(action.key, device.deviceId)}
>
{busy ? action.busyLabel : action.label}
)
})}
)
}
return (
{state.searching ? '搜索中' : '搜索'}
*手机需开启蓝牙功能,Android手机还需开启定位功能
搜索到的设备列表
{state.deviceList.length === 0 ? (
暂无搜索结果
) : (
state.deviceList.map(renderDevice)
)}
)
}