摘自:微信小程序蓝牙BLE开发实战——案例(二)_Smile_ping的博客-CSDN博客
另一个参考:微信小程序BLE控制8266
文章目录
微信小程序蓝牙BLE开发实战(二)
项目介绍
效果图
扫码使用`格子柜`流程
蓝牙通讯协议
加密理解
实例(`蓝牙操作`功能)
一. 新建`js`文件及使用时引入
1. 定义全局变量
2. 自定义方法
3. 初始化蓝牙`入口`
4. 应用到`蓝牙`API方法
5. 处理`设备返回数据`及`操作指令`(如何发指令?)
6. 处理回调一些方法
7. 蓝牙连接过程中错误码
8. 导出方法
二 、在需要页面中调用`蓝牙`
1. 引入文件
2. 全局中定义处理回调函数
全局方法中如何给`data`中属性赋值
3. 调用执行`蓝牙`方法
4. 执行开锁
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) {
//判断RSSI值在某个范围内时搜索设备,根据个人需求判断
if (parseFloat(device.RSSI) > parseFloat(rssiVal)) {
// 格子柜Android IOS通过名称匹配
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();
}
});
},
1
BLE项目实战下载
蓝牙BLE项目实战
————————————————
版权声明:本文为CSDN博主「Smile_ping」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Smile_ping/article/details/103148061