支付宝小程序:开放平台-官方文档地址:https://docs.alipay.com/mini/api/bluetooth-api#a-namegfgkonamyopenbluetoothadapter
微信小程序:公众平台-官方文档地址:https://developers.weixin.qq.com/miniprogram/dev/api/wx.closeBluetoothAdapter.html
支付宝小程序
介绍
依次用到了支付宝小程序提供的这几个接口:(已知服务id和特征id的情况)
- 初始化蓝牙模块:
my.openBluetoothAdapter
。可在页面加载的时候调用 - 关闭蓝牙模块:
my.closeBluetoothAdapter
。可在初始化失败(可能蓝牙未打开)的时候调用 - 开始搜寻附近的蓝牙外围设备:
my.startBluetoothDevicesDiscovery
。初始化完成或点击事件里调用,搜寻到设备或超时时记得停止搜寻 - 停止搜寻附近的蓝牙外围设备:
my.stopBluetoothDevicesDiscovery
。搜索到设备或请求超时时调用 - 监听搜索到新蓝牙设备时事件:
my.onBluetoothDeviceFound
。搜索到时记得移除事件监听 - 移除寻找到新的蓝牙设备事件的监听:
my.offBluetoothDeviceFound
。搜索到设备时调用 - 连接蓝牙设备:
my.connectBLEDevice
。放在监听事件的回调函数里 - 断开连接:
my.disconnectBLEDevice
。特定事件调用 - 向蓝牙设备特征值中写入数据:
my.writeBLECharacteristicValue
。搜寻到指定设备,获取到(或有指定的)serverId 和 characteristicId 时调用 - 读取蓝牙设备特征值中的数据:
my.readBLECharacteristicValue
。搜寻到指定设备,获取到(或有指定的)serverId 和 characteristicId 时调用
在不清楚服务id和特征id值的情况、或在调试阶段,可使用的接口:获取蓝牙设备所有 service(服务) my.getBLEDeviceServices
、获取蓝牙设备所有 characteristic(特征值) my.getBLEDeviceCharacteristics
。记住这个顺序:用macId或蓝牙名去匹配蓝牙,在蓝牙连接成功时会获得deviceId,用deviceId去获取想要的serverId,用deviceId和serverId去获取想要的characteristicId,再用这三个id去读/写数据。
代码示例
此示例中的服务id和特征值id为固定值,所以没有去主动获取。如果需要获取可在连接成功时调用相应接口
axml文件:
<button type="default" size="defaultSize" onTap="searchBluetooth"> 搜索蓝牙设备 </button>
<button type="default" size="defaultSize" onTap="disconnectBLEDevice"> 断开连接 </button>
<button type="default" size="defaultSize" onTap="writeBluetoothData1"> 执行1操作 </button>
<button type="default" size="defaultSize" onTap="writeBluetoothData2"> 执行2操作 </button>
js文件:
Page({
data: {
deviceId: "", //设备id
serviceId: "abc0", //固定的服务id
characteristicId: "abc1", //固定的特征值id-1
randomCharacteristicId: "FFF2" //固定的特征值id-2
},
onLoad() {
var that = this;
my.openBluetoothAdapter({ //初始化蓝牙模块
success: (res) => {
that.searchBluetooth(); //开始搜索蓝牙设备
},
fail:(res) => {
console.log("------初始化蓝牙模块失败!!------");
my.alert({ content: "请开启手机蓝牙后再试!" });
}
});
},
//移除事件监听
onUnload() { my.offBluetoothDeviceFound(this.callback); },
searchBluetooth: function(){ //开始搜索蓝牙设备
var that = this;
my.startBluetoothDevicesDiscovery({
services: [],
success: (res) => {
my.showLoading({ content: '正在搜索蓝牙设备' });
//搜索到蓝牙事件监听
that.callback = that.callback.bind(that);
my.onBluetoothDeviceFound(that.callback);
//5s内未搜索到设备,关闭搜索,关闭蓝牙模块
setTimeout(function(){
if (!that.data.deviceId){
my.hideLoading();
my.showToast({ type: 'exception', content: '搜索设备超时', duration: 3000 });
console.log("搜索设备超时");
my.stopBluetoothDevicesDiscovery({}); //关闭搜索
my.offBluetoothDeviceFound(that.callback); //移除搜索设备监听
my.closeBluetoothAdapter({}); //关闭蓝牙模块
}
}, 5000);
},
fail:(res) => {
console.log("-------调用搜寻蓝牙设备失败--------");
}
});
},
callback(res) { //新搜索到设备的回调函数(通过蓝牙名去匹配)
var deviceObj = res.devices[0]; //{"deviceId": "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "RSSI": -83, "manufacturerData": "", "deviceName": "ABCDEFG", "advertisData":"", "localName": "ABCDEFG", "name": "ABCDEFG"}
var name = deviceObj.name || deviceObj.deviceName;
if(name && name === "13579"){ //搜索到的目标蓝牙设备信息
my.stopBluetoothDevicesDiscovery({}); //关闭搜索
my.offBluetoothDeviceFound(this.callback); //移除搜索设备监听
this.setData({ deviceId: deviceObj.deviceId }); //存储目标蓝牙设备id
this.connectBLEDevice(); //去连接蓝牙设备
}
},
connectBLEDevice: function(){ //连接低功耗蓝牙设备
var that = this;
var deviceId = that.data.deviceId;
my.connectBLEDevice({
deviceId: that.data.deviceId,
success: (res) => {
console.log("蓝牙连接成功");
my.hideLoading();
},
fail:(res) => {}
});
},
disconnectBLEDevice: function(){ //断开与低功耗蓝牙设备的连接
var that = this;
my.disconnectBLEDevice({
deviceId: that.data.deviceId,
success: (res) => {
console.log("已断开连接!!");
},
fail:(res) => {}
});
},
writeBluetoothData1: function(){ //写入执行1指令
var that = this;
my.writeBLECharacteristicValue({
deviceId: that.data.deviceId,
serviceId: that.data.serviceId,
characteristicId: that.data.characteristicId,
value: "123456789"
});
},
writeBluetoothData2: function(){ //写入执行2指令
var that = this;
my.writeBLECharacteristicValue({
deviceId: that.data.deviceId,
serviceId: that.data.serviceId,
characteristicId: that.data.characteristicId,
value: "987654321"
});
}
});
微信小程序
介绍
用法与支付宝小程序基本相同,几点不同如下:
- 没有 移除寻找到新的蓝牙设备事件的监听 方法;
- 连接蓝牙设备后返回的服务id和特性值id与支付宝的不同,是一个很长的字符串(我这里先去获取了服务id和特性值id,然后将它们做了个存储,方便后续使用);
- 读取蓝牙设备特征值中的数据 接口,返回的是一个二进制数据。使用的时候需做下处理,且要在wx.onBLECharacteristicValueChange方法回调中接收数据;
- 向蓝牙设备特征值中写入数据 接口,需写入二进制数据。需转换数据格式后再写入。
依次用到了微信小程序提供的这几个接口:
- 初始化蓝牙模块:
wx.openBluetoothAdapter
。可在页面加载的时候调用; - 关闭蓝牙模块:
wx.closeBluetoothAdapter
; - 开始搜寻附近的蓝牙外围设备:
wx.startBluetoothDevicesDiscovery
。初始化完成或点击事件里调用,搜索并连接到设备后记得停止搜寻; - 停止搜寻附近的蓝牙外围设备:
wx.stopBluetoothDevicesDiscovery
。已经找到需要的蓝牙设备并不需要继续搜索时调用; - 监听寻找到新设备的事件:
wx.onBluetoothDeviceFound
; - 连接蓝牙设备:
wx.createBLEConnection
; - 断开连接:
wx.closeBLEConnection
; - 获取蓝牙设备所有服务(service):
wx.getBLEDeviceServices
; - 获取蓝牙设备某个服务中所有特征值(characteristic):
wx.getBLEDeviceCharacteristics
; - 向蓝牙设备特征值中写入二进制数据:
wx.writeBLECharacteristicValue
。搜寻到指定设备,获取到(或有指定的)serverId 和 characteristicId 时调用 - 读取蓝牙设备特征值中的二进制数据值:
wx.readBLECharacteristicValue
。读取到的信息需要在 onBLECharacteristicValueChange 方法注册的回调中获取。
代码示例
axml文件:
<button type="default" size="defaultSize" bindtap="startBluetoothDevicesDiscovery"> 搜索蓝牙设备 </button>
<button type="default" size="defaultSize" bindtap="closeBLEConnection"> 断开连接 </button>
<button type="default" size="defaultSize" bindtap="writeBluetoothData1"> 执行1操作 </button>
<button type="default" size="defaultSize" bindtap="writeBluetoothData2"> 执行2操作 </button>
js文件:
Page({
data: {
deviceId: "" //设备id
},
onLoad() {
var that = this;
wx.openBluetoothAdapter({ //初始化蓝牙模块
success: (res) => {
that.startBluetoothDevicesDiscovery(); //开始搜索蓝牙设备
},
fail: (res) => {
console.log("------初始化蓝牙模块失败!!------");
wx.showLoading({ title: '请打开蓝牙', icon: 'loading', duration: 3000 })
}
});
},
//当退出页面,断开蓝牙连接
onUnload() {
wx.closeBLEConnection({
deviceId: this.data.deviceId,
success(res) { }
})
},
startBluetoothDevicesDiscovery: function(){ //开始搜索蓝牙设备
var that = this;
wx.startBluetoothDevicesDiscovery({
allowDuplicatesKey: true,
services: [],
success: (res) => {
//搜索到新的蓝牙设备时触发事件
that.callback = that.callback.bind(that);
wx.onBluetoothDeviceFound(that.callback);
//5s内未搜索到设备,关闭搜索,关闭蓝牙模块
setTimeout(function () {
if (!that.data.deviceId) {
that.setData({ hiddenLoading: true });
wx.showToast({title: '搜索设备超时',duration: 3000 })
console.log("搜索设备超时");
wx.stopBluetoothDevicesDiscovery({}); //关闭搜索
wx.closeBluetoothAdapter({}); //关闭蓝牙模块
}
}, 5000);
},
fail: (res) => { }
});
},
callback(res) { //新搜索到设备的回调函数(通过mac地址去匹配)
var deviceObj = res.devices[0];
if (this.data.mac.toLowerCase() === deviceObj.manufacturerData.toLowerCase()) {
wx.stopBluetoothDevicesDiscovery({}); //关闭搜索
this.setData({ deviceId: deviceObj.deviceId }); //存储目标蓝牙设备id
this.connectBLEDevice(); //去连接蓝牙设备
}
},
connectBLEDevice: function(){ //连接低功耗蓝牙设备
var that = this;
var deviceId = that.data.deviceId;
wx.createBLEConnection({
deviceId: that.data.deviceId,
success: (res) => { //连接蓝牙设备成功
wx.getBLEDeviceServices({
deviceId: that.data.deviceId,
success(res) { //获取服务id成功
that.setData({ serviceId: res.services[1].uuid});
wx.getBLEDeviceCharacteristics({
deviceId: that.data.deviceId,
serviceId: that.data.serviceId,
success(res) { //获取特性值id成功
that.setData({ characteristicId: res.characteristics[0].uuid });
that.setData({ randomCharacteristicId: res.characteristics[1].uuid });
wx.onBLECharacteristicValueChange(function (res) {
//读取数据成功回调-接收并存储转换后的数据
that.setData({ charact1: that.ab2hex(res.value) });
});
wx.readBLECharacteristicValue({ //读取二进制数据
deviceId: that.data.deviceId,
serviceId: that.data.serviceId,
characteristicId: that.data.randomCharacteristicId,
success: (res) => { }
});
}
})
}
})
},
fail: (res) => {
console.log("连接蓝牙设备失败");
console.log(res);
}
});
},
ab2hex: function(buffer) { //将二进制数组进行转换
var hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function (bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('');
},
closeBLEConnection: function(){ //断开与低功耗蓝牙设备的连接
var that = this;
wx.closeBLEConnection({
deviceId: that.data.deviceId,
success: (res) => { console.log("已断开连接!!"); }
});
},
writeBluetoothData1: function(){ //写入执行1指令
var that = this;
wx.writeBLECharacteristicValue({
deviceId: that.data.deviceId,
serviceId: that.data.serviceId,
characteristicId: that.data.characteristicId,
value: that.getBinaryData("0B0075")
});
},
writeBluetoothData2: function(){ //写入执行2指令
var that = this;
wx.writeBLECharacteristicValue({
deviceId: that.data.deviceId,
serviceId: that.data.serviceId,
characteristicId: that.data.characteristicId,
value: that.getBinaryData("75000B")
});
},
getBinaryData: function (message) { //将数据转为二进制数组
let buffer = new ArrayBuffer(6);
let dataView = new DataView(buffer);
var numTitle = 0;
for (var i = 0; i < message.length; i = i + 2) {
var numStr16 = message.substr(i, 2);
var num = parseInt(numStr16, 16);
dataView.setUint8(numTitle, num);
numTitle++;
}
return buffer;
}
});
最后
匹配蓝牙设备的时候,可以通过设备名,但是如果附近有多个同名的设备时,就需要通过mac地址来匹配对应的蓝牙设备了。而在苹果手机上返回的mac地址是经过处理后不准确的。如果有这种情况可以联系蓝牙设备硬件方,将mac地址存入manufacturerData中,通过它的值去匹配&连接蓝牙。