這個模塊作了2周,找了不少資料文檔,看示例看別人的demo,最後發現其實仍是得靠本身,不吐槽了,開正文。我實現的小程序模塊自動鏈接(根據須要,可改手動),是在小程序初始化完成時開始自動調用執行。php
大體流程:小程序
一、 開啓藍牙適配
二、 獲取藍牙適配器狀態,判斷設備藍牙是否可用。
三、 判斷藍牙適配器可用時開啓掃描藍牙設備和開啓獲取已鏈接的藍牙設備
四、 若是開啓掃描藍牙設備失敗5s後自動再次開啓掃描
五、 開啓掃描藍牙設備成功後開啓監聽已掃描的設備
六、 若是已掃描到的新設備含FeiZhi名(我的產品須要)的設備則開始鏈接該設備
七、 開啓獲取已鏈接藍牙設備開啓獲取設備成功後判斷以獲取的設備名包含FeiZhi(我的產品須要)字符串的設備則開始鏈接該設備
八、 開始獲取已鏈接藍牙設備沒有成功獲取到已鏈接的藍牙設備5s後自動從新開啓獲取。
九、 開始鏈接某設備時中止掃描設備,中止循環獲取已鏈接設備。
十、鏈接成功後中止掃描設備,中止循環獲取已鏈接設備。微信小程序
點擊查看:藍牙模塊鏈接流程圖數組
一、app.js的onLaunch() 方法裏中調用開啓鏈接 this.startConnect();彈出提示框,開啓適配,若是失敗提示設備藍牙不可用,同時開啓藍牙適配器狀態監聽微信
startConnect: function () { var that = this; wx.showLoading({ title: '開啓藍牙適配' }); wx.openBluetoothAdapter({ success: function (res) { console.log("初始化藍牙適配器"); console.log(res); that.getBluetoothAdapterState(); }, fail: function (err) { console.log(err); wx.showToast({ title: '藍牙初始化失敗', icon: 'success', duration: 2000 }) setTimeout(function () { wx.hideToast() }, 2000) } }); wx.onBluetoothAdapterStateChange(function (res) { var available = res.available; if (available) { that.getBluetoothAdapterState(); } }) }
二、初始化藍牙適配器成功,調用this.getBluetoothAdapterState() 獲取本機藍牙適配器狀態,判斷是否可用,available爲false則由於用戶沒有開啓系統藍牙。同時判斷程序尚未開始搜索藍牙設備,調用this.startBluetoothDevicesDiscovery();開始掃描附近的藍牙設備,同時調用this.getConnectedBluetoothDevices() 開啓獲取本機已配對的藍牙設備。app
getBluetoothAdapterState: function () { var that = this; wx.getBluetoothAdapterState({ success: function (res) { var available = res.available, discovering = res.discovering; if (!available) { wx.showToast({ title: '設備沒法開啓藍牙鏈接', icon: 'success', duration: 2000 }) setTimeout(function () { wx.hideToast() }, 2000) } else { if (!discovering) { that.startBluetoothDevicesDiscovery(); that.getConnectedBluetoothDevices(); } } } }) }
三、開始搜索藍牙設備startBluetoothDevicesDiscovery() , 提示藍牙搜索。ide
startBluetoothDevicesDiscovery: function () { var that = this; wx.showLoading({ title: '藍牙搜索' }); wx.startBluetoothDevicesDiscovery({ services: [], allowDuplicatesKey: false, success: function (res) { if (!res.isDiscovering) { that.getBluetoothAdapterState(); } else { that.onBluetoothDeviceFound(); } }, fail: function (err) { console.log(err); } }); }
四、獲取已配對的藍牙設備。此方法特別說明參數services(Array)是必填的,可是官方示例中以及各類坑爹demo裏從沒見過有誰填寫,可是不填寫這個屬性此方法沒法獲取到任何已配對設備。若是要調用此方法則是須要鏈接特定設備,而且知道該設備的一個主服務serviceId。若是未知能夠先手動鏈接一次想要鏈接的設備,而後獲取service列表,記錄屬性primary爲true的值至少一個。oop
getConnectedBluetoothDevices: function () { var that = this; wx.getConnectedBluetoothDevices({ services: [that.serviceId], success: function (res) { console.log("獲取處於鏈接狀態的設備", res); var devices = res['devices'], flag = false, index = 0, conDevList = []; devices.forEach(function (value, index, array) { if (value['name'].indexOf('FeiZhi') != -1) { // 若是存在包含FeiZhi字段的設備 flag = true; index += 1; conDevList.push(value['deviceId']); that.deviceId = value['deviceId']; return; } }); if (flag) { this.connectDeviceIndex = 0; that.loopConnect(conDevList); } else { if (!this.getConnectedTimer) { that.getConnectedTimer = setTimeout(function () { that.getConnectedBluetoothDevices(); }, 5000); } } }, fail: function (err) { if (!this.getConnectedTimer) { that.getConnectedTimer = setTimeout(function () { that.getConnectedBluetoothDevices(); }, 5000); } } }); }
五、開啓藍牙搜索功能失敗,則回到第2步從新檢查藍牙是適配器是否可用,開啓藍牙搜索功能成功後開啓發現附近藍牙設備事件監聽。this.onBluetoothDeviceFound()學習
onBluetoothDeviceFound: function () { var that = this; console.log('onBluetoothDeviceFound'); wx.onBluetoothDeviceFound(function (res) { console.log('new device list has founded') console.log(res); if (res.devices[0]) { var name = res.devices[0]['name']; if (name != '') { if (name.indexOf('FeiZhi') != -1) { var deviceId = res.devices[0]['deviceId']; that.deviceId = deviceId; console.log(that.deviceId); that.startConnectDevices(); } } } }) }
此方法可自定義過濾一些無效的藍牙設備好比name爲空的,我的產品開發中須要過濾devices name 不含有FeiZhi字符串的設備。this
六、在第5步中發現了某個想配對的設備,則獲取到該設備的deviceId,而後開始配對該設備 this.startConnectDevices()。
startConnectDevices: function (ltype, array) { var that = this; clearTimeout(that.getConnectedTimer); that.getConnectedTimer = null; clearTimeout(that.discoveryDevicesTimer); that.stopBluetoothDevicesDiscovery(); this.isConnectting = true; wx.createBLEConnection({ deviceId: that.deviceId, success: function (res) { if (res.errCode == 0) { setTimeout(function () { that.getService(that.deviceId); }, 5000) } }, fail: function (err) { console.log('鏈接失敗:', err); if (ltype == 'loop') { that.connectDeviceIndex += 1; that.loopConnect(array); } else { that.startBluetoothDevicesDiscovery(); that.getConnectedBluetoothDevices(); } }, complete: function () { console.log('complete connect devices'); this.isConnectting = false; } }); }
開啓鏈接後爲了不出現衝突,一旦開啓鏈接則終止掃描附近藍牙設備,終止讀取本機已配對設備。
getService: function (deviceId) { var that = this; // 監聽藍牙鏈接 wx.onBLEConnectionStateChange(function (res) { console.log(res); }); // 獲取藍牙設備service值 wx.getBLEDeviceServices({ deviceId: deviceId, success: function (res) { that.getCharacter(deviceId, res.services); } }) }
八、讀取服務的特徵值。
getCharacter: function (deviceId, services) { var that = this; services.forEach(function (value, index, array) { if (value == that.serviceId) { that.serviceId = array[index]; } }); wx.getBLEDeviceCharacteristics({ deviceId: deviceId, serviceId: that.serviceId, success: function (res) { that.writeBLECharacteristicValue(deviceId, that.serviceId, that.characterId_write); that.openNotifyService(deviceId, that.serviceId, that.characterId_read); }, fail: function (err) { console.log(err); }, complete: function () { console.log('complete'); } }) }
九、若是掃描到的設備中沒有想要鏈接的設備,能夠嘗試使用系統藍牙手動配對,而後再小程序中調用getConnectedBluetoothDevices() 獲取本機已配對的藍牙設備,而後過濾設備(可能獲取多個已配對的藍牙設備)。將以獲取的藍牙設備deviceId放入到一個數組中調用自定義方法this.loopConnect(); 思路:經過遞歸調用獲取已配對藍牙設備的deviceId,若是獲取到了就去鏈接,devicesId[x] 爲空說明上傳調用getConnectedBluetoothDevices()時獲取到的已配對設備所有鏈接失敗了。則開啓從新獲取已配對藍牙設備,並開啓掃描附近藍牙設備。
loopConnect: function (devicesId) { var that = this; var listLen = devicesId.length; if (devicesId[this.connectDeviceIndex]) { this.deviceId = devicesId[this.connectDeviceIndex]; this.startConnectDevices('loop', devicesId); } else { console.log('已配對的設備小程序藍牙鏈接失敗'); that.startBluetoothDevicesDiscovery(); that.getConnectedBluetoothDevices(); } }
十、**startConnectDevices('loop', array)方法,是當獲取已配對藍牙設備進行鏈接時這樣調用。其中的處理邏輯上文已經貼出,意思就是在鏈接失敗後fail方法裏累加一個全局變量,而後回調loopConnect(array)方法。
**十一、手動鏈接,上文介紹的方法是爲了直接自動鏈接,若是不須要自動鏈接,可在使用方法getBluetoothDevices() 將會獲取到已掃描到的藍牙設備的列表,能夠作個頁面顯示出設備名,點擊該設備開始鏈接。
一、that.serviceId 是在初始化時設置的,因爲對須要鏈接設備的主服務serivceId和各類特徵值都是已知的所以能夠這樣作。若是不可知能夠作一個掃描方法本身檢查特徵值的用途。
二、 鏈接成功後的writeBLECharacteristicValue和openNotifyService操做須要注意,若是同時開啓這兩項操做要先調用wirte再開啓notify(緣由未知,我的心得)。
三、經人提醒還能夠再完善一下在onBlueToothAdapterStateChange()**能夠監聽藍牙適配器狀態,以此判斷鏈接過程當中或鏈接後用戶開關了設備藍牙,若是判斷到關了藍牙提示請開啓,若是監聽到開啓了,就從新回到第1步。
最後本文屬於我的開發者的一點總結,歡迎留言指導討論,也能夠加入微信小程序聯盟羣一塊兒探討學習。