不知道大家對低能藍牙的技術應用瞭解的怎麼樣,其實這是一個比較廣的應用,比如可以應用於一些信標、家庭娛樂或者醫療方面都有應用。
01 前言
因爲小程序官方是支持接入低能藍牙(BLE)的,所以在一個項目中也嘗試使用如何接入藍牙,我們從微信的官方網站就可以清楚知道如何使用,但是其中也是有很多坑的。本着學習的心態,自己也手把手帶你摸坑,一起處理一些平臺兼容性的問題
以及一些邏輯判斷
問題。
02 問題拋出
因爲藍牙在IOS客戶端6.5.6
版本開始支持,安卓6.5.7
開始支持,所以一開始我們就應該判斷版本問題,以免後面的功能不能使用。
我們從文檔上面看到這樣一段話:
由於系統限制,Android 上獲取到的 deviceId 爲設備 MAC 地址,iOS 上則爲設備 uuid。因此 deviceId 不能硬編碼到代碼中。
看到這裏我就想着,完犢子了,因爲我們的手機平臺有安卓和蘋果,唯一標識藍牙的就是deviceId,但是蘋果搜索出來就不是這個了,而是uuid的一串字符串。因爲蘋果官方認爲透露deviceId(MAC地址)會有安全問題,索性直接屏蔽了。
03 使用方法
爲了保證本文的完整性,我就大概介紹一下怎麼使用在小程序接入低能藍牙,大家也可以去官網看一下。
- 初始化藍牙模塊
openBluetoothAdapter() {
var that = this;
if (wx.openBluetoothAdapter) {
wx.openBluetoothAdapter({
success: function (res) {
wx.showToast({
title: "正在獲取藍牙列表",
icon: "loading",
});
that.getBluetoothAdapterState();
},
fail: function (err) {
wx.showModal({
title: "提示",
content: "請先打開藍牙",
showCancel: false,
});
that.stopBluetoothDevicesDiscovery();
},
});
} else {
}
},
- 獲取本機藍牙適配器狀態
var that = this;
wx.getBluetoothAdapterState({
success: function (res) {
that.startBluetoothDevicesDiscovery();
},
fail(err) {
console.log(err);
},
});
- 開始搜尋附近的藍牙外圍設備
startBluetoothDevicesDiscovery() {
console.log("獲取藍牙設備列表");
var that = this;
that.data.devices = [];
wx.startBluetoothDevicesDiscovery({
success: function (res) {
that.getBluetoothDevices();
},
fail(err) {
console.log(err);
},
});
},
- 獲取在藍牙模塊生效期間所有已發現的藍牙設備
getBluetoothDevices() {
var _this = this;
wx.getBluetoothDevices({
services: [],
allowDuplicatesKey: false,
interval: 0,
success: function (res) {
wx.hideToast();
console.log(res);
},
fail(res) {
console.log(res, "獲取藍牙設備列表失敗=====");
},
});
},
經過上面的一通操作之後我們就可以獲取到藍牙列表了,你可以查看你的低能藍牙是否可以獲取到。看到這裏你就可以發現安卓與蘋果的搜索結果是不一樣
的。
04 解決途徑
版本問題
首先就是版本的問題,我們要判斷寫一個版本的判斷函數用來判別用戶的版本:
function versionCompare(ver1, ver2) {
var version1pre = parseFloat(ver1)
var version2pre = parseFloat(ver2)
var version1next = parseInt(ver1.replace(version1pre + ".", ""))
var version2next = parseInt(ver2.replace(version2pre + ".", ""))
if (version1pre > version2pre)
return true
else if (version1pre < version2pre)
return false
else {
if (version1next > version2next)
return true
else
return false
}
}
然後調用微信的官方接口來獲取手機版本:
wx.getSystemInfo({
success(res) {
let currVersion = res.system.split(' ')[1];
if (res.platform == 'android' && util.versionCompare('6.5.7', currVersion)) {
wx.showModal({
title: '提示',
content: '當前android版本過低,暫不支持',
showCancel: false
})
} else if (res.platform == 'ios' && util.versionCompare('6.5.6', currVersion)) {
wx.showModal({
title: '提示',
content: '當前ios版本過低,暫不支持',
showCancel: false
})
}
}
})
跨平臺方案
我們必須保證設備的標識唯一
,兩種平臺獲取的數據是一樣的,那麼我們既然不能聯繫蘋果叫他開放,我們就採用一個折中
的方法。
我一開始網上查找了很多資料,其中有說道藍牙的advertisData
當中是含有MAC地址的數據包,你只要解析一下就可以獲取了,但是我按照他的方法操作一番發現安卓的deviceId和我獲取的是不一樣的值。所以就放棄這個方法了。
這時我就想着既然蘋果可以通過這個字段獲取到一個唯一值,那麼安卓同樣也可以呀。所以安卓端我也同樣使用這個方法獲取,不出所料果然可以。
我把這個方法稱之爲適配器方法
,因爲和設計模式的適配器模式思想一樣:
function getUniqueId(bf) {
let buffer = bf.slice(4, 10);
let mac = Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
return mac.toUpperCase()
}
簡單介紹一下,這是一個處理buffer的函數,因爲我們展開advertisData字段看到是buffer類型的,只要我們把它當作參數傳進去就可以獲取到16進制的值,我就把這個值當作藍牙的唯一標識。例如F3C85DF5EFFB
的這種標識。
05 小結
期間也用過嘗試很多種的方式來解決這個頑固的問題,但是都沒有成功。心裏就只有一個想法就是如何把這兩者通過中間方法獲取都是一樣的值。
這個項目我覺得最大的坑就是這個了,曾經研究了好多天的時間都不曾解決,一開始我也不知道有這個限制,我還問過淘寶的藍牙生產商能不能在藍牙上面多加一個廣播字段與deviceId一樣,加入可以的話就直接獲取了,也沒有這麼多事情了。奈何不行。
所以希望大家做這一塊的話可以留意一下這個問題,但是我還發現有一些藍牙的廣播字段沒有這個advertisData這個字段,那麼我的方法也就不管用了,我還在想着怎麼解決這個問題,後面有進展再更新吧。