uniapp 封装蓝牙(蓝牙和设备连接过程)
注意事项:
1、关键点:
初始化蓝牙——》 uni.openBluetoothAdapter
获取本机蓝牙适配器状态——》uni.getBluetoothAdapterState
开始搜索蓝牙设备——》uni.startBluetoothDevicesDiscovery
监听蓝牙设备(或者蓝牙设备列表,找到需要的那个)——》uni.onBluetoothDeviceFound(设备列表在回调函数中)
连接蓝牙——》uni.createBLEConnection
获取服务对应的uuid——》 uni.getBLEDeviceServices
获取指定服务对应的特征值——》 uni.getBLEDeviceCharacteristics
监听蓝牙连接状态——》 uni.notifyBLECharacteristicValueChange
发送指令 ——》uni.writeBLECharacteristicValue (必须设备的特征值支持 write 才可以成功调用,value是buffer类型的二进制类型;每次只能接受20字节的数据包,大于20字节的需要分包然后循环发生指令,注意延时!否则不成功)
指令发送成功后监听数据回传———》uni.onBLECharacteristicValueChange(回调函数返回蓝牙设备信息,主要是value值,且是buffer类型,需要转为16进制数据才可打印出具体数值。再根据16进制的数据进行对应解码)
2、具体实现过程(这里没有调用服务id,因为需要连接的蓝牙设备返回值中有服务id,直接用)
封装mixins中的bluetooth.js
import {
getLockInstructApi
} from '@/api/isolated/process/index.js'
let lock = null
import crypto from '@/utils/crypto.js'
export default {
data() {
return {
unLockType:0, //1蓝牙开锁、2网关开锁
list:[], // 已搜索到的蓝牙设备
adapterState:[],// 适配器状态
isLock: false, //是否开锁。蓝牙开锁出现问题重试
isConnect: false, //是否连接锁成功
deviceId: '', //锁的mac地址
JudegeDeviceId:'F6980DB69313', // 匹配要连接蓝牙用的设备id F6980DB69313 EC8275CE0A00
locktimer: null, //搜索锁的计时器
serviceId: '', // uuid
characteristicId:[] ,// 特征值集合
loadingText:'正在连接蓝牙...',
backData:[], // 蓝牙返回的数据集合
orderType:1 // 命令
}
},
created() {
lock = this
this.getLockMacAddress();
},
watch:{
backData:{
handler(newVal){
let result = '';
for (let i = 0; i < newVal.length; i++) {
newVal[i] = newVal[i].slice(2, newVal[i].length);
result += newVal[i];
}
console.log('结果 result',result);
if(result.length){
console.log('指令类型',this.orderType);
this.decryptionResult(result);
}
},
deep:true
}
},
methods: {
// ArrayBuffer转16进度字符串
ab2hex(buffer) {
const hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function(bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('')
},
// 生成buffer
getBuffer(str) {
let arr = []
for (let i = 0; i < str.length; i++) {
if ((i + 1) % 2 == 0) {
arr.push('0x' + str[i - 1] + str[i])
}
}
// console.log('字节长度',arr.length);
const buffer = new ArrayBuffer(arr.length)
const dataView = new DataView(buffer)
arr.forEach((item, i) => {
dataView.setUint8(i, item)
})
return buffer
},
// 初始化蓝牙
openBluetoothAdapter() {
this.unLockType = 1;
uni.openBluetoothAdapter({
success(res) {
lock.isConnect = false
lock.isLock = false
lock.getBluetoothAdapterState();
},
fail(e) {
uni.hideLoading();
lock.unLockType = 0;
if (e.errCode !== 0) {
initTypes(e.errCode,e.errMsg);
}
}
})
},
//获取本机蓝牙适配器状态
getBluetoothAdapterState() {
uni.getBluetoothAdapterState({
success: res => {
console.log('获取本机蓝牙适配器状态',JSON.stringify(res));
lock.adapterState = res;
lock.findBluetooth()
},
fail: e => {
this.unLockType = 0;
if (e.errCode !== 0) {
initTypes(e.errCode);
}
}
});
},
// 开始搜寻附近的蓝牙
findBluetooth() {
uni.showLoading({
title: lock.loadingText,
mask: true
});
uni.startBluetoothDevicesDiscovery({
success(res) {
// 开启监听回调
uni.onBluetoothDeviceFound(lock.watchNewBluetooth)
lock.locktimer = setTimeout(() => {
uni.showToast({
title: '未找到设备,请重试!',
icon: 'none',
duration: 1000,
complete: function() {
uni.stopBluetoothDevicesDiscovery()
}
});
}, 1000 * 60)
},
fail(e) {
uni.hideLoading();
if (e.errCode !== 0) {
initTypes(e.errCode);
}
}
})
},
//监听附近设备
watchNewBluetooth(res) {
res.devices.forEach(device => {
let mac = ''
for (let s of device.deviceId) {
if (s !== ':') mac += s
}
if (mac.indexOf(lock.JudegeDeviceId)>-1) {
console.log('找到了 mac',mac);
lock.serviceId = device.advertisServiceUUIDs?device.advertisServiceUUIDs[0] : '';
lock.deviceId = device.deviceId.toString()
lock.createBLEConnection();
uni.stopBluetoothDevicesDiscovery()
clearTimeout(lock.locktimer)
return
}
})
},
// 连接蓝牙
createBLEConnection() {
uni.createBLEConnection({
deviceId: lock.deviceId,
timeout: 1000 * 60,
success(res) {
// 需要延迟
setTimeout(() => {
// 知道服务和特征值,直接监听
// lock.notifyBLECharacteristicValueChange()
// 获取服务,再获取特征值,这里写死,就不用再获取
// lock.getServices()
lock.getCharacteristics() // 获取特征值
}, 6000)
// 关闭搜索
},
fail(e) {
uni.hideLoading();
if (e.errCode !== 0) {
initTypes(e.errCode);
}else{
uni.$u.toast('连接蓝牙失败,请重试!')
}
}
})
},
// 获取蓝牙服务
getServices() {
uni.getBLEDeviceServices({
deviceId:lock.deviceId,
success(res) {
lock.serviceId = res.services?res.services[0]['uuid'] : '';
// lock.serviceId='0000ff01-0000-1000-8000-00805f9b34fb'//这里返回设备服务uuid
lock.getCharacteristics();
},
fail(err) {
uni.$u.toast('连接蓝牙服务失败,请重试!')
uni.hideLoading();
}
})
},
// 获取特征值
getCharacteristics() {
uni.getBLEDeviceCharacteristics({
deviceId:lock.deviceId, // 设备ID C10101010C1A
serviceId:lock.serviceId, // 服务UUID
success(res) {
console.log('获取特征值',res);
lock.characteristicId = res.characteristics || [];
lock.notifyBLECharacteristicValueChange()
lock.loadingText = '蓝牙开锁中,请稍后...';
},
fail(err) {
uni.$u.toast('连接蓝牙特征失败,请重试!')
}
})
},
// 开启监听
notifyBLECharacteristicValueChange() {
uni.notifyBLECharacteristicValueChange({
deviceId: lock.deviceId, // 设备id
serviceId: lock.serviceId, // 监听指定的服务
characteristicId: lock.characteristicId?lock.characteristicId[0]['uuid']:'', // 监听对应的特征值
success(res) {
// uni.hideLoading()
lock.isConnect = true
uni.$u.toast('蓝牙连接成功!')
},
fail(e) {
uni.hideLoading();
if (e.errCode !== 0) {
initTypes(e.errCode);
}else{
uni.$u.toast('监听蓝牙失败,请重试!')
}
}
})
},
// 接收数据 监听低功耗蓝牙设备的特征值变化
onBLECharacteristicValueChange(type) {
uni.onBLECharacteristicValueChange(res => {
lock.unLockType = 0; // 接收到数据了,取消按钮loading
const data = lock.ab2hex(res.value);
const code = data.slice(0, 2);
console.log('接收数据=',data);
if(lock.backData.indexOf(data) == -1){
lock.backData.push(data);
}
},err=>{
console.log('获取失败了',err)
})
},
// 获取指令
getLockInstruct() {
// _type: 1 读取门锁信息 2初始化锁 3开锁
const orders = ['010200107d9a0538979e7bc6c2a731c9622a82b2','028b000000000000000000000000000000000000']
const order = ['0101000803795A5B33E0E7AEE100000000000000']; //
if(!this.deviceId) return uni.$u.toast('请先连接蓝牙锁')
try {
// 开启按钮loading
lock.unLockType = 1;
// 获取指令
// const get_order = await getLockInstructApi(lock.orderType)
// 发送指令
lock.sendInstruct(order,_type);
uni.hideLoading();
} catch (e) {
uni.hideLoading();
uni.$u.toast('开锁失败,请扫码重试!',e)
}
},
// 向蓝牙发送指令
async sendInstruct(obj,_type) {
// 必须设备的特征值支持 write 才可以成功调用
let idx = -1;
while(idx<obj.length-1){
idx += 1;
await lock.sendDelay(150,lock.getBuffer(obj[idx])).then(buffer=>{
uni.writeBLECharacteristicValue({
deviceId: lock.deviceId,
serviceId: lock.serviceId,
characteristicId: lock.characteristicId?lock.characteristicId[1]['uuid'].toLowerCase():'', //向蓝牙写数据的特征值,文档要求不一样
value: buffer,
success(res) {
lock.unLockType = 0;
lock.onBLECharacteristicValueChange(_type); // 指令发送成功后监听数据回传
console.log('指令发送成功后监听数据回传');
},
fail(err) {
if (err.errCode !== 0) {
initTypes(err.errCode);
}
},
complete(err) {
lock.unLockType = 0;
console.log('指令发送结果',err);
if (err.errCode !== 0) {
initTypes(err.errCode);
}
}
})
})
}
},
// 延时函数
sendDelay(delay, buffer) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(buffer), delay);
})
},
// 断开蓝牙
closeBLEConnection() {
uni.hideLoading();
uni.closeBLEConnection({
deviceId: lock.deviceId,
success(res) {
lock.unLockType = 0;
lock.isLock = false
lock.deviceId = '' //清楚mac地址
lock.isConnect = false //未连接
lock.backData = [];
uni.closeBluetoothAdapter()
clearTimeout(lock.locktimer)
},
fail(err) {
clearTimeout(lock.locktimer)
}
})
},
// 获取锁具mac地址
getLockMacAddress(){
// this.JudegeDeviceId = ''
},
// 获取锁具状态(isUnLock:是否直接开锁)
async getLockStatus(isUnLock){
const result = await this.getLockInstruct(1);
if(isUnLock){ // 锁具状态关闭且需要打开时执行(锁具状态:result)
this.bluetoothUnLocking();
}else{
console.log('锁具状态 toast:',result);
}
},
// 蓝牙开锁
async bluetoothUnLocking(){
lock.orderType = 3;
await this.getLockInstruct();
},
// 获取解密结果
decryptionResult(obj){
console.log('解密参数',obj);
}
},
}
/**
* 判断初始化蓝牙状态
*/
function initTypes(code, errMsg) {
switch (code) {
case 10000:
uni.$u.toast('未初始化蓝牙适配器');
break;
case 10001:
uni.$u.toast('未检测到蓝牙,请打开蓝牙重试!');
break;
case 10002:
uni.$u.toast('没有找到指定设备');
break;
case 10003:
uni.$u.toast('连接失败');
break;
case 10004:
uni.$u.toast('没有找到指定服务');
break;
case 10005:
uni.$u.toast('没有找到指定特征值');
break;
case 10006:
uni.$u.toast('当前连接已断开');
break;
case 10007:
uni.$u.toast('当前特征值不支持此操作');
break;
case 10008:
uni.$u.toast('其余所有系统上报的异常');
break;
case 10009:
uni.$u.toast('Android 系统特有,系统版本低于 4.3 不支持 BLE');
break;
case 10013:
uni.$u.toast('连接 deviceId 为空或者是格式不正确');
break;
default:
uni.$u.toast(errMsg);
}
}
3、调用
本文来自博客园,作者:小虾米吖~,转载请注明原文链接:https://www.cnblogs.com/LindaBlog/p/18293765