uni.openBluetoothAdapter({
// 蓝牙初始化成功执行
success:(res)=>{
// 这里成功之后就不用管了,直接执行就行
},
// 蓝牙初始化失败执行
fail:(err)=>{
// 初始化失败之后有需求的话可以进行一些处理
// 没有需求的也不用管
// 一般情况下,还是需要分析一下原因的,这用用户和自己就知道为什么失败了
if(err.errCode == 10001){
// 这种情况是未打开蓝牙 就需要提示用户检测蓝牙并打开
uni.showToast({
title: "请检查蓝牙是否开启!",
icon: "none",
duration: 2000,
});
}
// 我这里只演示这一个,其他的状态可进入官网进行查看
// uni-app https://uniapp.dcloud.io/api/system/bluetooth.html
// 微信原生 https://developers.weixin.qq.com/miniprogram/dev/api/device/bluetooth/wx.openBluetoothAdapter.html
}
})
uni.startBluetoothDevicesDiscovery({
success:()=>{
// 调用成功之后就开始查询附近蓝牙了
// 成功之后可调用这个函数,每次查询到新的蓝牙设备就会调用
// 这个函数使用不使用都可以,不影响查询的结果
uni.onBluetoothDeviceFound((devices)=>{
console.log(devices) // 蓝牙设备信息
// 返回的数据是ArrayBuffer格式的需要进行转换,不然咱也看不懂都是些啥
// ArrayBuffer 的转换后面会详细写出来
})
// 接着进行 成功之后建议等个几秒钟之后再获取查询到的列表
// 我这里就是用定时器做了一个两秒的延迟
setTimeout(()=>{
uni.getBluetoothDevices({
success:(res)=>{
// res.devices 为 查询到的蓝牙设备列表
// 拿到结果之后,进行处理
// 首先进行过滤一下查询的列表,会出现很多未知设备这类的,这里就直接把它们给排除掉了,只留下有完整名称的设备
var arr = []
res.devices.forEach((element)=>{
if(element.name !== "位置设备") {
arr.push(element)
}
})
// 筛选之后在进行判断是否有正常的蓝牙设备
// 当然你也可以查看一下被筛选掉的设备是否有你所使用的设备,如果有你可以去掉筛选 或者自己定义筛选条件
if(arr.length == 0){
uni.showToast({
title: "未查询到可用设备,请重新扫描",
duration: 1000,
icon: "none",
});
}
// 最后这个arr就是所查到的列表
console.log(arr)
// 不管查没查到一定要使用 stopBluetoothDevicesDiscovery 停止查询
// 不管查没查到一定要使用 stopBluetoothDevicesDiscovery 停止查询
// 不管查没查到一定要使用 stopBluetoothDevicesDiscovery 停止查询
uni.stopBluetoothDevicesDiscovery()
}
})
},2000)
}
})
// 为了能否顺利的连接蓝牙 可以先查询一下是否有设备已经连接蓝牙了
// 手环这一类的设备 可能会对程序造成干扰 会一直显示设备已经连接
uni.getConnectedBluetoothDevices({
success:(res)=>{
// 因为我为了蓝牙的连接的稳定性,就做了这一步
// 大家使用的过程中可以省略这一步直接进行蓝牙设备
// 但是不确定是否可以正常进行蓝牙连接, 大家可以尝试一下
// 如果返回的列表不等于空,就代表已经有设备连接
if(res.devices.length !== 0) {
// 这里就需要提示用户蓝牙已连接
uni.showModal({
title: "提示!",
content: "当前蓝牙已于id为"+res.devices[0].deviceId+"的设备连接,是否断开连接",
success: (row)=>{
// 用户点击确定执行
if (row.confirm) {
// 用户点击确定之后把当前连接的蓝牙断开
uni.closeBLEConnection({
// 一定要传入当前连接蓝牙的deviceId
deviceId: deviceId,
success:()=>{
// 到这里就已经断开成功了,再次点击就可以进行连接了
uni.showToast({
title: "连接已断开!",
icon: "none",
duration: 2000,
});
},
fail:(err)=>{
// 走到这就是断开失败了,可以进行操作提示用户或者自己查看
uni.showToast({
title: err.errMsg,
icon: "none",
duration: 2000,
});
}
})
}else{
// 用户取消之后不需要做任何操作
console.log('用户点击了取消')
}
}
});
}else {
// 当前未处于已连接状态就开始进行连接,没有连接的情况下就可以直接连接蓝牙
uni.createBLEConnection({
// 连接的时候一定传入要连接蓝牙的deviceId
deviceId:deviceId,
// 这里可以选择设置一个延迟,如果延迟时间过了没有连接成功就直接提示报错
timeout:5000,
success:(res)=>{
// 连接成功之后可以再次进行查询一下当前连接的蓝牙信息,保存下载,后面方便使用
uni.getConnectedBluetoothDevices({
success:(devicess)=>{
// devicess就是当前已经连接的蓝牙列表
// 在这判断一下有没有蓝牙,如果有就证明确实已经连接成功
if(devicess.devices[0]){
// 到这里就可以提示用户成功,并且吧蓝牙信息保存下来方便后面使用
console.log(devicess.devices[0]) // 蓝牙信息
}else {
// 如果走这里面就是没有蓝牙设备,就要查看一下,看看是否真的连接成功了
}
}
})
},
fail:(err)=>{
// 在这里查看连接失败的信息,判断为什么连接失败
console.log(err)
}
})
}
}
})
// 蓝牙接收数据主要使用的api是开启监听(uni.notifyBLECharacteristicValueChange)
// 但是开启监听是需要几个特殊的值才能开启
// 所以开启之前我们需要获取这个值
// deviceId 蓝牙deviceId,蓝牙信息中包含的有
// serviceId 蓝牙服务值,根据蓝牙deviceId获取
// characteristicId 蓝牙特征值 根据serviceId 获取
// 首先根据deviceId 获取到服务值 serviceId
uni.getBLEDeviceServices({
deviceId:deviceId, // 获取服务值,需要传入deviceId
success:(res)=>{
// res.services 返回一个数组,里面包含着支持不同的通讯方式的serviceId 一般为三个左右,也有可能更多
console.log(res.services)
// 拿到之后根据自己所需要的去保存serviceId,在后面使用
// 这里建议多试试,说不定那个可以用,又或者某个不能用
// 获取到之后就可以去拿着获取到的serviceId和deviceId去获取特征值
uni.getBLEDeviceCharacteristics({
deviceId:deviceId, // 传入获取到的deviceId
serviceId:serviceuuid, // 传入获取到的serviceuuid
success:(ress)=>{
// ress里面就是获取到的蓝牙特征值
// 注意:根据传入serviceuuid的不同获取到的特征值也是不一样的,
// 特征值分为,可读、可写、可通知等几个类型的,根据自己想要的操作选择特征值
console.log.(res.characteristics)
},
fial:(err)=>{
// 一般来说只要参数对,就不会报错
}
})
},
fial:(err)=>{
// 一般来说只要 deviceId 对,就不会报错
}
})
// 这里所声明介绍一下所用到的东西
// deviceId 就是上面蓝牙设备的deviceId
// serviceuuid 就是上面根据蓝牙设备获取到的serviceuuid
// characteristics 就是上面根据 deviceId 和 serviceuuid 获取到的
// characteristics 是一个数组里面包含着多个特征值, 根据使用去拿响应的特征值
// 我这里没有直接使用,而是进行一个循环判断,判断这么多的特征值中那个是符合要求的
var characteristicId;
var i = 0
then.characteristiclist.forEach((element) => {
if (element.properties.notify == true) {
if (i == 0) {
characteristicId = element.uuid;
i++;
}
}
});
// 为什么循环
// 因为开启uni.notifyBLECharacteristicValueChange需要特征值是需要固定的,我就直接判断写入了
uni.notifyBLECharacteristicValueChange({
deviceId: deviceId,
serviceId: serviceuuid,
characteristicId: characteristicId,
state: true,
success: () => {
console.log('监听启动成功');
// 启用成功之后就可以在uni.onBLECharacteristicValueChange 中获取到蓝牙设备发送的数据
},
});
uni.onBLECharacteristicValueChange((res)=>{
console.log(res.value)
// 这就是蓝牙发送的数据 但是现在的数据,还不能直观的看出来是什么,还需要进行一些列转换才能直观查看
console.log(this.buf2str(res.value))
// 经过 this.buf2str 转换之后就可以直观查看 蓝牙返回的信息
})
// 所用到的就是上面获取到的
// 但是特征值跟上面不一样,需要支持可写
var characteristicId;
var i = 0;
then.characteristiclist.forEach((element) => {
if (element.properties.write == true) {
if (i == 0) {
characteristicId = element.uuid;
i++;
}
}
});
uni.writeBLECharacteristicValue({
deviceId: deviceId,
serviceId: serviceuuid,
characteristicId: characteristicId,
value: this.string2buffer(row),
success: () => {
// console.log('指令写入成功');
// 写入成功之后在onBLECharacteristicValueChange里面应该是有反馈的
}
})
// this.string2buffer 把16进制字符串转换成buffer之后进行写入,我也忘了直接传入字符串可不可以使用,应该是不行,可以尝试一下,不行就按着我的来也行
// 因为我所写入的指令带有一些特殊字符,我是手动转成16进制之后在进行的转换ArrayBufer
// 如果需要直接字符串转ArrayBufer,百度一下你就知道
// 将16进制字符串转换成ArrayBufer
string2buffer (str) {
return new Uint8Array(
str.match(/[\da-f]{2}/gi).map(function (h) {
return parseInt(h, 16);
})
).buffer;
}
// ArrayBufer 转字符串
buf2str (buffer) {
let encodedString = String.fromCodePoint.apply(
null,
new Uint8Array(buffer)
);
let decodedString = decodeURIComponent(escape(encodedString));
//没有这一步中文会乱码
return decodedString;
},