1. 程式人生 > >微信小程式藍芽模組遇到的坑

微信小程式藍芽模組遇到的坑

測試手機:
手機名稱:iPhone 5s
版本:10.3.1
微信版本:6.5.7
藍芽:4.0

手機名稱:iPhone 6
版本:10.3.1
微信版本:6.5.7
藍芽:4.0

手機名稱:iPhone 6s
版本:10.3.1
微信版本:6.5.7
藍芽:4.2

手機名稱:紅米note
安卓版本:Android 4.4.4
微信版本:6.5.7
藍芽:4.0

手機名稱:小米mix
安卓版本:Android 6.0.1
微信版本:6.5.7
藍芽:4.2

首先說下流程:
openBluetoothAdapter(初始化藍芽介面卡)—》 wx.startBluetoothDevicesDiscovery(開始搜尋附近的藍芽外圍裝置)——》wx.getBluetoothDevices(獲取所有已發現的藍芽裝置)——》wx.createBLEConnection(連線裝置)——》wx.getBLEDeviceServices(獲取藍芽裝置所有 service(服務))——》wx.getBLEDeviceCharacteristics(獲取notify 特徵值)——》wx.notifyBLECharacteristicValueChange(開啟notify)——》 wx.onBLECharacteristicValueChange(監聽低功耗藍芽裝置的特徵值變化)——》wx.getBLEDeviceCharacteristics(獲取write特徵 )——》wx.writeBLECharacteristicValue(傳送 資料到裝置中)

整個流程就這樣,因為開啟了onBLECharacteristicValueChange,所以你在寫入資料(writeBLECharacteristicValue)的時候,裝置應答的資料就被監測到了,也就是說,最終最終獲取的資料是在wx.onBLECharacteristicValueChange這個介面中的。
我們來看看官方的例子:

// 向藍芽裝置傳送一個0x00的16進位制資料
let buffer = new ArrayBuffer(1)
let dataView = new DataView(buffer)
dataView.setUint8(0, 0)

wx.writeBLECharacteristicValue({
// 這裡的 deviceId 需要在上面的 getBluetoothDevices 或 onBluetoothDeviceFound 介面中獲取
deviceId: deviceId,
// 這裡的 serviceId 需要在上面的 getBLEDeviceServices 介面中獲取
serviceId: serviceId,
// 這裡的 characteristicId 需要在上面的 getBLEDeviceCharacteristics 介面中獲取
characteristicId: characteristicId,
// 這裡的value是ArrayBuffer型別
value: buffer,
success: function (res) {
console.log(‘writeBLECharacteristicValue success’, res.errMsg)
}
})
這裡得解釋一下ArrayBuffer:ArrayBuffer物件不提供任何直接讀寫記憶體的方法,只允許在其上方建立檢視,然後通過檢視讀寫

(來自http://blog.csdn.net/lichwei1983/article/details/43893025
但是我們傳的值是buffer,當你console.log(buffer)的時候,出來的是一個空物件就對了,因為上面那句話已經解釋了:不提供任何直接讀寫記憶體的方法。其實資料已經寫到buffer中的了,只是console.log(buffer)不能直接打印出來而已(空物件)。在我們的小程式中,通過writeBLECharacteristicValue其實已經把資料包傳送出去了,回撥也是success,那我們就可以大膽地在notifyBLECharacteristicValueChange的監聽事件中拿value了(前提是你寫入藍芽服務通道以及指令是正確的),只不過需要多做一件事情,藉助Dataview才能把資料拿出來,跟寫入也是一樣的(直接列印characteristic也是空的):

 wx.notifyBLECharacteristicValueChange({
        deviceId: that.data.deviceId,  //裝置mac   IOS和安卓系統不一樣
        serviceId: that.data.notifyServiceId,     //服務通道,這裡主要是notify
        characteristicId: that.data.cd01,     //notify uuid
        state: true,
        success: function (res) {
            console.log("開啟notify 成功")
            //TODO  onBLECharacteristicValueChange  監聽特徵值 裝置的資料在這裡獲取到
                wx.onBLECharacteristicValueChange(function (characteristic) {
                    console.log('characteristic value comed:')
                    let buffer = characteristic.value
                    let dataView = new DataView(buffer)
                    let dataResult = []
                    console.log("拿到的資料")
                    console.log("dataView.byteLength", dataView.byteLength)
                    for (let i = 0; i < dataView.byteLength; i++) {
                        console.log("0x" + dataView.getUint8(i).toString(16))
                        dataResult.push(dataView.getUint8(i).toString(16))
                    }
                    const result = dataResult
                })
        },
        fail: function (res) {}
    })

IOS確實可以很順利拿到data,但是對於我們的安卓系統呢?裡面有一個坑,我自己掉坑裡很久都出不來,直到一個同事的指導:

  bindViewTap: function () {
        var that = this;
        let buffer = new ArrayBuffer(5)
        let dataView = new DataView(buffer)
        //寫入通道指令 
        dataView.setUint8(0, 0x1B)    //這裡也能寫十進位制數
        dataView.setUint8(1, 0x11)    //...
        dataView.setUint8(2, 0x03)
        dataView.setUint8(3, 0x00)
        dataView.setUint8(4, 0x00)

        console.log("傳送的資料:")
        for (let i = 0; i < dataView.byteLength; i++) {
            console.log("0x" + dataView.getUint8(i).toString(16))
        }

        wx.writeBLECharacteristicValue({
            deviceId: that.data.deviceId,
            serviceId: that.data.writeServiceId,
            characteristicId: that.data.cd20,    //write
            value: buffer,
            success: function (res) {
                console.log("success  指令傳送成功");
            },
            fail: function (res) {
                // fail
                console.log(res);
            }
        })

    /**
     * 坑就在這裡了,對於安卓系統,需要新增下面這段程式碼。你寫完資料後,還必須讀一次,才能被onBLECharacteristicValueChange監聽到,才會把資料返回給你,
     * 但在蘋果系統裡面就不能有下面這段程式碼了,因為如果你新增上去的話,會出現發一次指令出現兩次返回值的情況
     */
        wx.readBLECharacteristicValue({
            deviceId: that.data.deviceId,
            serviceId: that.data.notifyServiceId,
            characteristicId: that.data.cd01,
            success: function (res) {
                console.log('readBLECharacteristicValue')
            }
        })

    }
})

但這裡還得說一下,測試結果是API對IOS系統支援良好。但對於安卓系統,低版本(藍芽4.0以上,系統4.x.x)的情況是,雖然能拿到資料,但是有時候不知道是手機太老的問題還是API不穩定的問題,拿到的資料有時候不全。然而對於6.x.x的安卓系統(藍芽也是4.x以上)則是完全拿不到資料,這個很奇怪,原因尚不清楚,好大個坑啊,也歡迎各位解答一下

不足之處,請各位朋友指正