小程序藍牙

一、創建 bluetoothUtil.js 工具文件

二、藍牙連接代碼如下

const util = require('util.js')
//初始化藍牙模塊。iOS 上開啓主機/叢機模式時需分別調用。
const openBluetoothAdapter = (mac) => {
     wx.showLoading({
          title: '藍牙連接中',
     })
     var timeOut = setTimeout(function () {
          wx.hideLoading()
          wx.showToast({
               title: '藍牙連接超時',
               icon: 'none',
               duration: 3000
          })
     }, 60000)
     let promise = new Promise((resolve, reject) => {
          wx.openBluetoothAdapter({
               success: (res) => {
                    console.log('openBluetoothAdapter success', res)
                    setTimeout(function () {
                         startBluetoothDevicesDiscovery().then(
                              success => {
                                   var device = wx.getStorageSync('device')
                                   if (mac) {
                                        setTimeout(function () {
                                             onBluetoothDeviceFound(mac).then(
                                                  success => {
                                                       wx.hideLoading()
                                                       clearTimeout(timeOut)
                                                       resolve()
                                                  }, fail => {
                                                       clearTimeout(timeOut)
                                                       reject()
                                                  }
                                             )
                                        }, 500)
                                   } else if (device) {
                                        createBLEConnection(device).then(
                                             success => {
                                                  wx.hideLoading()
                                                  wx.showToast({
                                                       title: '連接成功',
                                                       duration: 2000
                                                  })
                                                  clearTimeout(timeOut)
                                                  resolve()
                                             },
                                             fail => {
                                                  wx.hideLoading()
                                                  console.log('藍牙連接失敗:' + JSON.stringify(fail))
                                                  wx.showToast({
                                                       title: '連接失敗',
                                                       icon: 'none',
                                                       duration: 2000
                                                  })
                                                  clearTimeout(timeOut)
                                                  reject()
                                             }
                                        )
                                   } else {
                                        wx.hideLoading()
                                        clearTimeout(timeOut)
                                        resolve()
                                   }
                              },
                              fail => {
                                   wx.hideLoading()
                                   clearTimeout(timeOut)
                                   reject()
                              }
                         )
                    }, 500)
               },
               fail: (res) => {
                    wx.hideLoading()
                    clearTimeout(timeOut)
                    reject()
               }
          })
     })
     return promise;
}

//開始搜尋附近的藍牙外圍設備。此操作比較耗費系統資源,請在搜索並連接到設備後調用 wx.stopBluetoothDevicesDiscovery 方法停止搜索
const startBluetoothDevicesDiscovery = () => {
     let promise = new Promise((resolve, reject) => {
          wx.startBluetoothDevicesDiscovery({
               allowDuplicatesKey: true,
               success: (res) => {
                    resolve()
               },
               fail: (res) => {
                    console.log("開始收搜藍牙失敗:" + JSON.stringify(res))
                    reject()
               }
          })
     })
     return promise;


}

//停止搜尋附近的藍牙外圍設備。若已經找到需要的藍牙設備並不需要繼續搜索時,建議調用該接口停止藍牙搜索
const stopBluetoothDevicesDiscovery = () => {
     wx.stopBluetoothDevicesDiscovery({
          success: () => {
               console.log('停止收搜藍牙成功')
          },
          fail: () => {
               console.log('停止收搜藍牙失敗')
          }
     })
}

//監聽收搜到的藍牙設備
const onBluetoothDeviceFound = (mac) => {
     //是否在連接
     var canConnection = false;
     let promise = new Promise((resolve, reject) => {
          wx.onBluetoothDeviceFound((res) => {
               res.devices.forEach(device => {
                    if (!device.deviceId) {
                         return
                    }
                    if (!device.name && !device.localName) {
                         return
                    }
                    if (!device.advertisServiceUUIDs || device.advertisServiceUUIDs.length == 0) {
                         return
                    }
                    var advertisData = util.ab2hex(device.advertisData);
                    var MAC = advertisData.substring(4, 16)
                    if (!canConnection && MAC.replace(/:/g, "").toUpperCase() == mac.replace(/:/g, "").toUpperCase()) {
                         canConnection = true
                         device.manuId = advertisData.substring(0, 4)
                         device.advertisData = advertisData
                         device.serviceId = device.advertisServiceUUIDs[0]
                         wx.setStorageSync('device', device)
                         createBLEConnection(device).then(
                              success => {
                                   console.log('藍牙連接成功')
                                   wx.showToast({
                                        title: '連接成功',
                                        duration: 2000
                                   })
                                   resolve()
                              },
                              fail => {
                                   console.log('藍牙連接失敗:' + fail)
                                   wx.showToast({
                                        title: '連接失敗',
                                        icon: 'none',
                                        duration: 2000
                                   })
                                   reject()
                              }
                         )
                    }
               })
          })
     })
     return promise;
}

