335 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Taro from "@tarojs/taro";
import { handshake1, handshake2 } from "./sendOrder";
import TASK from "./taskQueue";
const errMsg = {
0: "正常",
10000: "未初始化蓝牙适配器",
10001: "请检查手机蓝牙是否打开或微信是否授权蓝牙",
10002: "没有找到指定设备",
10003: "连接失败",
10004: "没有找到指定服务",
10005: "没有找到指定特征",
10006: "当前连接已断开",
10007: "当前特征不支持此操作",
10008: "其余所有系统上报的异常",
10009: "Android系统版本低于4.3不支持蓝牙功能",
10012: "连接超时",
10013: "连接超时",
1509008: "请检查手机定位是否打开或微信是否授权定位",
};
class Bluetooth {
config = {
serviceId: "4E31BF4A-8507-3A2B-7344-C7EDACD38104", //设备服务id
NotifyUUID: "4E31BF4B-8507-3A2B-7344-C7EDACD38104",
WriteUUID: "4E31BF4C-8507-3A2B-7344-C7EDACD38104",
// serviceId: 'C7E6FAE0-E966-1000-8000-BEF9C723DF6A', //设备服务id
// NotifyUUID: 'C7E6FAE1-E966-1000-8000-BEF9C723DF6A',
// WriteUUID: 'C7E6FAE2-E966-1000-8000-BEF9C723DF6A',
};
// 连接状态
linkFlag = false;
// 蓝牙是否可用
available = true;
// 蓝牙初始化
isInit = false;
timeout = null;
timeout1 = null;
// 判断是否搜索到设备
isFindBt = null;
platform = Taro.getSystemInfoSync().platform;
appAuthorize = Taro.getAppAuthorizeSetting();
deviceInfo = {}
callBack = () => { };
searchBack = () => { };
constructor() {
this.onBluetoothAdapterStateChange();
this.onBLEConnectionStateChange();
this.onBluetoothDeviceFound();
}
// 错误
fail(res) {
this.linkFlag = false;
if (!res.errCode) return;
let starIde = res.errMsg.indexOf("fail") + 5;
Taro.showToast({ title: errMsg[res.errCode] || errMsg[res.errno] || res.errMsg.substring(starIde), icon: "none", duration: 3000 });
}
// 监测手机蓝牙状态
onBluetoothAdapterStateChange() {
Taro.onBluetoothAdapterStateChange(({ available, discovering }) => {
this.available = available;
// 手机蓝牙开启
if (this.available && !this.isInit) {
Taro.closeBluetoothAdapter({
success: (res) => {
this.openBluetoothAdapter();
},
});
console.log("手机蓝牙开启");
}
// 手机蓝牙关闭
if (!available) {
this.isInit = false;
this.deviceInfo.state = false;
this.linkFlag = false;
this.callBack(this.deviceInfo);
console.log("手机蓝牙关闭");
}
});
}
// 初始化蓝牙模块
openBluetoothAdapter() {
return Taro.openBluetoothAdapter({
success: () => {
console.log("初始化蓝牙模块");
this.isInit = true;
this.deviceInfo = Taro.getStorageSync('deviceInfo') || {}
if (this.deviceInfo.name) {
this.createBleConnection()
}
},
fail: (err) => {
this.isInit = false;
this.fail(err);
},
});
}
// 开始搜寻附近的蓝牙外围设备
startBluetoothDevicesDiscovery() {
console.log("搜索蓝牙");
if (this.appAuthorize.locationAuthorized != "authorized" && this.platform == "android")
return Taro.showToast({ title: "请打开微信定位权限", icon: "none", duration: 3000 });
Taro.startBluetoothDevicesDiscovery({
// allowDuplicatesKey: true,
powerLevel: "high",
success: (res) => {
this.isFindBt = setTimeout(() => {
if (this.platform == "android") {
this.stopBluetoothDevicesDiscovery();
Taro.showModal({
title: "未搜索到设备",
content: "1、请检查设备是否在附近或者设备是否被其他应用连接。2、请检查手机微信应用权限中的附近的设备权限是否打开。",
showCancel: false,
success: () => {
const pages = Taro.getCurrentPages();
if (pages?.length > 1) {
Taro.navigateBack();
}
},
});
}
console.log("未搜索到设备");
this.isFindBt && this.clearTimeoutFn("isFindBt");
}, 6000);
},
fail: (err) => {
this.fail(err);
this.stopBluetoothDevicesDiscovery();
},
});
}
// 监听搜索到新设备的事件
// 定义一个方法用于处理蓝牙设备发现事件
onBluetoothDeviceFound(fn) {
Taro.onBluetoothDeviceFound((res) => {
const devices = res.devices[0];
const advertisData = this.ab2hex(devices.advertisData);
const mac = this.strInsert(String(advertisData).substring(4, 16)).toLocaleUpperCase();
// 判断是否有搜索到设备
this.isFindBt && this.clearTimeoutFn("isFindBt");
// if (devices.name && devices.name == "W53A") {
if (devices.name && devices.name == "LE-AB2020") {
console.log(JSON.stringify(res), "搜索到设备");
const item = {
deviceId: devices.deviceId,
mac: mac,
name: devices.name,
};
fn && fn(item)
}
});
}
// 蓝牙连接
createBleConnection() {
if (!this.available || this.linkFlag || !this.deviceInfo.deviceId) return;
this.linkFlag = true;
Taro.setStorageSync("deviceInfo", this.deviceInfo);
console.log("正在连接设备");
Taro.createBLEConnection({
timeout: 3000,
deviceId: this.deviceInfo.deviceId,
success: () => {
this.deviceInfo.state = true;
this.getBLEDeviceServices();
},
fail: (res) => {
this.linkFlag = false;
console.log(res, this.deviceInfo, "连接错误");
this.callBack({ ...this.deviceInfo, errCode: 10003 });
if (res.errno == "1509007") {
this.closeBluetoothAdapter();
} else {
this.timeoutBleConnection()
}
},
});
}
// 获取蓝牙多个service
getBLEDeviceServices() {
Taro.getBLEDeviceServices({
deviceId: this.deviceInfo.deviceId,
success: () => {
this.getBLEDeviceCharacteristics();
},
fail: (err) => this.fail(err),
});
}
// 获取蓝牙低功耗设备某个服务中所有特征
getBLEDeviceCharacteristics() {
Taro.getBLEDeviceCharacteristics({
deviceId: this.deviceInfo.deviceId,
serviceId: this.config.serviceId,
success: (res) => {
this.notifyBLECharacteristicValueChange();
},
fail: (err) => this.fail(err),
});
}
// 启用蓝牙低功耗设备特征值变化时的 notify 功能
notifyBLECharacteristicValueChange() {
Taro.notifyBLECharacteristicValueChange({
deviceId: this.deviceInfo.deviceId,
serviceId: this.config.serviceId,
characteristicId: this.config.NotifyUUID,
state: true,
success: (res) => {
console.log("连接成功");
Taro.setStorageSync("deviceInfo", { ...this.deviceInfo, state: false });
// handshake1()
this.callBack(this.deviceInfo);
},
fail: (err) => this.fail(err),
});
}
//监听设备返回的数据
onBLECharacteristicValueChange(fn) {
Taro.onBLECharacteristicValueChange((data) => {
let bytes = new Uint8Array(data.value);
let value = String(this.ab2hex(bytes)).toLocaleUpperCase();
// 第二次握手
// if (bytes[2] == 0xea && bytes[3] == 0x01) {
// handshake2()
// }
console.log(`设备回复====>${value}`);
TASK.executeTask();
fn && fn(bytes, value);
});
}
// 向蓝牙写入数据
writeBleValue(value) {
console.log("发送指令====>" + String(this.ab2hex(value)).toLocaleUpperCase());
if (!this.deviceInfo.state) {
// console.log("蓝牙未连接")
return
}
return Taro.writeBLECharacteristicValue({
deviceId: this.deviceInfo.deviceId,
serviceId: this.config.serviceId,
characteristicId: this.config.WriteUUID,
writeType: "writeNoResponse",
value: value,
});
}
//蓝牙断开
onBLEConnectionStateChange() {
Taro.onBLEConnectionStateChange((res) => {
if (!res.connected) {
console.log(res, "蓝牙断开");
this.deviceInfo.state = res.connected;
this.callBack(this.deviceInfo);
this.timeoutBleConnection()
}
});
}
timeoutBleConnection() {
this.linkFlag = false;
if (!this.available || !this.isInit || !this.deviceInfo.deviceId) return;
this.timeout = setTimeout(() => {
this.timeout && this.clearTimeoutFn("timeout");
this.createBleConnection();
}, 3000);
}
//停止搜寻附近的蓝牙外围设备
stopBluetoothDevicesDiscovery() {
Taro.stopBluetoothDevicesDiscovery();
this.isFindBt && this.clearTimeoutFn("isFindBt");
console.log("停止搜寻");
}
// 断开与蓝牙低功耗设备的连接
closeBluetoothAdapter() {
this.linkFlag = false;
this.deviceInfo = { state: false };
Taro.removeStorageSync("deviceInfo");
Taro.closeBluetoothAdapter({
success: (res) => {
console.log(this.deviceInfo, '解绑1');
this.callBack(this.deviceInfo);
this.openBluetoothAdapter()
},
});
}
// 设备响应回调
deviceCallBack(fn) {
this.callBack = fn;
}
// 转换二进制数据
ab2hex(buffer) {
if (!buffer) return;
const hexArr = Array.prototype.map.call(new Uint8Array(buffer), function (bit) {
return ("00" + bit.toString(16)).slice(-2);
});
return hexArr.join("").toLocaleLowerCase();
}
// unBindDevice() {
// this.deviceInfo = {}
// Taro.removeStorageSync('deviceInfo')
// this.closeBluetoothAdapter()
// }
/**
* 字符串插入字符
* @param {*} str 字符串
* @param {*} length 间隔多少个插入
* @param {*} fmt 插入符号
* @returns
*/
strInsert(str, length = 2, fmt = ":") {
if (!str || !str.length) return "";
var reg = new RegExp("\\w{1," + length + "}", "g");
let ma = str.match(reg);
return ma.join(fmt).toLocaleLowerCase();
}
// 清除计时器
clearTimeoutFn(name) {
clearTimeout(this[name]);
this[name] = null;
}
}
export default new Bluetooth();