import * as t from "./tools"
|
|
|
|
/*
|
|
import { HTTP } from "../server";
|
|
*/
|
|
|
|
/**
|
|
* 蓝牙工具类
|
|
* 封装小程序蓝牙流程方法
|
|
* 处理事件通信
|
|
*/
|
|
class BLEHandler {
|
|
constructor(blename, emitter) {
|
|
this.blename = blename //厂家自定义的蓝牙设备名称
|
|
this.emitter = emitter
|
|
this.readCharacteristicId = ""; //能从硬件返回的信息中自动提取
|
|
this.writeCharacteristicId = "00002af1-0000-1000-8000-00805f9b34fb"; //能从硬件返回的信息中自动提取
|
|
this.notifyCharacteristicId = "00002af0-0000-1000-8000-00805f9b34fb"; //能从硬件返回的信息中自动提取
|
|
this.deviceId = ""; //蓝牙Mac地址
|
|
this.serviceId = "000018f0-0000-1000-8000-00805f9b34fb";//具体的serviceId要自己根据硬件提供设置。
|
|
|
|
this.receivePacket = [];
|
|
this.recPktLength = 0;
|
|
this.recPktOffset = 0;
|
|
}
|
|
async openAdapter() {
|
|
let [err, res] = await t._openAdapter.call(this);
|
|
if (err != null) {
|
|
this.emitter.emit("channel", {
|
|
type: "connect",
|
|
data: "未打开适配器"
|
|
})
|
|
return false;
|
|
}
|
|
return true
|
|
}
|
|
async startSearch() {
|
|
let [err, res] = await t._startSearch.call(this);
|
|
if (err != null) {
|
|
return;
|
|
}
|
|
this.emitter.emit("channel", {
|
|
type: "connect",
|
|
data: "正在连接中..."
|
|
})
|
|
|
|
}
|
|
async onBluetoothFound() {
|
|
let [err, res] = await t._onBluetoothFound.call(this);
|
|
if (err != null) {
|
|
this.emitter.emit("channel", {
|
|
type: "connect",
|
|
data: "未找到设备"
|
|
})
|
|
return false;
|
|
}
|
|
return true
|
|
}
|
|
|
|
async getBluetoothDevices() {
|
|
let [err, res] = await t._getBluetoothDevices.call(this);
|
|
if (err != null) {
|
|
this.emitter.emit("channel", {
|
|
type: "connect",
|
|
data: "未找到设备"
|
|
})
|
|
return false;
|
|
}
|
|
return true
|
|
}
|
|
|
|
|
|
async stopSearchBluetooth() {
|
|
let [err, res] = await t._stopSearchBluetooth.call(this);
|
|
if (err != null) {
|
|
return;
|
|
}
|
|
}
|
|
async connectBlue() {
|
|
let [err, res] = await t._connectBlue.call(this);
|
|
if (err != null) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
async setBLEMTU() {
|
|
let [err, res] = await t._setBLEMTU.call(this);
|
|
if (err != null) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
async getBLEServices() {
|
|
let [err, res] = await t._getBLEServices.call(this);
|
|
if (err != null) {
|
|
return;
|
|
}
|
|
}
|
|
async getCharacteristics() {
|
|
let [err, res] = await t._getCharacteristics.call(this);
|
|
if (err != null) {
|
|
this.emitter.emit("channel", {
|
|
type: "connect",
|
|
data: "无法订阅特征值"
|
|
})
|
|
// 取消连接
|
|
this.closeBLEConnection()
|
|
this.closeBLEAdapter()
|
|
wx.setStorageSync("bluestatus", "");
|
|
return false;
|
|
}
|
|
this.emitter.emit("channel", {
|
|
type: "connect",
|
|
data: "蓝牙已连接"
|
|
})
|
|
wx.setStorageSync("bluestatus", "on");
|
|
return true
|
|
}
|
|
async notifyBLECharacteristicValueChange() {
|
|
let [err, res] = await t._notifyBLECharacteristicValueChange.call(this);
|
|
if (err != null) {
|
|
return;
|
|
}
|
|
}
|
|
async closeBLEConnection() {
|
|
let [err, res] = await t._closeBLEConnection.call(this);
|
|
if (err != null) {
|
|
return;
|
|
}
|
|
}
|
|
async closeBLEAdapter() {
|
|
let [err, res] = await t._closeBLEAdapter.call(this);
|
|
if (err != null) {
|
|
return;
|
|
}
|
|
}
|
|
async sentOrder(cmd, payload) {
|
|
let data = t._sentOrder(cmd, payload)
|
|
console.log("-- 发送数据:", data)
|
|
let arrayBuffer = new Uint8Array(data).buffer;
|
|
let [err, res] = await t._writeBLECharacteristicValue.call(this, arrayBuffer)
|
|
if (err != null) {
|
|
return false
|
|
}
|
|
console.log("数据发送成功!")
|
|
return true
|
|
|
|
}
|
|
|
|
// 打开蓝牙适配器状态监听
|
|
onBLEConnectionStateChange() {
|
|
wx.onBLEConnectionStateChange(res => {
|
|
// 该方法回调中可以用于处理连接意外断开等异常情况
|
|
if (!res.connected) {
|
|
this.closeBLEAdapter()
|
|
wx.setStorageSync("bluestatus", "");
|
|
this.emitter.emit("channel", {
|
|
type: "connect",
|
|
data: "蓝牙已断开"
|
|
})
|
|
}
|
|
}, err => {
|
|
console.log('err', err)
|
|
})
|
|
}
|
|
|
|
// 收到设备推送的notification
|
|
onBLECharacteristicValueChange() {
|
|
wx.onBLECharacteristicValueChange(res => {
|
|
//let arrbf = new Uint8Array(res.value)
|
|
//console.log(`收到硬件数据反馈!命令码为:${arrbf[2]}`)
|
|
//if (this._checkData(arrbf)) {
|
|
//}
|
|
let arrbf = new Uint8Array(res.value)
|
|
if (arrbf[0] == 0x89 && arrbf[1] == 0x89)
|
|
{
|
|
let dataLength = ((arrbf[10] << 8) & 0xff00) + (arrbf[11] & 0x00ff)
|
|
this.recPktLength = 13 + dataLength
|
|
this.receivePacket = new Uint8Array(this.recPktLength)
|
|
this.recPktOffset = 0
|
|
console.log("开始接收数据:length= " + arrbf.length + " data= " + arrbf)
|
|
this.receivePacket.set(arrbf, this.recPktOffset)
|
|
this.recPktOffset += arrbf.length;
|
|
if( this.recPktOffset == this.recPktLength){
|
|
this.getReceivePacket(this.receivePacket)
|
|
}
|
|
}
|
|
else
|
|
{
|
|
console.log("继续接收数据:length= " + arrbf.length + " data= " + arrbf)
|
|
this.receivePacket.set(arrbf, this.recPktOffset)
|
|
this.recPktOffset += arrbf.length;
|
|
if( this.recPktOffset == this.recPktLength){
|
|
this.getReceivePacket(this.receivePacket)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
/*
|
|
_uploadInfo(message) {
|
|
console.log("-- 准备数据同步!", this._mapToArray(message))
|
|
let bleorder = wx.getStorageSync("bleorder");
|
|
let blecabinet = wx.getStorageSync("blecabinet")
|
|
HTTP({
|
|
url: "cabinet/uploadBlueData",
|
|
methods: "post",
|
|
data: {
|
|
cabinetQrCode: blecabinet,
|
|
order: bleorder,
|
|
message: this._mapToArray(message)
|
|
}
|
|
}).then(res => {
|
|
console.log("✔ 数据同步成功!")
|
|
|
|
}, err => {
|
|
console.log('✘ 数据同步失败', err)
|
|
})
|
|
}
|
|
*/
|
|
|
|
_mapToArray(arrbf) {
|
|
let arr = []
|
|
arrbf.map(item => {
|
|
arr.push(item)
|
|
})
|
|
return arr
|
|
}
|
|
|
|
// 校验数据正确性
|
|
_checkData(arrbf) {
|
|
let packetLen = arrbf.length;
|
|
console.log("接收数据:" + arrbf)
|
|
|
|
// 校验帧头帧尾
|
|
if (arrbf[0] != 0x89 || arrbf[1] != 0x89) {
|
|
console.log('不是该设备返回的包')
|
|
return false
|
|
}
|
|
if (packetLen < 14) {
|
|
console.log("包长太短,不是该设备返回的包");
|
|
return false;
|
|
}
|
|
|
|
let dataLength = ((arrbf[10] << 8) & 0xff00) + (arrbf[11] & 0x00ff);
|
|
if (dataLength != (packetLen - 13)) {
|
|
let calLen = packetLen - 13;
|
|
console.log("✘ 数据长度错误: " + dataLength + " is not " + calLen);
|
|
return false;
|
|
}
|
|
//校验包
|
|
let check = arrbf[0];
|
|
for (let i = 1; i < packetLen - 1; i++)
|
|
check ^= arrbf[i];
|
|
if (check != arrbf[packetLen - 1]) {
|
|
console.log("crc校验错误,请重发." + check);
|
|
return false;
|
|
}
|
|
console.log('✔ 数据校验成功,接收完整!')
|
|
return true
|
|
}
|
|
|
|
getReceivePacket(arrbf)
|
|
{
|
|
let packetLen = arrbf.length;
|
|
console.log("接收数据:" + arrbf)
|
|
// 校验帧头帧尾
|
|
if (arrbf[0] != 0x89 || arrbf[1] != 0x89) {
|
|
console.log('不是该设备返回的包')
|
|
return [0];
|
|
}
|
|
if (packetLen < 14) {
|
|
console.log("包长太短,不是该设备返回的包");
|
|
return [0];
|
|
}
|
|
|
|
let dataLength = ((arrbf[10] << 8) & 0xff00) + (arrbf[11] & 0x00ff);
|
|
if (dataLength != (packetLen - 13)) {
|
|
let calLen = packetLen - 13;
|
|
console.log("✘ 数据长度错误: " + dataLength + " is not " + calLen);
|
|
return [0];
|
|
}
|
|
//校验包
|
|
let check = arrbf[0];
|
|
for (let i = 1; i < packetLen - 1; i++)
|
|
check ^= arrbf[i];
|
|
if (check != arrbf[packetLen - 1]) {
|
|
console.log("crc校验错误,请重发." + check);
|
|
return [0];
|
|
}
|
|
|
|
//数据解密
|
|
let key = arrbf[3];
|
|
let data_offset = 12;
|
|
|
|
let result = new Uint8Array(dataLength)
|
|
for (let i = 0; i < dataLength; i++) {
|
|
result[i] = arrbf[i + data_offset];
|
|
result[i] = (result[i] ^ (key ^ i));
|
|
result[i] += (dataLength - i) ^ key;
|
|
}
|
|
|
|
console.log('✔ 数据校验成功,接收完整! packet= ' + arrbf)
|
|
|
|
console.log('解密明文 result= ' + result)
|
|
|
|
return result;
|
|
}
|
|
|
|
}
|
|
export default BLEHandler
|