1. 程式人生 > >小程式藍芽親身總結

小程式藍芽親身總結

問題:

最近做了一個涉及到藍芽模組小程式,做一下總結,為自己的成長做一份記錄,如果能幫到大家的話是再好不過的了;

1.小程式藍芽搜尋能不能搜到手機裝置 2.如何判斷藍芽是否開啟 3.搜尋指定裝置 4.開發者工具和 Android 上獲取到的deviceId為裝置 MAC 地址,iOS 上則為裝置 uuid。因此deviceId不能硬編碼到程式碼中, 如何連線藍芽 5.裝置服務所有 service(服務) 如何去選擇 6.裝置characteristic(特徵值)幹嘛的,怎麼用 7.開啟notify 8.寫入資料

1.小程式藍芽搜尋能不能搜到手機裝置

搜不到!!! 小程式藍芽只支援BLE低功耗藍芽 什麼是低功耗藍芽裝置呢?百度一下,你就知道(^__^

) 嘻嘻

2.如何判斷藍芽是否開啟

利用wx.openBluetoothAdapter(OBJECT)判斷藍芽是否可用 在使用者藍芽開關未開啟或者手機不支援藍芽功能的情況下,呼叫wx.openBluetoothAdapter會返回錯誤,表示手機藍芽功能不可用;

wx.openBluetoothAdapter({
  success: function (res) {
    console.log(res)
  },
  fail: function (res) {
      wx.showModal({
           content: '請開啟手機藍芽後再試'
       })
   }
})

注意:建議wx.openBluetoothAdapter(OBJECT)和wx.closeBluetoothAdapter(OBJECT)成對使用 wx.closeBluetoothAdapter:關閉藍芽模組,使其進入未初始化狀態。呼叫該方法將斷開所有已建立的連結並釋放系統資源;

3.搜尋指定裝置

wx.startBluetoothDevicesDiscovery(OBJECT)開始搜尋附近的藍芽外圍裝置wx.getBluetoothDevices(OBJECT)獲取在小程式藍芽模組生效期間所有已發現的藍芽裝置wx.onBluetoothDeviceFound(CALLBACK) 監聽尋找到新裝置的事件

注意:搜尋藍芽wx.startBluetoothDevicesDiscovery(OBJECT)操作比較耗費系統資源,在搜尋並連線到裝置後呼叫 wx.stopBluetoothDevicesDiscovery(OBJECT) 方法停止搜尋

//開始搜尋藍芽
    wx.startBluetoothDevicesDiscovery({
        success: function (res) {
            console.log('search', res)
        }
    })
//發現裝置
      wx.getBluetoothDevices({
         success: function (res) {
            console.log('發現裝置', res)
            if (res.devices[0]) { 
                console.log(that.ab2hext(res.devices[0].advertisData))                                      
            }
            //5s內未搜尋到裝置,關閉搜尋,關閉藍芽模組
            setTimeout(function(){
                  if (!that.data.deviceId){
                      wx.hideLoading()
                      app.showToast('搜尋裝置超時','none');
                      //關閉搜尋
                      that.stopBluetoothDevicesDiscovery();
                      //關閉藍芽
                      that.closeBluetoothAdapter();
                  }
             },5000)
         }
      })
    //監聽發現裝置
    wx.onBluetoothDeviceFound(function (devices) {
        console.log('發現裝置:', devices.devices)
        for (let i = 0; i < devices.devices.length; i++) {
            //檢索指定裝置
            if (devices.devices[i].name == '裝置name') {
                that.setData({
                    deviceId: devices.devices[i].deviceId
                })
                //關閉搜尋
                that.stopBluetoothDevicesDiscovery();
                console.log('已找到指定裝置:', devices.devices[i].deviceId);  
             }
          }
     })
     ab2hext: function(buffer) {
            var hexArr = Array.prototype.map.call(
                new Uint8Array(buffer),
                function (bit) {
                    return ('00' + bit.toString(16)).slice(-2)
                }
            )
            return hexArr.join('');
       }

