Bladeren bron

同名蓝牙连接bug解决

liyuliangjiazai 2 maanden geleden
bovenliggende
commit
9b25a00f26

+ 2 - 0
code/ajyApp/pages/device/deviceInfo/mixins/ble-mixin.js

@@ -105,6 +105,7 @@ export default {
 					if (!realBleDeviceId) {
 						try {
 							realBleDeviceId = uni.getStorageSync('ble_deviceId_' + this.advertisData) || ''
+							console.log("当前设备id",realBleDeviceId)
 						} catch (_) {}
 					}
 				}
@@ -121,6 +122,7 @@ export default {
 				if (this.advertisData) {
 					scanOpt.advertisData = this.advertisData
 				}
+				console.log("当前连接蓝牙参数",scanOpt)
 				await this.bleStore.scanAndConnect(scanOpt)
 				// 连接成功后缓存真实BLE deviceId,供下次直连使用
 				if (this.advertisData && this.bleStore.device && this.bleStore.device.deviceId) {

+ 36 - 7
code/ajyApp/stores/ble.js

@@ -437,6 +437,11 @@ export const useBleStore = defineStore('ble', {
 						devices.set(d.deviceId, d)
 						foundCount++
 						console.log(`[BLE Scan] 发现设备 #${foundCount}: name=${name}, deviceId=${d.deviceId}, RSSI=${d.RSSI}`)
+						// advertisData为空的设备跳过,无法区分同名设备
+						if (!advertisDataHex) {
+							console.log(`[BLE Scan] 跳过无广播数据的设备: ${name || d.deviceId}`)
+							continue
+						}
 						const hit =
 							(deviceName && name === deviceName) ||
 							(namePrefix && name.startsWith(namePrefix)) ||
@@ -562,6 +567,7 @@ export const useBleStore = defineStore('ble', {
 				this._setState(BLE_STATE.READY_COMM)
 				s.reconnectCount = 0
 			} catch (e) {
+				console.log("蓝牙连接失败",e)
 				this._setState(BLE_STATE.DISCONNECTED)
 				this.device = null // 连接失败,清空 device 防止延迟回调误触发重连
 				try { await _invoke(uni.closeBLEConnection, { deviceId }) } catch (_) {}
@@ -576,7 +582,8 @@ export const useBleStore = defineStore('ble', {
 		/** 扫描 + 连接一步到位(支持 deviceId 直连优先,跳过扫描) */
 		async scanAndConnect(opt = {}) {
 			const { deviceId: directId, deviceName, advertisData: passedAdvertisData, ...restOpt } = opt
-            console.log("连接opt",opt,directId,passedAdvertisData,restOpt)
+            console.log("连接opt",opt,directId,passedAdvertisData,restOpt,{ ...restOpt })
+			
 			// 策略:如果已有 deviceId,先尝试直连(不扫描),失败后回退扫描
 			if (directId) {
 				try {
@@ -598,14 +605,35 @@ export const useBleStore = defineStore('ble', {
 
 			// 回退:扫描 + 连接
 			const scanOpt = { ...restOpt }
-			if (deviceName) scanOpt.deviceName = deviceName
-			const device = await this.startScan(scanOpt)
+
+			let device = null
+			if (passedAdvertisData) {
+				// 有 advertisData 时:不传 deviceName 做名称过滤(后端名与蓝牙广播名可能不一致)
+				// 扫描所有设备,再通过 advertisData 精确定位目标
+				scanOpt.returnAll = true
+				const devices = await this.startScan(scanOpt)
+				console.log(`[BLE scanAndConnect] 扫描到 ${devices.length} 个设备,目标 advertisData=${passedAdvertisData}`)
+				// 精确匹配 advertisData
+				device = devices.find(d => {
+					const hex = d._advertisDataHex || d.advertisData || ''
+					return hex === passedAdvertisData
+				})
+				if (!device) {
+					throw _err(BLE_ERROR.SCAN_FAIL, { msg: '未找到目标设备(advertisData不匹配)' })
+				}
+				console.log(`[BLE scanAndConnect] ✅ 通过advertisData匹配到设备: name=${device.name || device.localName}, deviceId=${device.deviceId}`)
+			} else {
+				// 无 advertisData 时按设备名过滤,返回第一个匹配设备
+				if (deviceName) scanOpt.deviceName = deviceName
+				device = await this.startScan(scanOpt)
+			}
+
 			await this.connectDevice(device.deviceId)
 			this.device.name = device.name || device.localName || ''
 			console.log("连接device._advertisDataHex",device._advertisDataHex)
 			// 存储 advertisData(hex 字符串):优先用传入的(后台 deviceCode),其次用扫描结果的 hex
 			// 注意:device.advertisData 是原始 ArrayBuffer,不能直接存储,需使用 _advertisDataHex
-			this.device.advertisData = passedAdvertisData || device.advertisData || ''
+			this.device.advertisData = passedAdvertisData || device._advertisDataHex || device.advertisData || ''
 			return this.device
 		},
 
@@ -631,7 +659,8 @@ export const useBleStore = defineStore('ble', {
 			const s = _S()
 			const svcRes = await _invoke(uni.getBLEDeviceServices, { deviceId })
 			const services = svcRes.services || []
-			const targetSvc = services.find(sv => _uuidEq(sv.uuid, s.config.serviceId))
+			const strict = s.config.strictUUID
+			const targetSvc = (strict && services.find(sv => _uuidEq(sv.uuid, s.config.serviceId)))
 				|| services.find(sv => sv.isPrimary)
 				|| services[0]
 			if (!targetSvc) throw _err(BLE_ERROR.SERVICE_NOT_FOUND)
@@ -642,9 +671,9 @@ export const useBleStore = defineStore('ble', {
 			})
 			const chars = charRes.characteristics || []
 
-			const writeChar = chars.find(c => _uuidEq(c.uuid, s.config.writeCharId))
+			const writeChar = (strict && chars.find(c => _uuidEq(c.uuid, s.config.writeCharId)))
 				|| chars.find(c => c.properties && (c.properties.write || c.properties.writeNoResponse || c.properties.writeDefault))
-			const notifyChar = chars.find(c => _uuidEq(c.uuid, s.config.notifyCharId))
+			const notifyChar = (strict && chars.find(c => _uuidEq(c.uuid, s.config.notifyCharId)))
 				|| chars.find(c => c.properties && (c.properties.notify || c.properties.indicate))
 
 			if (!writeChar) throw _err(BLE_ERROR.CHAR_NOT_FOUND, { msg: '未找到写特征' })

+ 5 - 3
code/ajyApp/utils/ble/BleManager.js

@@ -285,7 +285,9 @@ class BleManager extends EventEmitter {
     // 1) 服务列表
     const svcRes = await this._invoke(uni.getBLEDeviceServices, { deviceId })
     const services = svcRes.services || []
-    const targetSvc = services.find(s => this._uuidEq(s.uuid, this.config.serviceId)) || services.find(s => s.isPrimary) || services[0]
+    const strict = this.config.strictUUID
+    const targetSvc = (strict && services.find(s => this._uuidEq(s.uuid, this.config.serviceId)))
+      || services.find(s => s.isPrimary) || services[0]
     if (!targetSvc) throw this._err(BLE_ERROR.SERVICE_NOT_FOUND)
     this._serviceId = targetSvc.uuid
 
@@ -295,9 +297,9 @@ class BleManager extends EventEmitter {
     })
     const chars = charRes.characteristics || []
 
-    const writeChar = chars.find(c => this._uuidEq(c.uuid, this.config.writeCharId))
+    const writeChar = (strict && chars.find(c => this._uuidEq(c.uuid, this.config.writeCharId)))
       || chars.find(c => c.properties && (c.properties.write || c.properties.writeNoResponse || c.properties.writeDefault))
-    const notifyChar = chars.find(c => this._uuidEq(c.uuid, this.config.notifyCharId))
+    const notifyChar = (strict && chars.find(c => this._uuidEq(c.uuid, this.config.notifyCharId)))
       || chars.find(c => c.properties && (c.properties.notify || c.properties.indicate))
 
     if (!writeChar)  throw this._err(BLE_ERROR.CHAR_NOT_FOUND, { msg: '未找到写特征' })

+ 27 - 3
code/ajyApp/utils/ble/constants.js

@@ -115,12 +115,14 @@ export const BLE_STATE = {
 export const DEFAULT_CONFIG = {
   // 目标设备名称前缀(扫描过滤,空字符串表示不过滤)
   deviceNamePrefix: '',
+  // 是否强制匹配下方配置的 UUID(false = 跳过 UUID 匹配,完全按属性自动发现服务和特征)
+  strictUUID: true,
   // 主服务 UUID
-  serviceId: '0000FFF0-0000-1000-8000-00805F9B34FB',
+  serviceId: '',
   // 写特征(APP -> 设备)
-  writeCharId: '0000FFF1-0000-1000-8000-00805F9B34FB',
+  writeCharId: '',
   // 通知特征(设备 -> APP)
-  notifyCharId: '0000FFF2-0000-1000-8000-00805F9B34FB',
+  notifyCharId: '',
   // 扫描超时
   scanTimeout: 10000,
   // 连接超时
@@ -132,3 +134,25 @@ export const DEFAULT_CONFIG = {
   // 是否打印日志
   debug: true
 }
+// export const DEFAULT_CONFIG = {
+//   // 目标设备名称前缀(扫描过滤,空字符串表示不过滤)
+//   deviceNamePrefix: '',
+//   // 是否强制匹配下方配置的 UUID(false = 跳过 UUID 匹配,完全按属性自动发现服务和特征)
+//   strictUUID: false,
+//   // 主服务 UUID
+//   serviceId: '0000FFF0-0000-1000-8000-00805F9B34FB',
+//   // 写特征(APP -> 设备)
+//   writeCharId: '0000FFF1-0000-1000-8000-00805F9B34FB',
+//   // 通知特征(设备 -> APP)
+//   notifyCharId: '0000FFF2-0000-1000-8000-00805F9B34FB',
+//   // 扫描超时
+//   scanTimeout: 10000,
+//   // 连接超时
+//   connectTimeout: 10000,
+//   // 自动重连
+//   autoReconnect: true,
+//   // 最大重连次数
+//   maxReconnect: 3,
+//   // 是否打印日志
+//   debug: true
+// }