微信小程序-蓝牙

一.硬件部分

  1. HC-08 蓝牙模块 4.0BLE主从一体 CC2540 无线串口透传模块 BLE串口通信
  2. 硬件官网
    汇承官网
  3. 基本连接教程
    avatar
    注意:串口模块和usb to ttl的连接方式

二. Windows串口调试助手

  1. 下载串口调试助手
  2. 设置默认波特率为9600

三.手机App测试

  1. LightBlue和Windows的调试
    avatar
    avatar
    avatar
    avatar
    注意:由图4可以看出串口通信的serviceId的UUID为FFE0(读写UUID)
  2. Android和Windows的调试

四.微信小程序初始化连接

  1. 初始化蓝牙适配器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    wx.openBluetoothAdapter({
    success: function (res) {
    console.log('初始化蓝牙适配器成功' + JSON.stringify(res))
    that.msg = '初始化蓝牙适配器成功'
    wx.showModal({
    title: '蓝牙适配情况',
    content: '初始化蓝牙适配器成功'
    })
    },
    fail: function () {
    that.msg = '初始化蓝牙适配器失败'
    wx.showModal({
    title: '蓝牙适配情况',
    content: '蓝牙适配失败,请检查手机蓝牙和定位功能是否打开'
    })
    },
    complete: function () {
    console.log('初始化蓝牙适配器完成')
    }
    })
  2. 开启蓝牙搜索,并获取蓝牙设备列表 wx.getBluetoothAdapterState –> wx.onBluetoothAdapterStateChange –> wx.startBluetoothDevicesDiscovery –> wx.onBluetoothDeviceFound –> getBluetoothDevices

  3. 选择蓝牙设备获取相应的deviceId
  4. 连接蓝牙设备 wx.createBLEConnection –> wx.getBLEDeviceService(获取设备的ServiceId)

    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
    wx.createBLEConnection({
    deviceId: deviceId,
    success: function (res) {
    console.log('蓝牙设备连接成功')
    wx.hideLoading()
    wx.getBLEDeviceServices({
    deviceId: deviceId,
    success: function (res) {
    that.deviceService = res.services
    for (var t = 0; t < that.deviceService.length; t++) {
    var service = that.deviceService[t]
    var serviceId = service.uuid.substring(4, 8)
    if (serviceId === 'FFE0') { //‘FFE0’为设备定义的读写UUID
    that.serviceId = service.uuid
    }
    }
    that.nowDevice = !that.nowDevice
    that.nowService = !that.nowService
    console.log('获取蓝牙设备Service' + res.errMsg)
    },
    fail: function (res) {
    wx.showModal({
    title: '设备Service信息',
    content: '蓝牙设备连接成功' + '\n' + '设备信息获取错误' + res.errMsg
    })
    }
    })
    },
    fail: function (res) {
    console.log('蓝牙设备连接失败,请稍后重试')
    wx.hideLoading()
    wx.showModal({
    title: '提示',
    content: '蓝牙设备连接失败,请稍后重试',
    duration: 2000
    })
    },
    complete: function () {
    console.log('蓝牙设备连接完成')
    wx.hideLoading()
    }
    })
  5. 连接设备同时关闭蓝牙搜索 wx.stopBluetoothDevicesDiscovery

  6. 向串口发送数据(重要)
    wx.getBLEDeviceCharacteristics –> success: wx.notifyBLECharacteristicValueChang (启用notify功能) –> success:wx.writeBLECharacteristicValue –> success:wx.readBLECharacteristicValue(必须读取,否则Android设备无法正常向串口发送数据
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
wx.getBLEDeviceCharacteristics({
deviceId: that.deviceId,
serviceId: that.serviceId,
success: function (res) {
console.log(res.characteristics)
that.deviceCharacteristics = res.characteristics
for (var i = 0; i < that.deviceCharacteristics.length; i++) {
that.characteristic = that.deviceCharacteristics[i]
that.characteristicProperties = that.characteristic.properties
if (that.characteristicProperties.notify === true) {
that.characteristicId = that.characteristic.uuid
wx.notifyBLECharacteristicValueChange({
state: true, // 启用 notify 功能
deviceId: that.deviceId,
serviceId: that.serviceId,
characteristicId: that.characteristicId,
success: function (res) {
console.log('开启notify成功' + that.characteristic.uuid)
for (let i = 0; i < dataView.byteLength; i++) {
var writeData = '0x' + dataView.getUint8(i).toString(16)
that.writeDatas = that.writeDatas + '\n' + writeData
}
wx.writeBLECharacteristicValue({
deviceId: that.deviceId,
serviceId: that.serviceId,
characteristicId: that.characteristicId,
value: dataBuffer,
success: function (res) {
console.log('发送的数据:' + that.writeDatas)
console.log('message发送成功')
wx.showModal({
title: '数据发送成功',
content: that.writeDatas
})
wx.readBLECharacteristicValue({
deviceId: that.deviceId,
serviceId: that.serviceId,
characteristicId: that.characteristicId,
success: function (res) {
console.log('读取数据成功')
}
})
},
fail: function (res) {
// fail
console.log('message发送失败' + that.characteristicIdw)
wx.showToast({
title: '数据发送失败,请稍后重试',
icon: 'none'
})
},
complete: function (res) {
// fail
console.log('message发送完成')
}
})
},
fail: function () {
console.log('开启notify失败' + that.characteristicId)
}
})
// that.writeMessage(that.deviceId, that.serviceId, that.characteristicIdw, that.characteristicIdr, that.characteristicIdn)
}
}
},
fail: function () {
console.log('获取characteristic失败')
}
})
  1. 读取串口发送的数据 (重要)
    wx.getBLEDeviceCharacteristics –> success:wx.notifyBLECharacteristicValueChange –> success:wx.readBLECharacteristicValue –> wx.onBLECharacteristicValueChange

五.微信小程序蓝牙未启动,离开小程序开启蓝牙后再启动小程序

蓝牙页面启动流程

  1. 在onLoad中wx.openBluetoothAdapter
  2. 在onShow中判断当前蓝牙适配器的状态wx.onBluetoothAdapterStateChange –> 若更改成功,则wx.openBluetoothAdapter

六.微信小程序开发注意

  1. Android设备在readBLECharacteristicValu后可能会出现显示message传输成功但是串口调试助手收不到数据的情况
    解决方法:在writeBLECharacteristicValu后添加readBLECharacteristicValue
  2. 串口读写设备的时候注意转换数据格式,传输的数据格式为ArrayBuffer,需要转换才可以显示,直接console返回的res.value为空
    用到的转换格式代码
    1
    2
    3
    4
    5
    6
    7
    8
    let data = that.sendData.split(',')
    let dataBuffer = new ArrayBuffer(data.length)
    let dataView = new DataView(dataBuffer)
    for (let j = 0; j < data.length; j++) {
    dataView.setUint8(j, '0x' + data[j])
    }

    var writeData = '0x' + dataView.getUint8(i).toString(16)
1
2
3
4
5
6
7
8
ab2hex: function (buffer) {
var hexArr = Array.prototype.map.call(
new Uint8Array(buffer), function (bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('')
}
  1. 根据serviceId获取characteristicId时需要采用for循环获取,不使用for循环会无法开启notify,使用for循环会开启两遍,两次开启UUID相同,但是第一次显示开启成功,第二次显示开启失败
  2. 实际读取串口发送数据的位置为wx.onBLECharacteristicValueChang,wx.readBLECharacteristicValue返回的res中只有接受信息是否成功的信息
  3. 问题:若手机蓝牙未启动,初始化页面无法成功开启蓝牙适配器,重新打开蓝牙后,页面无法重新开启蓝牙适配器
    解决:因为只在onLoad中定义了开始蓝牙适配器,没有在onShow中定义,通过《六》中来解决
    注意:必须在onShow中先进行判断,再选择是否调用wx.openBluetoothAdapter,否则在第一次启动页面的时候调用两次wx.openBluetoothAdapter,wx.showModal会显示两次(初始化页面的时候onLoad后会调用onShow)