1. 连接蓝牙设备,需要使用微信的wx.createBLEConnection接口,参数为蓝牙设备的deviceId(这个参数在搜索的设备信息里面可以直接拿到)。

2. 在ble.js里面新增connect、disconnect、getDevConStatus三个接口,用以统一管理设备连接和设备断开,因为在安卓平台上,重复去连接会导致设备没有办法断开连接。所以在ble.js里面还维护了一个连接/正在连接的设备数组,方便统一管理设备。当调用connect的时候,会先去这个数组里面查找是否有该设备,如果有就不再去调用连接了。当调用disconnect或者设备被动断开,会把该设备从这个数组里面删除。

微信小程序 ios连接蓝牙用deviceid 微信小程序蓝牙ble_微信小程序

3. Init函数中添加设备连接状态监听回调:wx.onBLEConnectionStateChange,并且在DeInit中关闭该回调。

4. 在DeInit函数中,会先去检查的设备数组是否为空,如果还有设备处于连接状态或者正在连接状态,就会依次主动断开这些设备,防止退出的时候,忘记关闭,导致蓝牙一直保存该连接。

5. 设备连接成功,并不是在createBLEConnection回调里面去置的状态,而是在设备连接状态回调里面去更新的该设备的状态,然后再调用的回调函数通知上层应用,因为有时候发现createBLEConnection回调比状态通知回调要早来,而且要等到状态回调回来了,才能拿到服务。

6. 其实这里还需要做一个连接设备的限制,当超过最大连接设备个数后,就直接返回失败。很多安卓平台当同时连接的设备个数超过了一定数量(3~5)个的样子,就会出问题。

7. connect实现

/**
* 连接指定的设备
* @param {string} deviceId 蓝牙设备ID
* @param {function} cb 连接状态回调,参数1为设备id,参数2连接状态
*/
function connect(deviceId, timeout, cb) {
    if (!bleInitFlag || bleConDevArr.length>BLE_CON_MAX_NUM) {
        if (typeof cb == "function") {
            cb(deviceId, BLE_CON_FAIL);
        }
    }


    // 在连接数组里面查找该设备是否已经处理正在连接或者连接成功的状态
    var index = findDevIndexInArrByDevId(deviceId);


    if (index >= 0) {  // 如果在列表中存在,判断该设备状态
        if (bleConDevArr[index].devStatus == BLE_CON_SUCCESS) { // 连接成功状态
            if (typeof cb == "function") {
                cb(deviceId, BLE_CON_SUCCESS);
            }
        } else {    // 正在连接状态,直接返回重复连接
            console.log("重复连接", deviceId);
            if (typeof cb == "function") {
                cb(deviceId, BLE_CON_ING);
            }
        }
    } else { // 创建一个新连接
        bleConDevArr.push({
            devId: deviceId,
            devStatus: BLE_CON_ING,
            devCb: cb
        });


        wx.createBLEConnection({
            deviceId, // 搜索到设备的 deviceId
            timeout: timeout,
            success: () => {
                // 不在这里处理连接成功回调事件,在状态改变里面处理,等状态回调回来才算真正连接成功
                // if (typeof cb == "function") {
                //     cb(deviceId, BLE_CON_SUCCESS);
                // }
            },
            fail: () => {
                if (typeof cb == "function") {
                    cb(deviceId, BLE_CON_FAIL);
                    debug.Debug(BLE_MODULE_NAME, debug.DEBUG_DEBUG,"连接失败", deviceId);


                    // 连接失败删除设备
                    // 在连接数组里面查找该设备是否已经处理正在连接或者连接成功的状态
                    var index1 = findDevIndexInArrByDevId(deviceId);
                    if (index1 >= 0) {
                        debug.Debug(BLE_MODULE_NAME, debug.DEBUG_DEBUG,"连接失败,删除设备", bleConDevArr[index1].devId);
                        bleConDevArr.splice(index1, 1);
                    }
                }
            }
        });
    }
}

8. disconnect实现

/**
* 主动断开某个设备的连接
*/
function disconnect(deviceId, cb) {
    // 在连接数组里面查找该设备是否已经处于正在连接或者连接成功的状态
    var index = findDevIndexInArrByDevId(deviceId);


    if (index >= 0) {
        // 不在这里做设备删除操作,在状态回调里面去做,防止断开连接失败,但是有提前把设备删除了,那么这个资源就没有办法释放了
        // bleConDevArr.splice(index, 1); // 从数组中删除


        debug.Debug(BLE_MODULE_NAME, debug.DEBUG_DEBUG,"断开设备", deviceId);
        if (typeof cb == "function") {
            wx.closeBLEConnection({
                deviceId,
                success: (res) => { // 成功回调
                    cb(true);
                },
                fail: (res) => { // 失败回调
                    cb(false);
                }
            });
        } else {
            wx.closeBLEConnection({deviceId});
        }
    } else {
        if (typeof cb == "function") {
            cb(false);
        }
    }
}

