前言:
記得上次分享過一篇小程序的文章《時隔兩年打掘,我開始學習微信小程序了~~仿小米手機天氣預報》华畏,那是我首次學習小程序,轉眼間又過去大半年了尊蚁,這次我就來談談--->小程序藍牙開發(fā)亡笑。
一、你了解藍牙嗎横朋?
藍牙是一種無線技術標準仑乌,可實現(xiàn)固定設備、移動設備和樓宇個人域網之間的短距離數據交換(使用2.4—2.485GHz的ISM波段的UHF無線電波)琴锭。藍牙技術最初由電信巨頭愛立信公司于1994年創(chuàng)制晰甚,當時是作為RS232數據線的替代方案。藍牙可連接多個設備决帖,克服了數據同步的難題厕九。
相信負責移動端開發(fā)的朋友們或大或小都有了解過“經典藍牙”和“低功耗藍牙”這兩個代名詞;而我總結了一下他們的優(yōu)缺點:
1古瓤、android手機必須系統(tǒng)版本4.3及以上才支持BLE API止剖。BLE藍牙較傳統(tǒng)藍牙, 傳輸速度更快落君,覆蓋范圍更廣穿香,安全性更高,延遲更短绎速,耗電極低等等優(yōu)點皮获;
2、傳統(tǒng)藍牙與BLE藍牙通信方式也有所不同纹冤,傳統(tǒng)的一般通過socket方式洒宝,而BLE藍牙是通過Gatt協(xié)議來實現(xiàn);
3萌京、傳統(tǒng)藍牙可以用與數據量比較大的傳輸雁歌,如語音,音樂知残,較高數據量傳輸等靠瞎;
低功耗藍牙這樣應用于實時性要求比較高,但是數據速率比較低的產品求妹,如遙控類的乏盐,如鼠標,鍵盤制恍,遙控鼠標(Air Mouse)父能,傳感設備的數據發(fā)送,如心跳帶净神,血壓計何吝,溫度傳感器等一些醫(yī)療器械溉委。
二、小程序藍牙開發(fā)
一直以來我都是負責Android端的藍牙軟件項目開發(fā)岔霸,突然間某某某領導對我說要用小程序開發(fā)薛躬,那時我心中有一百個不爽,由于小程序的API已經對藍牙提供支持了呆细,我也沒有什么理由去推卸了型宝,但我只能說對領導說關于小程序藍牙開發(fā)還不夠成熟,其中可能會有兼容性問題絮爷,對于可行性問題我也不太確定趴酣,所以我也是抱著學習的心態(tài)去面對的。開始行動起來吧坑夯,相信敢于挑戰(zhàn)岖寞,敢于付出的人,肯定有所收獲的柜蜈。
首先小程序開發(fā) 離不開小程序開發(fā)文檔:先去了解和熟悉藍牙API仗谆;都看一遍,對整個藍牙開發(fā)流程也不過如此簡單淑履,都是一些api的套路罷了隶垮。
微信客戶端對小程序藍牙的支持版本為:iOS 微信客戶端 6.5.6 版本開始支持,Android微信客戶端 6.5.7 版本開始支持秘噪,此外還需要注意的就是Android系統(tǒng)需要Android4.3以上才可以使用藍牙BLE狸吞,而小程序藍牙只支持BLE,這點需要注意下指煎。
1.獲取當前設備平臺以及微信版本蹋偏,判斷是否支持小程序藍牙:
//獲取當前設備平臺以及微信版本
if (app.getPlatform() == 'android' && this.versionCompare('6.5.7', app.getWxVersion())) {
wx.showModal({
title: '提示',
content: '當前微信版本過低,請更新至最新版本',
showCancel: false,
success: function (res) {
if (res.confirm) {
that.backPage();
}
}
})
} else if (app.getPlatform() == 'ios' && this.versionCompare('6.5.6', app.getWxVersion())){
wx.showModal({
title: '提示',
content: '當前微信版本過低至壤,請更新至最新版本',
showCancel: false,
success: function (res) {
if (res.confirm) {
that.backPage();
}
}
})
}
2.初始化小程序藍牙模塊威始,生效周期為調用wx.openBluetoothAdapter
至調用wx.closeBluetoothAdapter
或小程序被銷毀為止。 在小程序藍牙適配器模塊生效期間像街,開發(fā)者可以正常調用下面的小程序API字逗,并會收到藍牙模塊相關的on回調。
//初始化小程序藍牙模塊
openBluetoothAdapter:function(){
var that = this;
wx.openBluetoothAdapter({
success: function (res){
var log = that.data.textLog + "打開藍牙適配器成功宅广!\n";
that.setData({
textLog: log,
isopen:true
});
that.getBluetoothAdapterState();
},
fail: function (err){
isopen: true;
app.toastTap("藍牙開關未開啟");
var log = that.data.textLog + "藍牙開關未開啟 \n";
that.setData({
textLog: log
});
}
})
//監(jiān)聽藍牙適配器狀態(tài)變化事件
wx.onBluetoothAdapterStateChange(function (res) {
console.log('onBluetoothAdapterStateChange', res)
var isDvailable = res.available;//藍牙適配器是否可用
if (isDvailable) {
that.getBluetoothAdapterState();
} else {
that.stopBluetoothDevicesDiscovery();//停止搜索
that.setData({
devices: []
});
app.toastTap1("藍牙開關未開啟");
}
})
}
3.獲取本機藍牙適配器狀態(tài)
getBluetoothAdapterState: function () {
var that = this;
wx.getBluetoothAdapterState({
success: function (res) {
var isDiscov = res.discovering;//是否正在搜索設備
var isDvailable = res.available;//藍牙適配器是否可用
if (isDvailable) {
var log = that.data.textLog + "本機藍牙適配器狀態(tài):可用 \n";
that.setData({
textLog: log
});
if (!isDiscov){
that.startBluetoothDevicesDiscovery();
}else{
var log = that.data.textLog + "已在搜索設備 \n";
that.setData({
textLog: log
});
}
}
}
})
}
4.開始掃描附近的藍牙外圍設備。注意些举,該操作比較耗費系統(tǒng)資源跟狱,請在搜索并連接到設備后調用 stop 方法停止搜索。
wx.startBluetoothDevicesDiscovery({
services: [],// 以微信硬件平臺的藍牙智能燈為例户魏,主服務的 UUID 是 FEE7驶臊。傳入這個參數:services: ['FEE7']挪挤,只搜索主服務 UUID 為 FEE7 的設備
allowDuplicatesKey: true, //是否允許重復上報同一設備, 如果允許重復上報,則onDeviceFound 方法會多次上報同一設備关翎,但是 RSSI(信號) 值會有不同
success: function (res) {
var log = that.data.textLog + "掃描附近的藍牙外圍設備成功扛门,準備監(jiān)聽尋找新設備:" + res+"\n";
that.setData({
textLog: log
});
that.onBluetoothDeviceFound(); //監(jiān)聽尋找到新設備的事件
}
});
5.監(jiān)聽尋找到新設備的事件;Android 上獲取到的deviceId
為設備 MAC 地址纵寝,iOS 上則為設備 uuid论寨。因此deviceId
不能硬編碼到代碼中
//監(jiān)聽尋找到新設備的事件
onBluetoothDeviceFound:function() {
var that = this;
wx.onBluetoothDeviceFound(function(res) {
res.devices.forEach(function (device) {
if (!device.name && !device.localName) {
return
}
const foundDevices = that.data.devices;
const idx = inArray(foundDevices, 'deviceId', device.deviceId);
const data = {};
if (idx === -1) {
data[`devices[${foundDevices.length}]`] = device
} else {
data[`devices[${idx}]`] = device
}
that.setData(data)
})
})
}
至此整個過程就完成了對設備的搜索操作,這時就可以對掃描到的設備id以及name爽茴,進行處理葬凳;不過這個過程需要注意的是:安卓和IOS差別很大,安卓設備地址就是mac地址室奏,但是IOS無法獲取mac地址火焰,所以設備地址是針對本機范圍有效的UUID,所以這里需要注意胧沫。剩下的就是藍牙設備的連接昌简、讀、寫绒怨、還有監(jiān)聽獲取返回值了纯赎。
6.連接低功耗藍牙設備。
wx.createBLEConnection({ // 這里的 deviceId 需要已經通過 createBLEConnection 與對應設備建立鏈接
deviceId: deviceId,
success: function (res) {
console.log(res)
}
})
當使用此方法成功連接藍牙設備后窖逗,需要使用方法:wx.stopBluetoothDevicesDiscovery() 關閉藍牙掃描功能址否,釋放資源,減少消耗碎紊。
7.獲取藍牙設備所有 service(服務)
//獲取藍牙設備所有 service(服務)
getBLEDeviceServices:function(devId) {
var that = this;
wx.getBLEDeviceServices({
deviceId:devId,
success: function(res) {
for (let i = 0; i < res.services.length; i++) {
if (res.services[i].isPrimary) {//該服務是否為主服務
var log = that.data.textLog + "該服務是否為主服務:" + res.services[i].isPrimary + "\n";
that.setData({
textLog: log
});
}
}
}
})
}
8.獲取到服務ID后佑附,就可以獲取藍牙設備某個服務中的所有 characteristic(特征值)
//獲取藍牙設備某個服務中的所有 characteristic(特征值)
getBLEDeviceCharacteristics: function (deviceId, serviceId){
var that = this;
wx.getBLEDeviceCharacteristics({
deviceId: deviceId,
serviceId: serviceId,
success: function (res) {
for (let i = 0; i < res.characteristics.length; i++) {
let item = res.characteristics[i]
if (item.properties.read) {//該特征值是否支持 read 操作
var log = that.data.textLog + "該特征值支持 read 操作:" + item.uuid + "\n";
that.setData({
textLog: log,
readCharacteristicId: item.uuid
});
}
if (item.properties.write) {//該特征值是否支持 write 操作
var log = that.data.textLog + "該特征值支持 write 操作:" + item.uuid + "\n";
that.setData({
textLog: log,
writeCharacteristicId: item.uuid,
canWrite:true
});
}
if (item.properties.notify) {//該特征值是否支持 notify或indicate 操作
var log = that.data.textLog + "該特征值支持 notify 操作:" + item.uuid + "\n";
that.setData({
textLog: log,
notifyCharacteristicId: item.uuid,
});
that.notifyBLECharacteristicValueChange();
}
}
}
})
}
至此,我們已經獲取了 讀的特征值UUID仗考,有些設備不支持讀操作的話音同,就沒有這個UUID;我們還獲取了寫操作的UUID秃嗜,如果沒有此UUID的話权均,我們的設備就不支持寫入指令操作;我們還獲取了notify UUID锅锨,是用來執(zhí)行廣播監(jiān)聽事件的叽赊,就是寫入指令后,藍牙設備有返回數值必搞,都可以監(jiān)聽接收必指。
9.開啟監(jiān)聽藍牙設備的返回值,讀寫操作成功后的返回值也是在下面onBLECharacteristicValueChange這個方法獲取恕洲,這里相當于Android藍牙BLE的開啟廣播監(jiān)聽塔橡。
notifyBLECharacteristicValueChange:function(){
var that = this;
wx.notifyBLECharacteristicValueChange({
state: true, // 啟用 notify 功能
deviceId: that.data.deviceId,
serviceId: that.data.serviceId,
characteristicId: that.data.notifyCharacteristicId,
success: function (res) {
var log = that.data.textLog + "notify啟動成功\n";
that.setData({
textLog: log,
});
that.onBLECharacteristicValueChange(); //監(jiān)聽特征值變化
},
fail: function (res) {
wx.showToast({
title: 'notify啟動失敗',
mask: true
});
setTimeout(function () {
wx.hideToast();
}, 2000)
}
})
},
//監(jiān)聽低功耗藍牙設備的特征值變化梅割。必須先啟用notify接口才能接收到設備推送的notification。
onBLECharacteristicValueChange:function(){
var that = this;
var log = that.data.textLog + "準備監(jiān)聽低功耗藍牙設備的特征值變化\n";
that.setData({
textLog: log,
});
wx.onBLECharacteristicValueChange(function (res) {
var log = that.data.textLog + "監(jiān)聽低功耗藍牙設備的特征值變化\n";
that.setData({
textLog: log,
});
// var resValue = that.ab2hext(res.value); //16進制字符串
});
}
10.最后一步葛家,讀或寫操作户辞;這里需要注意的是:小程序中對藍牙數據的傳遞是使用ArrayBuffer的二進制類型來的,所以在我們的使用過程中需要進行轉碼再進行讀或者寫操作癞谒。
//讀
wx.readBLECharacteristicValue({
// 這里的 deviceId 需要已經通過 createBLEConnection 與對應設備建立鏈接 [**new**]
deviceId: deviceId,
// 這里的 serviceId 需要在上面的 getBLEDeviceServices 接口中獲取
serviceId: serviceId,
// 這里的 characteristicId 需要在上面的 getBLEDeviceCharacteristics 接口中獲取
characteristicId: characteristicId,
success: function (res) {
console.log('readBLECharacteristicValue:', res.errCode)
}
})
底燎、、扯俱、书蚪、、
//寫
wx.writeBLECharacteristicValue({
// 這里的 deviceId 需要在上面的 getBluetoothDevices 或 onBluetoothDeviceFound 接口中獲取
deviceId: deviceId,
// 這里的 serviceId 需要在上面的 getBLEDeviceServices 接口中獲取
serviceId: serviceId,
// 這里的 characteristicId 需要在上面的 getBLEDeviceCharacteristics 接口中獲取
characteristicId: characteristicId,
// 這里的value是ArrayBuffer類型
value: buffer,
success: function (res) {
console.log('writeBLECharacteristicValue success', res.errMsg)
}
})
迅栅、殊校、、读存、为流、
//寫
wx.writeBLECharacteristicValue({
// 這里的 deviceId 需要在上面的 getBluetoothDevices 或 onBluetoothDeviceFound 接口中獲取
deviceId: deviceId,
// 這里的 serviceId 需要在上面的 getBLEDeviceServices 接口中獲取
serviceId: serviceId,
// 這里的 characteristicId 需要在上面的 getBLEDeviceCharacteristics 接口中獲取
characteristicId: characteristicId,
// 這里的value是ArrayBuffer類型
value: buffer,
success: function (res) {
console.log('writeBLECharacteristicValue success', res.errMsg)
}
}
)
查看小程序藍牙api也會發(fā)現(xiàn)如下tip:
就是要控制單次傳送的指令,確保不要超過20個字節(jié)让簿,如果超過了敬察,就要進行分包發(fā)送了,也就是每次分20個字節(jié)尔当,分成多次發(fā)送莲祸,如果是Android開發(fā)的話,可以調整MTU的大小椭迎,但是小程序沒有封裝這個方法锐帜,所以只能分包也是可以的。
在學習小程序藍牙的過程中畜号,我也寫了個demo:小程序藍牙demo缴阎,希望能幫助到大家,并且也能趁此機會和大家交流简软,望多多指教蛮拔。
支持我的話可以關注下我的公眾號,也歡迎大家投稿~
掃一掃關注我的微信公眾號:程序猿在廣東