Javascript/Miniprogram
蓝牙
import { hideLoading, isAndroid, showLoading, showToastError, throttle } from '@cloud/shared'
import { defineStore } from 'pinia'
import { computed, reactive, ref, watch } from 'vue'
export interface DeviceType extends UniNamespace.BluetoothDeviceInfo {
macAddress?: string
}
/**
* 处理错误
* @param e
*/
function handleError(e: any) {
const err = e?.errMsg || e?.msg || e?.message || ''
showToastError(err)
throw e
}
/**
*
* @param buffer ArrayBuffer转16进度字符串示例
*/
function ab2hex(buffer: any) {
const hexArr = Array.prototype.map.call(new Uint8Array(buffer), (bit) => {
return `00${bit.toString(16)}`.slice(-2)
})
return hexArr.join('')
}
export const useBluetoothStore = defineStore('bluetooth', () => {
/**
* 体温枪默认名字
*/
const DEVICE_NAME = 'BLUETOOTH BP'
/**
* 平台
*/
const platform = uni.getSystemInfoSync().platform
/**
* 是否是开发环境
*/
const isDevtools = platform === 'devtools'
/**
* 是否连接
*/
const connected = ref(false)
/**
* 设备列表
*/
const devices = ref<DeviceType[]>([])
const macRecord = reactive<Record<string, string>>({})
/**
* 设备 按照信号强度排序 和 设备名称排序
*/
const devicesSortBySignal = computed(() => {
// console.log('devices.value.map(e => e.name)', devices.value.map(e => e.name));
return devices.value.sort((a, b) => Math.abs(a.RSSI) - Math.abs(b.RSSI))
.filter((d) => {
return (d.name?.toLocaleUpperCase() === DEVICE_NAME) || (d.localName?.toLocaleUpperCase() === DEVICE_NAME)
})
.sort((a, b) => {
if ((a.name).toLocaleUpperCase() === DEVICE_NAME && b.name.toLocaleUpperCase() !== DEVICE_NAME) {
return -1
}
else if ((a.name).toLocaleUpperCase() !== DEVICE_NAME && b.name.toLocaleUpperCase() === DEVICE_NAME) {
return 1
}
else {
return 0
}
})
.map((e) => {
return {
...e,
signal: Math.abs(100 + e.RSSI),
}
})
})
/**
* 蓝牙权限
*/
const bluetoothPermissions = ref(false)
/**
* 设备蓝牙是打开?
*/
const bluetoothAvailable = ref(false)
/**
* 已链接的设备
*/
const connectedDevice = ref<DeviceType>()
/**
* 是否扫描
*/
const discoveryStarted = ref(false)
/**
* 特征值列表
*/
const chs = ref<{ uuid: string, value: any }[]>([])
/**
* 是否可以写入
*/
const canWrite = ref(false)
/**
* 获取蓝牙授权
* @param authorize 是否需要跳转授权 true 调用 uni.authorize
*/
function getBluetoothPermissions(authorize = false) {
return uni.getSetting()
.then((res) => {
// 未授权状态
const authSetting = res.authSetting as unknown as Record<string, boolean>
// eslint-disable-next-line no-prototype-builtins
if (authSetting.hasOwnProperty('scope.bluetooth')
&& authSetting['scope.bluetooth'] === true) {
bluetoothPermissions.value = true
}
else {
if (authorize) {
console.log('未授权 向 用户发起授权请求')
return uni.authorize({
scope: 'scope.bluetooth',
})
}
else {
bluetoothPermissions.value = false
console.log('false 111')
}
}
})
.then((res) => {
console.log('getBluetoothPermissions [then] authorize', res)
/**
* uni.authorize 成功!
*/
if (res !== undefined) {
bluetoothPermissions.value = true
}
})
.catch((error) => {
console.log('getBluetoothPermissions [error]', error)
bluetoothPermissions.value = false
})
}
/**
* 打开授权设置
*/
function authorizeBluetooth() {
uni.openSetting({
withSubscriptions: true,
})
}
/**
* 开始扫描
*/
async function openBluetoothAdapter() {
/**
* 初始化蓝牙模块
*/
console.log('[初始化蓝牙模块]')
return uni.openBluetoothAdapter()
.then(() => {
console.log('[开始搜寻附近的蓝牙外围设备]')
return startBluetoothDevicesDiscovery()
})
.catch((e) => {
console.log('[初始化蓝牙模块] [开始搜寻附近的蓝牙外围设备] error', e)
console.log(e.errno)
if (e.errCode === 10001) {
bluetoothAvailable.value = false
watchBluetoothAdapterStateChange((res) => {
if (res.available) {
return startBluetoothDevicesDiscovery()
}
else {
resetStatus()
}
})
}
else if (e.errno === 1509008) {
closeBluetoothAdapter()
throw new Error('请打开[微信]位置权限后重试')
}
else {
handleError(e)
}
})
}
/**
* 开始搜寻附近的蓝牙外围设备
*/
function startBluetoothDevicesDiscovery() {
console.log('开始搜寻附近的蓝牙外围设备 >>> 当前扫描状态', discoveryStarted.value)
if (discoveryStarted.value)
return
discoveryStarted.value = true
console.log('开始搜寻附近的蓝牙外围设备 >>> start')
return uni.stopBluetoothDevicesDiscovery()
.then(() => {
return uni.startBluetoothDevicesDiscovery({
allowDuplicatesKey: true,
})
})
.then((res) => {
console.log('开始搜寻附近的蓝牙外围设备 success', res)
onBluetoothDeviceFound()
})
}
/**
* 监听搜索到新设备的事件
*/
function onBluetoothDeviceFound() {
uni.onBluetoothDeviceFound((res) => {
for (let index = 0; index < res.devices.length; index++) {
const device = res.devices[index]
if (!device.name && !device.localName)
break
const macAddress = macRecord[device.deviceId]
const foundDevices = [...devices.value]
const idx = foundDevices
.map(e => e.deviceId)
.findIndex(deviceId => deviceId === device.deviceId)
/**
* 添加蓝牙
*/
if (idx === -1) {
devices.value.push({
...device,
macAddress,
})
}
else {
devices.value[idx] = {
...device,
macAddress,
}
}
}
})
}
/**
* 停止扫描
*/
async function stopBluetoothDevicesDiscovery() {
try {
await uni.stopBluetoothDevicesDiscovery()
discoveryStarted.value = false
console.log('停止扫描')
}
catch (error) {
handleError(error)
}
}
/**
* 打开或者开启蓝牙扫描
*/
async function openOrCloseDevicesDiscovery() {
try {
if (discoveryStarted.value) {
console.log('[打开或者开启蓝牙扫描]', '停止')
await stopBluetoothDevicesDiscovery()
}
else {
console.log('[打开或者开启蓝牙扫描]', '打开')
await openBluetoothAdapter()
}
}
catch (error) {
console.log('打开或者开启蓝牙扫描', error)
handleError(error)
}
}
/**
* 连接低功耗蓝牙设备
* @param ds
*/
async function createBLEConnection(ds: DeviceType, autoGetBLEDeviceServices = true) {
console.log('连接低功耗蓝牙设备')
return closeBLEConnection()
.then(() => {
console.log('先停止扫描')
return stopBluetoothDevicesDiscovery()
})
.then(() => {
return ds.deviceId
})
.then((deviceId) => {
console.log('createBLEConnection 连接低功耗蓝牙设备')
return uni.createBLEConnection({ deviceId })
})
.then(() => {
connectedDevice.value = ds
connected.value = true
autoGetBLEDeviceServices && getBLEDeviceServices(ds.deviceId)
return ds.deviceId
})
.catch((e) => {
handleError(e)
})
}
/**
* 监听蓝牙低功耗连接状态改变事件。包括开发者主动连接或断开连接,设备丢失,连接异常断开等等
*/
function watchBLEConnectionStateChange() {
return uni.onBLEConnectionStateChange((res) => {
console.log('==> watchBLEConnectionStateChange', res)
if (res.connected === false) {
connected.value = false
if (connectedDevice.value) {
connectedDevice.value = undefined
showToastError('设备已断开连接')
}
// closeBluetoothAdapter();
}
})
}
/**
* 获取蓝牙设备的所有服务
* @param deviceId
*/
function getBLEDeviceServices(deviceId: string) {
return uni.getBLEDeviceServices({
deviceId,
}).then((res) => {
for (let i = 0; i < res.services.length; i++) {
if (res.services[i].isPrimary) {
getBLEDeviceCharacteristics(deviceId, res.services[i].uuid)
return
}
}
}).catch((e) => {
handleError(e)
})
}
/**
* 获取蓝牙设备指定服务中所有特征值
* @param deviceId
* @param serviceId
*/
function getBLEDeviceCharacteristics(deviceId: string, serviceId: string) {
uni.getBLEDeviceCharacteristics({
deviceId,
serviceId,
}).then((res) => {
for (let i = 0; i < res.characteristics.length; i++) {
const item = res.characteristics[i]
if (item.properties.read) {
uni
.readBLECharacteristicValue({
deviceId,
serviceId,
characteristicId: item.uuid,
})
}
if (item.properties.notify || item.properties.indicate) {
uni.notifyBLECharacteristicValueChange({
deviceId,
serviceId,
characteristicId: item.uuid,
state: true,
})
}
}
}).catch((e) => {
handleError(e)
})
}
/**
* 断开与低功耗蓝牙设备的连接
*/
function closeBLEConnection() {
return new Promise((resolve, reject) => {
if (connectedDevice.value) {
uni.closeBLEConnection({
deviceId: connectedDevice.value.deviceId,
}).then(() => {
connectedDevice.value = undefined
chs.value = []
canWrite.value = false
console.log('断开与低功耗蓝牙设备的连接 >>> success')
resolve('')
}).catch((e) => {
reject(e)
})
}
else {
console.log('断开与低功耗蓝牙设备的连接 >>> 没有连接的设备 直接断开')
resolve('')
}
})
}
/**
* 监听蓝牙低功耗设备的特征值变化事件
*/
function watchBLECharacteristicValueChange() {
uni.onBLECharacteristicValueChange((characteristic) => {
const idx = chs.value.findIndex(
e => e.uuid === characteristic.characteristicId,
)
if (idx === -1) {
chs.value.push({
uuid: characteristic.characteristicId,
value: ab2hex(characteristic.value),
})
}
else {
chs.value[idx] = {
uuid: characteristic.characteristicId,
value: ab2hex(characteristic.value),
}
}
})
}
/**
* 断开或者连接蓝牙设备
* @param _device
*/
async function handleToggleBluetoothDevice(_device: DeviceType) {
// 蓝牙已授权 且 搜寻到设备列表 连接设备
showLoading()
try {
if (connectedDevice.value) {
await closeBLEConnection()
}
else {
await createBLEConnection(_device)
}
hideLoading()
}
catch (e: any) {
if (e?.errCode === 10003) {
showToastError('设备连接失败!')
}
else {
handleError(e)
}
}
}
/**
* 监听蓝牙特征值变化
* @param cb
*/
function onBLECharacteristicValueChange(cb: (data: { uuid: string, value: any }) => void) {
uni.onBLECharacteristicValueChange((characteristic) => {
cb?.({
uuid: characteristic.characteristicId,
value: ab2hex(characteristic.value),
})
})
}
/**
* 结束
*/
function closeBluetoothAdapter() {
console.log('结束')
uni.offBluetoothDeviceFound()
uni.offBluetoothAdapterStateChange()
uni.closeBluetoothAdapter()
resetStatus()
}
function resetStatus() {
console.log('resetStatus >>> ')
bluetoothAvailable.value = false
connectedDevice.value = undefined
discoveryStarted.value = false
chs.value = []
canWrite.value = false
}
/**
* 监听蓝牙适配器状态变化事件 断开
*/
function watchBluetoothAdapterStateChange(cb?: (res: UniApp.OnBluetoothAdapterStateChangeResult) => void) {
uni.offBluetoothAdapterStateChange()
uni.onBluetoothAdapterStateChange((res) => {
console.log('watchBluetoothAdapterStateChange')
if (!res.available) {
resetStatus()
}
else {
console.log('watchBluetoothAdapterStateChange ==> bluetoothAvailable.value >>> true')
bluetoothAvailable.value = true
}
cb?.(res)
})
}
function getMacAddr() {
if (isAndroid)
return
console.log(['getMacAddr getMacAddr getMacAddr getMacAddr getMacAddr getMacAddr getMacAddr getMacAddr '])
uni.getBluetoothDevices().then((res) => {
const _devices = res.devices.filter(d => d.name.toLocaleUpperCase() === DEVICE_NAME)
console.log('_devices', _devices)
for (let i = 0; i < _devices.length; i++) {
const e = _devices[i]
// if (macRecord[e.deviceId]) {
// console.log(macRecord[e.deviceId], 'break');
// break;
// }
if (e.advertisData) {
const byteArray = new Uint8Array(e.advertisData)
const macAddress = Array.from(byteArray)
.map(byte => byte.toString(16).toUpperCase().padStart(2, '0'))
.reverse()
.join(':')
macRecord[e.deviceId] = macAddress
const index = devices.value.findIndex(d => d.deviceId === e.deviceId)
if (index !== -1) {
devices.value[index].macAddress = macAddress
}
}
}
})
}
function init() {
watchBluetoothAdapterStateChange()
watchBLECharacteristicValueChange()
watchBLEConnectionStateChange()
}
const _getMacAddr = throttle(getMacAddr, 500)
watch(devices.value, _getMacAddr, { deep: true, immediate: true })
init()
return {
/**
* 开始扫描蓝牙
*/
openBluetoothAdapter,
/**
* 停止扫描蓝牙
*/
stopBluetoothDevicesDiscovery,
/**
* 结束蓝牙流程
*/
closeBluetoothAdapter,
/**
* 连接低功耗蓝牙设备
*/
createBLEConnection,
/**
* 断开与低功耗蓝牙设备的连接
*/
closeBLEConnection,
/**
* 获取蓝牙设备的所有服务
*/
getBLEDeviceServices,
/**
* 打开或者关闭蓝牙扫描
*/
openOrCloseDevicesDiscovery,
/**
* 获取蓝牙授权
* @param authorize 是否需要跳转授权 true 调用 uni.authorize
*/
getBluetoothPermissions,
/**
* 打开授权设置
*/
authorizeBluetooth,
/**
* 断开或者连接蓝牙设备
* @param _device
*/
handleToggleBluetoothDevice,
/**
* 监听低功耗蓝牙设备的特征值变化事件
*/
onBLECharacteristicValueChange,
/**
* 蓝牙权限
*/
bluetoothPermissions,
/**
* 设备蓝牙是打开?
*/
bluetoothAvailable,
/**
* 设备 按照信号强度排序
*/
devicesSortBySignal,
/**
* 已链接的设备
*/
connectedDevice,
/**
* 特征值列表
*/
chs,
/**
* 设备
*/
devices,
/**
* 是否模拟器
*/
isDevtools,
/**
* 是否连接
*/
connected,
/**
* 是否扫描ing
*/
discoveryStarted,
}
})import { hideLoading, isAndroid, showLoading, showToastError, throttle } from "@cloud/shared";
import { defineStore } from "pinia";
import { computed, reactive, ref, watch } from "vue";
/**
* 处理错误
* @param e
*/
function handleError(e) {
const err = e?.errMsg || e?.msg || e?.message || "";
showToastError(err);
throw e;
}
/**
*
* @param buffer ArrayBuffer转16进度字符串示例
*/
function ab2hex(buffer) {
const hexArr = Array.prototype.map.call(new Uint8Array(buffer), (bit) => {
return `00${bit.toString(16)}`.slice(-2);
});
return hexArr.join("");
}
export const useBluetoothStore = defineStore("bluetooth", () => {
/**
* 体温枪默认名字
*/
const DEVICE_NAME = "BLUETOOTH BP";
/**
* 平台
*/
const platform = uni.getSystemInfoSync().platform;
/**
* 是否是开发环境
*/
const isDevtools = platform === "devtools";
/**
* 是否连接
*/
const connected = ref(false);
/**
* 设备列表
*/
const devices = ref([]);
const macRecord = reactive({});
/**
* 设备 按照信号强度排序 和 设备名称排序
*/
const devicesSortBySignal = computed(() => {
return devices.value.sort((a, b) => Math.abs(a.RSSI) - Math.abs(b.RSSI)).filter((d) => {
return d.name?.toLocaleUpperCase() === DEVICE_NAME || d.localName?.toLocaleUpperCase() === DEVICE_NAME;
}).sort((a, b) => {
if (a.name.toLocaleUpperCase() === DEVICE_NAME && b.name.toLocaleUpperCase() !== DEVICE_NAME) {
return -1;
} else if (a.name.toLocaleUpperCase() !== DEVICE_NAME && b.name.toLocaleUpperCase() === DEVICE_NAME) {
return 1;
} else {
return 0;
}
}).map((e) => {
return {
...e,
signal: Math.abs(100 + e.RSSI)
};
});
});
/**
* 蓝牙权限
*/
const bluetoothPermissions = ref(false);
/**
* 设备蓝牙是打开?
*/
const bluetoothAvailable = ref(false);
/**
* 已链接的设备
*/
const connectedDevice = ref();
/**
* 是否扫描
*/
const discoveryStarted = ref(false);
/**
* 特征值列表
*/
const chs = ref([]);
/**
* 是否可以写入
*/
const canWrite = ref(false);
/**
* 获取蓝牙授权
* @param authorize 是否需要跳转授权 true 调用 uni.authorize
*/
function getBluetoothPermissions(authorize = false) {
return uni.getSetting().then((res) => {
const authSetting = res.authSetting;
if (authSetting.hasOwnProperty("scope.bluetooth") && authSetting["scope.bluetooth"] === true) {
bluetoothPermissions.value = true;
} else {
if (authorize) {
console.log("未授权 向 用户发起授权请求");
return uni.authorize({ scope: "scope.bluetooth" });
} else {
bluetoothPermissions.value = false;
console.log("false 111");
}
}
}).then((res) => {
console.log("getBluetoothPermissions [then] authorize", res);
/**
* uni.authorize 成功!
*/
if (res !== undefined) {
bluetoothPermissions.value = true;
}
}).catch((error) => {
console.log("getBluetoothPermissions [error]", error);
bluetoothPermissions.value = false;
});
}
/**
* 打开授权设置
*/
function authorizeBluetooth() {
uni.openSetting({ withSubscriptions: true });
}
/**
* 开始扫描
*/
async function openBluetoothAdapter() {
/**
* 初始化蓝牙模块
*/
console.log("[初始化蓝牙模块]");
return uni.openBluetoothAdapter().then(() => {
console.log("[开始搜寻附近的蓝牙外围设备]");
return startBluetoothDevicesDiscovery();
}).catch((e) => {
console.log("[初始化蓝牙模块] [开始搜寻附近的蓝牙外围设备] error", e);
console.log(e.errno);
if (e.errCode === 10001) {
bluetoothAvailable.value = false;
watchBluetoothAdapterStateChange((res) => {
if (res.available) {
return startBluetoothDevicesDiscovery();
} else {
resetStatus();
}
});
} else if (e.errno === 1509008) {
closeBluetoothAdapter();
throw new Error("请打开[微信]位置权限后重试");
} else {
handleError(e);
}
});
}
/**
* 开始搜寻附近的蓝牙外围设备
*/
function startBluetoothDevicesDiscovery() {
console.log("开始搜寻附近的蓝牙外围设备 >>> 当前扫描状态", discoveryStarted.value);
if (discoveryStarted.value) return;
discoveryStarted.value = true;
console.log("开始搜寻附近的蓝牙外围设备 >>> start");
return uni.stopBluetoothDevicesDiscovery().then(() => {
return uni.startBluetoothDevicesDiscovery({ allowDuplicatesKey: true });
}).then((res) => {
console.log("开始搜寻附近的蓝牙外围设备 success", res);
onBluetoothDeviceFound();
});
}
/**
* 监听搜索到新设备的事件
*/
function onBluetoothDeviceFound() {
uni.onBluetoothDeviceFound((res) => {
for (let index = 0; index < res.devices.length; index++) {
const device = res.devices[index];
if (!device.name && !device.localName) break;
const macAddress = macRecord[device.deviceId];
const foundDevices = [...devices.value];
const idx = foundDevices.map((e) => e.deviceId).findIndex((deviceId) => deviceId === device.deviceId);
/**
* 添加蓝牙
*/
if (idx === -1) {
devices.value.push({
...device,
macAddress
});
} else {
devices.value[idx] = {
...device,
macAddress
};
}
}
});
}
/**
* 停止扫描
*/
async function stopBluetoothDevicesDiscovery() {
try {
await uni.stopBluetoothDevicesDiscovery();
discoveryStarted.value = false;
console.log("停止扫描");
} catch (error) {
handleError(error);
}
}
/**
* 打开或者开启蓝牙扫描
*/
async function openOrCloseDevicesDiscovery() {
try {
if (discoveryStarted.value) {
console.log("[打开或者开启蓝牙扫描]", "停止");
await stopBluetoothDevicesDiscovery();
} else {
console.log("[打开或者开启蓝牙扫描]", "打开");
await openBluetoothAdapter();
}
} catch (error) {
console.log("打开或者开启蓝牙扫描", error);
handleError(error);
}
}
/**
* 连接低功耗蓝牙设备
* @param ds
*/
async function createBLEConnection(ds, autoGetBLEDeviceServices = true) {
console.log("连接低功耗蓝牙设备");
return closeBLEConnection().then(() => {
console.log("先停止扫描");
return stopBluetoothDevicesDiscovery();
}).then(() => {
return ds.deviceId;
}).then((deviceId) => {
console.log("createBLEConnection 连接低功耗蓝牙设备");
return uni.createBLEConnection({ deviceId });
}).then(() => {
connectedDevice.value = ds;
connected.value = true;
autoGetBLEDeviceServices && getBLEDeviceServices(ds.deviceId);
return ds.deviceId;
}).catch((e) => {
handleError(e);
});
}
/**
* 监听蓝牙低功耗连接状态改变事件。包括开发者主动连接或断开连接,设备丢失,连接异常断开等等
*/
function watchBLEConnectionStateChange() {
return uni.onBLEConnectionStateChange((res) => {
console.log("==> watchBLEConnectionStateChange", res);
if (res.connected === false) {
connected.value = false;
if (connectedDevice.value) {
connectedDevice.value = undefined;
showToastError("设备已断开连接");
}
}
});
}
/**
* 获取蓝牙设备的所有服务
* @param deviceId
*/
function getBLEDeviceServices(deviceId) {
return uni.getBLEDeviceServices({ deviceId }).then((res) => {
for (let i = 0; i < res.services.length; i++) {
if (res.services[i].isPrimary) {
getBLEDeviceCharacteristics(deviceId, res.services[i].uuid);
return;
}
}
}).catch((e) => {
handleError(e);
});
}
/**
* 获取蓝牙设备指定服务中所有特征值
* @param deviceId
* @param serviceId
*/
function getBLEDeviceCharacteristics(deviceId, serviceId) {
uni.getBLEDeviceCharacteristics({
deviceId,
serviceId
}).then((res) => {
for (let i = 0; i < res.characteristics.length; i++) {
const item = res.characteristics[i];
if (item.properties.read) {
uni.readBLECharacteristicValue({
deviceId,
serviceId,
characteristicId: item.uuid
});
}
if (item.properties.notify || item.properties.indicate) {
uni.notifyBLECharacteristicValueChange({
deviceId,
serviceId,
characteristicId: item.uuid,
state: true
});
}
}
}).catch((e) => {
handleError(e);
});
}
/**
* 断开与低功耗蓝牙设备的连接
*/
function closeBLEConnection() {
return new Promise((resolve, reject) => {
if (connectedDevice.value) {
uni.closeBLEConnection({ deviceId: connectedDevice.value.deviceId }).then(() => {
connectedDevice.value = undefined;
chs.value = [];
canWrite.value = false;
console.log("断开与低功耗蓝牙设备的连接 >>> success");
resolve("");
}).catch((e) => {
reject(e);
});
} else {
console.log("断开与低功耗蓝牙设备的连接 >>> 没有连接的设备 直接断开");
resolve("");
}
});
}
/**
* 监听蓝牙低功耗设备的特征值变化事件
*/
function watchBLECharacteristicValueChange() {
uni.onBLECharacteristicValueChange((characteristic) => {
const idx = chs.value.findIndex((e) => e.uuid === characteristic.characteristicId);
if (idx === -1) {
chs.value.push({
uuid: characteristic.characteristicId,
value: ab2hex(characteristic.value)
});
} else {
chs.value[idx] = {
uuid: characteristic.characteristicId,
value: ab2hex(characteristic.value)
};
}
});
}
/**
* 断开或者连接蓝牙设备
* @param _device
*/
async function handleToggleBluetoothDevice(_device) {
showLoading();
try {
if (connectedDevice.value) {
await closeBLEConnection();
} else {
await createBLEConnection(_device);
}
hideLoading();
} catch (e) {
if (e?.errCode === 10003) {
showToastError("设备连接失败!");
} else {
handleError(e);
}
}
}
/**
* 监听蓝牙特征值变化
* @param cb
*/
function onBLECharacteristicValueChange(cb) {
uni.onBLECharacteristicValueChange((characteristic) => {
cb?.({
uuid: characteristic.characteristicId,
value: ab2hex(characteristic.value)
});
});
}
/**
* 结束
*/
function closeBluetoothAdapter() {
console.log("结束");
uni.offBluetoothDeviceFound();
uni.offBluetoothAdapterStateChange();
uni.closeBluetoothAdapter();
resetStatus();
}
function resetStatus() {
console.log("resetStatus >>> ");
bluetoothAvailable.value = false;
connectedDevice.value = undefined;
discoveryStarted.value = false;
chs.value = [];
canWrite.value = false;
}
/**
* 监听蓝牙适配器状态变化事件 断开
*/
function watchBluetoothAdapterStateChange(cb) {
uni.offBluetoothAdapterStateChange();
uni.onBluetoothAdapterStateChange((res) => {
console.log("watchBluetoothAdapterStateChange");
if (!res.available) {
resetStatus();
} else {
console.log("watchBluetoothAdapterStateChange ==> bluetoothAvailable.value >>> true");
bluetoothAvailable.value = true;
}
cb?.(res);
});
}
function getMacAddr() {
if (isAndroid) return;
console.log(["getMacAddr getMacAddr getMacAddr getMacAddr getMacAddr getMacAddr getMacAddr getMacAddr "]);
uni.getBluetoothDevices().then((res) => {
const _devices = res.devices.filter((d) => d.name.toLocaleUpperCase() === DEVICE_NAME);
console.log("_devices", _devices);
for (let i = 0; i < _devices.length; i++) {
const e = _devices[i];
if (e.advertisData) {
const byteArray = new Uint8Array(e.advertisData);
const macAddress = Array.from(byteArray).map((byte) => byte.toString(16).toUpperCase().padStart(2, "0")).reverse().join(":");
macRecord[e.deviceId] = macAddress;
const index = devices.value.findIndex((d) => d.deviceId === e.deviceId);
if (index !== -1) {
devices.value[index].macAddress = macAddress;
}
}
}
});
}
function init() {
watchBluetoothAdapterStateChange();
watchBLECharacteristicValueChange();
watchBLEConnectionStateChange();
}
const _getMacAddr = throttle(getMacAddr, 500);
watch(devices.value, _getMacAddr, {
deep: true,
immediate: true
});
init();
return {
openBluetoothAdapter,
stopBluetoothDevicesDiscovery,
closeBluetoothAdapter,
createBLEConnection,
closeBLEConnection,
getBLEDeviceServices,
openOrCloseDevicesDiscovery,
getBluetoothPermissions,
authorizeBluetooth,
handleToggleBluetoothDevice,
onBLECharacteristicValueChange,
bluetoothPermissions,
bluetoothAvailable,
devicesSortBySignal,
connectedDevice,
chs,
devices,
isDevtools,
connected,
discoveryStarted
};
});