(1)初始化
初始化藍牙模塊 --- wx.openBluetoothAdapter
// 定義數據
data: {
devices: [], // 搜索到的藍牙設備 deviceId 數組
deviceId: '', // 目標藍牙設備 deviceId
services: [] // 設備服務列表 serviceId 數組
serviceId: '',
characteristics: [] // 特征值列表
characteristicId: '' // 選擇某一個特征值
value: '' // 16 進制數據值
}
// 藍牙 API 調用步驟
openBluetoothAdapter() {
wx.openBluetoothAdapter({ // (1)
success: res => {
console.log('openBluetoothAdapter初始化藍牙模塊成功:', res)
this.startBluetoothDevicesDiscovery() // (2) 開始搜索
},
fail: err => {
console.log('openBluetoothAdapter初始化藍牙模塊失敗:', err)
if (err.errCode === 10001) { // 當前藍牙適配器不可用
wx.onBluetoothAdapterStateChange( res => {
if (res.available) {
this.startBluetoothDevicesDiscovery()
}
})
}
/*
wx.onBluetoothAdapterStateChange({
success: res => {
console.log('onBlueToothAdapterStateChange success 監聽藍牙適配器變化: ', res);
this.startBluetoothDevicesDiscovery();
},
fail: err => {
console.log('onBlueToothAdapterStateChange fail: ', err)
}
})
*/
}
})
}
###(2)搜索藍牙設備 ####搜尋附近的藍牙外圍設備 --- wx.startBluetoothDevicesDiscovery * 入參 services 作用要搜索的藍牙設備主 service 的 uuid 列表,某些藍牙設備會廣播自己的主 service 的 uuid,如果設置此參數,則只搜索廣播包括對應 uuid 的主服務的藍牙設備,可以通過該參數過濾掉周邊不需要處理的其他藍牙設備 * 入參 allowDuplicatesKey 作用是否允許重復上報同一設備,如果允許重復上報,則 wx.onBlueToothDeviceFound 方法會多次上報同一設備,但是 RSSI 值會有不同,默認為 false eg: services: ['FEE7'] 主服務的 UUID 是 FEE7,傳入這個參數,只搜索主服務 UUID 為 FEE7 的設備,該設備是微信硬件平台的藍牙智能燈
⚠️ 此操作比較耗費系統資源,需要在搜索並連接到設備后調用 wx.stopBluetoothDevicesDiscovery 方法停止搜索
startBluetoothDevicesDiscovery() {
wx.startBluetoothDevicesDiscovery({
success: res => {
console.log('startBluetoothDevicesDiscovery開始搜索外圍設備成功:', res)
this.getBluetoothDevices() // (3) 獲取藍牙列表
},
fail: err => {
console.log('startBluetoothDevicesDiscovery搜索外圍設備失敗:', err)
}
})
}
###(3)獲取藍牙設備 ####獲取在藍牙模塊生效期間所有已發現的藍牙設備,包括已經連接成功的藍牙設備 --- wx.getBluetoothDevices ``` getBluetoothDevices() { wx.getBluetoothDevices({ success: res => { console.log('getBluetoothDevices獲取藍牙設備成功:', res) this.setData({ devices: res. devices || [] // uuid 對應的的已連接設備列表 }) this.createBLEConnection(); // (4) 與目標設備建立連接 }, fail: err => { console.log('getBluetoothDevices獲取藍牙設備失敗:', err) } }) } ``` ####這里還可以用 wx.onBluetoothDeviceFound(),但是相較於 wx.getBluetoothDevices(),這個只會監聽尋找新設備,因而在一次編譯中,不方便同一個藍牙設備的復用 ``` // 監聽尋找新設備 onBluetoothDeviceFound() { let that = this; wx.onBluetoothDeviceFound(res => { console.log('onBluetoothDeviceFound success 監聽尋找新設備: ', res); (res.devices || []).forEach(item => { if(item.name == 'KunHong') { that.setData({ deviceId: item.deviceId || '' }) that.createBLEConnection(that.data.deviceId); } }) }) }, ```
###(4)建立連接 ####與目標藍牙設備建立連接,需要是低功耗藍牙設備 --- wx.createBLEConnection ⚠️ 如果微信小程序此前搜索過某個藍牙設備,並成功建立連接,可直接傳入之前搜索獲取的 deviceId 直接嘗試連接該設備,不用重新搜索 ``` createBLEConnection() { // 如果是第一次建立連接,可以通過名稱匹配,獲取相應設備的 deviceId let devices = this.data.devices; devices.forEach(item => { if(item.name == 'kunHong') { this.setData({ deviceId: item.deviceId }) } }) // 建立連接 wx.createBLEConnection({ deviceId: this.data.deviceId, success: res => { console.log('createBLEConnection與目標藍牙連接成功:', res) this.getBLEDeviceServices() // (5)獲取服務 }, fail: err => { console.log('createBLEConnection與目標藍牙連接失敗:', err) } }) } ```
###(5)獲取藍牙設備服務 ####獲取藍牙設備所有主服務的 uuid --- wx.getBLEDeviceServices * 入參 deviceId 為 wx.getBluetoothDevices 中獲取的目標藍牙設備的 deviceId
⚠️開發過程中,主服務 serviceId 和 主服務的特征值 characteristics 都是選取的實際操作過程中,得到的類似於該目標藍牙設備的 id,但是小程序官方文檔的 demo,遍歷了所有的列表(serviceId 和 characteristics),需要區分一下
getBLEDeviceServices() {
wx.getBLEDeviceServices({
deviceId: this.data.deviceId,
success: res => {
console.log('getBLEDeviceServices獲取藍牙設備服務', res)
// getBluetoothDevices 獲取的有 deviceId 和 advertisServiceUUIDs,可以在這里獲取的服務列表中選擇一個一樣的作為后續 API 請求的服務id,這個 id 需要滿足是否可讀
this.setData({
services: res.services,
serviceId: res.services[0].uuid // 假設是第一個
})
this.getBLEDeviceCharacteristics() // (6) 獲取特征值
// 官方 demo
for(var i = 0; i < res.services.length; i++) {
// 該服務是否為主服務
if(res.services[i].isPrimary) {
this.getBLEDeviceCharacteristics(res.services[i].uuid)
}
}
},
fail: err => {
console.log('getBLEDeviceServices獲取藍牙設備服務失敗:', err)
}
})
}
###(6)獲取特征值 ####獲取藍牙設備某個服務中所有特征值 --- wx.getBLEDeviceCharacteristics * 入參 deviceId 為 wx.getBluetoothDevices 中獲取的目標藍牙設備的 deviceId * 入參 serviceId 為藍牙服務 uuid ,通過 wx.getBLEDeviceServices 獲取 ``` getBLEDeviceCharacteristics(serviceId) { wx.getBLEDeviceCharacteristics({ deviceId: this.data.deviceId, serviceId: this.data.serviceId, success: res => { console.log('getBLEDeviceCharacteristics獲取藍牙服務特征值成功:', res) this.setData({ characteristics: res. characteristics, characteristics: res. characteristics[0].uuid }) (res.characteristics || []).forEach(item => { if(item.properties.read) { wx.readBLECharacteristicValue({ deviceId: this.data.deviceId, serviceId: serviceid, characteristicId: res.characteristicId[i].uuid }) } if(item.properties.notify || item.properties.indicate) { // 開啟通知 wx.notifyBLECharacteristicValueChange({ state: true, deviceId, serviceId, characteristicId: item.uuid, success(res) { console.log('notifyBLECharacteristicValueChange success state: ', res.errMsg) that.setData({ notifyFlag: true }) } }) } }) }, fail: err => { console.log('getBLEDeviceCharacteristics獲取藍牙服務特征值失敗:', err) } }) this.onBLECharacteristicValueChange() // (8)監聽特征值變化 } ```
###(7)啟用 notify 功能 ####啟用低功耗藍牙特征值變化時的 notify 功能,訂閱特征值 ⚠️必須設備的特征值支持 notify 或者 indicate 才可以成功啟用 ``` notifyBLECharacteristicValueChange() { wx.notifyBLECharacteristicValueChange({ deviceId: this.data.deviceId, serviceId: this.data.serviceId, characteristicId: this.data. characteristicId, state: true // 是否啟用 notify (四個字段全部必填) }) } ```
###(8)監聽特征值變化 ####監聽低功耗藍牙設備特征值的變化事件 --- wx.onBLECharacteristicValueChange ⚠️必須先啟用 notifyBLECharacteristicValueChange 接口才能接收到設備推送的 notification(通知) ``` // 先監聽一下,保證第一時間獲取數據 onBLECharacteristicValueChange() { wx.onBLECharacteristicValueChange( characteristic => { console.log('onBLECharacteristicValueChange從目標藍牙設備監聽到的數據值:', characteristic) this.setData({ value: this.ab2hex(characteristic.value) // (10) 轉為 16 進制 })
// 獲取最終結果 監聽值是否發生變化,變化時獲取最新值 避免一直監聽,數據改變量較大
let result = (this.ab2Str(characteristic.value) || '').split(' ').reverse()[1];
if(this.data.weight == result) {
return;
} else {
this.setData({
weight: result,
})
}
})
}
<br>
###(9)讀取數據
####讀取低功耗藍牙設備的特征值的二進制數據值 --- wx.readBLECharacteristicValue
⚠️必須目標藍牙設備的特征值支持 read 才可以成功調用,並且單獨使用 readBLECharacteristicValue 並不能獲取到真正的特征值,只能返回獲取特征值的狀態,即是否成功獲取到值,真正的值需要使用 wx.onBLECharacteristicValueChange() 執行回調才可以在 wx.onBLECharacteristicValueChange() 這個 API 中獲得讀取到的特征值
readBLECharacteristicValue() {
wx.readBLECharacteristicValue({
deviceId: this.data.deviceId,
serviceId: this.data.serviceId,
characteristicId: this.data.charecteristicId,
success: res => {
console.log('readBLECharacteristicValue讀取特征值成功:', res)
},
fail: err => {
console.log('readBLECharacteristicValue讀取特征值失敗:', err)
}
})
}
<br>
###(10)轉為 16 進制
####官方文檔中介紹了 ArrayBuffer 轉為 16 進制的方法
// ArrayBuffer轉16進制字符串示例
ab2hex(buffer) {
let hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function(bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('');
}
<br>
###(11)值轉換
####官方文檔介紹的方法似乎有點不適用哎,試下這個
ab2Str(arrayBuffer){
let unit8Arr = new Uint8Array(arrayBuffer);
let encodedString = String.fromCharCode.apply(null, unit8Arr);
return encodedString;
}