前言:UNI-APP是一個使用 Vue.js 開發所有前端應用的架構,開發者編寫一套代碼,可釋出到iOS、Android、Web(響應式)、以及各種小程式(微信/支付寶/百度/頭條/飛書/QQ/快手/釘釘/淘寶)、快應用等多個平台。即使你不需要釋出到那麼多的平台,UNI-APP也是一個不錯的微信小程式的開發架構
UNI-APP的官網
了解藍牙API傳回的報錯
錯誤碼 | 錯誤資訊 | 說明 |
---|---|---|
ok | 正常 | |
10000 | not init | 未初始化藍牙擴充卡 |
10001 | not available | 目前藍牙擴充卡不可用 |
10002 | no device | 沒有找到指定裝置 |
10003 | connection fail | 連接配接失敗 |
10004 | no service | 沒有找到指定服務 |
10005 | no characteristic | 沒有找到指定特征值 |
10006 | no connection | 目前連接配接已斷開 |
10007 | property not support | 目前特征值不支援此操作 |
10008 | system error | 其餘所有系統上報的異常 |
10009 | system not support | Android 系統特有,系統版本低于 4.3 不支援 BLE |
10012 | operate time out | 連接配接逾時 |
10013 | invalid_data | 連接配接 deviceId 為空或者是格式不正确 |
初始化藍牙子產品
uni.openBluetoothAdapter(OBJECT)
- 其他藍牙相關 API 必須在這個方法調用之後使用。否則 API 會傳回錯誤(errCode=10000)。
- 在使用者藍牙開關未開啟或者手機不支援藍牙功能的情況下,調用這個方法會傳回錯誤(errCode=10001),表示手機藍牙功能不可用。
- 初始化完成後,可通過
監聽手機藍牙狀态的改變,也可以調用藍牙子產品的所有API。uni.onBluetoothAdapterStateChange
示例代碼
uni.openBluetoothAdapter({
success: (res) => {
if (res.errMsg == 'openBluetoothAdapter:ok') {}
}
})
監聽藍牙狀态變化事件
uni.onBluetoothAdapterStateChange(CALLBACK)
CALLBACK 傳回參數
屬性 | 類型 | 說明 |
---|---|---|
available | boolean | 藍牙擴充卡是否可用 |
discovering | boolean | 藍牙擴充卡是否處于搜尋狀态 |
示例代碼
uni.onBLEConnectionStateChange((res) => {
if (res.connected == false) {
this.cut = true
uni.showModal({
title: "藍牙連接配接斷開",
content: "是否重新搜尋",
success: (res) => {
if (res.confirm) this.search()
}
})
}
})
搜尋周圍的藍牙
uni.startBluetoothDevicesDiscovery(OBJECT)
- App 端目前僅支援發現ble藍牙裝置
- 開始搜尋附近的藍牙外圍裝置。此操作比較耗費系統資源,請在搜尋并連接配接到裝置後調用
方法停止搜尋。uni.stopBluetoothDevicesDiscovery
OBJECT 參數說明
屬性 | 類型 | 預設值 | 必填 | 說明 |
---|---|---|---|---|
services | Array | 否 | 要搜尋但藍牙裝置主 service 的 uuid 清單。某些藍牙裝置會廣播自己的主 service 的 uuid。如果設定此參數,則隻搜尋廣播包有對應 uuid 的主服務的藍牙裝置。建議主要通過該參數過濾掉周邊不需要處理的其他藍牙裝置。 | |
allowDuplicatesKey | boolean | false | 否 | 是否允許重複上報同一裝置。如果允許重複上報,則 uni.onBlueToothDeviceFound 方法會多次上報同一裝置,但是 RSSI 值會有不同。 |
interval | number | 否 | 上報裝置的間隔。0 表示找到新裝置立即上報,其他數值根據傳入的間隔上報。 | |
success | function | 否 | 接口調用成功的回調函數 | |
fail | function | 否 | 接口調用失敗的回調函數 | |
complete | function | 否 | 接口調用結束的回調函數(調用成功、失敗都會執行) |
示例代碼
uni.startBluetoothDevicesDiscovery({
allowDuplicatesKey: true, //是否允許重複上報同一裝置
interval: 0, //搜尋間隔
success: (res2) => {
if (res2.errMsg == 'startBluetoothDevicesDiscovery:ok') {
this.monitor()
}
}
})
監聽尋找到新裝置的事件
uni.onBluetoothDeviceFound(CALLBACK)
CALLBACK 傳回參數
屬性 | 類型 | 說明 |
---|---|---|
devices | Array | 新搜尋到的裝置清單 |
devices 的結構
屬性 | 類型 | 說明 |
---|---|---|
name | string | 藍牙裝置名稱,某些裝置可能沒有 |
deviceId | string | 用于區分裝置的 id |
RSSI | number | 目前藍牙裝置的信号強度 |
advertisData | ArrayBuffer | 目前藍牙裝置的廣播資料段中的 ManufacturerData 資料段 |
advertisServiceUUIDs | Array | 目前藍牙裝置的廣播資料段中的 ServiceUUIDs 資料段 |
localName | string | 目前藍牙裝置的廣播資料段中的 LocalName 資料段 |
serviceData | Object | 目前藍牙裝置的廣播資料段中的 ServiceData 資料段 |
- 若在
回調了某個裝置,則此裝置會添加到uni.onBluetoothDeviceFound
(有興趣的話的查找一下)接口擷取到的數組中。uni.getBluetoothDevices
示例代碼
uni.onBluetoothDeviceFound((res) => {
res.devices.forEach(result => {
if ((result.name != '') && (result.localName != '')) {
let idx = util.inArray(this.booth.list, 'deviceId', result.deviceId)
if (idx === -1) {
this.booth.list.push(result)
} else {
this.booth.list[idx] = result
}
}
})
})
停止搜尋附近的藍牙外圍裝置
uni.stopBluetoothDevicesDiscovery(OBJECT)
- 搜尋藍牙是很費資源的行為,若已經找到需要的藍牙裝置并不需要繼續搜尋時,建議調用該接口停止藍牙搜尋。
OBJECT 參數說明
屬性 | 類型 | 說明 |
---|---|---|
success | function | 接口調用成功的回調函數 |
fail | function | 接口調用失敗的回調函數 |
complete | function | 接口調用結束的回調函數(調用成功、失敗都會執行) |
示例代碼
stopSearch() {
uni.stopBluetoothDevicesDiscovery()
}
連接配接低功耗藍牙裝置
uni.createBLEConnection(OBJECT)
- 若APP在之前已有搜尋過某個藍牙裝置,并成功建立連接配接,可直接傳入之前搜尋擷取的 deviceId 直接嘗試連接配接該裝置,無需進行搜尋操作。
- 藍牙連接配接随時可能斷開,建議監聽
回調事件,當藍牙裝置斷開時按需執行重連操作uni.onBLEConnectionStateChange
- 若對未連接配接的裝置或已斷開連接配接的裝置調用資料讀寫操作的接口,會傳回 10006 錯誤,建議進行重連操作。
- 盡量成對的調用連接配接和斷開的接口,如果多次調用連接配接接口,有可能導緻系統持有同一裝置多個連接配接的執行個體,導緻調用斷開接口失效
OBJECT 參數說明
屬性 | 類型 | 必填 | 說明 |
---|---|---|---|
deviceId | string | 是 | 用于區分裝置的 id |
timeout | number | 否 | 逾時時間,機關ms,不填表示不會逾時 |
success | function | 否 | 接口調用成功的回調函數 |
fail | function | 否 | 接口調用失敗的回調函數 |
complete | function | 否 | 接口調用結束的回調函數(調用成功、失敗都會執行) |
示例代碼
uni.createBLEConnection({
deviceId: this.uuid.deviceId,
success: (res) => {
if (res.errMsg == 'createBLEConnection:ok') {
setTimeout(() => {
this.Service()
this.BLEChange()
}, 2000)
}
}
})
擷取藍牙裝置所有服務
uni.getBLEDeviceServices(OBJECT)
- 這裡有一個坑,連接配接裝置成功後,不能立即調用
,否則擷取不到任何服務。解決方法:連接配接成功後,等個幾秒(看裝置的情況)在調用uni.getBLEDeviceServices(OBJECT)
uni.getBLEDeviceServices(OBJECT)
OBJECT 參數說明
屬性 | 類型 | 必填 | 說明 |
---|---|---|---|
deviceId | string | 是 | 藍牙裝置 id |
success | function | 否 | 接口調用成功的回調函數 |
fail | function | 否 | 接口調用失敗的回調函數 |
complete | function | 否 | 接口調用結束的回調函數(調用成功、失敗都會執行) |
success 傳回參數說明
屬性 | 類型 | 說明 |
---|---|---|
services | Array | 裝置服務清單 |
res.services 的結構
屬性 | 類型 | 說明 |
---|---|---|
uuid | string | 藍牙裝置服務的 uuid |
isPrimary | boolean | 該服務是否為主服務 |
示例代碼
uni.getBLEDeviceServices({
deviceId: this.uuid.deviceId,
success: (res) => {
if (res.services.length == 0) {
util.showError("找不到服務")
} else {
let booth = true
for (let i = 0; i < res.services.length; i++) {
if (res.services[i].uuid == this.uuid.service) {
booth = false
this.Character()
break;
}
}
if (booth) util.showError("服務uuid錯誤")
}
}
})
擷取藍牙裝置某個服務中所有特征值
uni.getBLEDeviceCharacteristics(OBJECT)
OBJECT 參數說明
屬性 | 類型 | 必填 | 說明 |
---|---|---|---|
deviceId | string | 是 | 藍牙裝置 id |
serviceId | string | 是 | 藍牙服務 uuid,需要使用 擷取 |
success | function | 否 | 接口調用成功的回調函數 |
fail | function | 否 | 接口調用失敗的回調函數 |
complete | function | 否 | 接口調用結束的回調函數(調用成功、失敗都會執行) |
success 傳回參數說明
屬性 | 類型 | 說明 |
---|---|---|
characteristics | Array | 裝置服務清單 |
res.characteristics 的結構
屬性 | 類型 | 說明 |
---|---|---|
uuid | string | 藍牙裝置特征值的 uuid |
properties | Object | 該特征值支援的操作類型 |
properties 的結構
屬性 | 類型 | 說明 |
---|---|---|
uuid | string | 藍牙裝置特征值的 uuid |
read | boolean | 該特征值是否支援 read 操作 |
write | boolean | 該特征值是否支援 write 操作 |
notify | boolean | 該特征值是否支援 notify操作 |
indicate | boolean | 該特征值是否支援 indicate操作 |
- read:讀取操作
- write:寫入操作
示例代碼
uni.getBLEDeviceServices({
deviceId: this.uuid.deviceId,
success: (res) => {
if (res.services.length == 0) {
util.showError("找不到服務")
} else {
let booth = true
for (let i = 0; i < res.services.length; i++) {
if (res.services[i].uuid == this.uuid.service) {
booth = false
this.Character()
break;
}
}
if (booth) util.showError("服務uuid錯誤")
}
}
})
啟用低功耗藍牙裝置特征值變化時的 notify 功能
uni.notifyBLECharacteristicValueChange(OBJECT)
- 必須裝置的特征值支援 notify 或者 indicate 才可以成功調用
- 訂閱操作成功後需要裝置主動更新特征值的 value,才會觸發
(後續監聽裝置的傳回消息)回調uni.onBLECharacteristicValueChange
- 安卓平台上,在調用
成功後立即調用notifyBLECharacteristicValueChange
(向裝置發送資訊)接口,在部分機型上會發生 10008 系統錯誤writeBLECharacteristicValue
- 連接配接藍牙裝置的過程到此結束
OBJECT 參數說明
屬性 | 類型 | 必填 | 說明 |
---|---|---|---|
deviceId | string | 是 | 藍牙裝置 id |
serviceId | string | 是 | 藍牙特征值對應服務的 uuid |
characteristicId | string | 是 | 藍牙特征值的 uuid |
state | boolean | 是 | 是否啟用 notify |
success | function | 否 | 接口調用成功的回調函數 |
fail | function | 否 | 接口調用失敗的回調函數 |
complete | function | 否 | 接口調用結束的回調函數(調用成功、失敗都會執行) |
示例代碼
uni.notifyBLECharacteristicValueChange({
deviceId: this.uuid.deviceId,
serviceId: this.uuid.service,
characteristicId: this.uuid.character,
state: true,
success: (res) => {
if (res.errMsg == 'notifyBLECharacteristicValueChange:ok') {
uni.hideLoading();
this.cut = false
this.BLEValue()
}
}
})
監聽低功耗藍牙裝置的特征值變化事件(擷取裝置發送的資訊)
uni.onBLECharacteristicValueChange(CALLBACK)
- 監聽低功耗藍牙裝置的特征值變化事件。必須先啟用
接口才能接收到裝置推送的 notification。notifyBLECharacteristicValueChange
- 有些藍牙裝置發送的資訊是多段發送的,需要特殊處理
CALLBACK 傳回參數
屬性 | 類型 | 說明 |
---|---|---|
deviceId | string | 藍牙裝置 id |
serviceId | string | 藍牙特征值對應服務的 uuid |
characteristicId | string | 藍牙特征值的 uuid |
value | ArrayBuffer | 特征值最新的值 |
- 接收裝置發送過來的資訊,需要對value字段進行處理才能擷取到資訊
- 漢字的編碼格式也需要進行特殊處理
###示例代碼
uni.onBLECharacteristicValueChange((res) => {
let caseoff = this.operation.Receive + util.ab2Str(res.value)
let len = caseoff.length - 1
let i = caseoff.charCodeAt(len)
if (i < 127) {
this.operation.Receive = ""
caseoff = util.gbkStrToUtf16Str(caseoff)
this.operation.receive += caseoff
} else {
if (caseoff.charCodeAt(len - 1) > 127) {
this.operation.Receive = ""
caseoff = util.gbkStrToUtf16Str(caseoff)
this.operation.receive += caseoff
} else {
this.operation.Receive = caseoff
}
}
})
向低功耗藍牙寫入資料
- 必須裝置的特征值支援 write 才可以成功調用。
- 并行調用多次會存在寫失敗的可能性。
- APP不會對寫入資料包大小做限制,但系統與藍牙裝置會限制藍牙4.0單次傳輸的資料大小,超過最大位元組數後會發生寫入錯誤,建議每次寫入不超過20位元組。
- 若單次寫入資料過長,iOS 上存在系統不會有任何回調的情況(包括錯誤回調)。
- 安卓平台上,在調用
成功後立即調用notifyBLECharacteristicValueChange
接口,在部分機型上會發生 10008 系統錯誤writeBLECharacteristicValue
屬性 | 類型 | 必填 | 說明 |
---|---|---|---|
deviceId | string | 是 | 藍牙裝置 id |
serviceId | string | 是 | 藍牙特征值對應服務的 uuid |
characteristicId | string | 是 | 藍牙特征值的 uuid |
value | ArrayBuffer | 是 | 藍牙裝置特征值對應的二進制值 |
success | function | 否 | 接口調用成功的回調函數 |
fail | function | 否 | 接口調用失敗的回調函數 |
complete | function | 否 | 接口調用結束的回調函數(調用成功、失敗都會執行) |
示例代碼
let j = 0;
for (let i = 0; i < SendStr.length / 20; i++) {
setTimeout(() => {
let setData = SendStr.substring(j, j + 20)
setData = new Uint8Array(util.stringToBytes(setData)).buffer
j = j + 20
uni.writeBLECharacteristicValue({
deviceId: this.uuid.deviceId,
serviceId: this.uuid.service,
characteristicId: this.uuid.write,
value: setData,
fail: (err) => {
util.showError("發生錯誤")
}
})
}, i * 300)
}