374 lines
10 KiB
JavaScript
Raw Normal View History

2024-12-19 16:01:45 +08:00
import { Result } from '../constant'
2024-10-12 14:35:58 +08:00
/**
* @typedef {Object} err
* @property {number} errno - 错误代码
* @property {number} errCode - 错误代码
* @property {String} errMsg - 错误信息
*/
// 查找设备并连接
2024-10-30 14:09:02 +08:00
export function searchAndConnectDevice(name, reset = true) {
2024-10-12 14:35:58 +08:00
// 循环查找设备
let timer
// 超时计时器
let timeoutTimer
2024-10-21 09:58:17 +08:00
return new Promise(async resolve => {
2024-10-12 14:35:58 +08:00
const result = await startBluetoothDevicesDiscovery()
2024-10-21 09:58:17 +08:00
if (result.code === Result.Success.code) {
2024-10-12 14:35:58 +08:00
let searchFlag = false
timeoutTimer = setTimeout(async () => {
await stopBluetoothDevicesDiscovery()
clearInterval(timer)
if (!searchFlag) {
resolve(Result.NotAvailableWeChatNearbyDevicesEmpty)
} else {
resolve(Result.Fail)
}
}, 10500)
timer = setInterval(async () => {
const queryResult = await getBluetoothDevices()
2024-10-21 09:58:17 +08:00
if (queryResult.code === Result.Success.code) {
2024-10-12 14:35:58 +08:00
const deviceList = queryResult.data
if (searchFlag === false && deviceList.length > 0) {
searchFlag = true
}
for (let i = 0; i < deviceList.length; i++) {
if (deviceList[i]?.name === name) {
const uuid = deviceList[i]?.advertisServiceUUIDs[0]
2024-10-21 09:58:17 +08:00
if (uuid && uuid.slice(2, 8) === '758824') {
2024-10-12 14:35:58 +08:00
await stopBluetoothDevicesDiscovery()
clearTimeout(timeoutTimer)
clearInterval(timer)
2024-10-30 14:09:02 +08:00
if (uuid.slice(30, 32) === '00' && reset) {
2024-10-12 14:35:58 +08:00
resolve(Result.DeviceHasBeenReset)
2024-10-30 14:09:02 +08:00
} else {
2024-10-12 14:35:58 +08:00
const connectResult = await createBLEConnection(deviceList[i].deviceId)
resolve(connectResult)
}
break
}
if (uuid && uuid.slice(0, 2) === '75') {
await stopBluetoothDevicesDiscovery()
clearTimeout(timeoutTimer)
clearInterval(timer)
if (uuid.slice(4, 6) === '00' && reset) {
resolve(Result.DeviceHasBeenReset)
} else {
const connectResult = await createBLEConnection(deviceList[i].deviceId)
resolve(connectResult)
}
break
}
2024-10-12 14:35:58 +08:00
}
}
} else {
resolve(queryResult)
}
}, 1000)
} else {
resolve(result)
}
})
}
// 蓝牙操作报错处理
2024-10-21 09:58:17 +08:00
async function handleError(err, event) {
2024-10-12 14:35:58 +08:00
if (err.errCode === 10000) {
const result = await openBluetoothAdapter()
if (result.code === Result.Success.code) {
return await event()
}
2024-10-21 09:58:17 +08:00
return result
}
if (err.errCode === 10001) {
2024-10-31 18:41:21 +08:00
if (err.state === 3) {
return Result.NotAvailableWeChatBluetoothPermission
}
2024-10-12 14:35:58 +08:00
return Result.NotAvailableBluetooth
2024-10-21 09:58:17 +08:00
}
if (err.errno === 3) {
2024-10-12 14:35:58 +08:00
return Result.NotAvailableWeChatNearbyDevicesPermission
2024-10-21 09:58:17 +08:00
}
if (err.errno === 103) {
2024-10-12 14:35:58 +08:00
return Result.NotAvailableBluetoothPermission
2024-10-21 09:58:17 +08:00
}
if (err.errno === 1509008) {
2024-10-12 14:35:58 +08:00
return Result.NotAvailableWeChatLocationPermission
2024-10-21 09:58:17 +08:00
}
if (err.errMsg === 'openBluetoothAdapter:fail already opened') {
2024-10-12 14:35:58 +08:00
return Result.Success
}
2024-10-21 09:58:17 +08:00
return Result.Fail
2024-10-12 14:35:58 +08:00
}
// 初始化蓝牙模块
function openBluetoothAdapter() {
2024-10-21 09:58:17 +08:00
return new Promise(resolve => {
2024-10-12 14:35:58 +08:00
uni.openBluetoothAdapter({
success() {
resolve(Result.Success)
},
2024-10-21 09:58:17 +08:00
async fail(err) {
2024-10-12 14:35:58 +08:00
resolve(await handleError(err))
}
})
})
}
// 关闭蓝牙模块
2024-11-13 14:36:51 +08:00
export function closeBluetoothAdapter() {
uni.closeBluetoothAdapter()
2024-10-12 14:35:58 +08:00
}
// 移除蓝牙适配器的全部监听
2024-11-13 14:36:51 +08:00
export function offBluetoothAdapterStateChange() {
2024-10-12 14:35:58 +08:00
uni.offBluetoothAdapterStateChange()
}
// 监听蓝牙特征值改变
export function onBLECharacteristicValueChange(callback) {
2024-10-21 09:58:17 +08:00
uni.onBLECharacteristicValueChange(res => {
2024-10-12 14:35:58 +08:00
callback(res)
})
}
// 开始搜索附近的蓝牙设备
2024-10-30 14:09:02 +08:00
export function startBluetoothDevicesDiscovery() {
2024-10-21 09:58:17 +08:00
return new Promise(resolve => {
2024-10-12 14:35:58 +08:00
uni.startBluetoothDevicesDiscovery({
success() {
resolve(Result.Success)
},
2024-10-21 09:58:17 +08:00
async fail(err) {
2024-10-12 14:35:58 +08:00
resolve(await handleError(err, startBluetoothDevicesDiscovery))
}
})
})
}
// 获取所有已发现的蓝牙设备
2024-10-30 14:09:02 +08:00
export function getBluetoothDevices() {
2024-10-21 09:58:17 +08:00
return new Promise(resolve => {
2024-10-12 14:35:58 +08:00
uni.getBluetoothDevices({
success(res) {
resolve(new Result(Result.Success.code, res.devices))
},
2024-10-21 09:58:17 +08:00
async fail(err) {
2024-10-12 14:35:58 +08:00
resolve(await handleError(err, getBluetoothDevices))
}
})
})
}
// 停止搜索附近的蓝牙设备
2024-10-30 14:09:02 +08:00
export function stopBluetoothDevicesDiscovery() {
2024-10-21 09:58:17 +08:00
return new Promise(resolve => {
2024-10-12 14:35:58 +08:00
uni.stopBluetoothDevicesDiscovery({
success() {
resolve(Result.Success)
},
2024-10-21 09:58:17 +08:00
async fail(err) {
2024-10-12 14:35:58 +08:00
resolve(await handleError(err))
}
})
})
}
// 连接低功耗蓝牙设备
2024-10-30 14:09:02 +08:00
export function createBLEConnection(deviceId, reconnectNumber = 0) {
2024-10-21 09:58:17 +08:00
return new Promise(resolve => {
2024-10-12 14:35:58 +08:00
uni.createBLEConnection({
deviceId,
timeout: 10000,
2024-10-21 09:58:17 +08:00
async success() {
2024-10-12 14:35:58 +08:00
const res = await getBLEDeviceServicesAndCharacteristics(deviceId)
2024-10-21 09:58:17 +08:00
await notifyBLECharacteristicValueChange(
deviceId,
res.data.serviceId,
res.data.notifyCharacteristicId
)
// 使用同步方法获取系统信息
const systemInfo = uni.getSystemInfoSync();
if (systemInfo.platform === 'android') {
// 如果是Android机型则设置BLE MTU
uni.setBLEMTU({
deviceId: deviceId,
mtu: 512,
fail: res => {
console.log('mtu fail', res);
},
success: res => {
console.log('mtu success', res);
}
});
} else {
// 对于非Android设备可以在这里添加其他逻辑或者直接忽略
console.log('当前设备不是Android跳过设置BLE MTU');
}
2024-10-12 14:35:58 +08:00
resolve(res)
},
2024-10-21 09:58:17 +08:00
async fail(err) {
2024-10-12 14:35:58 +08:00
if (err.errno === 1509007) {
const res = await getBLEDeviceServicesAndCharacteristics(deviceId)
2024-10-21 09:58:17 +08:00
await notifyBLECharacteristicValueChange(
deviceId,
res.data.serviceId,
res.data.notifyCharacteristicId
)
2024-10-12 14:35:58 +08:00
resolve(res)
} else if (err.errno === 1509001 && reconnectNumber < 1) {
resolve(Result.Fail)
} else if (reconnectNumber < 1) {
resolve(await createBLEConnection(deviceId, reconnectNumber + 1))
} else {
resolve(Result.Fail)
}
}
})
})
}
// 获取服务及对应特征值
2024-10-21 09:58:17 +08:00
async function getBLEDeviceServicesAndCharacteristics(deviceId) {
2024-10-12 14:35:58 +08:00
const { code, data } = await getBLEDeviceServices(deviceId)
if (code === Result.Success.code) {
const { serviceId } = data
const {
code,
data: { notifyCharacteristicId, writeCharacteristicId }
} = await getBLEDeviceCharacteristics(deviceId, serviceId)
if (code === Result.Success.code) {
2024-10-21 09:58:17 +08:00
return new Result(Result.Success.code, {
deviceId,
serviceId,
notifyCharacteristicId,
writeCharacteristicId
})
2024-10-12 14:35:58 +08:00
}
return Result.Fail
}
2024-10-21 09:58:17 +08:00
return Result.Fail
2024-10-12 14:35:58 +08:00
}
// 获取设备的服务
function getBLEDeviceServices(deviceId) {
2024-10-21 09:58:17 +08:00
return new Promise(resolve => {
2024-10-12 14:35:58 +08:00
uni.getBLEDeviceServices({
deviceId,
success(res) {
let serviceId
2024-10-21 09:58:17 +08:00
for (let i = 0; i < res.services.length; i++) {
if (res.services[i].uuid.indexOf('FFF0') !== -1) {
2024-10-12 14:35:58 +08:00
serviceId = res.services[i].uuid
}
}
2024-10-21 09:58:17 +08:00
if (!serviceId) {
2024-10-12 14:35:58 +08:00
resolve(Result.Fail)
return
}
resolve(new Result(Result.Success.code, { serviceId }))
},
fail() {
resolve(Result.Fail)
}
})
})
}
// 获取服务的特征值
function getBLEDeviceCharacteristics(deviceId, serviceId) {
2024-10-21 09:58:17 +08:00
return new Promise(resolve => {
2024-10-12 14:35:58 +08:00
uni.getBLEDeviceCharacteristics({
deviceId,
serviceId,
success(res) {
let notifyCharacteristicId
let writeCharacteristicId
2024-10-21 09:58:17 +08:00
for (let i = 0; i < res.characteristics.length; i++) {
2024-10-12 14:35:58 +08:00
const characteristic = res.characteristics[i]
2024-10-21 09:58:17 +08:00
if (characteristic.properties.notify) {
2024-10-12 14:35:58 +08:00
notifyCharacteristicId = characteristic.uuid
}
2024-10-21 09:58:17 +08:00
if (characteristic.properties.write) {
2024-10-12 14:35:58 +08:00
writeCharacteristicId = characteristic.uuid
}
}
2024-10-21 09:58:17 +08:00
if (notifyCharacteristicId && writeCharacteristicId) {
resolve(
new Result(Result.Success.code, { notifyCharacteristicId, writeCharacteristicId })
)
2024-10-12 14:35:58 +08:00
} else {
resolve(Result.Fail)
}
},
fail() {
resolve(Result.Fail)
}
})
})
}
// 订阅特征值
function notifyBLECharacteristicValueChange(deviceId, serviceId, characteristicId) {
2024-10-21 09:58:17 +08:00
return new Promise(resolve => {
2024-10-12 14:35:58 +08:00
uni.notifyBLECharacteristicValueChange({
deviceId,
serviceId,
characteristicId,
state: true,
success() {
resolve(Result.Success)
},
fail() {
resolve(Result.Fail)
}
})
})
}
// 断开与低功耗蓝牙设备的连接
export function closeBLEConnection(deviceId) {
2024-10-21 09:58:17 +08:00
return new Promise(resolve => {
2024-10-12 14:35:58 +08:00
uni.closeBLEConnection({
deviceId,
success() {
console.log('断开连接成功')
resolve(Result.Success)
},
fail() {
console.log('断开连接失败')
resolve(Result.Fail)
}
})
})
}
// 写入特征值
export function writeBLECharacteristicValue(deviceId, serviceId, characteristicId, binaryData) {
2024-10-21 09:58:17 +08:00
return new Promise(resolve => {
2024-10-12 14:35:58 +08:00
const count = Math.ceil(binaryData.length / 20)
let successCount = 0
2024-10-21 09:58:17 +08:00
for (let i = 0; i < count; i++) {
const writeData = binaryData.slice(i * 20, i === count - 1 ? binaryData.length : (i + 1) * 20)
2024-10-12 14:35:58 +08:00
uni.writeBLECharacteristicValue({
deviceId,
serviceId,
characteristicId,
value: writeData.buffer,
success() {
successCount++
2024-10-21 09:58:17 +08:00
if (successCount === count) {
2024-10-12 14:35:58 +08:00
resolve(Result.Success)
}
},
fail() {
resolve(Result.Fail)
}
})
}
})
}