小程序实例回顾分析--蓝牙使用

小程序的蓝牙使用流程

蓝牙的整个使用流程如下

  • 初始化蓝牙适配
  • 获取本机蓝牙适配状态
  • 开始搜索蓝牙
  • 获取发现的蓝牙设备
  • 监听新发现的设备
  • 链接低功耗蓝牙
  • 获取蓝牙设备所有服务
  • 获取蓝牙设备某个服务中所有特征值
  • 开启notify
  • 开始写入数据

下面把一些需要重点强调的地方说明一下。

匹配要搜索的蓝牙设备

这里是先通过搜索附近的蓝牙广播,根据广播值和自己要搜索的值进行比对,如果匹配成功,则去链接这个广播对应的deviceId。这里,有一个问题,就是广播值的advertisData是一个buffer数据,是没办法打印出来的。 这时候要按照arrayBufferToHexString的规则,转换一下。

从连接低功耗蓝牙到向设备写入数据

连接低功耗蓝牙--》每个蓝牙设备有多个服务,找到对应的服务 --》每个服务有不同特征值,notify为监听蓝牙状态变化特征值,write为写特征值。

这时候,要先开启notify,保证可以监听到蓝牙状态变化。然后才能对write特征值进行处理。

写入时只能写入buffer数据

这里需要说的是,安卓客户端是发送给设备一个byte[]数组,我要对照java的数据发送一个byte数组,但是小程序只能发送buffer。需要进行下面这样的转换。

const strArray = [14,6,14,6,14,6]
const array = new Int8Array(strArray.length)
strArray.forEach((item, index) => array[index] = item)
return array.buffer;

先创建一个同样长度的Int8Array。然后重新赋值,返回array。这时候array有一个buffer,可以直接提交过去

