前言
經過幾個月的時間,斷斷續續的修改,終於完成了個人的第一個微信藍牙小程序,僅此做一個小結。
一、知識儲備
1.微信小程序API
藍牙部分的API可以到微信公衆平臺去找,都是官方文件。Android 從微信 6.5.7 開始支持藍牙程序,iOS 從微信 6.5.6 開始支持。
之前自己稍微整理過一個流程。
2.BLE 4.0
BLE 4.0是現在流行的一種藍牙傳輸協議,其中 BLE 是 Bluetooth Low Energy 低功耗藍牙的簡寫。整個協議我也只是一知半解,就講點在應用過程中瞭解的東西。其餘大家感興趣可以直接搜索下。
先明確幾個概念:(個人理解,有問題歡迎指出)
MAC地址:(Media Access Control Address)藍牙設備的物理地址,每個設備只有一個唯一值。
UUID:(Universally Unique Identifier)通用唯一識別碼,一種軟件識別碼,一個設備中可以有 多個UUID,一個UUID對應一個軟件服務部分。
服務(service):有關特徵值的收集,用來操作特定功能,所以一個服務裏可以有多個特徵值。例如,“體溫計”服務包括一個溫度測量值,以及測量的時間間隔。
特徵值(characteristic):在藍牙設備之間傳遞的數據值,例如當前溫度測量值。
服務、特徵稱爲屬性(attributes),並以UUID標識。實現者可能會爲所用的專有格式挑選一個隨機或僞隨機UUID,但藍牙技術聯盟已預留一系列UUID(範圍xxxxxxxx-0000-1000-8000-00805F9B34FB))供標準屬性使用。
所以可以理解爲:
MAC地址:一個人的名字。
服務:一個人做了一件事情。
特徵性:考覈這件事情的幾個指標。
UIDD:用一串數字和字母表示事情或指標。
這些理解了,還要了解一下BLE 4.0和傳統藍牙的不同,在單模情況下無法通用傳統藍牙的設備。所以開發小程序前,你要了解你的手機和要連接的藍牙設備是否能滿足BLE 4.0的要求,否則硬件基礎都不支持,談何軟件實現。
3.vConsole
這是微信自帶一個真機調試工具,因爲藍牙程序部分無法在“微信web開發者工具”中仿真調試,需要大量的真機調試,所以好好應用vConsole,在後續的開發中至關重要。
二、開發過程中的磕磕碰碰
1.console.log先打出錯誤信息
最開始按照藍牙流程編寫完小程序後,總是遇到各種錯誤,一個頭兩個大。
後來就在每段程序里加入:
console.log('連接藍牙:', res.errMsg + res.errCode);
將全部錯誤信息打印出來和下表對比,就慢慢有了方向。
錯誤信息部分截圖
2.不行就加延遲
如果在使用多個藍牙API且有先後或者參數傳遞關係,請加入適當延遲。
沒有加延遲的後果是前一個API還沒執行完成,後一個API就在執行了,這樣後一個API缺少了一些必要的準備或參數。
vConsole中表現出兩種情況,1中間狀態的參數未賦值,2錯誤提示前一個API操作的結果出錯
以wx.getBLEDeviceServices和wx.getBLEDeviceCharacteristics爲例,兩者之間有參數傳遞關係,所以需要延長。
wx.getBLEDeviceServices({
deviceId: that.data.connectedDeviceId,
success: function(res) {
for (let i = 0; i < res.services.length; i++) {
if (res.services[i].uuid.toUpperCase().indexOf("FFE0") != -1) {
that.setData({
serviceUUID: res.services[i].uuid,
})
console.log("UUID1:" + that.data.serviceUUID);
break;
}
}
},
fail: function (res) {
}
})
setTimeout(function () {
wx.getBLEDeviceCharacteristics({
deviceId: that.data.connectedDeviceId,
serviceId: that.data.serviceUUID,
success: function(res) {
console.log('成功2:', res.errMsg + res.errCode);
var notify_id, write_id, read_id;
for (let i = 0; i < res.characteristics.length; i++) {
if (res.characteristics[i].properties.notify) {
notify_id = res.characteristics[i].uuid;
}
if (res.characteristics[i].properties.write) {
write_id = res.characteristics[i].uuid;
}
if (res.characteristics[i].properties.read) {
read_id = res.characteristics[i].uuid;
}
}
that.setData({
characteristicId_notify: notify_id,
characteristicId_write: write_id,
characteristicId_read: read_id,
})
},
fail: function (res) {
}
})
}, 1000)//添加延遲
3.爲什麼iPhone比較難連
就一個原因iPhone比較矯情。
使用iPhone時,就算你知道服務的UUID和特徵值的UUID,與必須通過wx.getBLEDeviceServices和wx.getBLEDeviceCharacteristics兩個API獲得。就是上面寫道那段代碼。
服務的UUID和特徵值的UUID,iPhone只識別大寫字母,安卓大小寫沒關係。
安卓和iPhone還有一個不同點: Android 上獲取到的deviceId爲設備 MAC 地址,iOS 上則爲設備的 UUID。但是在實際應用中僅發現deviceId這個值不同,會影響界面佈局,其他倒是沒什麼感覺。
最後在梳理下安卓和iPhone的連接過程:
安卓:
wx.getBluetoothDevices——獲得MAC地址(deviceId)
wx.createBLEConnection——通過MAC地址創建連接
wx.getBLEDeviceServices——獲得服務的UUID(ServicesId)如果已知ServicesId,可將ServicesId設置爲常量,省略該步驟。
wx.getBLEDeviceCharacteristics——獲得特徵值的UUID(CharacteristicsId)如果已知CharacteristicsId,可將CharacteristicsId設置爲常量,省略該步驟。
wx.notifyBLECharacteristicValueChanged——通過deviceId、ServicesId、CharacteristicsId啓動notify模式
iPhone:
wx.getBluetoothDevices——獲得設備的 UUID(deviceId)
wx.createBLEConnection——通過設備的 UUID創建連接
wx.getBLEDeviceServices——獲得服務的UUID(ServicesId)不論是否已知ServicesId,都無法省略該步驟。
wx.getBLEDeviceCharacteristics——獲得特徵值的UUID(CharacteristicsId)不論是否已知CharacteristicsId,都無法省略該步驟。
wx.notifyBLECharacteristicValueChanged——通過deviceId、ServicesId、CharacteristicsId啓動notify模式
所以,當你想要兩者共用,就乖乖將wx.getBLEDeviceServices和wx.getBLEDeviceCharacteristics兩個API都寫進去。
4.如何獲得可用的服務UUID
通過wx.getBLEDeviceServices可以獲得所有服務的UUID,但是那個是你需要的?
比如我就篩選了含有“FFE0”的UUID。
if (res.services[i].uuid.toUpperCase().indexOf("FFE0") != -1)
那麼怎麼獲得自己想要的UUID那?
我通過一個APP(在哪下載忘記了,紅框是它的logo),嘗試了哪些UUID可以使用。
APP界面
5.讀數據要用on,不能一口氣讀寫太多
比較坑的一點,讀取數據建議使用wx.onBLECharacteristicValueChange。
讀寫操作的buffer是有大小限制,印象中是20個字節大小,如果你沒有分段存儲,就只能讀取到頭20個字節。
大於 20 字節只能分包發送或讀取。微信小程序提供的 API 中沒有自動分包的功能,這就只能自己手動分包了。
6.關於波特率
暫時微信還沒有提供設置藍牙設備波特率的API,但是通過手機連接測試,波特率在9600-57600之間都可以連接。
後記
我已從坑中爬出,寫下此文,希望他人能爬的快點,哈哈哈哈!