微信小程式-藍芽連線
阿新 • • 發佈:2018-11-12
最近的專案需要使用小程式的藍芽功能與硬體裝置進行連線相互傳送資料指令,聯調過程中發現一些問題,於是想著記錄下來,方便以後檢視!
1.0一般使用藍芽功能肯定是想連線某一個藍芽裝置,所以需要知道這個藍芽裝置的名稱,一般來說都是掃描二維碼連線,那麼當你掃描這個裝置二維碼的時候,就需要去初始化你手機上的藍芽模組了
/** * 初始化藍芽裝置 */ initBlue:function(){ var that = this; wx.openBluetoothAdapter({//呼叫微信小程式api 開啟藍芽介面卡介面 success: function (res) { // console.log(res) wx.showToast({ title: '初始化成功', icon: 'success', duration: 800 }) that.findBlue();//2.0 }, fail: function (res) {//如果手機上的藍芽沒有開啟,可以提醒使用者 wx.showToast({ title: '請開啟藍芽', icon: 'fails', duration: 1000 }) } }) }, 2.0 手機藍芽初始化成功之後,就會去搜索周邊的藍芽裝置 /** *開始搜尋藍芽裝置 */ findBlue(){ var that = this wx.startBluetoothDevicesDiscovery({ allowDuplicatesKey: false, interval: 0, success: function (res) { wx.showLoading({ title: '正在搜尋裝置', }) that.getBlue()//3.0 } }) },3.0搜尋藍芽裝置之後,需要獲取搜尋到的藍芽裝置資訊,微信小程式提供了兩個方法可以獲取搜尋到的藍芽裝置資訊,分別是:
wx.onBluetoothDeviceFound(監聽尋找到新裝置的事件 ——表示只要找到一個新的藍芽裝置就會呼叫一次該方法)
wx.getBluetoothDevices(獲取在藍芽模組生效期間所有已發現的藍芽裝置。包括已經和本機處於連線狀態的裝置)
看兩個方法的介紹我們知道他們的區別,但是不瞭解他們的區別會造成什麼樣的問題?
第一次我使用的是wx.onBluetoothDeviceFound方法進行聯調,發現一切正常,由於除錯的時候就只有一臺裝置,發現第二次重新掃碼這個藍芽裝置的時候,找不到這個裝置了,因為對這個方法來說,這不是一個新的裝置,以前連線上過;或者當你因為某些原因藍芽傳送資料指令的時候出錯了需要重新連線,再次連線的時候也找不到當前裝置,還是同樣的原因,因為當前裝置對這個方法來說不是一個新裝置
所以後來我就用了wx.getBluetoothDevices方法
/** * 獲取搜尋到的裝置資訊 */ getBlue(){ var that = this wx.getBluetoothDevices({ success: function(res) { wx.hideLoading(); for (var i = 0; i < res.devices.length; i++){ //that.data.inputValue:表示的是需要連線的藍芽裝置ID,簡單點來說就是我想要連線這個藍芽裝置,所以我去遍歷我搜索到的藍芽裝置中是否有這個ID if (res.devices[i].name == that.data.inputValue || res.devices[i].localName == that.data.inputValue){ that.setData({ deviceId: res.devices[i].deviceId, consoleLog: "裝置:" + res.devices[i].deviceId, }) that.connetBlue(res.devices[i].deviceId);//4.0 return; } } }, fail: function(){ console.log("搜尋藍芽裝置失敗") } }) }, 4.0通過3.0步驟找到這個藍芽之後,通過藍芽裝置的id進行藍芽連線 /** * 獲取到裝置之後連線藍芽裝置 */ connetBlue(deviceId){ var that = this; wx.createBLEConnection({ // 這裡的 deviceId 需要已經通過 createBLEConnection 與對應裝置建立連結 deviceId: deviceId,//裝置id success: function (res) { wx.showToast({ title: '連線成功', icon: 'fails', duration: 800 }) console.log("連線藍芽成功!") wx.stopBluetoothDevicesDiscovery({ success: function (res) { console.log('連線藍芽成功之後關閉藍芽搜尋'); } }) that.getServiceId()//5.0 } }) }, 5.0連線上需要的藍芽裝置之後,獲取這個藍芽裝置的服務uuid getServiceId(){ var that = this wx.getBLEDeviceServices({ // 這裡的 deviceId 需要已經通過 createBLEConnection 與對應裝置建立連結 deviceId: that.data.deviceId, success: function (res) { var model = res.services[0] that.setData({ services: model.uuid }) that.getCharacteId()//6.0 } }) }, 6.0如果一個藍芽裝置需要進行資料的寫入以及資料傳輸,就必須具有某些特徵值,所以通過上面步驟獲取的id可以檢視當前藍芽裝置的特徵值 getCharacteId(){ var that = this wx.getBLEDeviceCharacteristics({ // 這裡的 deviceId 需要已經通過 createBLEConnection 與對應裝置建立連結 deviceId: that.data.deviceId, // 這裡的 serviceId 需要在上面的 getBLEDeviceServices 介面中獲取 serviceId: that.data.services, success: function (res) { for (var i = 0; i < res.characteristics.length; i++) {//2個值 var model = res.characteristics[i] if (model.properties.notify == true) { that.setData({ notifyId: model.uuid//監聽的值 }) that.startNotice(model.uuid)//7.0 } if (model.properties.write == true){ that.setData({ writeId: model.uuid//用來寫入的值 }) } } } }) }, 7.0 startNotice(uuid){ var that = this; wx.notifyBLECharacteristicValueChange({ state: true, // 啟用 notify 功能 // 這裡的 deviceId 需要已經通過 createBLEConnection 與對應裝置建立連結 deviceId: that.data.deviceId, // 這裡的 serviceId 需要在上面的 getBLEDeviceServices 介面中獲取 serviceId: that.data.services, // 這裡的 characteristicId 需要在上面的 getBLEDeviceCharacteristics 介面中獲取 characteristicId: uuid, //第一步 開啟監聽 notityid 第二步傳送指令 write success: function (res) { // 裝置返回的方法 wx.onBLECharacteristicValueChange(function (res) { // 此時可以拿到藍芽裝置返回來的資料是一個ArrayBuffer型別資料,所以需要通過一個方法轉換成字串 var nonceId = that.ab2hex(res.value) //拿到這個值後,肯定要去後臺請求服務(當前步驟根據當前需求自己書寫),獲取下一步操作指令寫入到藍芽裝置上去 wx.request({ method: "POST", data: { xx:nonceId }, url: url, success: (res) => { //res.data.data.ciphertext:我這邊服務返回來的是16進位制的字串,藍芽裝置是接收不到當前格式的資料的,需要轉換成ArrayBuffer that.sendMy(that.string2buffer(res.data.data.ciphertext))//8.0 // 伺服器返回一個命令 我們要把這個命令寫入藍芽裝置 } }) } }) }, 8.0 將從後臺服務獲取的指令寫入到藍芽裝置當中 sendMy(buffer){ var that = this wx.writeBLECharacteristicValue({ // 這裡的 deviceId 需要在上面的 getBluetoothDevices 或 onBluetoothDeviceFound 介面中獲取 deviceId: that.data.deviceId, // 這裡的 serviceId 需要在上面的 getBLEDeviceServices 介面中獲取 serviceId: that.data.services, // 這裡的 characteristicId 需要在上面的 getBLEDeviceCharacteristics 介面中獲取 characteristicId: that.data.writeId,//第二步寫入的特徵值 // 這裡的value是ArrayBuffer型別 value: buffer, success: function (res) { console.log("寫入成功") }, fail: function () { console.log('寫入失敗') }, complete:function(){ console.log("呼叫結束"); } }) }, //ps:下面是需要使用到的兩個格式相互轉換的方法 /** * 將字串轉換成ArrayBufer */ string2buffer(str) { let val = "" if(!str) return; let length = str.length; let index = 0; let array = [] while(index < length){ array.push(str.substring(index,index+2)); index = index + 2; } val = array.join(","); // 將16進位制轉化為ArrayBuffer return new Uint8Array(val.match(/[\da-f]{2}/gi).map(function (h) { return parseInt(h, 16) })).buffer }, /** * 將ArrayBuffer轉換成字串 */ ab2hex(buffer) { var hexArr = Array.prototype.map.call( new Uint8Array(buffer), function (bit) { return ('00' + bit.toString(16)).slice(-2) } ) return hexArr.join(''); }, //PS:以上是藍芽連線的全部流程,但是我們在實際使用中肯定不會這麼順暢,而且藍芽傳送指令的裝置都會有一個特性,就是當前藍芽裝置有人連線上之後,其他人是搜尋不到這個藍芽裝置的,所以你需要考慮在某些個特殊情況,程式碼裡需要主動斷開藍芽連線把裝置釋放出來供其他使用者使用,還有就是將指令寫入藍芽裝置的時候很容易出問題,所以要寫個回撥去多次寫入,保證成功性!第一次寫部落格,不正確的地方,歡迎大家討論,謝謝!