前言
目前主流蓝牙设备都是使用原生APP进行连接,因此官方对蓝牙API的改进比较少,在iOS设备上还存在很多小问题,而在Android设备上根据官方文档基本没有问题。 。 而众所周知,作为一个小公司,不可能花两笔钱来开发APP。 话不多说,这里主要说一下我在开发中是如何解决这个问题的。
1.微信小程序蓝牙如何工作?
2.使用步骤1.代码
1.代码不多说了微信小程序 连接网站,首先是初始化蓝牙适配器,获取蓝牙状态,开始扫描外围设备:
/**
* 开启蓝牙适配器
* 获取蓝牙适配器的状态
* 开启蓝牙扫描外围设备
* 监听蓝牙扫描到的设备
*/
openBluetoothAdapter(){
let that = this
wx.openBluetoothAdapter({
success(res){
// console.log("n成功打开adapter")
wx.getBluetoothAdapterState({
success: (res) => {
if(res.available){
if(res.discovering){
that.onBluetoothDeviceFound()
}else{
wx.startBluetoothDevicesDiscovery({
//过滤serviceId
services:["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"],
//允许重复名字的设备
allowDuplicatesKey: true,
success(){
// console.log("n开启扫描成功")
that.onBluetoothDeviceFound()
}
})
}
}
},
})
}
})
},
2.开启设备扫描和窃听:
/**
* 将扫描到的设备存起来
*/
onBluetoothDeviceFound() {
let that = this
wx.onBluetoothDeviceFound((res) => {
res.devices.forEach(device => {
if (!device.name && !device.localName) {
//将没有名字的设备命名为了“未知设备”
device.name = '未知设备'
// return
}
const foundDevices = that.data.devices
//console.log(foundDevices)
const idx = that.inArray(foundDevices,'deviceId',device.deviceId)
const data = {}
if (idx === -1) {
//新设备,直接存起来
data[`devices[${foundDevices.length}]`] = device
} else {
//老设备覆盖一遍
data[`devices[${idx}]`] = device
}
// console.log(data)
that.setData(data)
})
})
},
3、点击连接指定设备,同时开启设备连接状态监听,随时获取连接状态,及时响应:
/**
* 点击连接设备
* @param {点击事件} e
*/
tapToCreatBLEConnection(e){
let that = this
//防止连接多个设备,导致通信干扰
if(that.data.connected){
wx.showToast({
title: '已连接到设备,若要切换设备请断开当前设备',
icon: 'none',
duration:2000
})
}else{
const ds = e.currentTarget.dataset
const deviceId = ds.deviceId
const name = ds.name
wx.createBLEConnection({
deviceId,
success: (res) => {
that.getBLEDeviceServices(deviceId)
//监听蓝牙设备是否掉线
wx.onBLEConnectionStateChange((res) => {
if(!res.connected){
that.setData({
//相关操作
connected: false,
})
}
})
that.stopBluetoothDevicesDiscovery()
}
})
}
},
4、获取设备服务列表:
/**
* 获取设备的服务列表
* @param {设备id} deviceId
*/
getBLEDeviceServices(deviceId) {
//获取服务列表
wx.getBLEDeviceServices({
deviceId,
success: (res) => {
for (let i = 0; i < res.services.length; i++) {
if (res.services[i].isPrimary) {
//获取服务权限并进行相应操作
this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid)
return
}
}
}
})
},
5、获取特征值,并开启监听特征值变化,保证第一时间获取数据:
/**
* 获取设备的特征值、监听特征值变化,保证第一事件获取数据
* @param {设备id} deviceId
* @param {服务id} serviceId
*/
getBLEDeviceCharacteristics(deviceId, serviceId) {
let that = this
//获取服务具体权限
wx.getBLEDeviceCharacteristics({
deviceId,
serviceId,
success: (res) => {
device_data.deviceId = deviceId
device_data.serviceId = serviceId
let item = res.characteristics[0]
device_data.characteristicId = item.uuid
//读取数据
wx.readBLECharacteristicValue({
deviceId,
serviceId,
characteristicId: item.uuid,
})
//开启notify
wx.notifyBLECharacteristicValueChange({
deviceId,
serviceId,
characteristicId: item.uuid,
state: true,
success:function(res){
// console.log("开启notify成功n")
}
})
},
fail(res) {
console.error('getBLEDeviceCharacteristics', res)
}
})
// 操作之前先监听,保证第一时间获取数据
wx.onBLECharacteristicValueChange((characteristic) => {
//接收数据并进行存储
})
},
6. 发送数据时,提供ArrayBuffer和字符串之间转换的函数。 我找了很久了:
/**
* ArrayBuffer转字符串
* @param {接收到的arrayBuffer} arrayBuffer
*/
function ab2str(arrayBuffer){
let unit8Arr = new Uint8Array(arrayBuffer);
let encodedString = String.fromCharCode.apply(null, unit8Arr);
return encodedString;
}
/**
* 将要发送的str转换成ArrayBuffer
* @param {需要发送的str} str
*/
function str2ab(str){
var buf = new ArrayBuffer(str.length)// 每个字符占用2个字节
var bufView = new Uint8Array(buf)
for (var i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i)
}
return buf
}
/**
* 发送数据
*/
bindSentMessage(){
wx.writeBLECharacteristicValue({
deviceId: device_data.deviceId,
serviceId: device_data.serviceId,
characteristicId: device_data.characteristicId,
value: buff,//发送的数据,要是ArrayBuffer类型的
})
},
2、iOS无法扫描设备名称的解决方法
经过多次测试发现,部分设备的芯片型号和蓝牙合约的差异会导致iOS设备很难获取设备名称,无论是name还是LocalName。 我问过官方,官方不会说答案。 说出来和不说是一样的。 LocalName是包含在广播数据中的数组。 我认为解析可能有问题。 想到官方API里好像还有其他几个广播数组,就全部复制了,发现不仅serviceId有东西,其他的都是空的。 官方API没办法改变,所以先从名字开始吧。 name的数组只有在设备连接后才会获取到,所以我想到了一个很笨的办法:通过serviceId过滤蓝牙设备,然后将设备列表中的所有设备一起列出来。 一旦建立连接微信小程序 连接网站,就会断开连接并再次扫描。 就算伤心,问题解决了,还是等官方API建立吧。 (其实可能有掠夺者知道还有其他解决办法,希望看到这篇文章的掠夺者能够热心给我指点)
评论
代码中混杂了很多业务逻辑,因为涉及到公司的保密义务,还好,所以如果要复制粘贴代码,就会出现很大的问题。 (/剥皮)