需求背景 (低耗蓝牙设备,通过app控制,实现设备绑定、数据采集、数据上传、数据清空...)嗯...瑟瑟发抖最终选定uniapp愉快的开启懵逼握草搬砖。
开机最高仪式感当然是看文档 uniapp.dcloud.net.cn/api/system/… en...,文档是好文档,一个一个看挺清晰的,沉下心,问问度娘,大概有点谱,离离原上谱的那种,哈哈哈。
正经事来啦
总结:就是找到蓝牙的提供的通知的那个特征值 特征值支持读、写、通知等特征,发送指令无非就是操作该特征值的写入属性,通知类似于回调(uni.onBLECharacteristicValueChange)。
en...............................流程看着没毛病,实际调试设备,麻
设备约定的协议是CRC-16/IBM校验 16进制进行传输 分包发送
主要实现
1. 分包
function delayed(ms, res) {
return new Promise((resolve, reject) => {
setTimeout(function () {
resolve(res);
}, ms)
});
}
function writeDevice(deviceId, serviceId, characteristicId, arrayBuffer) {
for (let index = 0; index < arrayBuffer.length; index++) {
const buf = arrayBuffer[index];
delayed(200 * index).then(() => {
uni.writeBLECharacteristicValue({
deviceId,
serviceId,
characteristicId,
value: buf,
success: (res) => {
/* 发送成功 */
console.log(`第${index + 1}包成功`, res);
},
fail: (error) => {
/* 发送失败 */
console.log(`第${index + 1}包失败`, error);
},
});
});
}
}
2.数据转化 10进制转16进制 ASCII码转16进制 16进制转10进制
// ArrayBuffer转16进制字符串 主要解析回传的数据
function ab2hex(buffer) {
const hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function (bit) {
return ("00" + bit.toString(16)).slice(-2);
}
);
return hexArr.join("");
}
3.数据回传处理(设备返回的数据跟传统的数据对象不同,都是一串串编码回码)
let data = []
let flag = false // 传输完毕
for (let index = 0; index < result.length; index++) {
let item = result[index]
// 约定的数据开头标识
if (item.match(RegExp(/XXXXXXX/))) {
let str = ''
for (let i = 0; i < 4; i++) {
str += result[index + i]
}
data.push(str)
}
// 检验是不是传输完毕 约定的结束标识
if (item.match(RegExp(/XXXXXXX/))) {
console.log('--------------------------传输完毕------------------------')
let str = item.slice(-4);
let token = item.slice(0, item.length - 4)
let match = getCrc_16_ibm(token.replace(/\s*/g, ""))
if (str === match) {
flag = true
}
}
}
优化及考虑
1. 设备传输数据 数据量过大或者意外中断(设备存储有限)
处理:检测到传输完毕,执行上传数据操作,在其中过程中,如有中断,提示是否需要继续尝试拉取 确定需要继续拉取,则执行拉取指令,手动去重追加新数据
2. 数据上传
处理:先将数据切割分包,分包上传
3. 蓝牙未开启及异常
处理:错误页处理逻辑,根据情况处理是否需要初始化,是否直接连接等
4. 蓝牙调试
处理:nRf connect 调试软件
哈哈哈,记录一下。