這段程式碼是通過裝置名name去匹配配對裝置,若5s內未搜到指定裝置則關閉搜尋,關閉藍芽模組; 裝置名是已發現的藍芽裝置device 物件中的name這裡寫圖片描述

4.開發者工具和 Android 上獲取到的deviceId為裝置 MAC 地址,iOS 上則為裝置 uuid。因此deviceId不能硬編碼到程式碼中,如何連線藍芽

搜尋我們可以拿到了裝置的deviceId,通過deviceId去連線藍芽Android 上獲取到的deviceId為裝置 MAC 地址iOS 上獲取到的deviceId則為裝置 uuid,因此deviceId不能硬編碼到程式碼中 那麼可能就有機智的小夥伴說了,設定兩個變數,一個為裝置MAC,一個為裝置uuid 在連線裝置的之前判斷下機型,ios裝置deviceId取:裝置uuidandroid裝置deviceId:MAC地址!!! 我原本也是這樣想的,因為我們做的這個小程式是掃碼連線指定裝置(就好像共享單車一樣),所以本來是想在二維碼中直接放入mac和uuid然後連線的時候去根據機型去取對應值 但是!!!但是!!!但是!!! 在實現過程中發現,ios不同手機搜尋到的裝置deviceId還是不同的. 所以還是乖乖通過裝置name(廣播名),去獲取deviceId去連線這裡寫圖片描述這裡寫圖片描述 只怪自己經驗不足,還總想走捷徑 正確的流程是 初始化藍芽wx.openBluetoothAdapter(OBJECT) ↓ 開始搜尋藍芽 wx.startBluetoothDevicesDiscovery(OBJECT) ↓ 所有已發現的藍芽裝置wx.getBluetoothDevices(OBJECT) ↓ 監聽尋找到新裝置的事件wx.onBluetoothDeviceFound(CALLBACK) ↓ 連線低功耗藍芽裝置wx.createBLEConnection(OBJECT) ↓ 獲取藍芽裝置所有 service(服務) wx.getBLEDeviceServices(OBJECT) ↓ 獲取藍芽裝置某個服務中的所有 characteristic(特徵值)wx.getBLEDeviceCharacteristics(OBJECT) ↓ 啟用低功耗藍芽裝置特徵值變化時的 notify 功能wx.notifyBLECharacteristicValueChange(OBJECT) ↓ 寫入wx.writeBLECharacteristicValue(OBJECT)

在搜尋到裝置後通過拿到的裝置的deviceId去連線裝置

wx.createBLEConnection({
    deviceId: that.data.deviceId,//搜尋裝置獲得的藍芽裝置 id
    success: function (res) {
        console.log('連線藍芽:', res.errMsg);
    },
    fail: function (res) {
        app.showToast('連線超時,請重試或更換車輛', 'none');
        that.closeBluetoothAdapter();
    }
})

5.serviceId如何去選擇

連線成功以後就可以去獲取裝置的服務列表,我這邊拿的是FEE7的服務ID

wx.getBLEDeviceServices({
  deviceId: that.data.deviceId,//搜尋裝置獲得的藍芽裝置 id
  success: function (res) {        
    let service_id = "";
    for(let i = 0;i<res.services.length;i++){
      if(services[i].uuid.toUpperCase().indexOf("FEE7") != -1){
        service_id = services[i].uuid;
        break;
      }
    }
     console.log('fee7-service_id:', that.data.service_id);
  },
  fail(res){
    console.log(res);
  }
})

6.characteristic(特徵值)幹嘛的,怎麼用

服務特徵值是幹嘛的:每個服務都包含了一組特徵值用來描述服務的一些屬性,獲取是否可讀,是否可寫,是否可以開啟notify通知等,當你跟藍芽通訊時需要這些特徵值ID來傳遞資料。服務特徵值怎麼用

