微信小程序藍牙BLE開發實戰(二)
上篇主要介紹在開發過程中應用到相關API
操作。接下來介紹個人在項目開發中應用藍牙BLE
一些事情。
由於時間比較倉促, 有些註釋沒那麼詳細。請理解~寫的不好歡迎各位大神指點。
文章目錄
項目介紹
由於公司近階段開發的共享產品比較多,有共享
充電寶、陪護牀
等,這裏就不一一介紹哈。大部分產品通過藍牙通訊
的。
快捷方便
: 通過掃設備二維碼
進入小程序使用設備。
- 這裏拿最近開發一個產品
售賣機
,生活中比較常見的一個,例如: 儲物櫃、格子櫃等。 - 特點: 一個
售賣機
中有n個小格子(根據產品分類)
效果圖
掃碼使用格子櫃
流程
售賣機
上有設備的二維碼(自己生成普通二維碼)
,直接掃碼ps: 有個別標註鏈接的,是個人在項目開發中應用總結
知識點
。
- 微信掃普通二維碼進入小程序,授權獲取用戶信息
用戶授權成功後
,檢測用戶是否打開藍牙
未打開
時彈窗提示用戶, 否則自動跳轉到售賣機
頁面。售賣機
頁面會展示售賣商品(比如8個,那麼就展示8個商品)
- 選擇需要購買的
商品
, 點擊購買
按鈕 - 支付金額
- 支付完成後, 調用
執行藍牙方法
開始搜索設備
—>匹配設備
—>連接設備...
—>開鎖成功(櫃門打開)
【查看藍牙具體流程】如連接設備失敗,頁面顯示重連
按鈕 - 拿出商品,關好櫃門(可返回購買頁,繼續購買)。
藍牙通訊協議
主要通過與
供應商
提供的藍牙板子
、通訊協議
和硬件對接,實現操控設備
具備的功能。
-
不同的供應商設備
藍牙通訊協議
有所不同。反之產品不同通訊流程
也不同。有些文檔比較不規範,看起來會很茫然, 慢慢理解查資料
加密理解
基於數據
安全性
、完整性
等等,藍牙協議通過會在有加密
的過程,抵禦攻擊者。
密碼之AES五種加密模式(CBC、ECB、CTR、OCF、CFB)
- 下發某個
指令
時需要對數據進行加密
,設備會返回數據,通過後再操作其他指令。 - 下發
指令
時加密
, 得到設備返回數據後需要解密
,如果驗證通過,纔可以繼續操作後面流程。
不管使用哪種加密模式,會標註在協議文檔
或以其他方式說明
ps: 個人在項目中使用模式有 AES
ECB 128
、CFB 128
, 還有最近使用一種CRC(循環冗餘校驗)
來校驗。
AES加解密案例
實例(藍牙操作
功能)
說明:
- 以下代碼直接copy到
.js
中就可以使用。(這裏有分段說明下,按順序複製即可) - 因在項目中對接設備比較多, 把
藍牙設備
相關功能剝離到js
文件中。 - 注意:
開發工具上不支持
調試藍牙功能的 - 【藍牙API詳情介紹請點擊】
一. 新建js
文件及使用時引入
1. 定義全局變量
根據個人需求適用
const app = getApp()
var utils = require('.././util.js');
var cryptoService = require('../bleFile/cryptoService.js'); //引入加密文件
var crc = require('../bleFile/crc.js'); //引入crc校驗
var serviceUUID = [] //主 service 的 uuid 列表
var writeUUID = ""; //寫讀 UUID
var notifyUUID = ""; //notify UUID
var delayUUID = ""; //護眼儀控制時長UUID
var filterServiceUUID = ""; //過濾獲取到的服務uuid(有些會返回多條數據)
var filterDeviceName = ""; //設備名稱
var macAddress = ""; //保存得到mac地址
var flagFromTypes = ''; //來源類型(根據不同產品執行藍牙協議) 例:1-->充電寶 2-->售賣機....
var _discoveryStarted = false;
var deviceId = ''; //用於區分設備的 id
var _deviceId = '';
var _serviceId = '';
var _characteristicId = '';
var status = false; //當前狀態
var action_type = ''; //操作類型
var code = -1;
var isnotExist = true //防止多次執行
var asddCallBack = null; //接收數據處理
var asddErrorCallback = null; //接收錯誤碼處理
var asddWriteErrors = null; //接收寫入錯誤處理
var tempStr = ''; //拼接設備返回數據
var rssiVal = ''; //RSSI值
var currentSerialVal = ''; //當前點擊格子櫃序號
//當前操作類型
var OptionEnum = {
None: -1,
Connection: 0, //連接
Reconnection: 1, //重連
CloseLock: 2, //關閉
VendingOpenLock: 8, //打開售賣機
ReadStatus: 9, //讀售賣機狀態
ReadBattery: 10, //讀售賣機電量
};
//這個是變量, 存儲數據的變量
var action_type = OptionEnum.None;
2. 自定義方法
function inArray(arr, key, val) {
for (let i = 0; i < arr.length; i++) {
if (arr[i][key] === val) {
return i;
}
}
return -1;
}
// ArrayBuffer轉16進度字符串示例
function ab2hex(buffer) {
var hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function(bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('');
}
/**
* 去掉 冒號
*/
function clearSymbol(str) {
str = str.replace(/:/g, ""); //取消字符串中出現的所有冒號
return str;
}
/**
* 匹配規則: 取名稱後面的mac
*/
function getNameMac(macAddress, len, name) {
let clearColonMac = clearSymbol(macAddress);
let lastFourMac = clearColonMac.substring(clearColonMac.length - len);
let strName = name.toUpperCase();
strName = strName + lastFourMac.toUpperCase(); //轉大寫
console.log('拼接後的' + strName);
return strName
}
/**
* 區分不同類型的服務相關uuid
* 1-->充電寶 2-->售賣機
*/
function flagServiceIDFun(serviceType) {
console.log('方法中拿到type======>', serviceType);
if (serviceType == 1) {
serviceUUID[0] = "0000*E0-00*0-*0*0-*0*0-00**5F9**4*B"; //主 service的uuid 列表
writeUUID = "00*0**E2-00*0-*0*0-*0*0-00**5F9**4*B"; //寫讀 UUID
notifyUUID = "00*0**E1-00*0-*0*0-*0*0-00**5F9**4*B"; //notify UUID
filterServiceUUID = "*E0";
} else if (serviceType == 2) {
serviceUUID[0] = "0000*E0-00*0-*0*0-*0*0-00**5F9**4*B"; //主 service的uuid 列表
writeUUID = "00*0**E2-00*0-*0*0-*0*0-00**5F9**4*B"; //寫讀 UUID
notifyUUID = "00*0**E1-00*0-*0*0-*0*0-00**5F9**4*B"; //notify UUID
filterServiceUUID = "*E0";
//這裏介紹用name匹配方法
filterDeviceName = getNameMac(macAddress, 6, 'abc_'); //設備名稱
}
}
3. 初始化藍牙入口
注意:
在使用.js
文件中, 只需要調用initBle()
方法即可實現藍牙實現整個過程。【方法裏面每個步驟都有調用對應方法】
說明: 所有asddErrorCallback(res.errCode, "");
爲處理錯誤碼
回調, 在使用的頁面中接收並處理回調函數。
/**
* 初始化藍牙模塊
* 參數1: mac地址
* 參數2: 當前操作類型
* 參數3: 當前點擊格子的序號(第幾個格子)
*/
function initBle(fromMac, flagTypes, currentSerial) {
tempStr = ''; //清空
//斷開連接【每次初始化先斷開連接】
closeBLEConnection();
console.log("你獲取到mac地址了麼....", fromMac + '獲取到類型爲====》' + flagTypes);
// macAddress = clearSymbol(fromMac);
macAddress = fromMac; //保存mac
flagFromTypes = flagTypes //類型來源
//獲取RSSI值
let getRssi = wx.getStorageSync('rssi');
rssiVal = getRssi;
//調用主服務id相關
flagServiceIDFun(flagTypes);
// 獲取當前點擊售賣機序號值
currentSerialVal = currentSerial
_discoveryStarted = false;
//初始化藍牙模塊
wx.openBluetoothAdapter({
success: (res) => {
console.log('openBluetoothAdapter 初始化藍牙模塊是否成功:', res)
// 監聽尋找新設備事件
onBluetoothDeviceFound();
//開始搜尋附近的藍牙外圍設備
startBluetoothDevicesDiscovery();
},
fail: (res) => {
console.log('初始化藍牙失敗', res);
asddErrorCallback(res.errCode, "");
//監聽藍牙適配器狀態變化事件【根據需求是否執行】
// wx.onBluetoothAdapterStateChange(function (res) {
// console.log('藍牙適配器狀態更改結果: ', res)
// if (res.available) {
// console.log('藍牙可用,搜索設備:--》 ')
// onBluetoothDeviceFound();
// startBluetoothDevicesDiscovery();
// }
// })
}
})
}
4. 應用到藍牙
API方法
/**
* 監聽尋找新設備事件
* 注意咯: 這裏有展示三種不同方式來連接設備,請看備註【mac, name, 根據系統的】 各取所需吧。
*/
function onBluetoothDeviceFound() {
wx.onBluetoothDeviceFound((res) => {
console.log('廣播數據結果:', res);
res.devices.forEach(device => {
if (!device.name && !device.localName) {
return
}
// 轉換後, 根據協議文檔取需要數據 (advertisData不一定有數據)
if (device.advertisData != null) { //判斷對象是否爲null,advertisData不一定有
var hexStr = ab2hex(device.advertisData);
console.log("廣播數據中轉換後:advertisData---->" + hexStr);
}
// 充電寶 android用mac, ios用name匹配
if (flagFromTypes == 1) {
if (app.getPlatform() == 'android') {
if ((macAddress != "") && (macAddress == device.deviceId) && isnotExist) {
isnotExist = false;
deviceId = device.deviceId;
stopBluetoothDevicesDiscovery();
//連接設備
createBLEConnection();
}
} else if (app.getPlatform() == 'ios') {
let deviceName = device.name.toUpperCase();
if ((deviceName.indexOf(filterDeviceName) != -1) && isnotExist) {
isnotExist = false;
deviceId = device.deviceId;
//停止搜尋附近的藍牙外圍設備
stopBluetoothDevicesDiscovery();
//連接設備
createBLEConnection();
}
}
} else if (flagFromTypes == 2) {
// 格子櫃 Android IOS通過名稱匹配
if (parseFloat(device.RSSI) > parseFloat(rssiVal)) {
let deviceName = device.name.toUpperCase();
if ((deviceName.indexOf(filterDeviceName) != -1) && isnotExist) {
isnotExist = false;
deviceId = device.deviceId;
//停止搜尋附近的藍牙外圍設備
stopBluetoothDevicesDiscovery();
//連接設備
createBLEConnection();
}
}
}
})
})
}
/**
* 執行連接藍牙設備
*/
function startBluetoothDevicesDiscovery() {
if (_discoveryStarted) {
return;
}
_discoveryStarted = true
wx.startBluetoothDevicesDiscovery({
services: serviceUUID,
allowDuplicatesKey: false,
success: (res) => {
console.log('啓動搜索藍牙設備, 結果 :', res)
//onBluetoothDeviceFound() //先調用此方法再使用startBluetoothDevicesDiscovery
},
fail(res) {
asddErrorCallback(res.errCode, "");
console.log('startBluetoothDevicesDiscovery fail', res);
}
})
}
//停止搜尋附近的藍牙外圍設備。
function stopBluetoothDevicesDiscovery() {
wx.stopBluetoothDevicesDiscovery()
}
/**
* 連接藍牙設備
*/
function createBLEConnection() {
var that = this;
wx.createBLEConnection({
deviceId: deviceId,
success: (res) => {
wx.showToast({
title: '設備連接成功',
duration: 2000
})
//獲取藍牙所有服務
getBLEDeviceServices(deviceId)
},
fail: (res) => {
console.log('createBLEConnection fail', res);
asddErrorCallback(res.errCode, "");
}
})
stopBluetoothDevicesDiscovery(); //停止搜索
}
/**
* 斷開藍牙連接
*/
function closeBLEConnection() {
//停止搜索
stopBluetoothDevicesDiscovery();
tempStr = ''; //清空
if (deviceId) {
wx.closeBLEConnection({
deviceId: deviceId,
success: function(res) {
console.log("closeBLEConnection。success", res);
},
fail: function(res) {
console.log("closeBLEConnection。fail", res);
},
complete: function() {
status = false;
}
})
wx.closeBluetoothAdapter({
success: function(res) {
console.log("closeBluetoothAdapter ==>res:", res);
},
fail: function(error) {
console.log("closeBluetoothAdapter ==>error:", error);
}
})
}
_discoveryStarted = false;
isnotExist = true;
_deviceId = '';
deviceId = '';
}
/**
* 獲取藍牙所有服務
*/
function getBLEDeviceServices(deviceId) {
wx.onBLEConnectionStateChange(function(res) {
console.log("onBLEConnectionStateChange:", res);
// 該方法回調中可以用於處理連接意外斷開等異常情況
console.log(`device ${res.deviceId} state has changed, connected: ${res.connected}`)
if (res.connected == false) {
console.log("連接意外斷開等****", _deviceId);
_deviceId = '';
if (flagFromTypes == 1 && flagFromTypes == 2) {
asddErrorCallback(1010, ""); //?
}
}
});
wx.getBLEDeviceServices({
deviceId: deviceId,
success: (res) => {
// console.log("獲取藍牙設備所有服務(service)", res);
for (let i = 0; i < res.services.length; i++) {
let tmpUuid = res.services[i].uuid;
if ((res.services[i].isPrimary) && (tmpUuid.indexOf(filterServiceUUID) != -1)) {
getBLEDeviceCharacteristics(deviceId, res.services[i].uuid)
return
}
}
},
fail: (res) => {
console.log('getBLEDeviceServices fail', res);
asddErrorCallback(res.errCode, "");
}
})
}
/**
* 獲取藍牙特徵值
*/
function getBLEDeviceCharacteristics(deviceId, serviceId) {
wx.getBLEDeviceCharacteristics({
deviceId: deviceId,
serviceId: serviceId,
success: (res) => {
// console.log('藍牙設備特徵值信息:', res);
for (let i = 0; i < res.characteristics.length; i++) {
let item = res.characteristics[i]
var itemUUID = item.uuid.toUpperCase(); //轉大寫
if (item.properties.read && itemUUID == writeUUID) {
wx.readBLECharacteristicValue({
deviceId: deviceId,
serviceId: serviceId,
characteristicId: item.uuid,
})
}
if (item.properties.write && itemUUID == writeUUID) {
_deviceId = deviceId
_serviceId = serviceId
_characteristicId = item.uuid
//發送指令【說明:如需連接設備後發相關指令可以在這裏調用】
if (flagFromTypes == 1) { //充電寶
powerBank.send(); //充電開機指令
} else if (flagFromTypes == 2) { //售賣機
vendingObj.checkEnKey(); //AES校驗
}
}
if (notifyUUID == itemUUID) {
if (item.properties.notify || item.properties.indicate) {
console.log('調用notifyBLECharacteristicValueChange前', item.uuid);
wx.notifyBLECharacteristicValueChange({
deviceId: deviceId,
serviceId: serviceId,
characteristicId: item.uuid,
state: true,
success(res) {
console.log('notification通知數據', res);
status = true;
// wx.hideLoading();
},
fail(res) {
console.log('notifyBLECharacteristicValueChange fali', res);
}
})
}
}
}
},
fail: (res) => {
console.log('getBLEDeviceCharacteristics fail', res)
asddErrorCallback(res.errCode, "");
}
})
// 操作之前先監聽,保證第一時間獲取數據
wx.onBLECharacteristicValueChange(function(res) {
console.log(`characteristic ${res.characteristicId} has changed, now is ${res.value}`)
console.log("操作類型:" + action_type);
var resData = ab2hex(res.value);
console.log("設備返回數據--->", resData); //5d0000000001be304d
// 判斷不同類型處理數據
if (flagFromTypes == 2) {
console.log('開始調用 自動售賣機====> 處理返回的數據');
vendingObj.handleResData(resData); //處理返回數據
}
})
}
/**
* 寫入數據
*/
function writeData(hex, action = '') {
if (!status) {
return;
}
if (!_deviceId) {
asddWriteErrors('w');
return;
}
setTimeout(() => {
//向設備特徵值中寫入二進制數據
//這裏使用`TypedArray視圖`中`Uint8Array(無符號 8 位整數)`操作
var enDataBuf = new Uint8Array(hex);
var buffer1 = enDataBuf.buffer
wx.writeBLECharacteristicValue({
deviceId: _deviceId,
serviceId: _serviceId,
characteristicId: _characteristicId,
value: buffer1,
success: (res) => {
wx.hideLoading();
console.log("寫數據返回結果", res.errMsg);
},
fail(res) {
console.log("寫數據失敗..", res);
asddErrorCallback(res.errCode, "");
}
})
}, 1000)
}
5. 處理設備返回數據
及操作指令
(如何發指令?)
以
售賣機
爲例, 注意:交互流程
及指令格式
根據文檔說明
/**
* 售賣機
*/
var vendingObj = {
/**
* 校驗AES密鑰
* 字符、key文檔有說明
*/
checkEnKey: function() {
status = true;
var strKey = [0xd0, 0xf0, 0xf0, 0x80, 0x50, 0xa0, 0x60, 0x10, 0x20, 0x50, 0xc0, 0xd0, 0x80, 0x80, 0x40, 0x90];
var key = [0xd0, 0xf0, 0xf0, 0x80, 0x50, 0xa0, 0x60, 0x10, 0x20, 0x50, 0xc0, 0xd0, 0x80, 0x80, 0x40, 0x90];
var cryptoKey = new Uint8Array(key);
enKEY = cryptoKey;
//得出加密後的指令, 十六進制的數據
var enHEX = cryptoService.updateEncrypt(strKey, enKEY);
writeData(enHEX);
},
/**
* 查詢設備信息
*/
queryDeviceInfo: function() {
action_type = OptionEnum.ReadBattery; //改變操作類型
let hex = [0x69, 0xf2, 0x00, 0x89];
writeData(hex); //寫入數據
},
/**
* 開鎖指令
*/
openVendingLock: function(callBack) {
status = true;
action_type = OptionEnum.VendingOpenLock;
asddCallBack = callBack;
//獲取當前開鎖的編號及轉換
let getCurrentVal = Number(currentSerialVal);
getCurrentVal = getCurrentVal.toString(16);
// let tempVal = '0x0' + getCurrentVal;
let tempVal = parseInt(getCurrentVal, 16);
console.log('====開鎖編號===》', tempVal);
let hex = [0xfe, 0x4e, 0x30, 0x46, 0x4a, 0x00, tempVal, 0x00, 0x00, 0x3e];
writeData(hex);
},
/**
* 處理格子機查詢信息電量回調
* 目的:獲取到相關數據,發送給後端(查看設備電量)
*/
readBatteryCallBack: function(battery) {
console.log("=======>>>電量:", battery);
action_type = OptionEnum.None;
//這裏獲取到電量, 返回給index.js頁面
if (asddCallBack != null) {
asddCallBack(battery, OptionEnum.ReadBattery);
} else {
console.log("是否爲空=======標籤 2");
}
},
/**
* 處理開鎖成功回調
*/
openLockCallback: function(resData) {
var isOpenLock = false;
// 根據當前點擊的櫃子序號,截取對應的數據狀態
var star = Number(currentSerialVal) * 2
var subSerial = resData.substring(star, star + 2);
if (subSerial.toUpperCase() == 'F0') {
isOpenLock = true;
}
console.log("=======>>>開鎖:", isOpenLock ? "成功" : "失敗");
action_type = OptionEnum.None;
if (asddCallBack != null) {
asddCallBack(isOpenLock, OptionEnum.VendingOpenLock);
} else {
console.log("是否爲空=======標籤 3");
}
},
/**
* 處理返回數據
* 例如: 00f05d09000001be304d
*/
handleResData: function (resData) {
let checkStatus = resData.substring(2, 4);
if (checkStatus.toUpperCase() == 'F0' && action_type == OptionEnum.Connection) { //校驗狀態
vendingObj.queryDeviceInfo(); //查詢設備信息
} else if (action_type == OptionEnum.ReadBattery) { //操作的是獲取設備電量
let batteryVal = resData.substring(6, 8);
batteryVal = parseInt(batteryVal, 16);
vendingObj.readBatteryCallBack(batteryVal);
} else if (action_type == OptionEnum.VendingOpenLock) { //操作的是 開鎖
vendingObj.openLockCallback(resData);
}
}
}
6. 處理回調一些方法
//設置連接
function setConnectionActionType(callBack) {
action_type = OptionEnum.Connection;
asddCallBack = callBack;
}
//設置重連
function setReconnectionActionType() {
action_type = OptionEnum.Reconnection;
}
// 設置錯誤
function setAsddErrorCallback(callBack) {
asddErrorCallback = callBack;
}
//設置關閉
function setCloseActionType(callBack) {
action_type = OptionEnum.CloseLock;
asddCallBack = callBack;
}
//設置寫入錯誤
function setWriteError(callBack) {
asddWriteErrors = callBack;
}
//清除
function clearCallBack() {
asddCallBack = null;
}
/**
* 清空loadding
*/
function hideLoading() {
wx.hideLoading();
}
/**
* 檢查是否打開藍牙
* 未連接設備前檢測
*/
function checkIsOpenBluetooth(isEXec) {
wx.openBluetoothAdapter({
success: (res) => {
// console.log('openBluetoothAdapter 初始化藍牙模塊是否成功:', res);
isEXec(true);
},
fail: (res) => {
// console.log('初始化藍牙失敗', res);
wx.showModal({
title: '提示',
content: '請檢查手機藍牙是否打開',
showCancel: false
})
isEXec(false);
}
})
}
7. 藍牙連接過程中錯誤碼
/**
* 藍牙連接過程中錯誤碼
* 10000 / 10006
*/
function bluetoothStatus(errorType) {
switch (errorType) {
case 10001:
wx.showModal({
title: '提示',
content: '請檢查手機藍牙是否打開',
showCancel: false
})
break;
case 10002:
wx.showToast({
title: '沒有找到指定設備',
icon: 'none'
})
break;
case 10003:
wx.showToast({
title: '連接失敗',
icon: 'none'
})
closeBLEConnection();
break;
case 10004:
wx.showToast({
title: '沒有找到指定服務',
icon: 'none'
})
closeBLEConnection();
break;
case 10005:
wx.showToast({
title: '沒有找到指定特徵值',
icon: 'none'
})
closeBLEConnection();
break;
case 10007:
case 10008:
case 10013:
wx.showToast({
title: '設備啓動失敗,請重試',
icon: 'none'
})
break;
case 10009:
wx.showModal({
title: '提示',
content: '當前系統版本過低,請更新版本體驗',
showCancel: false
})
break;
case 10012:
wx.showToast({
title: '連接超時',
icon: 'none'
})
break;
}
}
8. 導出方法
外部需使用的方法,
注意導出
。否則無法使用
module.exports = {
initBle: initBle,
clearCallBack: clearCallBack,
closeBLEConnection: closeBLEConnection,
setConnectionActionType: setConnectionActionType,
setReconnectionActionType: setReconnectionActionType,
setAsddErrorCallback: setAsddErrorCallback,
setCloseActionType: setCloseActionType,
setWriteError: setWriteError,
checkIsOpenBluetooth: checkIsOpenBluetooth,
bluetoothStatus: bluetoothStatus,
openVendingLock: vendingObj.openVendingLock,
}
二 、在需要頁面中調用藍牙
1. 引入文件
const app = getApp()
let commonBLE = require('../../../../../utils/fromCategory/commonBLE.js'); //公共BLE
let commonBLEDatas = null; //保存當前頁面對象
2. 全局中定義處理回調函數
全局方法中如何給data
中屬性賦值
- 定義一個全局變量,來保存當前頁面對象
- 在
onLoad()
中給變量賦值, 即commonBLEDatas = this
- 使用: 通過
變量名.data.屬性
,即commonBLEDatas.data.battery = obj
/**
* 處理返回部分數據回調函數
* obj: 傳過來的數據
* types: 當前操作類型 【可在`commBLE.js`查看定義的】
*/
let callBack = function(obj, types) {
console.log("index.js回調函數" + obj, types);
// commonBLE.clearCallBack();
if (commonBLEDatas.data.currentMeasureType == 4) { //售賣機
if (types == 10) {
//給電量賦值
commonBLEDatas.data.battery = obj;
//調用開鎖指令
commonBLEDatas.successOpenLock();
}
}
}
/**
* 處理錯誤碼回調
*/
let errorCallBack = function(errorType, errorMessage) {
// feedbackApi.hideTimerToast(); //清空loadding
commonBLEDatas.deviceConnectFail(); //展示 設備連接失敗
if (errorType == 10000 || errorType == 10006) {
//連接藍牙
commonBLE.setReconnectionActionType();
commonBLE.setAsddErrorCallback(errorCallBack);
commonBLE.setWriteError(writeError);
if (commonBLEDatas.data.currentMeasureType == 4) {
commonBLE.initBle(commonBLEDatas.data.macAdress, OptionEnumType.Vending, commonBLEDatas.data.currentSerial);
}
} else {
commonBLE.bluetoothStatus(errorType);
}
}
/**
* 寫入失敗回調
*/
let writeError = function(writeE) {
console.log('寫入數據狀態', writeE);
//寫入錯誤頁面展示狀態
commonBLEDatas.setData({
connectStatus: 1,
isConnect: 2,
clickFlags: false
})
if (writeE == 'w') {
feedbackApi.hideTimerToast(); //清空loadding
clearInterval(commonBLEDatas.downSecondId); //清空倒計時
wx.showToast({
title: '連接失敗,請再次嘗試(0)',
icon: 'none'
})
commonBLE.closeBLEConnection();
}
}
3. 調用執行藍牙
方法
- 點擊
購買商品按鈕
, 執行此方法。 - 傳參: 當前設備的
mac地址(後臺獲取的)
、操作的產品類型
及操作序號(操作幾號櫃子)
說明: 櫃子序號1,2,3,4…, 和頁面展示商品對應的。
Page({
/**
* 頁面的初始數據
*/
data: {
currentMeasureType: 2, //測試 當前類型售賣機
macAdress: '3b3533115510', //mac地址(這裏後臺保存時沒有:號的,可自行處理)
currentSerial: '', //當前操作格子序號
},
/**
* 生命週期函數--監聽頁面加載
*/
onLoad: function(options) {
commonBLEDatas = this;
},
/**
* 連接BLE
*/
connectVendingBLE: function() {
let that = this;
commonBLE.setConnectionActionType(callBack); //連接後操作回調
commonBLE.setAsddErrorCallback(errorCallBack); //執行錯誤時錯誤碼回調
commonBLE.setWriteError(writeError); //寫入數據錯誤回調
if (that.data.currentMeasureType == 2) {
commonBLE.initBle(that.data.macAdress, OptionEnumType.Vending, that.data.currentSerial);
}
},
/**
* 設備連接失敗
*/
deviceConnectFail: function () {
// feedbackApi.hideTimerToast(); //清空loadding
clearInterval(this.downSecondId); //清空倒計時
this.setData({
descTxt2: '設備連接失敗',
connectStatus: 1,
isConnect: 2,
clickFlags: false
})
},
})
4. 執行開鎖
如獲取電量成功後, 執行
開鎖指令
,成功後頁面展示對應【具體流程根據需求來】
/**
* 售賣機開鎖成功後提交數據 並展示相關的ui
* 寫在 Page({})中的, 這裏爲了說明寫在外面
*/
successOpenLock: function() {
let that = this;
// 調用開鎖及處理回調數據
commonBLE.openVendingLock(function(isOpenLock, obj) {
console.log('處理開鎖指令回調====》' + isOpenLock);
commonBLE.clearCallBack();
var tempStr = "失敗";
if (isOpenLock) {
tempStr = "成功";
// 提交數據並展示成功開鎖後Ui
that.showSuccessBack();
}else {
wx.showToast({
title: "開鎖" + tempStr,
duration: 3000,
image: '/page/common/libs/assets/images/error.png',
})
that.deviceConnectFail(); //展示 設備連接失敗
//斷開藍牙連接
commonBLE.closeBLEConnection();
}
});
},
BLE項目實戰下載
關於下篇內容
- BLE開發中遇到問題及踩坑