|
|
@@ -259,6 +259,8 @@ export const useBleStore = defineStore('ble', {
|
|
|
})
|
|
|
// 永久注册设备发现监听器(不可反复 on/off,否则多次后系统丢失监听)
|
|
|
uni.onBluetoothDeviceFound((res) => {
|
|
|
+ const deviceCount = res && res.devices ? res.devices.length : 0
|
|
|
+ console.log(`[BLE Global] onBluetoothDeviceFound 触发, 设备数=${deviceCount}, s.onDeviceFound=${!!s.onDeviceFound}`)
|
|
|
if (s.onDeviceFound) s.onDeviceFound(res)
|
|
|
})
|
|
|
s.bound = true
|
|
|
@@ -290,20 +292,78 @@ export const useBleStore = defineStore('ble', {
|
|
|
// ============== 扫描 ==============
|
|
|
async startScan(opt = {}) {
|
|
|
const s = _S()
|
|
|
- console.log(`[BLE Store] startScan() called, instanceId = ${s.instanceId}`)
|
|
|
+ const platform = uni.getSystemInfoSync().platform
|
|
|
+ console.log(`[BLE Scan] ====== startScan 开始 ====== platform=${platform}, instanceId=${s.instanceId}`)
|
|
|
+ console.log(`[BLE Scan] 当前状态: bleState=${this.bleState}, searching=${this.searching}, linked=${this.linked}, bound=${s.bound}`)
|
|
|
// 重置中止标记
|
|
|
s.scanAborted = false
|
|
|
this.scanThrottled = false
|
|
|
// 取消上一次残留扫描
|
|
|
- if (s.cancelScan) { s.cancelScan(); s.cancelScan = null }
|
|
|
- // 停止上一次发现
|
|
|
- await _invoke(uni.stopBluetoothDevicesDiscovery, {}).catch(() => {})
|
|
|
+ if (s.cancelScan) {
|
|
|
+ console.log('[BLE Scan] 取消上一次残留扫描')
|
|
|
+ s.cancelScan(); s.cancelScan = null
|
|
|
+ }
|
|
|
+ // 停止上一次发现(不使用 await _invoke,因为 iOS 无活跃扫描时不回调会导致卡死)
|
|
|
+ console.log('[BLE Scan] 调用 stopBluetoothDevicesDiscovery 清除上一次扫描')
|
|
|
+ try {
|
|
|
+ uni.stopBluetoothDevicesDiscovery({
|
|
|
+ success: () => console.log('[BLE Scan] stopDiscovery 成功'),
|
|
|
+ fail: (e) => console.log('[BLE Scan] stopDiscovery 失败(无害):', JSON.stringify(e)),
|
|
|
+ complete: () => {}
|
|
|
+ })
|
|
|
+ } catch (e) {
|
|
|
+ console.log('[BLE Scan] stopDiscovery 异常(无害):', e)
|
|
|
+ }
|
|
|
+ // 给 iOS 一点时间处理 stop
|
|
|
+ await new Promise(r => setTimeout(r, 100))
|
|
|
+ console.log('[BLE Scan] stopDiscovery 处理完毕,继续...')
|
|
|
+
|
|
|
+ // iOS 专用修复:关闭并重新打开蓝牙适配器以清除 CoreBluetooth 外设缓存
|
|
|
+ // iOS 的 CBCentralManager 会缓存已发现的外设,单纯 stop/start 不会清除缓存
|
|
|
+ // 导致重新扫描时系统不再上报之前已发现的设备
|
|
|
+ // 只有 close + open adapter 才能让 CoreBluetooth 重置外设缓存
|
|
|
+ if (platform === 'ios' && !this.linked) {
|
|
|
+ console.log('[BLE Scan] [iOS] 开始回收适配器以清除 CoreBluetooth 缓存...')
|
|
|
+ s.intentionalDisconnect = true
|
|
|
+ s.onDeviceFound = null
|
|
|
+ try {
|
|
|
+ await _invoke(uni.closeBluetoothAdapter, {})
|
|
|
+ console.log('[BLE Scan] [iOS] closeBluetoothAdapter 成功')
|
|
|
+ } catch (e) {
|
|
|
+ console.log('[BLE Scan] [iOS] closeBluetoothAdapter 失败(无害):', JSON.stringify(e))
|
|
|
+ }
|
|
|
+ this._setState(BLE_STATE.IDLE)
|
|
|
+ s.intentionalDisconnect = false
|
|
|
+ // 等待 iOS BLE 栈完全释放资源
|
|
|
+ await new Promise(r => setTimeout(r, 300))
|
|
|
+ console.log('[BLE Scan] [iOS] 等待 300ms 后重新打开适配器...')
|
|
|
+ // 重新打开适配器
|
|
|
+ try {
|
|
|
+ await _invoke(uni.openBluetoothAdapter, {})
|
|
|
+ this.bleAdapterOff = false
|
|
|
+ this._setState(BLE_STATE.READY)
|
|
|
+ console.log('[BLE Scan] [iOS] openBluetoothAdapter 成功, state=READY')
|
|
|
+ } catch (e) {
|
|
|
+ console.log('[BLE Scan] [iOS] openBluetoothAdapter 失败:', JSON.stringify(e))
|
|
|
+ const code = e && (e.errCode || e.code)
|
|
|
+ if (code === 10001) {
|
|
|
+ this.bleAdapterOff = true
|
|
|
+ throw _err(BLE_ERROR.ADAPTER_OFF, e)
|
|
|
+ }
|
|
|
+ throw _err(BLE_ERROR.NOT_SUPPORT, e)
|
|
|
+ }
|
|
|
+ // 再等 200ms 让 adapter 完全就绪
|
|
|
+ await new Promise(r => setTimeout(r, 200))
|
|
|
+ console.log('[BLE Scan] [iOS] 适配器回收完成,准备开始扫描')
|
|
|
+ }
|
|
|
|
|
|
+ console.log('[BLE Scan] 调用 _ensureReady...')
|
|
|
await this._ensureReady()
|
|
|
+ console.log('[BLE Scan] _ensureReady 完成, bleState=', this.bleState)
|
|
|
|
|
|
// 如果在 await 期间页面已卸载并调用了 stopScan,直接中止
|
|
|
if (s.scanAborted) {
|
|
|
- logger.info('startScan aborted (page already unloaded)')
|
|
|
+ console.log('[BLE Scan] 扫描已被中止(scanAborted=true),直接返回')
|
|
|
return opt.returnAll ? [] : null
|
|
|
}
|
|
|
|
|
|
@@ -317,9 +377,9 @@ export const useBleStore = defineStore('ble', {
|
|
|
|
|
|
// 清空上次扫描结果
|
|
|
this.scannedDevices = []
|
|
|
+ console.log(`[BLE Scan] 扫描参数: namePrefix=${namePrefix || '(无)'}, deviceName=${deviceName || '(无)'}, timeout=${timeout}, returnAll=${returnAll}`)
|
|
|
|
|
|
// Android 限流检测(30秒内最多5次,iOS 无此限制)
|
|
|
- const platform = uni.getSystemInfoSync().platform
|
|
|
if (platform === 'android') {
|
|
|
const now = Date.now()
|
|
|
s.scanStartHistory = s.scanStartHistory.filter(t => now - t < 30000)
|
|
|
@@ -333,15 +393,25 @@ export const useBleStore = defineStore('ble', {
|
|
|
const devices = new Map()
|
|
|
const matched = []
|
|
|
|
|
|
+ // iOS 上使用 allowDuplicatesKey=true 确保系统持续上报所有设备
|
|
|
+ // 避免 CoreBluetooth 缓存导致重新扫描时不报告已知设备
|
|
|
+ const allowDuplicates = (platform === 'ios')
|
|
|
+ console.log(`[BLE Scan] allowDuplicatesKey=${allowDuplicates} (iOS=${platform === 'ios'})`)
|
|
|
+
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
let finished = false
|
|
|
+ let foundCount = 0
|
|
|
+ // 保存扫描前的连接状态,扫描结束后恢复,避免覆盖 READY_COMM
|
|
|
+ const wasConnected = (this.bleState === BLE_STATE.READY_COMM)
|
|
|
|
|
|
const onFound = (res) => {
|
|
|
if (finished) return
|
|
|
for (const d of res.devices) {
|
|
|
if (devices.has(d.deviceId)) continue
|
|
|
devices.set(d.deviceId, d)
|
|
|
+ foundCount++
|
|
|
const name = d.name || d.localName || ''
|
|
|
+ console.log(`[BLE Scan] 发现设备 #${foundCount}: name=${name}, deviceId=${d.deviceId}, RSSI=${d.RSSI}`)
|
|
|
const hit =
|
|
|
(deviceName && name === deviceName) ||
|
|
|
(namePrefix && name.startsWith(namePrefix)) ||
|
|
|
@@ -350,6 +420,7 @@ export const useBleStore = defineStore('ble', {
|
|
|
matched.push(d)
|
|
|
const exists = this.scannedDevices.find(item => item.deviceId === d.deviceId)
|
|
|
if (!exists) {
|
|
|
+ console.log(`[BLE Scan] ✅ 设备匹配并加入列表: ${name || d.deviceId}`)
|
|
|
this.scannedDevices.push({
|
|
|
deviceId: d.deviceId,
|
|
|
name: name,
|
|
|
@@ -362,6 +433,7 @@ export const useBleStore = defineStore('ble', {
|
|
|
}
|
|
|
|
|
|
const timer = setTimeout(() => {
|
|
|
+ console.log(`[BLE Scan] 扫描超时(${timeout}ms),共发现 ${foundCount} 个设备,匹配 ${matched.length} 个`)
|
|
|
if (returnAll) finish(null, matched)
|
|
|
else if (matched.length) finish(null, matched[0])
|
|
|
else finish(_err(BLE_ERROR.SCAN_FAIL, { msg: '扫描超时,未发现目标设备' }))
|
|
|
@@ -370,11 +442,20 @@ export const useBleStore = defineStore('ble', {
|
|
|
const finish = (err, data) => {
|
|
|
if (finished) return
|
|
|
finished = true
|
|
|
+ console.log(`[BLE Scan] finish 被调用, err=${err ? err.message || err.code : 'null'}, 设备数=${Array.isArray(data) ? data.length : (data ? 1 : 0)}, wasConnected=${wasConnected}`)
|
|
|
s.cancelScan = null
|
|
|
s.onDeviceFound = null
|
|
|
clearTimeout(timer)
|
|
|
- _invoke(uni.stopBluetoothDevicesDiscovery, {}).catch(() => {})
|
|
|
- this._setState(BLE_STATE.READY)
|
|
|
+ try {
|
|
|
+ uni.stopBluetoothDevicesDiscovery({ success() {}, fail() {}, complete() {} })
|
|
|
+ } catch (_) {}
|
|
|
+ // 如果扫描前是连接状态,恢复为 READY_COMM,不要降级为 READY
|
|
|
+ if (wasConnected) {
|
|
|
+ this._setState(BLE_STATE.READY_COMM)
|
|
|
+ } else {
|
|
|
+ this._setState(BLE_STATE.READY)
|
|
|
+ }
|
|
|
+ this.searching = false
|
|
|
err ? reject(err) : resolve(data)
|
|
|
}
|
|
|
|
|
|
@@ -382,15 +463,23 @@ export const useBleStore = defineStore('ble', {
|
|
|
|
|
|
// 通过共享回调分发事件(监听器已在 _bindSystemListeners 中永久注册)
|
|
|
s.onDeviceFound = onFound
|
|
|
- this._setState(BLE_STATE.SCANNING)
|
|
|
+ // 如果当前已连接,不调用 _setState 避免覆盖 linked 状态
|
|
|
+ if (!wasConnected) {
|
|
|
+ this._setState(BLE_STATE.SCANNING)
|
|
|
+ } else {
|
|
|
+ this.searching = true
|
|
|
+ }
|
|
|
+ console.log(`[BLE Scan] s.onDeviceFound 已设置, s.bound=${s.bound}, wasConnected=${wasConnected}, 准备调用 startBluetoothDevicesDiscovery`)
|
|
|
|
|
|
try {
|
|
|
await _invoke(uni.startBluetoothDevicesDiscovery, {
|
|
|
- allowDuplicatesKey: false,
|
|
|
+ allowDuplicatesKey: allowDuplicates,
|
|
|
interval: 0,
|
|
|
services
|
|
|
})
|
|
|
+ console.log('[BLE Scan] ✅ startBluetoothDevicesDiscovery 调用成功,等待设备回调...')
|
|
|
} catch (e) {
|
|
|
+ console.log('[BLE Scan] ❌ startBluetoothDevicesDiscovery 失败:', JSON.stringify(e))
|
|
|
finish(_err(BLE_ERROR.SCAN_FAIL, e))
|
|
|
}
|
|
|
})
|
|
|
@@ -650,6 +739,7 @@ export const useBleStore = defineStore('ble', {
|
|
|
|
|
|
// ============== 收包处理 ==============
|
|
|
_onFrame(decoded, frame) {
|
|
|
+ console.log("获取到消息",decoded)
|
|
|
logger.info('frame received', decoded.funcCode)
|
|
|
if (decoded.parsed) {
|
|
|
if (decoded.parsed.type === 'GROUP_1') {
|