//獲取特徵值
wx.getBLEDeviceCharacteristics({
    deviceId: that.data.deviceId,//搜尋裝置獲得的藍芽裝置 id
    serviceId: that.data.service_id,//服務ID
    success: function (res) {
        console.log('device特徵值:', res.characteristics)
        for (let i = 0; i < res.characteristics.length; i++) {
            let charc = res.characteristics[i];
            if (charc.properties.indicate) {
                that.setData({indicate_id: charc.uuid});
                console.log('indicate_id:', that.data.indicate_id);
            }
            if (charc.properties.write) {
                that.setData({write_id: charc.uuid});
                console.log('寫write_id:', that.data.write_id);
            }
            if (charc.properties.read) {
                that.setData({read_id: charc.uuid});
                console.log('讀read_id:', that.data.read_id);
            }
        }
   }
});

篩選出你所需要的服務特徵值 在得到對應特徵值後可以在執行相關操作時使用 例如: 開啟notify:必須裝置的特徵值支援notify或者indicate才可以成功呼叫 支不支援notify或者indicate就是我們上面篩選出來的對應值

 if (charc.properties.indicate) {
     that.setData({indicate_id: charc.uuid});
     console.log('indicate_id:', that.data.indicate_id);
 }

7.開啟notify

開啟notify後可以監聽低功耗藍芽裝置的特徵值變化。必須先啟用notify接口才能接收到裝置推送的notification

//開啟notify
wx.notifyBLECharacteristicValueChange({
    state: true, // 啟用 notify 功能
    deviceId: that.data.deviceId,//藍芽裝置id
    serviceId: that.data.service_id,//服務id
    characteristicId: that.data.indicate_id,//服務特徵值indicate
    success: function (res) {
        console.log('開啟notify', res.errMsg)
        //監聽低功耗藍芽裝置的特徵值變化
        wx.onBLECharacteristicValueChange(function (res) {
            console.log('特徵值變化', that.arrayBufferToHexString(res.value));
        })
        //寫入資料

    }
});

8.如何寫入資料

如何寫入資料呢,通過獲取到的write特徵值write_id注意:必須裝置的特徵值支援write才可以成功呼叫

 let buffer = that.hexStringToArrayBuffer(ArrayBuffer);
 //寫入資料
 wx.writeBLECharacteristicValue({
     deviceId: that.data.deviceId,//裝置deviceId
     serviceId: that.data.service_id,//裝置service_id
     characteristicId: that.data.write_id,//裝置write特徵值
     value: buffer,//寫入資料
     success: function (res) {
         console.log('傳送資料:', res.errMsg)
     }
 });
 hexStringToArrayBuffer:function (str) {
        if(!str) {
            return new ArrayBuffer(0);
        }
        var buffer = new ArrayBuffer(str.length);
        let dataView = new DataView(buffer)
        let ind = 0;
        for (var i = 0, len = str.length; i < len; i += 2) {
            let code = parseInt(str.substr(i, 2), 16)
            dataView.setUint8(ind, code)
            ind++
        }
        return buffer;
 }

總結:有幾點特別需要注意,快拿出小本本1.IOS裡面藍芽狀態變化以後不能馬上開始搜尋,否則會搜尋不到裝置,必須要等待2秒以上2.開啟notify以後並不能馬上傳送訊息,藍芽裝置有個準備的過程,需要在setTimeout中延遲1秒以上才能傳送,否則會發送失敗

setTimeout(function () {
   wx.writeBLECharacteristicValue({
     deviceId: that.data.deviceId,
     serviceId: that.data.service_id,
     characteristicId: that.data.write_id,
     value: buffer,
     success: function (res) {
         console.log('傳送資料:', res.errMsg)
     }
 });
}, 1100);

3.搜尋到裝置後記得釋放資源stopBluetoothDevicesDiscovery4.不需要使用藍芽的時候一定要關閉藍芽.wx.openBluetoothAdapter(OBJECT)和wx.closeBluetoothAdapter(OBJECT)成對使用