微信小程序之蓝牙 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,页面跳转和参数传递实例 首先说一下我遇到的需求有一个我的消息页面,里面的数据都是后端返回的,返回的数据大致如下,有一个是 ...
- 小程序语音红包开发中 汉字转拼音的问题 微信小程序红包开发遇到的坑
公司最近在开发微信小程序的红包功能,语音红包需要用到文字转拼音的功能. 之前介绍过怎么将中文的汉字转为拼音的,具体看下面这篇文章. 微信语音红包小程序开发如何提高精准度 红包小程序语音识别精准度 微信 ...
- 微信小程序那些令人眼泪汪汪的坑儿
前言 最近做了一个麻雀虽小,五脏俱全的微信小程序项目.一看就会,一用就废的小程序.有些坑真的坑的你两眼泪汪汪.我就爱干前人栽树后人乘凉的事儿,看到文章的你,也许是同道中人,相视一笑:亦或是小程序外围人 ...
随机推荐
- Yii2 windows 安装步骤
安装 Yii2 高级版应用 基础版可以看官方文档 今天安装了YII2高级版应用 写下步骤 留个记号,以备查询! 在 Windows 中,你首先需要下载并运行 Composer-Setup.exe 查看 ...
- [IIS] 测试的产品登陆之后有个引用外部站点js的请求半天都无法返回,导致网页一直在打转,Selenium的driver也无法对页面进行下一步的操作
测试的产品登陆之后有个引用外部站点js的请求半天都无法返回: https://cdn.heapanalytics.com/js/heap-3497400264.js 这个js如果是在美国的机器上就可以 ...
- 关于删除MySQL Logs的一点记录
五一前,一个DBA同事反馈,在日常环境中删除一个大的slow log文件(假设文件大小10G以上吧),然后在MySQL中执行flush slow logs,会发现mysqld hang住. 今天尝试着 ...
- 数据挖掘算法以及其实现zz
实验一 分类技术及其应用 实习要求: 基于线性回归模型拟合一个班学生的学习成绩,建立预测模型.数据可由自己建立100个学生的学习成绩. 1) 算法思想: 最小二乘法 设经验方程是y=F(x ...
- web应用安全权威指南(文摘)
第1章 什么是web应用的安全隐患 第3章 Web安全基础,HTTP,会话管理,同源策略 content_length 字节数 content_type mime类型 百分号编码 referer :请 ...
- HDU 1071 The area (数学定积分)
题意:求阴影部分面积. 析:没什么可说的,就是一个普通的定积分. 代码如下: #include <cstdio> #include <iostream> using names ...
- RocketMQ runbroker.sh 分析JVM启动参数
runbroker.sh #====================================================================================== ...
- Linux 非阻塞connect,错误码:EINPROGRESS
当我们以非阻塞的方式来进行连接的时候,返回的结果如果是 -1,这并不代表这次连接发生了错误,如果它的返回结果是 EINPROGRESS,那么就代表连接还在进行中. 后面可以通过poll或者select ...
- [转]WCF体系结构-一张图就是好
本文转自:http://www.cnblogs.com/snakevash/archive/2011/05/02/2034414.html 今天在MSDN上面看到了这么一张图,让我顿时感觉脑袋清醒很多 ...
- 随笔-未整理-linux下流量查看
nethogs: 按进程查看流量占用 iptraf: 按连接/端口查看流量 ifstat: 按设备查看流量 ethtool: 诊断工具 tcpdump: 抓包工具 ss: 连接查看工具 其他: dst ...