1. 程式人生 > >微信小程式:藍芽BLE連線10003問題分析及解決

微信小程式:藍芽BLE連線10003問題分析及解決

10003是微信藍芽連線經常碰到的問題,微信官方給出的文件中就簡單的描述為“connection fail”,備註為“連線失敗”。然而,實際上出現10003的狀況有很多,比如根據deviceId連線藍芽時,藍芽裝置未開啟或異常導致無法連線;藍芽裝置被佔用或者上次藍芽連線未斷開導致無法連線;出現該錯誤後,去微信官方社群尋求幫助,在社群發現了整整4頁(將近40條)都是反饋該問題,然而都沒有得到官方答覆,有極個別解決了的也不適用於我的情況;於是,只有自己分析。

###問題描述:
1.啟動app,搜尋並連線藍芽成功後,第一次採集資料正常;
2.下次採集如果手機藍芽是開啟的,也能正常採集;
3.但如果手機藍芽關閉,點選採集資料試圖連線,提示使用者開啟手機藍芽;當開啟手機藍芽後再去連線藍芽,此時會連線不上,報錯10003;
4.後續會一致連不上藍芽,不管是重啟小程式還是重新關閉開啟藍芽,都不能正常連線藍芽裝置。
###問題定位
1.復現問題,根據測試提供的方法,先測試iphone正常,三星S7edge,結果是能正常連線藍芽,後來又測試vivo x7plus和小米MI5,終於成功復現該問題;
2.針對10003錯誤在微信開發社群找解決方案,可是面對著幾十條相似問題,幾乎都沒有得到解決,有幾條說在連線前先呼叫wx.closeBLEConnection斷開上次連線,嘗試後,不能解決我的問題;
3.既然沒有找到現成的解決方案,就只有跟蹤程式碼了,在關鍵方法中加日誌;發現,在頂部欄關閉手機藍芽時,小程式中無法斷開藍芽連線,報錯(10001(not available)當前藍芽介面卡不可用);
4.後來又在偶然情況下,清除了藍芽裝置的繫結關係,重新進入藍芽搜尋頁面,發現這樣操作後竟然能成功連線上藍芽。
###問題修復
上述問題定位中,(3)可以發現應該是沒有斷開上次藍芽連線導致的,(4)又發現,重新搜尋藍芽以後再連線可以解決該問題;
於是按照這兩個方向去找解決方案:
1.既然是因為沒有斷開藍芽連線導致的,那就在關閉手機藍芽時去斷開藍芽;然而,在藍芽狀態監聽中呼叫斷開連線函式,返回錯誤(10001(not available)當前藍芽介面卡不可用);
2.於是只能考慮重新搜尋藍芽後再連線的方法,在出現10003錯誤後,重新搜尋藍芽,並且在找到對應的裝置後進行藍芽連線;修改程式碼反覆測試,根據日誌顯示,確實是出現了10003,然後進入搜尋模組,搜到指定裝置後進行藍芽連線,之後連線成功,這個方案解決了該問題。

wx.createBLEConnection({
    deviceId: deviceId,
    success: function (res) { //連線成功
      initnotifyCharacteristic(notifyCharacteristic);// 指定特徵值,並進行資料互動
      // 已連線
      _bthConnectStaus = BTH_STATUS_CONNECTED;
    },
    fail: function (res) {// 連線藍芽失敗
      _bthConnectStaus = BTH_STATUS_DISCONNECT;
      // 回撥上層藍芽連線失敗
      callback(res.errCode, "connect failed")
    }

然後根據fail中的res.errCode判斷是否10003。

if(code == 10003) { //  部分android手機特殊情況下需要重新搜尋才能連線藍芽,此時報錯10003,進行藍芽搜尋(ps:原因可能是系統中將手機藍芽關閉導致連線狀態不能改為斷開,導致下次無法連線同一個裝置)
    var timeId = setTimeout(function () {
      stopSearchBluetooth();
      callback(false, "timout")
    }, 5000); // 最多搜尋5s
    searchBluetooth(function (res) {
      if (res.devices === undefined || res.devices === null) {
        return;
      }
      for (var i = 0; i < res.devices.length; i++) {
        if (res.devices[i] && res.devices[i].deviceId == deviceId) { // 搜尋到該裝置 
          console.log("searchDeviceAndReConnect:find device and re connect");
          clearTimeout(timeId);
          stopSearchBluetooth() // 停止搜尋
          callback(true, "find device");// 找到裝置,在回撥函式中連線藍芽
          break;
        }
      }
    }, function (res) {
      clearTimeout(timeId);
      stopSearchBluetooth() // 停止搜尋
      callback(false, "searchBluetooth fail")
    });
  }

上述程式碼提供了一個簡單的流程,當連接出現10003錯誤時,搜尋藍芽裝置,找到後,重新連線藍芽。
考慮到只有部分手機出現10003錯誤,所以會先連線一次藍芽,報錯10003才進行,以免其他手機會因為搜尋藍芽導致連線藍芽採集資料的速度減慢;
當然10003,不只是該問題才報的錯,所有,在裝置沒有開啟藍芽時也報10003,而因為加了搜尋邏輯,在裝置沒有開啟藍芽時的提醒就會慢一點(裝置藍芽沒開啟需要提醒使用者開啟裝置藍芽),不過好在這一點影響不大,目前沒有好的思路去解決,後續再慢慢研究。

該方法僅解決了我這種情況,10003出現的情況很多,不過基本上可以從上一次藍芽連線是否結束來定位,重新搜尋藍芽後進行連線也是基於上次藍芽連線未斷開這一情況

###相關問題
1.微信小程式藍芽連線僅支援4.0,而BLE低功耗藍芽裝置是帶有定位功能的,所以,需要有定位許可權,部分手機(如vivo x7plus)需要開啟手機定位功能才能搜尋到藍芽裝置,詳細可百度 “Android6.0藍芽BLE連線,定位動態許可權相關”
2.根據services呼叫wx.startBluetoothDevicesDiscovery搜尋藍芽時,如果搜尋不到,可以去掉services試試,我的一臺測試機(印象中是華為P6)就出現帶services搜尋不到裝置,最後只能去掉services, 然後在搜尋到的結果中進行過濾
3.wx.startBluetoothDevicesDiscovery搜尋藍芽時,一般人都知道使用wx.onBluetoothDeviceFound,然後部分手機在短時間內進行第二次搜尋onBluetoothDeviceFound回撥中不能得到所有的裝置,此時可以試試wx.getBluetoothDevices,這個方法可以獲取到快取的藍芽裝置,這一部分快取的藍芽裝置在部分手機中不會再出現在wx.onBluetoothDeviceFound中
4.連線藍芽後,在進行寫操作時,如果寫失敗,請檢查是否設定了characteristicId,這個特徵值每次做寫操作時都要帶上

原文:簡書ThinkinLiu 部落格: IT老五

Android機型多,BLE低功耗藍芽也不是很穩定,這就導致了在Android上開發藍芽會有很多奇怪的問題,而微信小程式基於Android和IOS,相應的也會出現一些問題,IOS還好,系統軟硬體都單一,但Android的問題就多了,之前開發還遇到一些需要注意的,暫時想不起來,後續再補充