0%

微信小程序蓝牙BLE开发——实战遇到问题及踩坑(三)

对于我这种小白,遇到问题是常见的哈。这里记录下,避免日后再踩坑

1. IPHONE6及6PLUS无法搜索到设备?

特别注意: wx.onBluetoothDeviceFoundAPI返回的数据结构, 其中advertisData数据段。来看下res.devices 的结构。 有些供应商设备是没有返回的。

返回的数据结构图:

下图是不同设备上返回的数据。明显看到左图有返回advertisData数据段, 右图则没有

在这里插入图片描述

复现:

当广播数据中没有advertisData数据段情况下, 代码中获取时,除了真机调试下正常运行, 其他的预览模式、体验版及线上运行均有问题

1
2
3
4
// 转换后,根据协议文档取需要数据(advertisData不一定有数据)

var hexStr = ab2hex(device.advertisData);
console.log("广播数据中转换后:advertisData---->" + hexStr);

解决方案:

注意:advertisData数据段,返回是ArrayBuffer类型。 使用时需转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
if (device.advertisData != null) { //判断对象是否为null,advertisData不一定有
var hexStr = ab2hex(device.advertisData);
console.log("广播数据中转换后:advertisData---->" + hexStr);
}


// ArrayBuffer转16进度字符串示例
function ab2hex(buffer) {
var hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function(bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('');
}

ps: 当时第一次接触微信小程序BLE, 项目上线发现此问题。那时项目中对接多个供应商有些没有返回advertisData数据段, 忘加判断语句。【细节很重要】

记得那个周末休息慢慢排查解决的。

2. IOS无法获取MAC地址,如何连接设备呢?

再一次的了解 wx.onBluetoothDeviceFoundAPI返回的数据结构。主要关注deviceId数据

注意: deviceId

  1. Android设备中的deviceId得到是mac地址
  2. IOS设备中的deviceId得到是UUID, 而且是动态的。

返回数据效果图:

在这里插入图片描述

解决方案:

  • 通过广播数据段advertisData中获取需要的mac地址。【注意:有些供应商设备是没有返回的】

  • 通过广播数据段namelocalName中通过名称匹配设备。【有些供应商直接把mac地址拼接到name中】

    1. 如上图: 关注下name返回的格式, 通常供应商以: 前缀+mac(供应商缩写+设备mac
    2. 格式都可以更改的, 根据需求和硬件硬件部商量
    1
    2
    3
    // 例如:advertisData字段返回数据是0000365544332211a7d4...,可根据文档说明取需要数据
    let data = '0000365544332211a7d4';
    let subMac = data.subString(4, 16); //例取365544332211为mac

3. ANDROID二次连接搜索不到设备?

注意: 操作完成后一定要断开设备连接释放蓝牙模块。否则再次连接会出现搜索不到设备,需关闭小程序再次搜索才可以,IOS不受影响

wx.closeBLEConnection(Object object)

wx.closeBluetoothAdapter(Object object)

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
function closeBLEConnection() {
console.log("断开与低功耗蓝牙设备的连接。", deviceId);

if (deviceId) {
wx.closeBLEConnection({
deviceId: deviceId,
success: function(res) {
console.log("closeBLEConnection。success", res);

},
fail: function(res) {
console.log("closeBLEConnection。fail", res);
},
complete: function() {
status = false;
}
})

wx.closeBluetoothAdapter({
success: function(res) {
console.log("closeBluetoothAdapter ==>res:", res);
},
fail: function(error) {
console.log("closeBluetoothAdapter ==>error:", error);
}
})
}

_discoveryStarted = false;
isnotExist = true;
_deviceId = '';
deviceId = '';
}

4. 发送数据过程中易出现写入失败

注意: 开启notify建议不要马上发送指令,否则易出现写入失败

解决方案:

  • wx.writeBLECharacteristicValue向设备写入数据时,添加setTimeout()延迟1秒左右的动作。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function writeData(hex) {
setTimeout(() => {
//类型转换
var enDataBuf = new Uint8Array(hex);
var buffer1 = enDataBuf.buffer

wx.writeBLECharacteristicValue({
deviceId: _deviceId,
serviceId: _serviceId,
characteristicId: _characteristicId,
value: buffer1,
success: (res) => {
wx.hideLoading();
console.log("写数据返回结果", res.errMsg);
},
fail(res) {
console.log("写数据失败..", res);
asddErrorCallback(res.errCode, "");
}
})
}, 1000)
}

5. 什么版本能支持蓝牙功能?

iOS微信客户端 6.5.6版本开始支持Android 6.5.7 版本开始支持因此项目中需要做好版本检测

蓝牙说明

解决方案:

  • 第一步:app.jsonLaunch()方法中,获取系统信息接口
1
2
//获取系统信息
this.globalData.sysinfo = wx.getSystemInfoSync();
  • 第二步: 得到versionsystemplatform等需要的相关信息。
1
2
3
4
5
6
7
8
9
getVersion: function() { //获取微信版本号
return this.globalData.sysinfo["version"]
},
getSystem: function() { //获取操作系统版本
return this.globalData.sysinfo["system"]
},
getPlatform: function() { //获取客户端平台
return this.globalData.sysinfo["platform"]
},
  • 第三步: 在需要检测版本页面,通常在首页对应的.js中,判断版本是否支持蓝牙API。

    这里放在单独.js文件中, 在index.js中引入并使用。

    A: 新建checkVersion.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    const app = getApp()

    /**
    * 版本比较
    */
    function versionCompare (ver1, ver2) { //版本比较
    // console.log("ver1" + ver1 + 'ver2' + 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
    }
    }


    /**
    * 微信版本检测
    * Android从微信 6.5.7 开始支持,iOS从微信 6.5.6 开始支持
    */
    function checkWechatVersion() {
    if (app.getPlatform() == 'android' && versionCompare('6.5.7', app.getVersion())) {
    wx.showModal({
    title: '提示',
    content: '当前微信版本过低,请更新至最新版本体验',
    showCancel: false
    })
    }else if (app.getPlatform() == 'ios' && versionCompare('6.5.6', app.getVersion())) {
    wx.showModal({
    title: '提示',
    content: '当前微信版本过低,请更新至最新版本体验',
    showCancel: false
    })
    }
    }


    //导出
    module.exports = {
    checkWechatVersion: checkWechatVersion
    }

    B:index.jsonLoad()方法中使用

    1
    2
    3
    4
    5
    6
    var checkVersion = require('../../../utils/checkVersion.js');

    onLoad: function(options) {
    // 检测版本
    checkVersion.checkWechatVersion();
    }

wx.getSystemInfoSync()返回的数据效果图

在这里插入图片描述

版本比较参考大神们

6. 安卓 6.0 及以上设备需打开定位服务?

  • 在测试过程中,发现Android 6.0及以上系统的一些设备, 无法搜索蓝牙设备, 因此建议在项目中提示用户打开微信定位服务(GPS)
  • 打开权限: 设置—>应用程序—>找到已安装微信应用—>权限—>打开定位

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
isOpenLocation: function() {
let that = this;
//判断提示安卓系统6.0及以上需打开定位服务
if (app.getPlatform() == 'android' && app.getSystem() >= 'Android 6.0') {
wx.getSystemInfo({
success(res) {
// console.log("获取系统信息", res);
if (!res.locationAuthorized && res.locationAuthorized != undefined) {
wx.showModal({
title: '提示',
content: '为了更好体验测量,\r\n请您打开微信允许授权定位并刷新页面',
showCancel: false
})
} else {
that.scanCode();
}
}
})
} else {
that.scanCode();
}
},

7. 写入数据大于20字节,如何处理?

注意:

  • 并行调用多次会存在写失败的可能性。
  • 小程序不会写入数据包大小限制,但系统与蓝牙设备限制蓝牙4.0单次传输的数据大小,超过最大字节数后会发生写入错误建议每次写入不超过20字节
  • 若单次写入数据过长,iOS 上存在系统不会有任何回调的情况(包括错误回调)

解决方案:

分包发送:

系统与蓝牙单次传输只能发送20个字节, 因此大于20个字节时需要手动分包发送

说明:写入数据时,需要延迟,否则易出现写入失败【可查看:第4个案例】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var hex = [0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x50, 0x51, 0x52]; //22个字节

if (hex.length > 20) {
var result = this.split_array(hex, 20);
console.log('分包后的数组', result);
writeData(result[0]); //写入第一条数据
setTimeout(() => {
writeData(result[1]); //写入第二条数据
}, 5)
} else {
console.log('小于20字节写入数据');
writeData(hex);
}

/**
* 将一个数组分割两个
*/
split_array: function(arr, len) {
var a_len = arr.length;
var result = [];
for (var i = 0; i < a_len; i += len) {
result.push(arr.slice(i, i + len));
}
return result;
},

BLE项目实战

蓝牙BLE项目实战

关于下篇内容

  • 在开发蓝牙BLE应用一些进制转换