微信小程序之蓝牙 BLE 踩坑记录
前言
前段时间接手了一个微信小程序的开发,主要使用了小程序在今年 3 月开放的蓝牙 API ,此过程踩坑无数,特此记录一下跳坑过程。顺便开了另一个相关的小项目,欢迎 start 和 fork: BLE_MiniProgram
API简介
微信小程序目前有蓝牙 API 共 18 个,其中操作蓝牙适配器的共有 4 个,分别是
wx.openBluetoothAdapter 初始化蓝牙适配器
wx.closeBluetoothAdapter 关闭蓝牙模块
wx.getBluetoothAdapterState 获取本机蓝牙适配器状态
wx.onBluetoothAdapterStateChange 监听蓝牙适配器状态变化事件
连接前使用的共有 4 个,分别是
wx.startBluetoothDevicesDiscovery 开始搜寻附近的蓝牙外围设备
wx.stopBluetoothDevicesDiscovery 停止搜寻附近的蓝牙外围设备
wx.getBluetoothDevices 获取所有已发现的蓝牙设备
wx.onBluetoothDeviceFound 监听寻找到新设备的事件
连接和断开时使用的共有 2 个,分别是
wx.createBLEConnection 连接低功耗蓝牙设备
wx.closeBLEConnection 断开与低功耗蓝牙设备的连接
连接成功后使用的共有 8 个,分别是
wx.getConnectedBluetoothDevices 根据 uuid 获取处于已连接状态的设备
wx.getBLEDeviceServices 获取蓝牙设备所有 service(服务)
wx.getBLEDeviceCharacteristics 获取蓝牙设备所有 characteristic(特征值)
wx.readBLECharacteristicValue 读取低功耗蓝牙设备的特征值的二进制数据值
wx.writeBLECharacteristicValue 向低功耗蓝牙设备特征值中写入二进制数据
wx.notifyBLECharacteristicValueChange 启用低功耗蓝牙设备特征值变化时的 notify 功能
wx.onBLECharacteristicValueChange 监听低功耗蓝牙设备的特征值变化
wx.onBLEConnectionStateChange 监听低功耗蓝牙连接的错误事件
基本操作流程
最基本的操作流程是:初始化蓝牙适配器→开始搜寻附近的蓝牙外围设备→监听寻找到新设备的事件→连接低功耗蓝牙设备→获取蓝牙设备所有 service 和 characteristic →读取或写入低功耗蓝牙设备的特征值的二进制数据值。
踩过的几个坑
支持蓝牙 API 的版本
Android 从微信 6.5.7 开始支持,iOS 从微信 6.5.6 开始支持,因此小程序中需要做好版本检测,在 app.js 文件中加入以下代码,其中 wx.getSystemInfoSync 是一个获取系统信息的API。
onLaunch: function() {
this.globalData.sysinfo = wx.getSystemInfoSync()
},
getModel: function () { //获取手机型号
return this.globalData.sysinfo["model"]
},
getVersion: function () { //获取微信版本号
return this.globalData.sysinfo["version"]
},
getSystem: function () { //获取操作系统版本
return this.globalData.sysinfo["system"]
},
getPlatform: function () { //获取客户端平台
return this.globalData.sysinfo["platform"]
},
getSDKVersion: function () { //获取客户端基础库版本
return this.globalData.sysinfo["SDKVersion"]
}
在初始页面(一般是 index.wxml)对应的 js 文件中使用 app.getPlatform() 和 app.getVersion() 即可获取到客户端平台(安卓或 iOS)和微信版本号。在onLoad中获取这两个信息后进行比较即可,使用了下面的版本比较方法。
versionCompare: function (ver1, ver2) { //版本比较
var version1pre = parseFloat(ver1)
var version2pre = parseFloat(ver2)
var version1next = parseInt(ver1.replace(version1pre + ".", ""))
var version2next = parseInt(ver2.replace(version2pre + ".", ""))
if (version1pre > version2pre)
return true
else if (version1pre < version2pre)
return false
else {
if (version1next > version2next)
return true
else
return false
}
}
if (app.getPlatform() == 'android' && this.versionCompare('6.5.7', app.getVersion())) {
wx.showModal({
title: '提示',
content: '当前微信版本过低,请更新至最新版本',
showCancel: false
})
}
else if (app.getPlatform() == 'ios' && this.versionCompare('6.5.6', app.getVersion())) {
wx.showModal({
title: '提示',
content: '当前微信版本过低,请更新至最新版本',
showCancel: false
})
}
安卓 6.0 及以上设备需打开定位服务
在测试中发现安卓 6.0 以上的手机未打开系统定位服务时,搜索不到蓝牙设备,因此最好在页面中提示用户打开定位服务。
wx.onBluetoothDeviceFound 不兼容
安卓及iOS设备使用 wx.onBluetoothDeviceFound 时会出现不同的返回值,且有概率出现重复设备,所以使用以下代码可以清除重复的设备和解决 API 不兼容问题。
wx.onBluetoothDeviceFound(function (devices) {
var isnotExist = true
if (devices.deviceId) {
for (var i = 0; i < foundDevice.length; i ++) {
if (devices.deviceId == foundDevice[i].deviceId) {
isnotExist = false
}
}
if (isnotexist)
foundDevice.push(devices)
}
else if (devices.devices) {
for (var i = 0; i < foundDevice.length; i++) {
if (devices.devices[0].deviceId == foundDevice[i].deviceId) {
isnotExist = false
}
}
if (isnotexist)
foundDevice.push(devices.devices[0])
}
else if (devices[0]) {
for (var i = 0; i < foundDevice.length; i++) {
if (devices[0].deviceId == foundDevice[i].deviceId) {
isnotExist = false
}
}
if (isnotexist)
foundDevice.push(devices[0])
}
})
读取广播数据和特征值
小程序中读取 BLE 广播数据使用 wx.onBluetoothDeviceFound 接口中的 advertisData,对应上面兼容问题的 devices 格式,如 devices.advertisData,这个数据是 ArrayBuffer,需要转换,可以使用以下两种转换方法。另外 wx.getBLEDeviceCharacteristics 读取的特征值 characteristic.value 也是 ArrayBuffer,用同样的方法转换。
buf2string: function (buffer) {
var arr = Array.prototype.map.call(new Uint8Array(buffer), x => x)
var str = ''
for (var i = 0; i < arr.length; i++) {
str += String.fromCharCode(arr[i])
}
return str
}
buf2hex: function (buffer) {
return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
}
发送大于 20 字节的数据包
众所周知,BLE 4.0 中发送一个数据包只能包含 20 字节的数据,大于 20 字节只能分包发送。微信小程序提供的 API 中似乎没有自动分包的功能,这就只能自己手动分包了。调试中发现,在 iOS 系统中调用 wx.writeBLECharacteristicValue 发送数据包,回调 success 后紧接着发送下一个数据包,很少出现问题,可以很快全部发送完毕。而安卓系统中,发送一个数据包成功后紧接着发送下一个,很大概率会出现发送失败的情况,在中间稍做延时再发送下一个就可以解决这个问题(不同安卓手机的时间长短也不一致),照顾下一些比较奇葩的手机,大概需要延时 250 ms 。不太好的但是比较科学的办法是,只要成功发送一个数据包则发送下一个,否则不断重发,具体就是
wx.writeBLECharacteristicValue 回调 fail 则重新发送,直至发送完毕。
补充说明
此处补充说明一下,华为荣耀部分机型、还有蓝绿厂的部分机型,在蓝牙 API 有深坑,谨慎调试。另:发现挺多同学没有注意到官方文档最下方的错误码列表,顺便在此处贴出来。
蓝牙错误码 (errCode) 列表
错误码 | 说明 | 备注 |
---|---|---|
0 | ok | 正常 |
10000 | not init | 未初始化蓝牙适配器 |
10001 | not available | 当前蓝牙适配器不可用 |
10002 | no device | 没有找到指定设备 |
10003 | connection fail | 连接失败 |
10004 | no service | 没有找到指定服务 |
10005 | no characteristic | 没有找到指定特征值 |
10006 | no connection | 当前连接已断开 |
10007 | property not support | 当前特征值不支持此操作 |
10008 | system error | 其余所有系统上报的异常 |
10009 | system not support | Android 系统特有,系统版本低于 4.3 不支持BLE |
微信小程序之蓝牙 BLE 踩坑记录的更多相关文章
- 微信小程序之mpvue+iview踩坑之旅
因为之前参照微信的原生的文档写过一些小程序的demo,写的过程比较繁琐,后来出了美团的mpvue,可以直接使用vue开发,其他的不作对比,这篇文章记录一下踩坑之旅. 参照mpvue http://mp ...
- 微信小程序性能测试之jmeter踩坑秘籍(前言)
最近要做个微信小程序的性能压测,虽然之前只做过web端的,但想一想都是压后端的接口,所以果断答应了下来,之前对jmeter都是小打小闹,所以趁着这次机会好好摆弄摆弄. ---------------- ...
- 微信小程序开发技巧及填坑记录
以下是自己在开发过程中遇到的坑和小技巧,记录以下: 1.出现了 page[pages/XXX/XXX] not found.May be caused by :1. Forgot to add pag ...
- 微信小程序开发-蓝牙功能开发
0. 前言 这两天刚好了解了一下微信小程序的蓝牙功能.主要用于配网功能.发现微信的小程序蓝牙API已经封装的很好了.编程起来很方便.什么蓝牙知识都不懂的情况下,不到两天就晚上数据的收发了,剩下的就是数 ...
- 微信小程序调用蓝牙功能控制车位锁
第一次学用微信小程序,项目需要,被逼着研究了一下,功能是调用微信小程序的蓝牙功能,连接上智能车位锁,控制升降,大概步骤及调用的小程序接口API如下: 1.打开蓝牙模块 wx.openBluetooth ...
- 微信小程序之蓝牙开发(详细读数据、写数据、附源码)
本文将详细介绍微信小程序的蓝牙开发流程(附源码)准备:微信只支持低功耗蓝牙也就是蓝牙4.0,普通的蓝牙模块是用不了的,一定要注意. 蓝牙可以连TTL接到电脑上,再用XCOM调试 一开始定义的变量 va ...
- 总结微信小程序开发中遇到的坑
总结微信小程序开发中遇到的坑,一些坑你得一个一个的跳啊,/(ㄒoㄒ)/~~ 1,页面跳转和参数传递实例 首先说一下我遇到的需求有一个我的消息页面,里面的数据都是后端返回的,返回的数据大致如下,有一个是 ...
- 小程序语音红包开发中 汉字转拼音的问题 微信小程序红包开发遇到的坑
公司最近在开发微信小程序的红包功能,语音红包需要用到文字转拼音的功能. 之前介绍过怎么将中文的汉字转为拼音的,具体看下面这篇文章. 微信语音红包小程序开发如何提高精准度 红包小程序语音识别精准度 微信 ...
- 微信小程序那些令人眼泪汪汪的坑儿
前言 最近做了一个麻雀虽小,五脏俱全的微信小程序项目.一看就会,一用就废的小程序.有些坑真的坑的你两眼泪汪汪.我就爱干前人栽树后人乘凉的事儿,看到文章的你,也许是同道中人,相视一笑:亦或是小程序外围人 ...
随机推荐
- sql游标使用
一.游标的作用:Select时,返回的是一个结果集,若需要为结果集返回的过程中,读取到一行数据.需要对此行数据进行处理,比如按读取到的数据作为查询条件返回一个查询结果集等等,应用都需要用到游标.游标可 ...
- Ubuntu解决sudo: source: command not found错误
Ubuntu Server上执行以下命令,可以看到默认打开的文件数限制为1024个. $ ulimit -n 1024 编辑/etc/profile配置文件,在最后添加一行: ulimit -SHn ...
- Golang template和junit xml report转html工具
最近刚好有个task是要用Golang把Junit的XML格式report转换成HTML格式,便学习了Golang的template包. 基于template做的那个junit XML转HTML工具. ...
- [Selenium] Java代码获取,设置屏幕分辨率
import java.awt.Dimension; import java.awt.DisplayMode; import java.awt.GraphicsDevice; import java. ...
- MySQL中触发器
触发器是与某个事件相关的特殊存储过程,与存储过程不同的是,存储过程需要用 call 调用而出发器不需要使用call调用调用. 也就是自己预先定义好了,当某个事件发生时,就会自动出发触发器进行相关的操作 ...
- android listView布局等分列
android listView布局4等分列. 必须要加上<RelativeLayout 在外层,不然等分不起作用 <RelativeLayout xmlns:android=" ...
- Button或者ImageButton的背景设为透明或者半透明
Button或者ImageButton的背景设为透明或者半透明 半透明<Button android:background="#e0000000" ... /> 透明& ...
- 我大中华微软MVP中国区人才库(转)
出处:http://www.genshuixue.com/i-cxy/p/15349735 刘海峰:国内知名微软开源技术网站51Aspx 创始人,十年以上的asp.net从业经验,微软MSDN特约讲师 ...
- PHP(八)数组
- angularjs之事件绑定、解除事件绑定
今天在开发时,遇到一个坑,花了一下午时间也没找到原因,无奈小菜鸟只能寻求公司里大牛的帮助,果然,大牛就是大牛,对比了几个输出结果,就看出问题所在.所以小菜鸟当然不会错过这个分享的时机啦~废话不多说进入 ...