微信小程式BLE踩坑記錄

Loren1994發表於2018-08-31

小程式BLE踩坑記錄

前往官方文件

專案描述

手機小程式通過BLE向android裝置傳送WIFI名稱/密碼等資訊,裝置收到後自動聯網。

專案流程

裝置首先新增自定義服務UUID和特徵UUID。

使用者預先連線WiFi、自動獲取當前WiFi名稱、使用者填寫當前WiFi密碼、

初始化藍芽、掃描BLE、獲取掃描到的裝置、點選連線BLE裝置、獲取該裝置的所有服務UUID、

獲取目標服務UUID的所有特徵值、根據裝置ID,特定服務UUID,特定特徵值UUID寫入資料。

寫入資料特殊部分
  • IOS:不需要分包傳送,傳送資料無限制,資料多傳送時間削微變長。
  • Android:單次最大傳送20位元組,所以需要分包傳送,且需要自己實現。
踩坑記錄
  • 掃描

掃描成功後,不要立馬呼叫停止掃描,不然在遠端除錯的時候一切正常,預覽或者釋出之後顯示搜尋到的結果列表長度為0。

  • 獲取掃描結果

該專案掃描場景是已進入頁面自動掃描,測試時wx.getBluetoothDevices每次都是一進入時搜不到,點選重新掃描便可以立馬搜尋到。建議使用wx.onBluetoothDeviceFound獲取掃描結果,但需要自行去重和過濾。掃描時間持續比較長,可以在點選連線時先用wx.stopBluetoothDevicesDiscovery停止掃描。

//去重及過濾
wx.onBluetoothDeviceFound(function (obj) {
  var temp = _this.data.scanDevices
  if (obj.devices[0].name) {
    obj.devices.map(dev => {
      let pDev = temp.find((it) => {
        return it.deviceId == dev.deviceId
      })
      if (!pDev) {
        temp.push(dev)
      }
    })
  }
  _this.setData({
    scanDevices: temp
  })
})
複製程式碼
  • 連線裝置

遇到過連線一直操作超時,errCode10003,這裡的原因很多,官方的討論也很多,這裡我重啟了一次裝置就好了,因此可能是裝置問題,也可能是連線例項太多導致,最好傳送完資料後用wx.closeBLEConnection關閉連線。

  • 寫資料

寫資料是需要用到deviceId,serviceUUID,characteristicUUID,這三個值都必須通過Api獲取,我試過不走Api,直接填入serviceUUID,characteristicUUID,結果寫入失敗。也可能是大小寫和分隔符“-”的問題,不過最好是通過Api去拿值。還有,傳送的資料需要轉為ArrayBuffer格式。

//字串轉ArrayBuffer
char2buf(str) {
  var out = new ArrayBuffer(str.length)
  var u8a = new Uint8Array(out)
  var strs = str.split("")
  for (var i = 0; i < strs.length; i++) {
    u8a[i] = strs[i].charCodeAt()
  }
  return out
}
複製程式碼
  • 分包

整體思路為:

將傳送的資料分為多條資料,儲存到一個全域性陣列中,迴圈傳送每一條資料,傳送一條後在傳送成功的回撥中進行下一條資料傳送,若其中一條失敗,則從頭重新開始。這裡傳送用的遞迴。特別注意的是,android每次傳送後必須延時一段時間再傳送下一條資料,不然會寫入失敗,推薦延時250ms。

一個包資料為20位元組,但實際上單次可供傳送的只有18位元組,所以按照18去分包。

還需要對資料進行分割,這裡每種資料使用||分割,使用#end作為結束識別符號。裝置監測到有此識別符號則開始聯網。

//遞迴
writeData: function (devId, serviceId, charaId) {
    var _this = this
    if (_this.data.sendNum >= _this.data.sendDataList.length) {
      wx.closeBLEConnection({
        deviceId: devId,
        success: function (res) {
          console.log(res)
        }
      })
      wx.hideLoading()
      wx.showToast({
        title: '傳送成功',
        icon: 'success',
        duration: 2000
      })
      return
    }
    wx.writeBLECharacteristicValue({
      deviceId: devId,
      serviceId: serviceId,
      characteristicId: charaId,
      value: _this.data.sendDataList[_this.data.sendNum],
      success: function (res) {
        console.log('寫入成功', res.errMsg)
        setTimeout(function () {
          _this.data.sendNum++
          console.log(_this.data.sendNum)
          _this.writeData(devId, serviceId, charaId)
        }, 250)
      },
      fail: function (res) {
        console.log(res)
        _this.setData({
          sendNum: 0
        })
      }
    })
  }
複製程式碼

完整BLE程式碼

實際上#end和||分割存在bug,若資料中含有此類字元會導致裝置端接收資料錯誤。此處不再深究。

專案地址

相關文章