最近的項目需要使用小程序的藍牙功能與硬件設備進行連接相互傳送數據指令,聯調過程中發現一些問題,於是想着記錄下來,方便以后查看!
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 }) } }) },
/** *開始搜索藍牙設備 */ 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("搜索藍牙設備失敗") } }) },
/** * 獲取到設備之后連接藍牙設備 */ 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 } }) },
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 } }) },
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//用來寫入的值 }) } } } }) },
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 // 服務器返回一個命令 我們要把這個命令寫入藍牙設備 } }) } }) },
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("調用結束"); } }) },
/** * 將字符串轉換成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(''); },
BLE低功耗藍牙具有以下要求的應用:
1.通信距離長達100米左右。很多低功耗藍牙需要使用紐扣電池運行。很多的物聯網設備需要使用標准紐扣電池運行很多年。BLE低功耗藍牙可實現超低的峰值、均衡和空閑模式的功耗。另外,低占空比設備還能節省更多電能。
2.多智能廠商互操作性。作為一個標准協議,BLE低功耗藍牙與此前的藍牙版本一樣,也得到了主設備制造商的廣泛采用。也有很多的物聯網從設備也支持BLE低功耗藍牙。安卓、iOS、Windows 10、Linux等主流操作系統均原生支持BLE低功耗藍牙。預測,到2020年,95%的智能手機都將支持BLE低功耗藍牙。而這個生態系統將有助於實現多廠商互操作性。
3.BLE低功耗藍牙是搭建集體、家庭、個人網絡的最佳選擇,可通過無線方式將供電型智能設備連接至手機或計算機。因此,越來越多的智能穿戴設備、計算機/手機外設和醫療監測設備將BLE低功耗藍牙視為了首選通信協議。在藍牙技術聯盟的網站上也列出了很多不同支持智能藍牙協議的產品和藍牙智能設備產品。這直接表明了BLE低功耗藍牙通信協議在物聯網應用領域的重要性。