//連接低功耗藍牙設備。
//若小程序在之前已有搜索過某個藍牙設備,併成功建立連接,可直接傳入之前搜索獲取的 deviceId 直接嘗試連接該設備,無需進行搜索操作
const createBLEConnection = (device) => {
     stopBluetoothDevicesDiscovery()
     //判斷是否開啓藍牙綁定
     var advertisData = device.advertisData;
     let promise = new Promise((resolve, reject) => {
          if (wx.getStorageSync('bluetoothStatus') != 1) {
               wx.onBLEConnectionStateChange(function (res) {
                    if (res.connected) {
                         wx.setStorageSync('bluetoothStatus', 1)
                    } else {
                         wx.showToast({
                              title: '藍牙已斷開',
                              icon: 'none'
                         })
                         closeBluetoothAdapter()
                         console.log("藍牙斷開:" + JSON.stringify(res))
                         wx.setStorageSync('bluetoothStatus', 0)
                         hintOpenBluetooth()
                    }
               })
               const deviceId = device.deviceId
               wx.createBLEConnection({
                    deviceId,
                    success: (res) => {
                         device.blueBrdInfo = advertisData.toUpperCase().substring(4, advertisData.length - 4)
                         device.MAC = advertisData.substring(4, 16)
                         var sv_1 = util.sixToInt(advertisData.substring(18, 20));
                         var sv_2 = util.sixToInt(advertisData.substring(20, 22)) < 10 ? "0" + util.sixToInt(advertisData.substring(20, 22)) : util.sixToInt(advertisData.substring(20, 22));
                         var hv_1 = util.sixToInt(advertisData.substring(22, 24));
                         var hv_2 = util.sixToInt(advertisData.substring(24, 26)) < 10 ? "0" + util.sixToInt(advertisData.substring(24, 26)) : util.sixToInt(advertisData.substring(24, 26));
                         device.softwareVersion = sv_1 + "." + sv_2
                         device.hardwareVersion = hv_1 + "." + hv_2
                         wx.setStorageSync('device', device)
                         setTimeout(function () {
                              getBLEDeviceServices(device).then(
                                   success => {
                                        console.log('查詢所有服務成功')
                                        resolve()
                                   },
                                   fail => {
                                        console.log('查詢所有服務失敗:' + JSON.stringify(fail))
                                        reject()
                                   }
                              )
                         }, 500)
                    },
                    fail: (res) => {
                         console.log('創建連接失敗:' + JSON.stringify(res))
                         reject(res)
                    },
                    complete: () => {
                         console.log('創建連接完成')
                    }
               })
          }

     })
     return promise;

}

//關閉藍牙模塊。調用該方法將斷開所有已建立的連接並釋放系統資源。建議在使用藍牙流程後,與 wx.openBluetoothAdapter 成對調用。
const closeBluetoothAdapter = () => {
     wx.closeBluetoothAdapter()
}

//斷開 當前連接的藍牙設備
const closeBLEConnection = () => {
     var device = wx.getStorageSync('device')
     if (device) {
          wx.closeBLEConnection({
               deviceId: device.deviceId,
               success() {
                    console.log('斷開當前連接的藍牙設備成功')
               },
               fail() {
                    console.log('斷開當前連接的藍牙設備失敗')
               }
          })
     }
     closeBluetoothAdapter()
}
//刪除連接過的藍牙數據
const deleteBLEConnectionData = () => {
     wx.removeStorageSync('device')
     wx.removeStorageSync('characteristics')
     wx.removeStorageSync('bluetoothStatus')
}

//獲取藍牙設備所有服務(service)
const getBLEDeviceServices = (device) => {
     let promise = new Promise((resolve, reject) => {
          var deviceId = device.deviceId
          wx.getBLEDeviceServices({
               deviceId,
               success: (res) => {
                    console.log('所有服務:', res.services)
                    var serviceId = res.services[0].uuid
                    device.serviceId = serviceId
                    wx.setStorageSync('device', device)
                    getBLEDeviceCharacteristics(device, serviceId).then(
                         success => {
                              console.log('查詢特徵值成功')
                              resolve()
                         },
                         fail => {
                              console.log('查詢特徵值失敗:' + JSON.stringify(fail))
                              reject()
                         }
                    )
               },
               fail(res) {
                    console.log('查詢特徵值失敗:' + JSON.stringify(res))
                    reject()
               },
               complete() {
                    console.log('查詢特徵值完成')
               }
          })
     })
     return promise
}

