微信小程序——蓝牙应用小结
前言
经过几个月的时间,断断续续的修改,终于完成了个人的第一个微信蓝牙小程序,仅此做一个小结。
一、知识储备
1.微信小程序API
蓝牙部分的API可以到微信公众平台去找,都是官方文件。Android 从微信 6.5.7 开始支持蓝牙程序,iOS 从微信 6.5.6 开始支持。
之前自己稍微整理过一个流程。
2.BLE 4.0
BLE 4.0是现在流行的一种蓝牙传输协议,其中 BLE 是 Bluetooth Low Energy 低功耗蓝牙的简写。整个协议我也只是一知半解,就讲点在应用过程中了解的东西。其余大家感兴趣可以直接搜索下。
先明确几个概念:(个人理解,有问题欢迎指出)
MAC地址:(Media Access Control Address)蓝牙设备的物理地址,每个设备只有一个唯一值。
UUID:(Universally Unique Identifier)通用唯一识别码,一种软件识别码,一个设备中可以有 多个UUID,一个UUID对应一个软件服务部分。
服务(service):有关特征值的收集,用来操作特定功能,所以一个服务里可以有多个特征值。例如,“体温计”服务包括一个温度测量值,以及测量的时间间隔。
特征值(characteristic):在蓝牙设备之间传递的数据值,例如当前温度测量值。
服务、特征称为属性(attributes),并以UUID标识。实现者可能会为所用的专有格式挑选一个随机或伪随机UUID,但蓝牙技术联盟已预留一系列UUID(范围xxxxxxxx-0000-1000-8000-00805F9B34FB))供标准属性使用。
所以可以理解为:
MAC地址:一个人的名字。
服务:一个人做了一件事情。
特征性:考核这件事情的几个指标。
UIDD:用一串数字和字母表示事情或指标。
这些理解了,还要了解一下BLE 4.0和传统蓝牙的不同,在单模情况下无法通用传统蓝牙的设备。所以开发小程序前,你要了解你的手机和要连接的蓝牙设备是否能满足BLE 4.0的要求,否则硬件基础都不支持,谈何软件实现。
3.vConsole
这是微信自带一个真机调试工具,因为蓝牙程序部分无法在“微信web开发者工具”中仿真调试,需要大量的真机调试,所以好好应用vConsole,在后续的开发中至关重要。
二、开发过程中的磕磕碰碰
1.console.log先打出错误信息
最开始按照蓝牙流程编写完小程序后,总是遇到各种错误,一个头两个大。
后来就在每段程序里加入:
console.log('连接蓝牙:', res.errMsg + res.errCode);
将全部错误信息打印出来和下表对比,就慢慢有了方向。
错误信息部分截图
2.不行就加延迟
如果在使用多个蓝牙API且有先后或者参数传递关系,请加入适当延迟。
没有加延迟的后果是前一个API还没执行完成,后一个API就在执行了,这样后一个API缺少了一些必要的准备或参数。
vConsole中表现出两种情况,1中间状态的参数未赋值,2错误提示前一个API操作的结果出错
以wx.getBLEDeviceServices和wx.getBLEDeviceCharacteristics为例,两者之间有参数传递关系,所以需要延长。
wx.getBLEDeviceServices({
deviceId: that.data.connectedDeviceId,
success: function(res) {
for (let i = 0; i < res.services.length; i++) {
if (res.services[i].uuid.toUpperCase().indexOf("FFE0") != -1) {
that.setData({
serviceUUID: res.services[i].uuid,
})
console.log("UUID1:" + that.data.serviceUUID);
break;
}
}
},
fail: function (res) {
}
})
setTimeout(function () {
wx.getBLEDeviceCharacteristics({
deviceId: that.data.connectedDeviceId,
serviceId: that.data.serviceUUID,
success: function(res) {
console.log('成功2:', res.errMsg + res.errCode);
var notify_id, write_id, read_id;
for (let i = 0; i < res.characteristics.length; i++) {
if (res.characteristics[i].properties.notify) {
notify_id = res.characteristics[i].uuid;
}
if (res.characteristics[i].properties.write) {
write_id = res.characteristics[i].uuid;
}
if (res.characteristics[i].properties.read) {
read_id = res.characteristics[i].uuid;
}
}
that.setData({
characteristicId_notify: notify_id,
characteristicId_write: write_id,
characteristicId_read: read_id,
})
},
fail: function (res) {
}
})
}, 1000)//添加延迟
3.为什么iPhone比较难连
就一个原因iPhone比较矫情。
使用iPhone时,就算你知道服务的UUID和特征值的UUID,与必须通过wx.getBLEDeviceServices和wx.getBLEDeviceCharacteristics两个API获得。就是上面写道那段代码。
服务的UUID和特征值的UUID,iPhone只识别大写字母,安卓大小写没关系。
安卓和iPhone还有一个不同点: Android 上获取到的deviceId为设备 MAC 地址,iOS 上则为设备的 UUID。但是在实际应用中仅发现deviceId这个值不同,会影响界面布局,其他倒是没什么感觉。
最后在梳理下安卓和iPhone的连接过程:
安卓:
wx.getBluetoothDevices——获得MAC地址(deviceId)
wx.createBLEConnection——通过MAC地址创建连接
wx.getBLEDeviceServices——获得服务的UUID(ServicesId)如果已知ServicesId,可将ServicesId设置为常量,省略该步骤。
wx.getBLEDeviceCharacteristics——获得特征值的UUID(CharacteristicsId)如果已知CharacteristicsId,可将CharacteristicsId设置为常量,省略该步骤。
wx.notifyBLECharacteristicValueChanged——通过deviceId、ServicesId、CharacteristicsId启动notify模式
iPhone:
wx.getBluetoothDevices——获得设备的 UUID(deviceId)
wx.createBLEConnection——通过设备的 UUID创建连接
wx.getBLEDeviceServices——获得服务的UUID(ServicesId)不论是否已知ServicesId,都无法省略该步骤。
wx.getBLEDeviceCharacteristics——获得特征值的UUID(CharacteristicsId)不论是否已知CharacteristicsId,都无法省略该步骤。
wx.notifyBLECharacteristicValueChanged——通过deviceId、ServicesId、CharacteristicsId启动notify模式
所以,当你想要两者共用,就乖乖将wx.getBLEDeviceServices和wx.getBLEDeviceCharacteristics两个API都写进去。
4.如何获得可用的服务UUID
通过wx.getBLEDeviceServices可以获得所有服务的UUID,但是那个是你需要的?
比如我就筛选了含有“FFE0”的UUID。
if (res.services[i].uuid.toUpperCase().indexOf("FFE0") != -1)
那么怎么获得自己想要的UUID那?
我通过一个APP(在哪下载忘记了,红框是它的logo),尝试了哪些UUID可以使用。
APP界面
5.读数据要用on,不能一口气读写太多
比较坑的一点,读取数据建议使用wx.onBLECharacteristicValueChange。
读写操作的buffer是有大小限制,印象中是20个字节大小,如果你没有分段存储,就只能读取到头20个字节。
大于 20 字节只能分包发送或读取。微信小程序提供的 API 中没有自动分包的功能,这就只能自己手动分包了。
6.关于波特率
暂时微信还没有提供设置蓝牙设备波特率的API,但是通过手机连接测试,波特率在9600-57600之间都可以连接。
后记
我已从坑中爬出,写下此文,希望他人能爬的快点,哈哈哈哈!