9. BLE连接状态回调 

// 设备连接状态监听回调
      wx.onBLEConnectionStateChange(function(res) {
        debug.Debug(BLE_MODULE_NAME, debug.DEBUG_DEBUG, `device ${res.deviceId} state has changed, connected: ${res.connected}`)
        
        // 在连接数组里面查找该设备是否已经处理正在连接或者连接成功的状态
        var index = findDevIndexInArrByDevId(res.deviceId);


        if (index >= 0) {
            if (res.connected) {
                bleConDevArr[index].devStatus = BLE_CON_SUCCESS; // 连接成功,更改设备状态


                if (typeof bleConDevArr[index].devCb == "function") {
                    bleConDevArr[index].devCb(bleConDevArr[index].devId, BLE_CON_SUCCESS);
                }
            } else {
                if (typeof bleConDevArr[index].devCb == "function") {
                    bleConDevArr[index].devCb(bleConDevArr[index].devId, BLE_CON_FAIL);
                }


                debug.Debug(BLE_MODULE_NAME, debug.DEBUG_DEBUG,"设备断开,删除设备", bleConDevArr[index].devId);
                bleConDevArr.splice(index, 1); // 断开连接,直接从数组中删除
            }
        }
      });

10. 然后在设备列表元素点击事件中,添加跳转到设备操作界面的代码,页面参数为当前设备的ID

// “保留当前页面,跳转到应用内的某个页面”,并且带一个返回按键,可传递参数
    wx.navigateTo({
      url: '../blectr/blectr?devId='+e.currentTarget.id
    });

 11. 然在blectr.js的onLoad函数中,解析出该设备ID,并去执行连接操作

/**
     * 生命周期函数--监听页面加载
     */
    onLoad: function (options) {
        debug.Debug(BLECTR_MODUAL_NAME,debug.DEBUG_DEBUG,"page onLoad", options);
        
        this.userData.currDevId = options.devId;
        // 根据devId去连接设备
        this.conDev();
    },

         这里新增了一个conDev函数和disConDev函数,该函数回去执行连接/断开操作,并把连接状态和设备操作按键的状态给关联起来。按键会有未连接、连接中、断开三种状态。

conDev: function() {
        debug.Debug(BLECTR_MODUAL_NAME, debug.DEBUG_DEBUG, "开始连接设备", this.userData.currDevId);


        this.data.bleCtrButtonObj.loadingFlag = true;
        this.data.bleCtrButtonObj.text = "连接中";
        this.setData({["bleCtrButtonObj"]: this.data.bleCtrButtonObj});


        ble.connect(this.userData.currDevId, BLECTR_BLE_CON_TIMEOUT,
            (deviceId, status) => {
                if (deviceId != this.userData.currDevId) {
                    return;
                }


                if (status == ble.BLE_CON_ING) {
                    // this.data.bleCtrButtonObj.loadingFlag = true;
                    // this.data.bleCtrButtonObj.text = "连接中";
                    // this.setData({["bleCtrButtonObj"]: this.data.bleCtrButtonObj});
                } else if (status == ble.BLE_CON_SUCCESS) {
                    this.data.bleCtrButtonObj.loadingFlag = false;
                    this.data.bleCtrButtonObj.text = "断开";
                    this.setData({["bleCtrButtonObj"]: this.data.bleCtrButtonObj});
                } else {
                    this.data.bleCtrButtonObj.loadingFlag = false;
                    this.data.bleCtrButtonObj.text = "未连接";
                    this.setData({["bleCtrButtonObj"]: this.data.bleCtrButtonObj});
                }
            }
        )
    },

    disConDev: function() {
        debug.Debug(BLECTR_MODUAL_NAME, debug.DEBUG_DEBUG, "断开设备", this.userData.currDevId);


        ble.disconnect(this.userData.currDevId,
            (res) => {
                if (res) {
                    this.data.bleCtrButtonObj.loadingFlag = false;
                    this.data.bleCtrButtonObj.text = "未连接";
                    this.setData({["bleCtrButtonObj"]: this.data.bleCtrButtonObj});
                }
            }
        );
    },

12. 当然在onUnload函数中需要去判断当前设备是否处于连接状态,如果是,就断开,防止页面退出了,设备还保持连接

/**
     * 生命周期函数--监听页面卸载
     */
    onUnload: function () {
        debug.Debug(BLECTR_MODUAL_NAME,debug.DEBUG_DEBUG,"page onUnload");
        // 如果当前设备处于连接状态,退出该页面的时候,要去处理


        // 断开连接
        var status = ble.getDevConStaus(this.userData.currDevId);
        if (status == ble.BLE_CON_SUCCESS || status == ble.BLE_CON_ING) {
            ble.disconnect(this.userData.currDevId);
        }
    },

13. 到此设备连接相关操作就完成了,后面就是获取服务列表和特征值列表,并且进行读写操作了。