//獲取藍牙設備某個服務中所有特徵值(characteristic)
const getBLEDeviceCharacteristics = (device, serviceId) => {
     let promise = new Promise((resolve, reject) => {
          var deviceId = device.deviceId
          wx.getBLEDeviceCharacteristics({
               deviceId,
               serviceId,
               success: (res) => {
                    console.log('getBLEDeviceCharacteristics success', res.characteristics)
                    var list = {}
                    for (let i = 0; i < res.characteristics.length; i++) {
                         let item = res.characteristics[i]
                         if (item.properties.notify || item.properties.indicate) {
                              var matchList = wx.getStorageSync('matchList')      
                              var  personType = wx.getStorageSync('personType')                         
                              if (personType == 2 && !(matchList.indexOf(device.MAC) > -1)) {
                                   if (item.uuid.indexOf('FF0B') > -1) {
                                        notifyBLECharacteristic(deviceId, serviceId, item.uuid)
                                   }
                              } else {
                                   notifyBLECharacteristic(deviceId, serviceId, item.uuid)
                              }
                         }
                         if (item.uuid.indexOf('FF01') > -1) {
                              list.FF01 = item.uuid
                         }
                         if (item.uuid.indexOf('FF02') > -1) {
                              list.FF02 = item.uuid
                         }
                         if (item.uuid.indexOf('FF03') > -1) {
                              list.FF03 = item.uuid
                         }
                         if (item.uuid.indexOf('FF04') > -1) {
                              list.FF04 = item.uuid
                         }
                         if (item.uuid.indexOf('FF05') > -1) {
                              list.FF05 = item.uuid
                         }
                         if (item.uuid.indexOf('FF06') > -1) {
                              list.FF06 = item.uuid
                         }
                         if (item.uuid.indexOf('FF07') > -1) {
                              list.FF07 = item.uuid
                         }
                         if (item.uuid.indexOf('FF08') > -1) {
                              list.FF08 = item.uuid
                         }
                         if (item.uuid.indexOf('FF09') > -1) {
                              list.FF09 = item.uuid
                         }
                         if (item.uuid.indexOf('FF0B') > -1) {
                              list.FF0B = item.uuid
                         }

                    }
                    wx.setStorageSync('characteristics', list)
                    resolve()
               },
               fail(res) {
                    reject()
                    console.log('getBLEDeviceCharacteristics', res)
               }
          })
     })
     return promise
}

/**啓動notify功能 */
const notifyBLECharacteristic = (deviceId, serviceId, characteristicId) => {
     let promise = new Promise((resolve, reject) => {
          wx.notifyBLECharacteristicValueChange({
               deviceId,
               serviceId,
               characteristicId: characteristicId,
               state: true,
               success(res) {
                    console.log('啓用notify功能成功:' + characteristicId)
                    resolve()
               },
               fail(res) {
                    console.log('啓用notify功能失敗:' + JSON.stringify(res))
                    reject()
               }
          })
     })
     return promise
}



var sendCurrentIndex = 0;
/**
 * 發送數據
 * data:16進制數據
 * deviceId:設備ID
 * serviceId:服務ID
 * characteristicId:特徵值ID
 */
const sendBluetoothData = (data, deviceId, serviceId, characteristicId) => {
     sendCurrentIndex = 0
     var list = []
     for (var i = 0; i < data.length; i += 2) {
          var it = data.substr(i, 2)
          list.push(it)
     }
     var total = list.length
     console.log("包的總長" + total)
     subpackage(0, total, list, deviceId, serviceId, characteristicId)
}

/**
 *  分包   
 * index: 當前發送的第幾個包
 * list: 按照2個字符存在的數據數組  
 * deviceId:設備ID
 * serviceId:服務ID
 * characteristicId:特徵值ID 
 */
const subpackage = (index, totle, list, deviceId, serviceId, characteristicId) => {
     var maxLenght = 20
     var maxIndex = Math.ceil(totle / maxLenght)
     if (index < maxIndex - 1) {
          //分包發送
          var subBuffer = new ArrayBuffer(maxLenght)
          var subDataView = new DataView(subBuffer)
          for (var i = 0; i < maxLenght; i++) {
               var item = list[i + index * maxLenght]
               var itemF = util.sixToInt(item.substr(0, 1)) * 16
               var itemS = util.sixToInt(item.substr(1, 1))
               var itemInt = itemF + itemS
               subDataView.setUint8(i, itemInt)
          }
          var dataStr = util.ab2hex(subBuffer)
          console.log("subBuffer:" + dataStr)
          sendBlueData(subBuffer, false, index, totle, list, deviceId, serviceId, characteristicId)
     } else if (index == maxIndex - 1) {
          //不需要分包發送
          var count = totle - (parseInt(totle / maxLenght)) * maxLenght
          let subbBuffer = new ArrayBuffer(count)
          let subbDataView = new DataView(subbBuffer)
          for (var i = 0; i < count; i++) {
               var item = list[i + (parseInt(totle / maxLenght)) * maxLenght]
               var itemF = util.sixToInt(item.substr(0, 1)) * 16
               var itemS = util.sixToInt(item.substr(1, 1))
               var itemInt = itemF + itemS
               subbDataView.setUint8(i, itemInt)
          }
          var dataStr = util.ab2hex(subbBuffer)
          console.log("subBuffer++++:" + dataStr) //發送數據          
          sendBlueData(subbBuffer, true, index, totle, list, deviceId, serviceId, characteristicId)
     }
}

