蓝牙程序的调用并没有想象中跟其他接口对接那么简单,除了调用开启链接后,还需要商家蓝牙api提供的特定服务uuid以及特征码uuid才能正常进行数据交汇通信
下面简单说明下微信小程序的蓝牙调用:
1.wx.openBluetoothAdapter 初始化蓝牙
wx.openBluetoothAdapter({
success: (res) => {
wx.showLoading({
title: '蓝牙开启成功',
mask: true
})
app.globalData.reboot_ble_bool = false;
//初始化成功后开始搜索蓝牙设备
this.startBluetoothDevicesDiscovery();
},
fail: (res) => {
console.error("ble adapter open fail");
wx.hideLoading();
wx.showModal({
title: '提示',
content: '请确保设备蓝牙功能已打开,且允许微信连接蓝牙,部分机型需要授予微信定位权限',
showCancel: false,
complete: () => {
app.globalData.reboot_ble_bool = true;
//todo
wx.navigateTo({
url: '未打开蓝牙跳转界面',
});
}
});
}
})
2.wx.startBluetoothDevicesDiscovery 搜索附近蓝牙设备,获得其参数
wx.startBluetoothDevicesDiscovery({
allowDuplicatesKey: true,
success: (res) => {
console.log('startBluetoothDevicesDiscovery success', res);
//注册蓝牙设备发现事件
this.onBluetoothDeviceFound();
//设置蓝牙设备发现结束事件
setTimeout(function(){
console.log("设备搜索完成时间到了,执行停止搜索");
_this.stopBleDeviceDiscovery();
},this.data.deviceDiscoveryDuration);
},
})
- wx.onBluetoothDeviceFound 监听寻找到新设备的事件
/**
* 找到设备 回调函数
* Android 6.0以上需要手机打开定位服务 否则搜不到设备
*/
onBluetoothDeviceFound:function() {
wx.onBluetoothDeviceFound((res) => {
console.log("device number:"+res.devices.length);
//会不断出现新设备 可能需要通过rssi强度过滤
res.devices.forEach(device => {
//console.log("获得搜索蓝牙的名称:"+device.name);
//有的设备没有设备名
if (!device.name || !device.localName) {
// console.log("device name or localName is null");
return;
}
//过滤其他设备
if (this.data.deviceFilter && device.name.indexOf(this.data.devicePrefix) !== 0){
return;
}
const foundDevices = this.data.devices;
const idx = this.inArray(foundDevices, 'deviceId', device.deviceId);
const data = {};
if (idx === -1) {
data[`devices[${foundDevices.length}]`] = device;
} else {
data[`devices[${idx}]`] = device;
}
console.log(foundDevices.length);
console.log(foundDevices);
if(foundDevices.length < 1){
wx.hideLoading();
}
//把上面监听到新设备的信息显示到小程序页面端,并绑定点击按钮事件,用于连接对应蓝牙
this.setData(data);
})
});
},
4.wx.createBLEConnection 连接对应的连接低功耗蓝牙设备。
/**
* 对应设备点击事件
*/
createBLEConnection(e) {
const ds = e.currentTarget.dataset;
const deviceId = ds.deviceId;
const name = ds.name;
console.log("开始连接" + name + ":" + deviceId);
var deviceInfo={id:deviceId,name:name};
app.globalData.connectedDevice=deviceInfo;
console.log("开始连接:" + app.globalData.connectedDevice.toString);
this.stopBleDeviceDiscovery();
wx.showLoading({
title: '正在连接',
mask: true
});
var _this = this;
wx.createBLEConnection({
deviceId,
success: (res) => {
this.setData({
connected: true,
// name,
// deviceId,
})
_this.getBLEDeviceServices(deviceId);
//_this.connectComplete();
}
});
},
5.wx.getBLEDeviceServices 获取蓝牙设备所有服务(service)UUID。
这里开始对于没有接触过蓝牙的人来说可能就出现懵逼状态(比如我),前面的步骤都可以按部就班。
通过连接事件wx.createBLEConnection后,这里就会出现很多个服务UUID,我们需要根据商家提供的AIP找到需要的那个进行通信,不然选择了其他的可以连接,但无法自由收发通信。
正常来说有些商家会固定只有一个 isPrimary 为 true.但不排除有这种全为true的商家,此时我们只能根据以下两种情况进行链接:
1.固定的uuid判断,直接通过写死 用 == 来获取
2。通过特征码判断获取,这就是下面第6点
6.wx.getBLEDeviceCharacteristics 获取蓝牙设备某个服务uuid中所有特征值(characteristic)。
想要完全进行通信,必须有servuceUUID跟其下的 characteristic中的指定uuid
每个characteristic下也有多个不同的权限
wx.getBLEDeviceCharacteristics({
deviceId,
serviceId,
success: (res) => {
console.log('getBLEDeviceCharacteristics success', res.characteristics)
for (let i = 0; i < res.characteristics.length; i++) {
let item = res.characteristics[i]
if (item.properties.read) {
wx.readBLECharacteristicValue({
deviceId,
serviceId,
characteristicId: item.uuid,
})
}
console.log("!!!:" + item.uuid);
if (item.properties.write) {
this.setData({
canWrite: true,
})
this._deviceUUID = deviceId
this._serviceUUID = serviceId
this._characteristicUUID = item.uuid
}
if ((item.properties.notify || item.properties.indicate)
&& item.properties.write
&& item.properties.read) {
this._deviceUUID = deviceId;
this._serviceUUID = serviceId;
this._characteristicUUID = item.uuid;
this._writeUUID = item.uuid;
console.log("订阅设备:" + this._deviceUUID + ":" + this._serviceUUID + ":" + this._characteristicUUID);
this.connectComplete();
console.log("订阅结束:" + res.errCode);
return;
}else{
for(let l = 0; l < venderBLE.venderBLEInformation.length;l++){
if(serviceId == venderBLE.venderBLEInformation[l].SERVICE_UUID){
this._deviceUUID = deviceId;
this._serviceUUID = venderBLE.venderBLEInformation[l].SERVICE_UUID;
this._characteristicUUID = venderBLE.venderBLEInformation[l].NOTIFY_UUID; //item.uuid;
this._writeUUID = venderBLE.venderBLEInformation[l].WRITE_UUID;
this.connectComplete();
console.log("通过固定特征码跳转:" + res.errCode);
return;
}
}
}
console.log("*********");
console.log(this._deviceUUID);
console.log(this._serviceUUID);
console.log(this._characteristicUUID);
console.log("*********");
}
},
fail(res) {
console.error('getBLEDeviceCharacteristics', res)
}
});
- 重点说下:item.properties.write,
item.properties.read,
(item.properties.notify || item.properties.indicate)
每一个特征码下都要对应的功能权限,有的只能读,有的只能写。而我们要找到那个拥有notify或indicate为true的那个,同时这个具备write与read权限。如果没有只能根据商家提供的api规定来获取不同的characteristicsUUI值进行操作。(比如我现在这个蓝牙模块商家的write与read权限是分开的两个characteristicsUUID),
7.后面的wx.writeBLECharacteristicValue发送数据跟 wx.notifyBLECharacteristicValueChange与wx.onBLECharacteristicValueChange我就不详说了。主要是上面的两点UUID。只有对上了就能进行通信使用
PS: 根据官方文档,目前貌似依旧只能支持低功耗蓝牙模块,也就是说。我们手机开启的蓝牙功能使用该程序来搜索,是搜索不到的。