整体代码

    /****************************
     * 开始蓝牙处理
     *****************************/
    // 蓝牙开锁
    lanyaOpen () {
        console.log('开始蓝牙锁处理')
        this.startBlueTooth()
    },
    // 取消蓝牙开锁
    lanyaClose () {
        this.handleCloseAlert()
    },
    startBlueTooth () {
        this.lanya1()
    },
    // 初始化蓝牙适配
    lanya1 () {
        let _this = this
        console.log('初始化蓝牙适配')
        wx.openBluetoothAdapter({
            success: function (res) {
                console.log(res)
                _this.lanya2()
            },
            fail: function (res) {
                console.log(res);
                _this.showTips('初始化蓝牙适配失败,请开启蓝牙后重试')
            }
        })
    },
    // 获取本机蓝牙适配状态
    lanya2 () {
        let _this = this
        console.log('获取本机蓝牙适配状态')
        wx.getBluetoothAdapterState({
            success: function (res) {
                console.log(res)
                if (res.available){
                    _this.lanya3()
                }
            },
            fail: function () {
                _this.showTips('获取本机蓝牙适配状态失败,请开启蓝牙')
            }
        })
    },
    // 开始搜索蓝牙
    lanya3 () {
        let _this = this
        wx.showLoading({
            title: '开锁中',
        })
        console.log('开始搜索蓝牙')
        wx.startBluetoothDevicesDiscovery({
            success (res) {
                console.log(res)
                _this.lanya5()
            }
        })
    },
    // 获取发现的蓝牙设备
    lanya4 () {
        let _this = this
        let ad = 'aaaaaa'

        wx.getBluetoothDevices({
            success: function (obj) {
                console.log(obj.devices);
                console.log('获取发现的蓝牙设备列表', _this.data.deviceList)
                _this.data.deviceList = []

                for (let key in obj.devices){
                    let _new = true
                    _this.data.deviceList.forEach(item => {
                        if (item.deviceId === obj.devices[key].deviceId){
                            _new = false
                        }
                    })
                    if (_new){
                        _this.data.deviceList.push(obj.devices[key])
                    }
                }

                _this.data.deviceList.forEach(item => {
                    let advertisData = item.advertisData;
                    var data = _this.arrayBufferToHexString(advertisData);//二进制转字符串
                    if (!!data && data.indexOf(ad) > -1) {
                        _this.data.deviceId = item.deviceId;
                    }
                })
                console.log('设备列表', _this.data.deviceList)

                if (_this.data.deviceId){
                    wx.stopBluetoothDevicesDiscovery()
                    console.log("广播匹配成功");
                    _this.lanya6()
                }
            }
        })
    },
    // 监听新发现的设备
    lanya5 () {
        // ArrayBuffer转16进度字符串示例
        let _this = this
        console.log('监听新发现的设备')
        if (_this.data.linking){
            return
        }
        wx.onBluetoothDeviceFound(function(obj) {
            console.log('new device list has founded', obj)
            _this.lanya4()
        })
    },
    // 链接低功耗蓝牙
    lanya6 () {
        let _this = this

        if (_this.data.linking){
            return
        }
        _this.data.linking = 0
        console.log('链接低功耗蓝牙', _this.data.deviceId)
        wx.createBLEConnection({
            deviceId: _this.data.deviceId,
            success: function (res) {
                console.log(res);
                _this.lanya7()
            },
            fail: function (res) {
                console.log(res, '链接失败')
                setTimeout(() => {
                    _this.data.linking ++
                    _this.lanya6()
                }, 5000)
            }
        })
    },
    // 获取蓝牙设备所有服务(service)。
    lanya7 () {
        let _this = this
        console.log('获取蓝牙设备所有服务')
        wx.getBLEDeviceServices({
            deviceId: _this.data.deviceId,
            success: function (res) {
                console.log(res, '蓝牙服务列表');
                res.services.forEach(item => {
                    if (item.uuid === _this.data.RX_SERVICE_UUID){
                        _this.lanya8()
                    }
                })
            },
            fail: function (res) {
                console.log(res);
            }
        })
    },
    // 获取蓝牙设备某个服务中所有特征值
    lanya8 () {
        let _this = this
        console.log('获取蓝牙设备某个服务中所有特征值')
        wx.getBLEDeviceCharacteristics({
            deviceId: _this.data.deviceId,//搜索设备获得的蓝牙设备 id
            serviceId: _this.data.RX_SERVICE_UUID,//服务ID
            success: function (res) {
                console.log(res);
                _this.lanya9()
            },
            fail: function (res) {
                console.log(res);
            }
        })

    },
    //开启notify
    lanya9 () {
        let _this = this
        console.log('开启notify11')
        wx.notifyBLECharacteristicValueChange({
            state: true, // 启用 notify 功能
            deviceId: _this.data.deviceId,//蓝牙设备id
            serviceId: _this.data.RX_SERVICE_UUID,//服务id
            characteristicId: _this.data.TX_CHAR_UUID,//服务特征值indicate
            success: function (res) {
                console.log('开启notify', res.errMsg)
                //监听低功耗蓝牙设备的特征值变化
                wx.onBLECharacteristicValueChange(function(res) {
                    console.log(`characteristic ${res.characteristicId} has changed, now is ${res.value}`)
                    console.log(_this.arrayBufferToHexString(res.value))
                    _this.closeLanya()
                    _this.handleCloseAlert()
                })

                //写入数据
                setTimeout(() => {
                    _this.lanya10()
                }, 2000)

            },
            fail: function (res) {
                console.log(res, '开启notify失败');
            }
        })
    },
    // 开始写入数据
    lanya10 () {
        console.log('开始写入数据')
        let _this = this
        let buffer = _this.stringToByte()

        wx.writeBLECharacteristicValue({
            deviceId: _this.data.deviceId,//设备deviceId
            serviceId: _this.data.RX_SERVICE_UUID,//设备service_id
            characteristicId: _this.data.RX_CHAR_UUID,//设备write特征值
            value: buffer,//写入数据
            success: function (res) {
                console.log('发送数据:', res.errMsg)
                wx.hideLoading()
            },
            fail: function (res) {
                wx.hideLoading()
                this.showTips('开锁失败,请重新尝试')
            }
        });

    },
    stringToByte: function(str) {
        const strArray = [14,6,14,6,14,6]
        const array = new Int8Array(strArray.length)
        strArray.forEach((item, index) => array[index] = item)
        return array.buffer;
    },
    closeLanya () {
        wx.stopBluetoothDevicesDiscovery()
        wx.closeBLEConnection({
            deviceId: this.data.deviceId,
            success: function (res) {
                console.log('断开蓝牙链接成功')
            }
        })
    },
    Str2Bytes (str)
    {
        var pos = 0;
        var len = str.length;
        if(len %2 != 0)
        {
            return null;
        }
        len /= 2;
        var hexA = new Array();
        for(var i=0; i< len; i++) { var s = str.substr(pos, 2); var v = parseInt(s, 16); hexA.push(v); pos += 2; } return hexA; }, arrayBufferToHexString (buffer) { let bufferType = Object.prototype.toString.call(buffer) if (buffer != '[object ArrayBuffer]') { return } let dataView = new DataView(buffer) var hexStr = ''; for (var i = 0; i < dataView.byteLength; i++) { var str = dataView.getUint8(i); var hex = (str & 0xff).toString(16); hex = (hex.length === 1) ? '0' + hex : hex; hexStr += hex; } return hexStr.toUpperCase(); }, Str2Bytes(str) { var pos = 0 var len = str.length if (len % 2 != 0) return null len /= 2 var hexA = new Array() for (var i = 0; i < len; i++) { var s = str.substr(pos, 2) var v = parseInt(s, 16) hexA.push(v) pos += 2 } return hexA } 

随机浏览