/**
 * 向藍牙設備發送數據   
 * buffer:發送的二進制數據   
 * isLast:是否爲最後一個包,不是則繼續發送   
 * index:表示當前的第幾個包   
 * totle:list 數組的長度   
 * list:按照2個字符存在的數據數組   
 * deviceId:設備ID
 * serviceId:服務ID
 * characteristicId:特徵值ID
 */
const sendBlueData = (buffer, isLast, index, totle, list, deviceId, serviceId, characteristicId) => {
     wx.writeBLECharacteristicValue({
          deviceId: deviceId,
          serviceId: serviceId,
          characteristicId: characteristicId,
          value: buffer,
          success: function (res) {
               console.log("發送發包數據成功" + JSON.stringify(res))
               if (!isLast) {
                    sendCurrentIndex = index + 1
                    subpackage(sendCurrentIndex, totle, list, deviceId, serviceId, characteristicId)
               } else {
                    console.log("數據指令發送成功")
                    // 當最後一個包的數據發送到門鎖裏面去了,那麼你也可以在監聽數據的返回函數----wx.onBLECharacteristicValueChange()這裏面去監聽數據的返回,根據協議看成功失敗
                    // wx.showToast({
                    //      title: '操作成功',
                    // })
               }
          },
          fail: function (res) {
               hintOpenBluetooth()
               wx.removeStorageSync('bluetoothStatus')
               closeBLEConnection()
               deleteBLEConnectionData()
               closeBluetoothAdapter()
               console.log("發送發包數據失敗" + JSON.stringify(res))
          }
     })
}
/**
 * 提醒打開門鎖藍牙配對
 */
const hintOpenBluetooth = () => {
     var device = wx.getStorageSync('device')
     if (!device) {
          return
     }
     if (wx.getStorageSync('closeHintOpenBluetooth')) {
          return
     }
     //判斷門鎖是否被初始化
     var advertisData = device.advertisData;
     //電量的二進制數據
     var binary = util.sixToBinary(advertisData.substring(16, 18))
     if (binary.substring(0, 1) == "0") {
          wx.showModal({
               title: '提示',
               content: '請確定門鎖上是否打開藍牙配對!',
               confirmText: '確定',
               showCancel: false,
               confirmColor: "#23C16E",
               success(res) {
                    if (res.confirm) {
                         wx.navigateBack()
                    } else if (res.cancel) {
                         console.log("取消")
                    }
               }
          })
     }
}


module.exports = {
     sendBluetoothData: sendBluetoothData,
     openBluetoothAdapter: openBluetoothAdapter,
     createBLEConnection: createBLEConnection,
     closeBLEConnection: closeBLEConnection,
     deleteBLEConnectionData: deleteBLEConnectionData,
     notifyBLECharacteristic: notifyBLECharacteristic
}

三、如何引用工具類 

const bluetoothUtil = require('../../utils/bluetoothUtil.js')

四、如何使用工具類 

onLoad: function (options) {
          var self = this;
          bluetoothUtil.openBluetoothAdapter(lockInfo.mac).then(
                    success => {
                         var characteristicId = wx.getStorageSync('characteristics').FF07                         
                         dataView.setUint8(0, 0x0a)
                         self.writeBLECharacteristicValue(buffer, characteristicId)
                    },
                    fail => {
                         wx.showToast({
                              title: '藍牙初始化失敗,請確定藍牙是否打開',
                              icon: 'none',
                              duration: 3000
                         })
                    }
               )
}


//向藍牙寫數據
writeBLECharacteristicValue(buffer, characteristicId) {
          var self = this;
          //監聽返回值
          wx.onBLECharacteristicValueChange(function (res) {
               //處理返回值
               self.getResultInfo(res)
          })
          var device = wx.getStorageSync('device')         
          var deviceId = device.deviceId
          var serviceId = device.serviceId
          if (typeof (buffer) != "string") {
               buffer = util.ab2hex(buffer)
          }
          bluetoothUtil.sendBluetoothData(buffer, deviceId, serviceId, characteristicId)
},

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章