2025-08-27 10:32:13 +08:00
|
|
|
|
import receivTool from "@/utils/BleReceive.js"
|
|
|
|
|
|
var recei = null;
|
2025-09-19 12:01:06 +08:00
|
|
|
|
const serviceDic = [ //合作供应商的蓝牙主服务
|
2025-09-25 09:59:37 +08:00
|
|
|
|
{
|
2025-09-23 16:57:31 +08:00
|
|
|
|
"serviceId": "0000FFE0-0000-1000-8000-00805F9B34FB",
|
|
|
|
|
|
"writeId": "0000FFE1-0000-1000-8000-00805F9B34FB",
|
|
|
|
|
|
"notifyId": "0000FFE2-0000-1000-8000-00805F9B34FB"
|
|
|
|
|
|
},
|
2025-11-17 15:30:57 +08:00
|
|
|
|
{
|
|
|
|
|
|
"serviceId": "0000FFF0-0000-1000-8000-00805F9B34FB",
|
|
|
|
|
|
"writeId": "0000FFF2-0000-1000-8000-00805F9B34FB",
|
|
|
|
|
|
"notifyId": "0000FFF1-0000-1000-8000-00805F9B34FB"
|
|
|
|
|
|
},
|
2025-09-19 12:01:06 +08:00
|
|
|
|
{
|
|
|
|
|
|
"serviceId": "0000AE30-0000-1000-8000-00805F9B34FB",
|
|
|
|
|
|
"writeId": "0000AE03-0000-1000-8000-00805F9B34FB",
|
|
|
|
|
|
"notifyId": "0000AE02-0000-1000-8000-00805F9B34FB"
|
|
|
|
|
|
}
|
2025-09-25 09:59:37 +08:00
|
|
|
|
|
2025-09-19 12:01:06 +08:00
|
|
|
|
];
|
|
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
class BleHelper {
|
|
|
|
|
|
constructor() {
|
|
|
|
|
|
this.StorageKey = "linkedDevices";
|
2025-10-17 11:52:26 +08:00
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
recei = receivTool.getBleReceive();
|
|
|
|
|
|
|
|
|
|
|
|
this.init();
|
|
|
|
|
|
}
|
|
|
|
|
|
init() {
|
2025-10-17 11:52:26 +08:00
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
var store = uni.getStorageInfoSync();
|
2025-10-16 11:07:04 +08:00
|
|
|
|
var f = store.keys.includes(this.StorageKey);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
var linkedDevices = [];
|
|
|
|
|
|
if (f) {
|
2025-10-16 11:07:04 +08:00
|
|
|
|
linkedDevices = uni.getStorageSync(this.StorageKey);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
if (linkedDevices && linkedDevices.length && linkedDevices.length > 0) {
|
2025-10-13 10:57:03 +08:00
|
|
|
|
// console.log("111111", linkedDevices);
|
2025-09-26 13:50:29 +08:00
|
|
|
|
linkedDevices = linkedDevices.filter((v) => {
|
2025-10-27 10:52:17 +08:00
|
|
|
|
if (v) {
|
2025-10-24 10:29:46 +08:00
|
|
|
|
v.Linked = false;
|
|
|
|
|
|
v.notifyState = false;
|
2025-10-27 10:52:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
return v ? true : false;
|
2025-08-27 10:32:13 +08:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-17 11:52:26 +08:00
|
|
|
|
|
2025-10-27 10:52:17 +08:00
|
|
|
|
const systemInfo = uni.getSystemInfoSync();
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-09-26 13:50:29 +08:00
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
setTimeout(() => {
|
2025-09-25 09:59:37 +08:00
|
|
|
|
this.OpenBlue().then(() => {
|
2025-09-23 16:57:31 +08:00
|
|
|
|
this.linkAllDevices();
|
|
|
|
|
|
});
|
2025-09-25 09:59:37 +08:00
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}, 10);
|
|
|
|
|
|
this.data = {
|
|
|
|
|
|
isOpenBlue: false, //蓝牙模块是否开启
|
|
|
|
|
|
available: false, //蓝牙状态是否可用
|
|
|
|
|
|
discovering: false, //蓝牙是否正在搜索
|
|
|
|
|
|
searchList: [], //已搜索到的设备列表,
|
|
|
|
|
|
isSubscribe: false, //是否开启了订阅
|
2025-10-27 10:52:17 +08:00
|
|
|
|
LinkedList: linkedDevices, //已连接的设备列表
|
|
|
|
|
|
platform: systemInfo.uniPlatform
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
this.cfg = {
|
|
|
|
|
|
onDeviceFound: [], //发现新设备的事件
|
2025-10-16 11:07:04 +08:00
|
|
|
|
receivDataCallback: [], //接收到数据的事件
|
|
|
|
|
|
bleDisposeCallback: [], //蓝牙断开连接的事件
|
|
|
|
|
|
recoveryCallback: [], //蓝牙连接恢复的事件
|
2025-10-17 11:52:26 +08:00
|
|
|
|
stateRecoveryCallback: [], //蓝牙适配器恢复可用事件
|
|
|
|
|
|
stateBreakCallback: [] //蓝牙适配器不可用事件
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
2025-09-17 15:21:20 +08:00
|
|
|
|
// this.addReceiveCallback((a, b, c) => {
|
|
|
|
|
|
// recei.ReceiveData(a, b, c);
|
|
|
|
|
|
// }, "BleReceiveData");
|
2025-08-27 10:32:13 +08:00
|
|
|
|
this.dic = {
|
|
|
|
|
|
errRemarks: [{
|
|
|
|
|
|
key: '10000',
|
|
|
|
|
|
remark: '未初始化蓝牙适配器'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: '10001',
|
|
|
|
|
|
remark: '当前蓝牙适配器不可用'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: '10002',
|
|
|
|
|
|
remark: '没有找到指定设备'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: '10003',
|
|
|
|
|
|
remark: '蓝牙设备连接失败'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: '10004',
|
|
|
|
|
|
remark: '蓝牙设备没有找到指定服务'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: '10005',
|
|
|
|
|
|
remark: '蓝牙设备没有找到指定特征值'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: '10006',
|
|
|
|
|
|
remark: '蓝牙连接已断开'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: '10007',
|
|
|
|
|
|
remark: '蓝牙设备当前特征值不支持此操作'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: '10008',
|
|
|
|
|
|
remark: '其余所有系统上报的异常'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: '10009',
|
|
|
|
|
|
remark: '蓝牙设备不支持BLE低功耗蓝牙'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: '10010',
|
|
|
|
|
|
remark: '已连接'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: '10011',
|
|
|
|
|
|
remark: '蓝牙设备配对设备需要配对码'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: '10012',
|
|
|
|
|
|
remark: '蓝牙设备连接超时'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: '10013',
|
|
|
|
|
|
remark: '连接 deviceId 为空或者是格式不正确'
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-25 09:59:37 +08:00
|
|
|
|
//从缓存中删除某个设备,bleId蓝牙id,deviceId数据库中的设备id
|
2025-09-17 15:21:20 +08:00
|
|
|
|
DropDevice(bleId, deviceId) {
|
2025-10-17 11:52:26 +08:00
|
|
|
|
|
2025-10-16 11:07:04 +08:00
|
|
|
|
let flag = false;
|
2025-09-17 15:21:20 +08:00
|
|
|
|
for (var i = 0; i < this.data.LinkedList.length; i++) {
|
|
|
|
|
|
let item = this.data.LinkedList[i];
|
2025-10-17 11:52:26 +08:00
|
|
|
|
if (deviceId && item.device) {
|
|
|
|
|
|
if (item.device.id == deviceId) {
|
2025-10-17 17:29:08 +08:00
|
|
|
|
console.log("找到要删除的设备", item);
|
2025-09-17 15:21:20 +08:00
|
|
|
|
this.data.LinkedList.splice(i, 1);
|
2025-09-26 13:50:29 +08:00
|
|
|
|
this.disconnectDevice(item.deviceId);
|
2025-09-17 15:21:20 +08:00
|
|
|
|
flag = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
2025-10-17 11:52:26 +08:00
|
|
|
|
if (bleId && item.deviceId == bleId) {
|
2025-10-17 17:29:08 +08:00
|
|
|
|
console.log("找到要删除的设备1,", item)
|
2025-09-17 15:21:20 +08:00
|
|
|
|
this.data.LinkedList.splice(i, 1);
|
2025-09-26 13:50:29 +08:00
|
|
|
|
this.disconnectDevice(item.deviceId);
|
2025-10-17 11:52:26 +08:00
|
|
|
|
flag = true;
|
2025-09-17 15:21:20 +08:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-10-17 11:52:26 +08:00
|
|
|
|
if (flag) {
|
2025-09-17 15:21:20 +08:00
|
|
|
|
this.updateCache();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-25 09:59:37 +08:00
|
|
|
|
//更新缓存
|
2025-09-17 15:21:20 +08:00
|
|
|
|
updateCache() {
|
2025-10-17 11:52:26 +08:00
|
|
|
|
|
2025-09-17 15:21:20 +08:00
|
|
|
|
uni.setStorageSync(this.StorageKey, this.data.LinkedList);
|
2025-10-17 11:52:26 +08:00
|
|
|
|
|
2025-09-17 15:21:20 +08:00
|
|
|
|
}
|
2025-10-16 11:07:04 +08:00
|
|
|
|
//连接所有已连接过的设备
|
2025-08-27 10:32:13 +08:00
|
|
|
|
linkAllDevices() {
|
2025-09-19 13:46:33 +08:00
|
|
|
|
// console.log("模块启动时,自动连接已连接过的设备", this.data.LinkedList);
|
2025-10-27 11:51:38 +08:00
|
|
|
|
if (this.data.platform == 'web') {
|
2025-10-27 10:52:17 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
if (this.data.LinkedList && this.data.LinkedList.length > 0) {
|
2025-09-26 13:50:29 +08:00
|
|
|
|
let flag = false;
|
2025-08-27 10:32:13 +08:00
|
|
|
|
for (var i = 0; i < this.data.LinkedList.length; i++) {
|
|
|
|
|
|
let device = this.data.LinkedList[i];
|
2025-09-16 11:37:06 +08:00
|
|
|
|
// console.log("自动连接绑定过的设备:" + device.deviceId);
|
2025-09-16 17:30:46 +08:00
|
|
|
|
if (device.macAddress && device.device && device.device.id) {
|
2025-09-16 11:37:06 +08:00
|
|
|
|
this.LinkBlue(device.deviceId, device.writeServiceId, device.wirteCharactId, device
|
2025-09-16 17:30:46 +08:00
|
|
|
|
.notifyCharactId);
|
2025-09-26 13:50:29 +08:00
|
|
|
|
flag = true;
|
2025-09-16 11:37:06 +08:00
|
|
|
|
}
|
2025-09-16 17:30:46 +08:00
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
2025-09-26 13:50:29 +08:00
|
|
|
|
if (!flag) {
|
2025-09-25 09:59:37 +08:00
|
|
|
|
this.updateCache();
|
|
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
} else {
|
2025-10-13 10:57:03 +08:00
|
|
|
|
// console.log("蓝牙未连接过任何设备");
|
2025-09-25 09:59:37 +08:00
|
|
|
|
this.updateCache();
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-10-16 11:07:04 +08:00
|
|
|
|
//获取当前页面栈
|
2025-08-27 10:32:13 +08:00
|
|
|
|
getCurrentPagePath() {
|
|
|
|
|
|
|
|
|
|
|
|
const pages = getCurrentPages();
|
|
|
|
|
|
|
|
|
|
|
|
if (pages.length === 0) {
|
|
|
|
|
|
return "";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const currentPage = pages[pages.length - 1];
|
2025-08-28 14:05:06 +08:00
|
|
|
|
// console.log("currentPage=", currentPage.route);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
return currentPage.route;
|
|
|
|
|
|
}
|
2025-10-16 11:07:04 +08:00
|
|
|
|
//添加事件回调
|
|
|
|
|
|
addCallback(callback, currKey, type) {
|
|
|
|
|
|
if (!type) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
let key = currKey ? currKey : this.getCurrentPagePath();
|
|
|
|
|
|
if (!key) {
|
|
|
|
|
|
key = new Date().getTime();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (key) {
|
2025-09-23 16:57:31 +08:00
|
|
|
|
// console.log("key=" + key);
|
2025-10-16 11:07:04 +08:00
|
|
|
|
let f = this.cfg[type].findIndex((v) => {
|
2025-08-27 10:32:13 +08:00
|
|
|
|
return v.key == key;
|
|
|
|
|
|
});
|
|
|
|
|
|
if (f > -1) {
|
2025-10-16 11:07:04 +08:00
|
|
|
|
this.cfg[type][f].callback = callback;
|
2025-08-27 10:32:13 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-10-16 11:07:04 +08:00
|
|
|
|
this.cfg[type].push({
|
2025-08-27 10:32:13 +08:00
|
|
|
|
key: key,
|
|
|
|
|
|
callback: callback
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-10-16 11:07:04 +08:00
|
|
|
|
//移除事件回调
|
|
|
|
|
|
removeCallback(currKey, type) {
|
|
|
|
|
|
if (!type) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
let key = currKey ? currKey : this.getCurrentPagePath();
|
|
|
|
|
|
|
|
|
|
|
|
if (key) {
|
2025-09-17 15:21:20 +08:00
|
|
|
|
// console.log("key=" + key);
|
2025-10-16 11:07:04 +08:00
|
|
|
|
let f = this.cfg[type].findIndex((v) => {
|
2025-08-27 10:32:13 +08:00
|
|
|
|
return v.key == key;
|
|
|
|
|
|
});
|
|
|
|
|
|
if (f > -1) {
|
2025-10-16 11:07:04 +08:00
|
|
|
|
this.cfg[type].splice(f, 1);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
} else {
|
2025-10-16 11:07:04 +08:00
|
|
|
|
if (this.cfg[type].length > 0) {
|
|
|
|
|
|
this.cfg[type].splice(this.cfg[type].length - 1, 1);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-16 11:07:04 +08:00
|
|
|
|
|
2025-10-17 17:29:08 +08:00
|
|
|
|
|
2025-10-16 11:07:04 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//设置蓝牙恢复连接的回调
|
|
|
|
|
|
addRecoveryCallback(callback, currKey) {
|
2025-10-17 11:52:26 +08:00
|
|
|
|
this.addCallback(callback, currKey, 'recoveryCallback');
|
2025-10-16 11:07:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//移除蓝牙恢复连接的回调
|
|
|
|
|
|
removeRecoveryCallback(currKey) {
|
2025-10-17 11:52:26 +08:00
|
|
|
|
this.removeCallback(currKey, 'recoveryCallback');
|
2025-10-16 11:07:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//设置蓝牙断开连接的回调
|
|
|
|
|
|
addDisposeCallback(callback, currKey) {
|
2025-10-17 11:52:26 +08:00
|
|
|
|
this.addCallback(callback, currKey, 'bleDisposeCallback');
|
2025-10-16 11:07:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//移除蓝牙断开连接的回调
|
|
|
|
|
|
removeDisposeCallback(currKey) {
|
2025-10-17 11:52:26 +08:00
|
|
|
|
this.removeCallback(currKey, 'bleDisposeCallback');
|
2025-10-16 11:07:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//设置发现新设备的回调
|
|
|
|
|
|
addDeviceFound(callback, currKey) {
|
2025-10-17 11:52:26 +08:00
|
|
|
|
this.addCallback(callback, currKey, 'onDeviceFound');
|
2025-10-16 11:07:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//移除发现新设备的回调
|
|
|
|
|
|
removeDeviceFound(currKey) {
|
2025-10-17 11:52:26 +08:00
|
|
|
|
this.removeCallback(currKey, 'onDeviceFound');
|
2025-10-16 11:07:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
//添加接收到数据的回调
|
|
|
|
|
|
addReceiveCallback(callback, currKey) {
|
2025-10-17 11:52:26 +08:00
|
|
|
|
this.addCallback(callback, currKey, 'receivDataCallback');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//移除接收到数据的回调
|
|
|
|
|
|
removeReceiveCallback(currKey) {
|
|
|
|
|
|
this.removeCallback(currKey, 'receivDataCallback');
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-17 11:52:26 +08:00
|
|
|
|
//添加蓝牙不可用的回调
|
|
|
|
|
|
addStateBreakCallback(callback, currKey) {
|
|
|
|
|
|
this.addCallback(callback, currKey, 'stateBreakCallback');
|
|
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
|
2025-10-17 11:52:26 +08:00
|
|
|
|
//移除蓝牙不可用的回调
|
|
|
|
|
|
removeStateBreakCallback(currKey) {
|
|
|
|
|
|
this.removeCallback(currKey, 'stateBreakCallback');
|
|
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
|
2025-10-17 11:52:26 +08:00
|
|
|
|
|
|
|
|
|
|
//设置蓝牙适配器恢复可用的回调
|
|
|
|
|
|
addStateRecoveryCallback(callback, currKey) {
|
|
|
|
|
|
this.addCallback(callback, currKey, 'stateRecoveryCallback');
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-17 11:52:26 +08:00
|
|
|
|
//移除蓝牙适配器恢复的回调
|
|
|
|
|
|
removeStateRecoveryCallback(currKey) {
|
|
|
|
|
|
this.removeCallback(currKey, 'stateRecoveryCallback');
|
|
|
|
|
|
}
|
2025-10-17 17:29:08 +08:00
|
|
|
|
|
2025-10-17 11:52:26 +08:00
|
|
|
|
//清除所有事件回调
|
|
|
|
|
|
removeAllCallback(currKey) {
|
|
|
|
|
|
this.removeDeviceFound(currKey)
|
|
|
|
|
|
this.removeDisposeCallback(currKey);
|
|
|
|
|
|
this.removeReceiveCallback(currKey);
|
|
|
|
|
|
this.removeRecoveryCallback(currKey);
|
|
|
|
|
|
this.removeStateRecoveryCallback(currKey);
|
|
|
|
|
|
this.removeStateBreakCallback(currKey);
|
|
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getError(ex) {
|
|
|
|
|
|
let code = ex.code;
|
|
|
|
|
|
ex.msg = "未知的异常"
|
|
|
|
|
|
let f = this.dic.errRemarks.find((v) => {
|
|
|
|
|
|
return v.key == code;
|
|
|
|
|
|
});
|
|
|
|
|
|
if (f) {
|
|
|
|
|
|
ex.msg = f.remark;
|
|
|
|
|
|
}
|
|
|
|
|
|
return ex;
|
|
|
|
|
|
}
|
|
|
|
|
|
//引导到设置中打开蓝牙
|
|
|
|
|
|
showBlueSetting(showTip) {
|
|
|
|
|
|
let platform = process.env.UNI_PLATFORM;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var openBlueSetting = function() {
|
|
|
|
|
|
// 判断平台类型
|
|
|
|
|
|
if (platform === 'mp-weixin') {
|
|
|
|
|
|
uni.openSetting();
|
|
|
|
|
|
} else if (platform === 'app-plus' || platform === 'app') {
|
|
|
|
|
|
//----------------------------------------------------------------
|
|
|
|
|
|
const osName = plus.os.name;
|
|
|
|
|
|
|
|
|
|
|
|
if (osName === 'iOS') {
|
|
|
|
|
|
// iOS 平台打开蓝牙设置
|
|
|
|
|
|
plus.runtime.openURL('App-Prefs:root=Bluetooth', function() {
|
|
|
|
|
|
////console.log('成功打开蓝牙设置');
|
|
|
|
|
|
}, function(err) {
|
|
|
|
|
|
console.error('打开蓝牙设置失败:' + err.message);
|
|
|
|
|
|
uni.showModal({
|
|
|
|
|
|
title: '提示',
|
|
|
|
|
|
content: '无法自动打开蓝牙设置,请手动前往设置 > 蓝牙 进行操作。',
|
|
|
|
|
|
showCancel: false
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
} else if (osName === 'Android') {
|
|
|
|
|
|
// Android 平台打开蓝牙设置
|
|
|
|
|
|
try {
|
|
|
|
|
|
const Intent = plus.android.importClass('android.content.Intent');
|
|
|
|
|
|
const Settings = plus.android.importClass('android.provider.Settings');
|
|
|
|
|
|
const main = plus.android.runtimeMainActivity();
|
|
|
|
|
|
const intent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
|
|
|
|
|
|
main.startActivity(intent);
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
console.error('打开蓝牙设置失败:' + e.message);
|
|
|
|
|
|
// 尝试使用通用设置页面作为备选方案
|
|
|
|
|
|
plus.runtime.openURL('settings://', function() {
|
|
|
|
|
|
////console.log('打开系统设置成功,请手动找到蓝牙选项');
|
|
|
|
|
|
}, function() {
|
|
|
|
|
|
uni.showModal({
|
|
|
|
|
|
title: '提示',
|
|
|
|
|
|
content: '无法自动打开蓝牙设置,请手动前往设置页面开启蓝牙。',
|
|
|
|
|
|
showCancel: false
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
uni.showModal({
|
|
|
|
|
|
title: '提示',
|
|
|
|
|
|
content: '当前系统不支持自动打开蓝牙设置,请手动操作。',
|
|
|
|
|
|
showCancel: false
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
|
|
|
|
} else if (platform === 'mp-alipay') {
|
|
|
|
|
|
uni.openSetting();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (showTip !== undefined) {
|
|
|
|
|
|
openBlueSetting();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (platform === 'mp-weixin' || platform === 'app-plus' ||
|
|
|
|
|
|
platform === 'mp-alipay' || platform === 'app') {
|
|
|
|
|
|
uni.showModal({
|
|
|
|
|
|
title: '蓝牙未开启',
|
|
|
|
|
|
content: '请在系统设置中打开蓝牙以使用此功能',
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
if (res.confirm) {
|
|
|
|
|
|
openBlueSetting();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
////console.log("当前平台不支持打开系统设置" + platform);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//获取蓝牙适配器状态
|
|
|
|
|
|
CheckBlue() {
|
2025-10-27 10:52:17 +08:00
|
|
|
|
if (this.data.platform == 'web') {
|
|
|
|
|
|
return Promise.resolve({
|
|
|
|
|
|
available: true,
|
|
|
|
|
|
discovering: false
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
if (this.data.available) {
|
2025-10-13 10:57:03 +08:00
|
|
|
|
// console.log("蓝牙模块是可用状态");
|
2025-08-27 10:32:13 +08:00
|
|
|
|
resolve({
|
|
|
|
|
|
available: this.data.available,
|
|
|
|
|
|
discovering: this.data.discovering
|
|
|
|
|
|
});
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!this.data.isOpenBlue) {
|
2025-10-13 10:57:03 +08:00
|
|
|
|
console.error("蓝牙模块未打开");
|
2025-08-27 10:32:13 +08:00
|
|
|
|
resolve({
|
|
|
|
|
|
available: false,
|
|
|
|
|
|
discovering: false
|
|
|
|
|
|
});
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
uni.getBluetoothAdapterState({
|
|
|
|
|
|
success: (info) => {
|
2025-10-13 10:57:03 +08:00
|
|
|
|
// console.log("蓝牙状态获取成功,", info)
|
2025-09-16 11:37:06 +08:00
|
|
|
|
this.data.available = info.available;
|
|
|
|
|
|
this.data.discovering = info.discovering;
|
2025-08-27 10:32:13 +08:00
|
|
|
|
resolve(info);
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (ex1) => {
|
2025-10-13 10:57:03 +08:00
|
|
|
|
console.error("蓝牙状态获取失败", ex1);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
let res1 = {
|
|
|
|
|
|
available: false,
|
|
|
|
|
|
discovering: false
|
|
|
|
|
|
}
|
|
|
|
|
|
resolve(res1);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
//打开蓝牙适配器
|
|
|
|
|
|
OpenBlue() {
|
|
|
|
|
|
|
2025-10-27 10:52:17 +08:00
|
|
|
|
if (this.data.platform == 'web') {
|
|
|
|
|
|
this.data.isOpenBlue = true;
|
|
|
|
|
|
this.data.available = true;
|
|
|
|
|
|
this.data.isSubscribe = true;
|
|
|
|
|
|
return Promise.resolve(true);
|
|
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
var init = () => {
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
if (this.data.isOpenBlue) {
|
2025-10-13 10:57:03 +08:00
|
|
|
|
// console.log("蓝牙状态已可用,提前返回");
|
2025-08-27 10:32:13 +08:00
|
|
|
|
resolve(false);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-09-16 11:37:06 +08:00
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
uni.openBluetoothAdapter({
|
|
|
|
|
|
success: (args) => {
|
2025-10-16 11:07:04 +08:00
|
|
|
|
// console.log("蓝牙初始化成功:" + JSON.stringify(args));
|
2025-08-27 10:32:13 +08:00
|
|
|
|
this.data.isOpenBlue = true;
|
2025-09-16 11:37:06 +08:00
|
|
|
|
this.data.available = true;
|
2025-08-27 10:32:13 +08:00
|
|
|
|
resolve(true);
|
|
|
|
|
|
|
|
|
|
|
|
if (this.data.isSubscribe) { //整个App生命周期,只订阅一次
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-10-16 11:07:04 +08:00
|
|
|
|
console.log("开始订阅各类变化消息");
|
2025-08-27 10:32:13 +08:00
|
|
|
|
this.data.isSubscribe = true;
|
|
|
|
|
|
|
2025-10-17 11:52:26 +08:00
|
|
|
|
// 保存每个设备的连接状态
|
|
|
|
|
|
let bleDeviceStates = {};
|
|
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
|
|
|
|
|
|
var bytesToHexString = (bytes) => {
|
|
|
|
|
|
return bytes.map(byte => byte.toString(16).padStart(2,
|
|
|
|
|
|
'0'));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uni.onBluetoothAdapterStateChange((state) => {
|
2025-11-14 17:28:20 +08:00
|
|
|
|
console.log('蓝牙状态发生变化:' + JSON.stringify(state));
|
2025-10-30 11:10:57 +08:00
|
|
|
|
this.data.discovering = state.discovering;
|
|
|
|
|
|
|
2025-09-19 12:01:06 +08:00
|
|
|
|
if (this.data.available !== state.available) {
|
|
|
|
|
|
this.data.available = state.available;
|
2025-10-30 11:10:57 +08:00
|
|
|
|
|
2025-09-19 12:01:06 +08:00
|
|
|
|
if (this.data.available && this.data
|
|
|
|
|
|
.isOpenBlue) { //蓝牙状态再次可用,重连所有设备
|
2025-10-17 11:52:26 +08:00
|
|
|
|
|
|
|
|
|
|
if (this.cfg.stateRecoveryCallback.length > 0) {
|
|
|
|
|
|
this.cfg.stateRecoveryCallback.forEach(
|
|
|
|
|
|
c => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
c.callback();
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error(
|
|
|
|
|
|
"蓝牙适配器已恢复,但回调函数发生错误",
|
|
|
|
|
|
error);
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
2025-10-16 11:07:04 +08:00
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
|
2025-09-19 12:01:06 +08:00
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-19 12:01:06 +08:00
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
if (!state.available) { //蓝牙状态不可用了,将所有设备标记为断开连接
|
2025-10-17 11:52:26 +08:00
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
this.data.LinkedList.filter((v) => {
|
|
|
|
|
|
v.Linked = false;
|
|
|
|
|
|
v.notifyState = false;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
});
|
2025-10-17 11:52:26 +08:00
|
|
|
|
let keys = Object.keys(bleDeviceStates)
|
|
|
|
|
|
keys.filter(v => {
|
|
|
|
|
|
bleDeviceStates[v] = false;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
this.cfg.stateBreakCallback.forEach(f => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
f.callback();
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error("蓝牙状态不可用了,执行回调异常",
|
|
|
|
|
|
error)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
})
|
2025-09-17 15:21:20 +08:00
|
|
|
|
|
|
|
|
|
|
this.updateCache();
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-10-17 11:52:26 +08:00
|
|
|
|
uni.onBLEConnectionStateChange((res) => {
|
|
|
|
|
|
console.log("蓝牙连接状态变化了", res);
|
|
|
|
|
|
// 检查状态是否真的发生了变化
|
|
|
|
|
|
if (bleDeviceStates[res.deviceId] === res.connected) {
|
2025-10-23 10:42:30 +08:00
|
|
|
|
console.error('专业给Uniapp填坑,连接状态重复回调');
|
2025-10-17 11:52:26 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-10-16 11:07:04 +08:00
|
|
|
|
|
2025-10-17 11:52:26 +08:00
|
|
|
|
// 更新状态记录
|
|
|
|
|
|
bleDeviceStates[res.deviceId] = res.connected;
|
2025-09-25 09:59:37 +08:00
|
|
|
|
|
2025-10-17 11:52:26 +08:00
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
if (!res.connected) {
|
|
|
|
|
|
console.error("蓝牙已断开", res);
|
|
|
|
|
|
let f = this.data.LinkedList.find((
|
|
|
|
|
|
v) => {
|
|
|
|
|
|
if (v.deviceId == res
|
|
|
|
|
|
.deviceId) {
|
|
|
|
|
|
v.Linked = false;
|
|
|
|
|
|
v.notifyState = false;
|
|
|
|
|
|
return true;
|
2025-10-16 11:07:04 +08:00
|
|
|
|
}
|
2025-10-17 11:52:26 +08:00
|
|
|
|
return false;
|
2025-10-16 11:07:04 +08:00
|
|
|
|
});
|
2025-10-17 11:52:26 +08:00
|
|
|
|
this.updateCache();
|
|
|
|
|
|
if (f && f.device && f.device.id) {
|
|
|
|
|
|
console.log("尝试5次恢复连接,", f
|
|
|
|
|
|
.deviceId);
|
|
|
|
|
|
this.LinkBlue(res.deviceId, f
|
|
|
|
|
|
.writeServiceId, f
|
|
|
|
|
|
.wirteCharactId, f
|
|
|
|
|
|
.notifyCharactId, 5);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (this.cfg.bleDisposeCallback.length >
|
|
|
|
|
|
0) {
|
|
|
|
|
|
this.cfg.bleDisposeCallback.forEach(
|
|
|
|
|
|
(c) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
c.callback(res);
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error(
|
|
|
|
|
|
"执行蓝牙断开连接的回调出现异常,",
|
|
|
|
|
|
error)
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2025-10-16 11:07:04 +08:00
|
|
|
|
|
2025-10-17 11:52:26 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
console.log("蓝牙连接已恢复,", res);
|
|
|
|
|
|
if (this.cfg.recoveryCallback.length >
|
|
|
|
|
|
0) {
|
|
|
|
|
|
this.cfg.recoveryCallback.forEach((
|
|
|
|
|
|
c) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
c.callback(res);
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error(
|
|
|
|
|
|
"执行蓝牙恢复连接的回调出现异常,",
|
|
|
|
|
|
error)
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2025-10-16 11:07:04 +08:00
|
|
|
|
}
|
2025-10-17 11:52:26 +08:00
|
|
|
|
|
|
|
|
|
|
}, 0);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2025-11-14 17:28:20 +08:00
|
|
|
|
console.log("111111111")
|
2025-10-09 14:34:22 +08:00
|
|
|
|
uni.onBluetoothDeviceFound((res) => {
|
2025-11-14 17:28:20 +08:00
|
|
|
|
// console.log("发现新设备:" + JSON.stringify(res,'name'));
|
2025-10-16 11:07:04 +08:00
|
|
|
|
let arr = [];
|
2025-10-09 14:34:22 +08:00
|
|
|
|
for (var i = 0; i < res.devices.length; i++) {
|
|
|
|
|
|
let item = res.devices[i];
|
2025-11-17 15:30:57 +08:00
|
|
|
|
// if(item.name){
|
|
|
|
|
|
// console.log("发现新设备",item.name+" "+item.RSSI);
|
|
|
|
|
|
// }
|
2025-11-14 17:28:20 +08:00
|
|
|
|
|
2025-10-16 11:07:04 +08:00
|
|
|
|
let f = serviceDic.find(v => {
|
|
|
|
|
|
return item.advertisServiceUUIDs
|
|
|
|
|
|
.includes(v.serviceId);
|
2025-10-09 14:34:22 +08:00
|
|
|
|
});
|
2025-10-16 11:07:04 +08:00
|
|
|
|
if (f) {
|
2025-10-17 11:52:26 +08:00
|
|
|
|
|
2025-11-17 15:30:57 +08:00
|
|
|
|
// console.log("发现目标设备:", item);
|
2025-10-09 14:34:22 +08:00
|
|
|
|
arr.push(item);
|
|
|
|
|
|
}
|
2025-10-16 11:07:04 +08:00
|
|
|
|
|
2025-10-09 14:34:22 +08:00
|
|
|
|
}
|
2025-10-16 11:07:04 +08:00
|
|
|
|
if (arr.length === 0) {
|
2025-10-17 11:52:26 +08:00
|
|
|
|
// console.error("发现了设备,但不是想要的设备", res);
|
2025-10-09 14:34:22 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-10-16 11:07:04 +08:00
|
|
|
|
res.devices = arr;
|
2025-08-27 10:32:13 +08:00
|
|
|
|
this.data.searchList = this.data.searchList.concat(
|
2025-10-09 14:34:22 +08:00
|
|
|
|
res);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
if (this.cfg.onDeviceFound) {
|
|
|
|
|
|
if (this.cfg.onDeviceFound.length > 0) {
|
|
|
|
|
|
this.cfg.onDeviceFound.forEach((found) => {
|
2025-10-17 11:52:26 +08:00
|
|
|
|
try {
|
|
|
|
|
|
found.callback(res);
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error("处理发现设备的回调出现异常,",
|
|
|
|
|
|
error);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
uni.onBLECharacteristicValueChange((receive) => {
|
|
|
|
|
|
//订阅消息
|
2025-09-16 11:37:06 +08:00
|
|
|
|
console.log("收到订阅消息", receive);
|
|
|
|
|
|
let f = this.data.LinkedList.find((v) => {
|
|
|
|
|
|
return v.deviceId == receive.deviceId;
|
2025-08-27 10:32:13 +08:00
|
|
|
|
})
|
|
|
|
|
|
let dataView = new DataView(receive.value);
|
|
|
|
|
|
|
|
|
|
|
|
// 转换为字节数组
|
|
|
|
|
|
let bytes = [];
|
|
|
|
|
|
for (let i = 0; i < dataView.byteLength; i++) {
|
|
|
|
|
|
bytes.push(dataView.getUint8(i));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let hexs = bytesToHexString(bytes);
|
|
|
|
|
|
let str = '';
|
|
|
|
|
|
try {
|
|
|
|
|
|
let uint8Array = new Uint8Array(receive.value);
|
|
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < uint8Array.length; i++) {
|
|
|
|
|
|
// 将每个字节转换为对应的字符
|
|
|
|
|
|
str += String.fromCharCode(uint8Array[i]);
|
|
|
|
|
|
}
|
2025-09-16 11:37:06 +08:00
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
let header = "mac address:";
|
2025-10-27 10:52:17 +08:00
|
|
|
|
let isUpdate = false;
|
2025-08-27 10:32:13 +08:00
|
|
|
|
if (str.indexOf(header) == 0) { //650以文本传输mac
|
2025-09-17 15:21:20 +08:00
|
|
|
|
console.log("str=", str);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
this.data.LinkedList.find((v) => {
|
|
|
|
|
|
if (v.deviceId == receive
|
|
|
|
|
|
.deviceId) {
|
2025-09-17 15:21:20 +08:00
|
|
|
|
let macStr = str.replace(
|
2025-08-27 10:32:13 +08:00
|
|
|
|
header, "");
|
2025-09-17 15:21:20 +08:00
|
|
|
|
if (macStr.includes(':')) {
|
|
|
|
|
|
v.macAddress = macStr;
|
2025-09-16 17:30:46 +08:00
|
|
|
|
} else {
|
2025-09-17 15:21:20 +08:00
|
|
|
|
v.macAddress = macStr
|
|
|
|
|
|
.replace(
|
2025-09-16 17:30:46 +08:00
|
|
|
|
/(.{2})/g, '$1:')
|
|
|
|
|
|
.slice(0, -1)
|
|
|
|
|
|
}
|
2025-09-17 15:21:20 +08:00
|
|
|
|
str = header + v.macAddress;
|
2025-09-16 17:30:46 +08:00
|
|
|
|
console.log("收到mac地址:", v
|
|
|
|
|
|
.macAddress)
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-10-27 10:52:17 +08:00
|
|
|
|
isUpdate = true;
|
|
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
2025-09-25 09:59:37 +08:00
|
|
|
|
|
2025-10-27 10:52:17 +08:00
|
|
|
|
if (str.indexOf('imei:') == 0) { //670以此方式传输imei
|
2025-09-23 08:36:21 +08:00
|
|
|
|
let imei = str.split(':')[1];
|
2025-09-25 09:59:37 +08:00
|
|
|
|
|
|
|
|
|
|
|
2025-09-23 08:36:21 +08:00
|
|
|
|
this.data.LinkedList.find((v) => {
|
|
|
|
|
|
if (v.deviceId == receive
|
|
|
|
|
|
.deviceId) {
|
2025-09-25 09:59:37 +08:00
|
|
|
|
v.imei = imei;
|
2025-10-27 10:52:17 +08:00
|
|
|
|
isUpdate = true;
|
2025-09-23 08:36:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-10-27 10:52:17 +08:00
|
|
|
|
|
2025-09-25 09:59:37 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
|
|
|
|
|
|
if (bytes[0] == 0xFC) { //6155以0xFC开头代表mac地址
|
2025-09-16 11:37:06 +08:00
|
|
|
|
console.log("收到mac地址:", bytes)
|
2025-08-27 10:32:13 +08:00
|
|
|
|
if (bytes.length >= 7) {
|
2025-09-16 11:37:06 +08:00
|
|
|
|
console.log("hexs=", hexs);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
let mac = hexs.slice(1, 7).join(":")
|
|
|
|
|
|
.toUpperCase();
|
|
|
|
|
|
this.data.LinkedList.find((v) => {
|
|
|
|
|
|
if (v.deviceId == receive
|
|
|
|
|
|
.deviceId) {
|
|
|
|
|
|
v.macAddress = mac;
|
2025-10-27 10:52:17 +08:00
|
|
|
|
isUpdate = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
2025-11-07 12:16:10 +08:00
|
|
|
|
let trimmedStr = str.trim();
|
|
|
|
|
|
if (trimmedStr && (trimmedStr.startsWith('{') || trimmedStr.startsWith('['))) {
|
|
|
|
|
|
let receivJson = JSON.parse(str);
|
|
|
|
|
|
let key = "sta_address"; //HBY100以此方式上传mac地址
|
|
|
|
|
|
if (key in receivJson) {
|
|
|
|
|
|
this.data.LinkedList.find((v) => {
|
|
|
|
|
|
if (v.deviceId == receive
|
|
|
|
|
|
.deviceId) {
|
|
|
|
|
|
let macStr = receivJson[
|
|
|
|
|
|
key];
|
|
|
|
|
|
if (macStr.includes(':')) {
|
|
|
|
|
|
v.macAddress = macStr;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
v.macAddress = macStr
|
|
|
|
|
|
.replace(/(.{2})/g,
|
|
|
|
|
|
'$1:').slice(0,
|
|
|
|
|
|
-1)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
isUpdate = true;
|
2025-10-27 10:52:17 +08:00
|
|
|
|
}
|
2025-11-07 12:16:10 +08:00
|
|
|
|
});
|
2025-10-27 10:52:17 +08:00
|
|
|
|
|
2025-11-07 12:16:10 +08:00
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
2025-10-27 10:52:17 +08:00
|
|
|
|
} catch (convertException) {
|
2025-11-07 12:16:10 +08:00
|
|
|
|
if (str && (str.trim().startsWith('{') || str.trim().startsWith('['))) {
|
|
|
|
|
|
console.error("JSON解析失败(可能是格式错误的数据)", convertException);
|
|
|
|
|
|
}
|
2025-10-27 10:52:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (isUpdate) {
|
|
|
|
|
|
this.updateCache();
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
2025-11-14 17:28:20 +08:00
|
|
|
|
console.log("str1=", str);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
} catch (ex) {
|
2025-09-25 09:59:37 +08:00
|
|
|
|
console.error("将数据转文本失败", ex);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
2025-10-27 10:52:17 +08:00
|
|
|
|
|
2025-09-16 17:30:46 +08:00
|
|
|
|
try {
|
2025-11-07 11:57:35 +08:00
|
|
|
|
// console.log("11111");
|
2025-10-23 08:46:44 +08:00
|
|
|
|
let recData = {
|
|
|
|
|
|
deviceId: receive.deviceId,
|
|
|
|
|
|
serviceId: receive.serviceId,
|
|
|
|
|
|
characteristicId: receive.characteristicId,
|
|
|
|
|
|
bytes: bytes,
|
|
|
|
|
|
str: str,
|
|
|
|
|
|
hexs: hexs
|
|
|
|
|
|
};
|
2025-11-07 11:57:35 +08:00
|
|
|
|
// console.log("监听到特征值:" + JSON.stringify(recData));
|
2025-09-16 14:51:23 +08:00
|
|
|
|
if (this.cfg.receivDataCallback) {
|
2025-09-16 17:30:46 +08:00
|
|
|
|
|
2025-09-16 14:51:23 +08:00
|
|
|
|
if (this.cfg.receivDataCallback.length > 0) {
|
2025-09-16 17:30:46 +08:00
|
|
|
|
|
2025-09-17 15:21:20 +08:00
|
|
|
|
let path = this.getCurrentPagePath();
|
2025-09-25 09:59:37 +08:00
|
|
|
|
// console.log("有人订阅消息")
|
2025-09-16 17:30:46 +08:00
|
|
|
|
this.cfg.receivDataCallback.forEach((
|
2025-09-17 15:21:20 +08:00
|
|
|
|
rec) => {
|
2025-09-25 09:59:37 +08:00
|
|
|
|
// console.log("有人订阅消息111", )
|
2025-09-16 14:51:23 +08:00
|
|
|
|
if (rec.callback) {
|
2025-09-19 12:01:06 +08:00
|
|
|
|
try {
|
|
|
|
|
|
rec.callback(recData, f,
|
|
|
|
|
|
path, this.cfg
|
|
|
|
|
|
.receivDataCallback
|
2025-09-25 09:59:37 +08:00
|
|
|
|
);
|
2025-09-19 12:01:06 +08:00
|
|
|
|
} catch (err) {
|
2025-09-25 09:59:37 +08:00
|
|
|
|
console.error(
|
|
|
|
|
|
"订阅消息出现异常",
|
2025-09-19 12:01:06 +08:00
|
|
|
|
err);
|
2025-09-17 15:21:20 +08:00
|
|
|
|
}
|
2025-09-19 12:01:06 +08:00
|
|
|
|
|
2025-09-16 14:51:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
})
|
2025-09-16 17:30:46 +08:00
|
|
|
|
} else {
|
2025-10-27 10:52:17 +08:00
|
|
|
|
console.log("无人订阅消息");
|
2025-09-16 14:51:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
} else {
|
2025-10-27 10:52:17 +08:00
|
|
|
|
console.log("无人订阅receivDataCallback,不处理数据");
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
2025-09-16 17:30:46 +08:00
|
|
|
|
} catch (ex) {
|
2025-09-25 09:59:37 +08:00
|
|
|
|
console.error("处理订阅消息失败,ex=", ex);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
2025-09-16 17:30:46 +08:00
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (ex2) => {
|
2025-10-13 10:57:03 +08:00
|
|
|
|
console.error("蓝牙模块启动失败", ex2);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
reject(this.getError(ex2));
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
if (this.data.isOpenBlue) {
|
|
|
|
|
|
resolve();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this.CheckBlue().then((res) => {
|
2025-10-13 10:57:03 +08:00
|
|
|
|
// console.log("res=", res)
|
2025-08-27 10:32:13 +08:00
|
|
|
|
return init();
|
|
|
|
|
|
}).then(resolve).catch((ex) => {
|
2025-09-25 09:59:37 +08:00
|
|
|
|
console.error("异常:", ex);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
reject(ex);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
//关闭蓝牙适配器
|
|
|
|
|
|
CloseBlue() {
|
2025-10-27 10:52:17 +08:00
|
|
|
|
if (this.data.platform == 'web') {
|
|
|
|
|
|
this.data.available = false;
|
|
|
|
|
|
this.data.discovering = false;
|
|
|
|
|
|
this.data.isOpenBlue = false;
|
|
|
|
|
|
this.data.searchList = [];
|
|
|
|
|
|
|
|
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
return new Promise((resolve, reject) => {
|
2025-10-30 11:10:57 +08:00
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
|
|
|
|
|
|
this.StopSearch();
|
|
|
|
|
|
|
|
|
|
|
|
this.disconnectDevice();
|
|
|
|
|
|
|
|
|
|
|
|
uni.closeBluetoothAdapter({
|
|
|
|
|
|
success: () => {
|
2025-10-13 10:57:03 +08:00
|
|
|
|
// console.log("蓝牙模块已关闭");
|
2025-10-30 11:10:57 +08:00
|
|
|
|
this.data.available = false;
|
|
|
|
|
|
this.data.discovering = false;
|
|
|
|
|
|
this.data.isOpenBlue = false;
|
|
|
|
|
|
this.data.searchList = [];
|
|
|
|
|
|
resolve();
|
2025-08-27 10:32:13 +08:00
|
|
|
|
},
|
|
|
|
|
|
fail: (ex) => {
|
2025-10-16 11:07:04 +08:00
|
|
|
|
console.error('无法关闭蓝牙模块:', ex);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
ex = this.getError(ex);
|
2025-10-30 11:10:57 +08:00
|
|
|
|
reject(ex);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
},
|
|
|
|
|
|
complete: () => {
|
2025-10-30 11:10:57 +08:00
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//开始搜索新设备
|
|
|
|
|
|
StartSearch() {
|
2025-10-27 10:52:17 +08:00
|
|
|
|
if (this.data.platform == 'web') {
|
|
|
|
|
|
return Promise.resolve({});
|
|
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
this.data.searchList = [];
|
|
|
|
|
|
var these = this;
|
|
|
|
|
|
//开始搜索
|
|
|
|
|
|
var Search = () => {
|
2025-09-19 12:01:06 +08:00
|
|
|
|
//只搜索合作供应商的服务id
|
|
|
|
|
|
let serviceIds = serviceDic.map(v => {
|
|
|
|
|
|
return v.serviceId
|
|
|
|
|
|
});
|
2025-08-27 10:32:13 +08:00
|
|
|
|
|
2025-09-19 12:01:06 +08:00
|
|
|
|
//搜索一个服务id的设备,循环调用
|
|
|
|
|
|
let RunSearch = (serviceId) => {
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
uni.startBluetoothDevicesDiscovery({
|
2025-09-25 09:59:37 +08:00
|
|
|
|
services: serviceId ? [serviceId] : [],
|
2025-09-23 08:36:21 +08:00
|
|
|
|
allowDuplicatesKey: true,
|
2025-09-19 12:01:06 +08:00
|
|
|
|
success: (res) => {
|
2025-11-14 17:28:20 +08:00
|
|
|
|
console.log('开始搜索蓝牙设备成功');
|
2025-09-19 12:01:06 +08:00
|
|
|
|
resolve(res);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
|
2025-09-19 12:01:06 +08:00
|
|
|
|
},
|
|
|
|
|
|
fail: (err) => {
|
2025-10-13 10:57:03 +08:00
|
|
|
|
console.error(`搜索蓝牙设备失败:`, err);
|
2025-09-19 12:01:06 +08:00
|
|
|
|
|
|
|
|
|
|
reject(this.getError(err));
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-08-27 10:32:13 +08:00
|
|
|
|
});
|
2025-09-19 12:01:06 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
let promises = [];
|
2025-09-23 08:36:21 +08:00
|
|
|
|
// for (let i = 0; i < serviceIds.length; i++) {
|
2025-09-19 12:01:06 +08:00
|
|
|
|
|
2025-09-23 08:36:21 +08:00
|
|
|
|
// promises.push(RunSearch(serviceIds[i]));
|
2025-09-25 09:59:37 +08:00
|
|
|
|
|
2025-09-23 08:36:21 +08:00
|
|
|
|
// }
|
2025-09-25 09:59:37 +08:00
|
|
|
|
promises.push(RunSearch());
|
2025-09-19 12:01:06 +08:00
|
|
|
|
Promise.all(promises).then(resolve).catch(reject);
|
|
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return this.OpenBlue().then((res) => {
|
2025-09-19 12:01:06 +08:00
|
|
|
|
// console.log("蓝牙适配器状态", res)
|
2025-08-27 10:32:13 +08:00
|
|
|
|
|
|
|
|
|
|
return Search();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2025-09-19 12:01:06 +08:00
|
|
|
|
|
|
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
//停止搜索
|
|
|
|
|
|
StopSearch() {
|
2025-10-30 11:10:57 +08:00
|
|
|
|
if (this.data.platform == 'web' || !this.data.discovering) {
|
|
|
|
|
|
console.error("web平台或当前没有搜索,直接返回");
|
2025-10-27 10:52:17 +08:00
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
}
|
2025-10-16 11:07:04 +08:00
|
|
|
|
let p1 = new Promise((resolve, reject) => {
|
2025-08-27 10:32:13 +08:00
|
|
|
|
uni.stopBluetoothDevicesDiscovery({
|
|
|
|
|
|
success: (res) => {
|
2025-10-13 10:57:03 +08:00
|
|
|
|
// console.log("停止搜索蓝牙设备成功");
|
2025-08-27 10:32:13 +08:00
|
|
|
|
resolve();
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (ex) => {
|
2025-10-13 10:57:03 +08:00
|
|
|
|
console.error("无法停止蓝牙搜索");
|
2025-08-27 10:32:13 +08:00
|
|
|
|
|
|
|
|
|
|
reject(this.getError(ex));
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-10-09 14:34:22 +08:00
|
|
|
|
});
|
2025-10-16 11:07:04 +08:00
|
|
|
|
|
2025-10-09 14:34:22 +08:00
|
|
|
|
let p2 = new Promise((succ, err) => {
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
err({
|
|
|
|
|
|
code: -1
|
|
|
|
|
|
});
|
2025-10-17 11:52:26 +08:00
|
|
|
|
}, 100);
|
2025-10-09 14:34:22 +08:00
|
|
|
|
});
|
2025-10-16 11:07:04 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
Promise.race([p1, p2]).then(resolve).catch(ex => {
|
2025-10-09 14:34:22 +08:00
|
|
|
|
if (ex.code == -1) {
|
2025-10-23 10:42:30 +08:00
|
|
|
|
console.error('专业给Uniapp填坑,停止搜索永无回调处理');
|
2025-10-09 14:34:22 +08:00
|
|
|
|
resolve();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
reject(ex);
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
2025-10-16 11:07:04 +08:00
|
|
|
|
|
|
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
//获取已连接的设备
|
|
|
|
|
|
getLinkBlue(callback) {
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
uni.getConnectedBluetoothDevices({
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
|
|
|
|
|
|
resolve(res);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (ex) => {
|
|
|
|
|
|
////console.log("获取已连接设备异常", ex);
|
|
|
|
|
|
|
|
|
|
|
|
reject({
|
|
|
|
|
|
devices: []
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//订阅消息
|
|
|
|
|
|
subScribe(deviceId, state) {
|
2025-11-07 12:16:10 +08:00
|
|
|
|
console.log("开始订阅消息", deviceId, state);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
setTimeout(() => {
|
2025-09-25 09:59:37 +08:00
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
let c = this.data.LinkedList.find((v) => {
|
|
|
|
|
|
return v.deviceId == deviceId;
|
|
|
|
|
|
});
|
2025-09-25 09:59:37 +08:00
|
|
|
|
if (!deviceId) {
|
|
|
|
|
|
console.error('deviceId无效')
|
|
|
|
|
|
reject({
|
|
|
|
|
|
code: 404,
|
|
|
|
|
|
msg: 'deviceId无效'
|
|
|
|
|
|
});
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!c) {
|
|
|
|
|
|
console.error("已找不到该设备");
|
|
|
|
|
|
reject({
|
|
|
|
|
|
code: 404,
|
|
|
|
|
|
msg: '已找不到该设备'
|
|
|
|
|
|
});
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
if (state) {
|
|
|
|
|
|
if (c.notifyState) {
|
|
|
|
|
|
resolve();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-19 12:01:06 +08:00
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
let startSubScribe = (id, serviceId, characteristicId) => {
|
2025-09-25 09:59:37 +08:00
|
|
|
|
// console.log("serviceId=", serviceId);
|
|
|
|
|
|
// console.log("characteristicId=", characteristicId);
|
2025-09-17 15:21:20 +08:00
|
|
|
|
let p1 = new Promise((succ, err) => {
|
|
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
uni.notifyBLECharacteristicValueChange({
|
|
|
|
|
|
deviceId: id,
|
|
|
|
|
|
serviceId: serviceId,
|
|
|
|
|
|
characteristicId: characteristicId,
|
|
|
|
|
|
state: state,
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
if (state) {
|
2025-10-13 10:57:03 +08:00
|
|
|
|
// console.log("订阅消息成功", res);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
} else {
|
2025-10-13 10:57:03 +08:00
|
|
|
|
// console.log("取消订阅成功", res);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this.data.LinkedList.find((v) => {
|
|
|
|
|
|
if (v.deviceId == deviceId) {
|
|
|
|
|
|
v.notifyState = state;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-09-17 15:21:20 +08:00
|
|
|
|
// console.log("success SubScribe");
|
|
|
|
|
|
succ(
|
|
|
|
|
|
res
|
|
|
|
|
|
); //见了鬼了,有时候执行了succ但promise永远pending了
|
2025-08-27 10:32:13 +08:00
|
|
|
|
},
|
|
|
|
|
|
fail: (ex) => {
|
|
|
|
|
|
|
|
|
|
|
|
err(this.getError(ex));
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
2025-09-17 15:21:20 +08:00
|
|
|
|
|
|
|
|
|
|
let p2 = new Promise((succ, err) => {
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
err({
|
|
|
|
|
|
code: -1
|
|
|
|
|
|
});
|
|
|
|
|
|
}, 50);
|
2025-09-16 17:30:46 +08:00
|
|
|
|
});
|
2025-09-17 15:21:20 +08:00
|
|
|
|
return new Promise((succ, err) => {
|
|
|
|
|
|
Promise.race([p1, p2]).then(succ).catch(ex => {
|
2025-09-25 09:59:37 +08:00
|
|
|
|
// console.error("异常了:",ex);
|
2025-09-17 15:21:20 +08:00
|
|
|
|
if (ex.code == -1) {
|
2025-10-23 10:42:30 +08:00
|
|
|
|
console.error('专业给Uniapp填坑,订阅消息永无回调了');
|
2025-09-16 17:30:46 +08:00
|
|
|
|
succ();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
err(ex);
|
|
|
|
|
|
})
|
|
|
|
|
|
});
|
2025-09-17 15:21:20 +08:00
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
2025-09-25 09:59:37 +08:00
|
|
|
|
|
|
|
|
|
|
let serv = serviceDic.find(v => {
|
|
|
|
|
|
return v.serviceId == c.writeServiceId;
|
|
|
|
|
|
});
|
2025-08-27 10:32:13 +08:00
|
|
|
|
let promies = new Array();
|
2025-09-25 09:59:37 +08:00
|
|
|
|
if (c.notifyServiceid && c.notifyCharactId) {
|
|
|
|
|
|
promies.push(startSubScribe(c.deviceId, c.notifyServiceid, c.notifyCharactId));
|
|
|
|
|
|
} else if (serv) {
|
|
|
|
|
|
promies.push(startSubScribe(c.deviceId, serv.serviceId, serv.notifyId));
|
|
|
|
|
|
} else if (c.Characteristics && c.Characteristics.length) {
|
2025-09-16 11:37:06 +08:00
|
|
|
|
for (var i = 0; i < c.Characteristics.length; i++) {
|
|
|
|
|
|
let item = c.Characteristics[i];
|
|
|
|
|
|
let serviceId = item.serviceId;
|
|
|
|
|
|
let characteristicId = item.uuid;
|
2025-09-16 17:30:46 +08:00
|
|
|
|
|
2025-09-16 11:37:06 +08:00
|
|
|
|
if (item.properties.notify) {
|
|
|
|
|
|
promies.push(startSubScribe(deviceId, serviceId, characteristicId));
|
2025-09-25 09:59:37 +08:00
|
|
|
|
|
2025-09-16 11:37:06 +08:00
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
2025-09-25 09:59:37 +08:00
|
|
|
|
} else {
|
2025-10-13 10:57:03 +08:00
|
|
|
|
// console.log("c=", c);
|
|
|
|
|
|
// console.log("serv=", serv);
|
2025-09-25 09:59:37 +08:00
|
|
|
|
reject({
|
|
|
|
|
|
code: 403,
|
|
|
|
|
|
msg: "出现错误,找不到任何通知特征"
|
|
|
|
|
|
});
|
|
|
|
|
|
return;
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
2025-09-16 17:30:46 +08:00
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
if (promies.length > 0) {
|
|
|
|
|
|
|
2025-09-25 09:59:37 +08:00
|
|
|
|
|
2025-09-16 17:30:46 +08:00
|
|
|
|
Promise.allSettled(promies).then((results) => {
|
2025-09-25 09:59:37 +08:00
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
results.forEach((result, index) => {
|
|
|
|
|
|
if (result.status === "fulfilled") {
|
2025-11-07 12:16:10 +08:00
|
|
|
|
console.log(`订阅消息操作${index + 1}成功:`, result.value);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
} else {
|
2025-11-07 12:16:10 +08:00
|
|
|
|
console.error(`订阅消息操作${index + 1}失败:`, result.reason);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-11-07 12:16:10 +08:00
|
|
|
|
console.log("订阅消息完成,deviceId:", deviceId);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
resolve();
|
|
|
|
|
|
}).catch((ex) => {
|
2025-09-25 09:59:37 +08:00
|
|
|
|
console.error("异常,ex=", ex);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
reject(ex);
|
2025-09-17 15:21:20 +08:00
|
|
|
|
}).finally(() => {
|
|
|
|
|
|
// console.log("finally")
|
2025-08-27 10:32:13 +08:00
|
|
|
|
});
|
|
|
|
|
|
} else {
|
2025-10-13 10:57:03 +08:00
|
|
|
|
console.error("没有特征需要订阅");
|
2025-08-27 10:32:13 +08:00
|
|
|
|
resolve();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-09-16 11:37:06 +08:00
|
|
|
|
}, 800);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//获取服务
|
|
|
|
|
|
getService(id, targetServiceId, writeCharId, notifyCharId) {
|
|
|
|
|
|
|
|
|
|
|
|
if (!targetServiceId) {
|
|
|
|
|
|
targetServiceId = "xx"; // "FFE0";
|
|
|
|
|
|
}
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
var repeatCnt = 0;
|
|
|
|
|
|
var startgetService = () => {
|
|
|
|
|
|
|
|
|
|
|
|
uni.getBLEDeviceServices({
|
|
|
|
|
|
deviceId: id,
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
if (res.services && res.services.length > 0) {
|
2025-11-17 15:30:57 +08:00
|
|
|
|
console.log("获取到服务:" + JSON.stringify(res));
|
2025-08-27 10:32:13 +08:00
|
|
|
|
|
|
|
|
|
|
this.data.LinkedList.find((v) => {
|
|
|
|
|
|
if (v.deviceId == id) {
|
|
|
|
|
|
v.services = res.services;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-09-19 12:01:06 +08:00
|
|
|
|
//this.updateCache();
|
2025-08-27 10:32:13 +08:00
|
|
|
|
|
|
|
|
|
|
var promises = [];
|
2025-09-19 12:01:06 +08:00
|
|
|
|
let s = null;
|
2025-08-27 10:32:13 +08:00
|
|
|
|
let se = res.services.find((v) => {
|
2025-09-19 12:01:06 +08:00
|
|
|
|
|
|
|
|
|
|
s = serviceDic.find(k => {
|
|
|
|
|
|
|
|
|
|
|
|
return k.serviceId == v.uuid;
|
|
|
|
|
|
})
|
|
|
|
|
|
if (s) {
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
// return v.uuid.indexOf(targetServiceId) > -1;
|
2025-08-27 10:32:13 +08:00
|
|
|
|
});
|
2025-09-19 12:01:06 +08:00
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
if (se) {
|
2025-11-17 15:30:57 +08:00
|
|
|
|
console.log("合作供应商的", s)
|
2025-09-19 12:01:06 +08:00
|
|
|
|
this.data.LinkedList.find((v) => {
|
|
|
|
|
|
if (v.deviceId == id) {
|
|
|
|
|
|
v.writeServiceId = s.serviceId;
|
|
|
|
|
|
v.wirteCharactId = s.writeId;
|
|
|
|
|
|
v.notifyServiceid = s.serviceId;
|
|
|
|
|
|
v.notifyCharactId = s.notifyId;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
this.updateCache();
|
|
|
|
|
|
|
|
|
|
|
|
//合作供应商的设备,直接订阅消息,不走发现特征了
|
|
|
|
|
|
promises.push(this.subScribe(id, true));
|
|
|
|
|
|
|
|
|
|
|
|
// promises.push(this.getFeatrus(id, se.uuid, writeCharId,
|
|
|
|
|
|
// notifyCharId));
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-11-17 15:30:57 +08:00
|
|
|
|
} else
|
|
|
|
|
|
|
|
|
|
|
|
{
|
2025-10-13 10:57:03 +08:00
|
|
|
|
console.error("预设的蓝牙服务和特征中找不到");
|
2025-08-27 10:32:13 +08:00
|
|
|
|
for (var i = 0; i < res.services.length; i++) {
|
|
|
|
|
|
let service = res.services[i];
|
|
|
|
|
|
promises.push(this.getFeatrus(id, service.uuid,
|
|
|
|
|
|
writeCharId, notifyCharId));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (promises.length == 0) {
|
2025-10-13 10:57:03 +08:00
|
|
|
|
console.error("未找到主服务");
|
2025-08-27 10:32:13 +08:00
|
|
|
|
reject({
|
|
|
|
|
|
msg: "未找到主服务",
|
|
|
|
|
|
code: -1
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
|
|
Promise.all(promises)
|
|
|
|
|
|
.then(results => {
|
2025-11-17 15:30:57 +08:00
|
|
|
|
console.log("results= ",results);
|
2025-09-19 12:01:06 +08:00
|
|
|
|
if (!s) {
|
|
|
|
|
|
//非指定供应商的设备,走订阅消息
|
|
|
|
|
|
return this.subScribe(id, true);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
//指定供应商的设备已经订阅过了
|
|
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
.then((res) => {
|
2025-10-13 10:57:03 +08:00
|
|
|
|
// console.log('设备连接成功,初始化完成', this.data
|
|
|
|
|
|
// .LinkedList);
|
2025-09-25 09:59:37 +08:00
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
resolve();
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch(error => {
|
2025-09-25 09:59:37 +08:00
|
|
|
|
console.error("errrr=", error);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
reject(error);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
repeatCnt++;
|
|
|
|
|
|
if (repeatCnt > 5) {
|
|
|
|
|
|
|
|
|
|
|
|
reject({
|
|
|
|
|
|
msg: "获取设备服务失败",
|
|
|
|
|
|
code: -1
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
setTimeout(function() {
|
|
|
|
|
|
startgetService(id);
|
2025-10-27 10:52:17 +08:00
|
|
|
|
|
|
|
|
|
|
}, 100 + repeatCnt * 300);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (ex) => {
|
|
|
|
|
|
reject(this.getError(ex));
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
setTimeout(function() {
|
|
|
|
|
|
startgetService(id);
|
|
|
|
|
|
}, 100);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//获取特征
|
|
|
|
|
|
getFeatrus(id, serviceId, writeCharId, notifyCharId) {
|
|
|
|
|
|
var promise = new Promise((resolve, reject) => {
|
|
|
|
|
|
uni.getBLEDeviceCharacteristics({
|
|
|
|
|
|
deviceId: id,
|
|
|
|
|
|
serviceId: serviceId,
|
|
|
|
|
|
success: (res) => {
|
2025-09-19 12:01:06 +08:00
|
|
|
|
|
2025-11-17 15:30:57 +08:00
|
|
|
|
console.log("获取到特征:" + JSON.stringify(res));
|
|
|
|
|
|
res.characteristics.forEach((v) => {
|
|
|
|
|
|
v.serviceId = serviceId;
|
|
|
|
|
|
});
|
2025-09-19 12:01:06 +08:00
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
//写特征
|
|
|
|
|
|
let writeChar = res.characteristics.find(char => {
|
2025-09-19 12:01:06 +08:00
|
|
|
|
let fe = serviceDic.find(v => {
|
|
|
|
|
|
return v.serviceId == serviceId && v.writeId == char
|
|
|
|
|
|
.uuid;
|
|
|
|
|
|
})
|
|
|
|
|
|
// return char.uuid.indexOf(writeCharId) > -1
|
|
|
|
|
|
if (fe) {
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
2025-08-27 10:32:13 +08:00
|
|
|
|
});
|
2025-09-19 12:01:06 +08:00
|
|
|
|
// if (!writeChar) {
|
|
|
|
|
|
// writeChar = res.characteristics.find(char => {
|
|
|
|
|
|
// return char.properties.write;
|
|
|
|
|
|
// });
|
|
|
|
|
|
// }
|
2025-08-27 10:32:13 +08:00
|
|
|
|
//通知特征
|
|
|
|
|
|
let notiChar = res.characteristics.find(char => {
|
2025-09-19 12:01:06 +08:00
|
|
|
|
let fe = serviceDic.find(v => {
|
|
|
|
|
|
return v.serviceId == serviceId && v.notifyId ==
|
|
|
|
|
|
char.uuid;
|
|
|
|
|
|
})
|
|
|
|
|
|
// return char.uuid.indexOf(writeCharId) > -1
|
|
|
|
|
|
if (fe) {
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
// return char.uuid.indexOf(notifyCharId) > -1;
|
2025-08-27 10:32:13 +08:00
|
|
|
|
});
|
2025-09-19 12:01:06 +08:00
|
|
|
|
// if (!notiChar) {
|
|
|
|
|
|
// notiChar = res.characteristics.find(char => {
|
|
|
|
|
|
// return char.properties.notify;
|
|
|
|
|
|
// });
|
|
|
|
|
|
// }
|
2025-08-27 10:32:13 +08:00
|
|
|
|
this.data.LinkedList.find(function(v) {
|
|
|
|
|
|
if (v.deviceId == id) {
|
|
|
|
|
|
if (!v.Characteristics) {
|
|
|
|
|
|
v.Characteristics = [];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < res.characteristics.length; i++) {
|
|
|
|
|
|
let item = res.characteristics[i];
|
|
|
|
|
|
let flag = false;
|
|
|
|
|
|
for (var j = 0; j < v.Characteristics.length; j++) {
|
|
|
|
|
|
let charact = v.Characteristics[j];
|
|
|
|
|
|
if (charact.uuid == item.uuid) {
|
|
|
|
|
|
flag = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!flag) {
|
|
|
|
|
|
v.Characteristics.push(item);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (writeChar) {
|
|
|
|
|
|
v.writeServiceId = serviceId;
|
|
|
|
|
|
v.wirteCharactId = writeChar.uuid;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (notiChar) {
|
|
|
|
|
|
v.notifyServiceid = serviceId;
|
|
|
|
|
|
v.notifyCharactId = notiChar.uuid;
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-09-17 15:21:20 +08:00
|
|
|
|
this.updateCache();
|
2025-08-27 10:32:13 +08:00
|
|
|
|
resolve(res);
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (ex) => {
|
|
|
|
|
|
////console.log("获取特征出现异常:" + JSON.stringify(ex));
|
|
|
|
|
|
reject(ex);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
return promise;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//连接某个设备
|
2025-09-19 12:01:06 +08:00
|
|
|
|
LinkBlue(deviceId, targetServiceId, writeCharId, notifyCharId, maxRetries) {
|
2025-10-27 11:51:38 +08:00
|
|
|
|
if (this.data.platform == 'web') {
|
2025-10-27 10:52:17 +08:00
|
|
|
|
return Promise.resolve(true);
|
|
|
|
|
|
}
|
2025-09-19 12:01:06 +08:00
|
|
|
|
if (maxRetries === undefined) {
|
|
|
|
|
|
maxRetries = 0; // 最大重试次数
|
|
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
if (!writeCharId) {
|
|
|
|
|
|
writeCharId = "xxxx"; // "FFE1";
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!notifyCharId) {
|
|
|
|
|
|
notifyCharId = "xxxxx"; // "FFE2";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let fIndex = -1;
|
|
|
|
|
|
let f = this.data.LinkedList.find((v, index) => {
|
|
|
|
|
|
if (v.deviceId == deviceId) {
|
|
|
|
|
|
fIndex = index;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
});
|
|
|
|
|
|
////console.log("findex=" + fIndex);
|
|
|
|
|
|
|
|
|
|
|
|
var these = this;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//连接设备
|
|
|
|
|
|
var linkDevice = () => {
|
2025-09-16 17:30:46 +08:00
|
|
|
|
// 添加重试次数限制
|
|
|
|
|
|
let retryCount = 0;
|
2025-09-19 12:01:06 +08:00
|
|
|
|
|
2025-09-16 17:30:46 +08:00
|
|
|
|
|
|
|
|
|
|
const connect = () => {
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
if (fIndex > -1 && f?.Linked) {
|
2025-09-17 15:21:20 +08:00
|
|
|
|
// console.log("当前已连接,跳过其他步骤");
|
2025-09-16 17:30:46 +08:00
|
|
|
|
resolve(false);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!this.data.available) {
|
|
|
|
|
|
reject(this.getError({
|
|
|
|
|
|
code: 10001
|
|
|
|
|
|
}));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-13 10:57:03 +08:00
|
|
|
|
// console.log("正在连接" + deviceId);
|
2025-09-16 17:30:46 +08:00
|
|
|
|
uni.createBLEConnection({
|
|
|
|
|
|
deviceId: deviceId,
|
2025-09-23 08:36:21 +08:00
|
|
|
|
timeout: 30000,
|
2025-09-16 17:30:46 +08:00
|
|
|
|
success: (info) => {
|
2025-10-13 10:57:03 +08:00
|
|
|
|
// console.log("新连接成功", this.data.LinkedList);
|
2025-09-16 17:30:46 +08:00
|
|
|
|
this.getLinkBlue().then((arr) => {
|
|
|
|
|
|
let cr = arr.devices.find(c => {
|
|
|
|
|
|
if (c.deviceId == deviceId) {
|
|
|
|
|
|
c.Linked = true;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (fIndex > -1) {
|
|
|
|
|
|
this.data.LinkedList[fIndex].Linked = true;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.data.LinkedList.push(cr);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-17 15:21:20 +08:00
|
|
|
|
this.updateCache();
|
2025-10-13 10:57:03 +08:00
|
|
|
|
// console.log("LinkedList=", this.data
|
|
|
|
|
|
// .LinkedList);
|
2025-09-16 17:30:46 +08:00
|
|
|
|
|
|
|
|
|
|
// 处理 MTU 设置
|
2025-10-27 10:52:17 +08:00
|
|
|
|
if (plus.os.name === 'Android') {
|
2025-10-30 11:10:57 +08:00
|
|
|
|
this.setMtu(deviceId).catch(ex=>{
|
|
|
|
|
|
console.error("mtu设置失败=",ex);
|
|
|
|
|
|
});
|
2025-10-27 10:52:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
resolve(true);
|
|
|
|
|
|
|
2025-09-16 17:30:46 +08:00
|
|
|
|
}).catch((ex) => {
|
|
|
|
|
|
reject(this.getError(ex));
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (ex) => {
|
|
|
|
|
|
ex = this.getError(ex);
|
2025-10-16 11:07:04 +08:00
|
|
|
|
console.error("蓝牙" + deviceId + "连接失败" + JSON.stringify(
|
2025-10-17 11:52:26 +08:00
|
|
|
|
ex));
|
2025-09-16 17:30:46 +08:00
|
|
|
|
|
|
|
|
|
|
// 连接超时后自动重试
|
|
|
|
|
|
if (ex.code === 10012 && retryCount < maxRetries) {
|
|
|
|
|
|
retryCount++;
|
|
|
|
|
|
console.log(`重试连接 (${retryCount}/${maxRetries})`);
|
|
|
|
|
|
// 使用 setTimeout 避免递归调用栈溢出
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
connect().then(resolve).catch(reject);
|
|
|
|
|
|
}, 1000); // 延迟1秒后重试
|
|
|
|
|
|
} else {
|
|
|
|
|
|
reject(ex);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return connect();
|
2025-09-16 11:37:06 +08:00
|
|
|
|
};
|
2025-08-27 10:32:13 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
this.OpenBlue().then((res) => {
|
|
|
|
|
|
////console.log("2222222");
|
|
|
|
|
|
return linkDevice(deviceId);
|
|
|
|
|
|
}).then((res) => {
|
2025-09-16 17:30:46 +08:00
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
if (res) { //新连接
|
2025-09-17 15:21:20 +08:00
|
|
|
|
// console.log("11111111");
|
2025-08-27 10:32:13 +08:00
|
|
|
|
if (fIndex == -1) {
|
2025-09-17 15:21:20 +08:00
|
|
|
|
// console.log("开始获取服务", targetServiceId)
|
2025-08-27 10:32:13 +08:00
|
|
|
|
return this.getService(deviceId, targetServiceId, writeCharId,
|
2025-09-16 11:37:06 +08:00
|
|
|
|
notifyCharId); //获取服务
|
2025-08-27 10:32:13 +08:00
|
|
|
|
} else {
|
2025-09-16 17:30:46 +08:00
|
|
|
|
if (f.wirteCharactId && f.notifyCharactId) {
|
2025-09-16 11:37:06 +08:00
|
|
|
|
if (!f.notifyState) {
|
2025-09-17 15:21:20 +08:00
|
|
|
|
// console.log("开始订阅特征");
|
2025-09-16 11:37:06 +08:00
|
|
|
|
this.subScribe(deviceId, true);
|
2025-09-16 17:30:46 +08:00
|
|
|
|
} else {
|
2025-09-16 11:37:06 +08:00
|
|
|
|
console.log("不订阅消息");
|
|
|
|
|
|
}
|
|
|
|
|
|
return Promise.resolve(true);
|
2025-09-16 17:30:46 +08:00
|
|
|
|
} else {
|
2025-09-16 11:37:06 +08:00
|
|
|
|
console.log("开始获取服务", targetServiceId)
|
|
|
|
|
|
return this.getService(deviceId, targetServiceId, writeCharId,
|
|
|
|
|
|
notifyCharId);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
2025-09-16 17:30:46 +08:00
|
|
|
|
|
|
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
2025-09-16 11:37:06 +08:00
|
|
|
|
} else { //已连接过,直接订阅消息
|
2025-09-17 15:21:20 +08:00
|
|
|
|
// console.log("11111111");
|
2025-11-07 12:16:10 +08:00
|
|
|
|
if (fIndex > -1 && f) {
|
|
|
|
|
|
if (!f.notifyState) {
|
|
|
|
|
|
console.log("设备已连接但未订阅,开始订阅消息");
|
|
|
|
|
|
return this.subScribe(deviceId, true).then(() => {
|
|
|
|
|
|
console.log("订阅消息完成");
|
|
|
|
|
|
return Promise.resolve(true);
|
|
|
|
|
|
}).catch(err => {
|
|
|
|
|
|
console.error("订阅消息失败:", err);
|
|
|
|
|
|
return Promise.resolve(true);
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.log("设备已连接且已订阅消息");
|
|
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
return Promise.resolve(true); //已连接过的设备无需获取服务
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}).then(() => {
|
2025-09-17 15:21:20 +08:00
|
|
|
|
// console.log("then.....");
|
2025-08-27 10:32:13 +08:00
|
|
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
resolve();
|
|
|
|
|
|
}, 500);
|
|
|
|
|
|
}).catch((ex) => {
|
2025-09-25 09:59:37 +08:00
|
|
|
|
console.error("出现异常", ex);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
reject(ex);
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2025-10-27 10:52:17 +08:00
|
|
|
|
|
|
|
|
|
|
setMtu(deviceId) {
|
|
|
|
|
|
let prom = new Promise((_succ, _err) => {
|
2025-10-23 08:46:44 +08:00
|
|
|
|
uni.setBLEMTU({
|
|
|
|
|
|
deviceId: deviceId,
|
|
|
|
|
|
mtu: 512,
|
|
|
|
|
|
success: (mtuRes) => {
|
|
|
|
|
|
console.log("mtu约定成功");
|
|
|
|
|
|
_succ(mtuRes);
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (ex) => {
|
2025-10-30 11:10:57 +08:00
|
|
|
|
|
2025-10-27 10:52:17 +08:00
|
|
|
|
ex = this.getError(ex);
|
2025-10-23 08:46:44 +08:00
|
|
|
|
_err(
|
|
|
|
|
|
ex
|
2025-10-30 11:10:57 +08:00
|
|
|
|
);
|
2025-10-27 10:52:17 +08:00
|
|
|
|
},
|
|
|
|
|
|
complete() {
|
2025-10-23 08:46:44 +08:00
|
|
|
|
console.log("设置mtu完毕");
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
return prom;
|
|
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
//断开连接
|
|
|
|
|
|
disconnectDevice(deviceId) {
|
2025-10-27 11:51:38 +08:00
|
|
|
|
if (this.data.platform == 'web') {
|
2025-10-27 10:52:17 +08:00
|
|
|
|
return Promise.resolve();
|
|
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
var disconnect = (id) => {
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
uni.closeBLEConnection({
|
|
|
|
|
|
deviceId: id,
|
|
|
|
|
|
success: (res) => {
|
2025-10-17 11:52:26 +08:00
|
|
|
|
console.log("用户主动断开了蓝牙:" + id);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
this.subScribe(id, false);
|
|
|
|
|
|
resolve();
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (ex) => {
|
2025-10-17 11:52:26 +08:00
|
|
|
|
console.error("无法断开蓝牙连接", ex);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
reject(this.getError(ex));
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
if (deviceId) {
|
2025-10-27 11:51:38 +08:00
|
|
|
|
return disconnect(deviceId);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (this.data.LinkedList.length > 0) {
|
|
|
|
|
|
let arr = [];
|
|
|
|
|
|
for (var i = 0; i < this.data.LinkedList.length; i++) {
|
|
|
|
|
|
let item = this.data.LinkedList[i];
|
|
|
|
|
|
if (item.Linked) {
|
|
|
|
|
|
arr.push(disconnect(item.deviceId));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2025-10-27 11:51:38 +08:00
|
|
|
|
if (arr.length) {
|
|
|
|
|
|
return new Promise((_succ, _err) => {
|
|
|
|
|
|
Promise.allSettled(arr).then((results) => {
|
|
|
|
|
|
results.forEach((result, index) => {
|
|
|
|
|
|
if (result.status === 'fulfilled') {
|
|
|
|
|
|
////console.log(`第${index + 1}个Promise成功:`, result.value);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
////console.log(`第${index + 1}个Promise失败:`, result.reason.message);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
_succ()
|
|
|
|
|
|
}).catch((ex) => {
|
|
|
|
|
|
_err();
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
2025-10-27 11:51:38 +08:00
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
|
2025-10-27 11:51:38 +08:00
|
|
|
|
return Promise.resolve();
|
2025-08-27 10:32:13 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
2025-10-17 17:29:08 +08:00
|
|
|
|
//向蓝牙设备发送一个字符串的ASCII码
|
|
|
|
|
|
sendString(deviceid, str, writeServiceId, wirteCharactId, ms) {
|
2025-10-27 10:52:17 +08:00
|
|
|
|
if (str && typeof(str) == 'object') {
|
|
|
|
|
|
str = JSON.stringify(str);
|
2025-10-24 17:21:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
if (str) {
|
2025-10-27 10:52:17 +08:00
|
|
|
|
|
2025-10-17 17:29:08 +08:00
|
|
|
|
let buffer = new ArrayBuffer(str.length);
|
|
|
|
|
|
let dataView = new DataView(buffer);
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 将字符串转换为 ASCII 码并写入 DataView
|
|
|
|
|
|
for (let i = 0; i < str.length; i++) {
|
|
|
|
|
|
dataView.setUint8(i, str.charCodeAt(i));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return this.sendData(deviceid, buffer, writeServiceId, wirteCharactId, ms);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return Promise.resolve({
|
|
|
|
|
|
code: 200,
|
|
|
|
|
|
msg: "没有数据要发送"
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
|
2025-10-17 17:29:08 +08:00
|
|
|
|
//向蓝牙设备发送一个16进制的数组数据
|
|
|
|
|
|
sendHexs(deviceid, array, writeServiceId, wirteCharactId, ms) {
|
|
|
|
|
|
if (array && array.length) {
|
|
|
|
|
|
let bufferSize = array.length;
|
|
|
|
|
|
let buffer = new ArrayBuffer(bufferSize);
|
|
|
|
|
|
let dataView = new DataView(buffer);
|
|
|
|
|
|
for (let i = 0; i < array.length; i++) {
|
|
|
|
|
|
dataView.setUint8(i, array);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return this.sendData(deviceid, buffer, writeServiceId, wirteCharactId, ms);
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return Promise.resolve({
|
|
|
|
|
|
code: 200,
|
|
|
|
|
|
msg: "没有数据要发送"
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2025-08-27 10:32:13 +08:00
|
|
|
|
//向蓝牙设备发送数据,如果没连接将自动连接后再发
|
|
|
|
|
|
sendData(deviceid, buffer, writeServiceId, wirteCharactId, ms) {
|
2025-10-27 10:52:17 +08:00
|
|
|
|
if (this.data.platform == 'web') {
|
|
|
|
|
|
return Promise.resolve("h5平台默认成功");
|
|
|
|
|
|
}
|
2025-11-07 12:16:10 +08:00
|
|
|
|
|
|
|
|
|
|
// 打印发送的蓝牙指令
|
|
|
|
|
|
let bufferHex = '';
|
|
|
|
|
|
if (buffer) {
|
|
|
|
|
|
let bytes = [];
|
|
|
|
|
|
// 处理不同类型的buffer(ArrayBuffer、Uint8Array等)
|
|
|
|
|
|
if (buffer instanceof ArrayBuffer) {
|
|
|
|
|
|
let dataView = new DataView(buffer);
|
|
|
|
|
|
for (let i = 0; i < buffer.byteLength; i++) {
|
|
|
|
|
|
bytes.push(dataView.getUint8(i));
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (buffer.byteLength !== undefined) {
|
|
|
|
|
|
// 如果是 Uint8Array 或其他类型
|
|
|
|
|
|
for (let i = 0; i < buffer.byteLength; i++) {
|
|
|
|
|
|
bytes.push(buffer[i] || 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (Array.isArray(buffer)) {
|
|
|
|
|
|
bytes = buffer;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (bytes.length > 0) {
|
|
|
|
|
|
bufferHex = bytes.map(b => '0x' + b.toString(16).padStart(2, '0').toUpperCase()).join(' ');
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-11-10 17:27:37 +08:00
|
|
|
|
// console.log("准备发送蓝牙指令 - deviceId:", deviceid, "writeServiceId:", writeServiceId, "writeCharactId:", wirteCharactId);
|
|
|
|
|
|
// console.log("发送数据(Hex):", bufferHex || "(空数据)");
|
|
|
|
|
|
// console.log("发送数据(原始buffer长度):", buffer ? (buffer.byteLength || buffer.length || 0) : 0);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
if (ms === undefined) {
|
|
|
|
|
|
ms = 50;
|
|
|
|
|
|
}
|
|
|
|
|
|
let c = this.data.LinkedList.find((v) => {
|
|
|
|
|
|
return v.deviceId == deviceid;
|
|
|
|
|
|
});
|
|
|
|
|
|
let device = {
|
|
|
|
|
|
deviceId: deviceid,
|
|
|
|
|
|
writeServiceId: null,
|
|
|
|
|
|
wirteCharactId: null
|
|
|
|
|
|
};
|
|
|
|
|
|
if (writeServiceId) {
|
|
|
|
|
|
device.writeServiceId = writeServiceId;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (wirteCharactId) {
|
|
|
|
|
|
device.wirteCharactId = wirteCharactId;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!device.writeServiceId || !device.wirteCharactId) {
|
|
|
|
|
|
//console.log("从已连接中找设备")
|
|
|
|
|
|
if (c) {
|
|
|
|
|
|
device = c;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let sendBuffer = () => {
|
|
|
|
|
|
|
|
|
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
|
|
|
|
|
|
|
|
var promise = new Promise((succ, err) => {
|
|
|
|
|
|
if (!c) {
|
|
|
|
|
|
err(this.getError({
|
|
|
|
|
|
code: 10002
|
|
|
|
|
|
})); //没有找到指定设备
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-09-17 15:21:20 +08:00
|
|
|
|
// console.log("device=", device);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
uni.writeBLECharacteristicValue({
|
|
|
|
|
|
deviceId: device.deviceId,
|
|
|
|
|
|
serviceId: device.writeServiceId,
|
|
|
|
|
|
characteristicId: device.wirteCharactId,
|
|
|
|
|
|
value: buffer,
|
2025-11-07 12:16:10 +08:00
|
|
|
|
writeType: 'write',
|
2025-08-27 10:32:13 +08:00
|
|
|
|
success: () => {
|
2025-11-07 12:16:10 +08:00
|
|
|
|
console.log("✓ 蓝牙指令发送成功 - deviceId:", device.deviceId);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
succ();
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (ex) => {
|
|
|
|
|
|
ex = this.getError(ex);
|
2025-11-07 12:16:10 +08:00
|
|
|
|
console.error("✗ 蓝牙指令发送失败 - deviceId:", device.deviceId, "错误:", ex);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
|
|
|
|
|
|
err(ex);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
if (plus.os.name == 'iOS') {
|
|
|
|
|
|
|
|
|
|
|
|
function timeOut(ms) {
|
|
|
|
|
|
return new Promise((_, err) => {
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
err({
|
|
|
|
|
|
code: -1,
|
|
|
|
|
|
errMsg: '超时了'
|
|
|
|
|
|
})
|
|
|
|
|
|
}, ms);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Promise.race([timeOut(ms), promise]).then(resolve).catch((ex) => {
|
2025-09-25 09:59:37 +08:00
|
|
|
|
// console.error("ex=", ex);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
if (ex.code == -1) {
|
2025-10-23 10:42:30 +08:00
|
|
|
|
console.error('专业给Uniapp填坑,发送消息永无回调');
|
2025-08-27 10:32:13 +08:00
|
|
|
|
resolve(ex);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
reject(ex);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}).finally(() => {
|
|
|
|
|
|
//console.log("完成了")
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
promise.then(resolve).catch(reject);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
if (c.Linked) {
|
2025-11-10 17:27:37 +08:00
|
|
|
|
// console.log("蓝牙已连接,直接发送数据");
|
2025-08-27 10:32:13 +08:00
|
|
|
|
return sendBuffer();
|
|
|
|
|
|
} else {
|
2025-11-10 17:27:37 +08:00
|
|
|
|
// console.log("蓝牙未连接,先连接蓝牙再发送数据");
|
2025-08-27 10:32:13 +08:00
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
let f = this.data.LinkedList.find((v) => {
|
|
|
|
|
|
return v.deviceId == deviceid;
|
|
|
|
|
|
});
|
|
|
|
|
|
if (!f) {
|
|
|
|
|
|
reject({
|
|
|
|
|
|
code: '-9',
|
|
|
|
|
|
msg: '蓝牙未连接过此设备,请重新使用蓝牙添加该设备'
|
|
|
|
|
|
});
|
|
|
|
|
|
retrn;
|
|
|
|
|
|
}
|
|
|
|
|
|
this.LinkBlue(f.deviceId, f.writeServiceId, f.wirteCharactId, f.notifyCharactId).then((
|
|
|
|
|
|
res) => {
|
|
|
|
|
|
console.log("连接成功");
|
|
|
|
|
|
return sendBuffer();
|
|
|
|
|
|
}).then(() => {
|
|
|
|
|
|
//console.log("发送成功")
|
|
|
|
|
|
resolve();
|
|
|
|
|
|
}).catch((ex) => {
|
2025-09-25 09:59:37 +08:00
|
|
|
|
console.error("出现异常", ex);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
reject(this.getError(ex));
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//将点阵数据转换成RGB565
|
|
|
|
|
|
convertToRGB565(pixels, type) {
|
|
|
|
|
|
if (!type) {
|
|
|
|
|
|
type = 'rgb';
|
|
|
|
|
|
}
|
|
|
|
|
|
const result = new Uint16Array(pixels.length / 4);
|
|
|
|
|
|
let index = 0;
|
|
|
|
|
|
for (let i = 0; i < pixels.length; i += 4) {
|
|
|
|
|
|
let r = pixels[i];
|
|
|
|
|
|
let g = pixels[i + 1];
|
|
|
|
|
|
let b = pixels[i + 2];
|
|
|
|
|
|
let a = pixels[i + 3];
|
|
|
|
|
|
|
|
|
|
|
|
if (type == 'bgr') {
|
2025-09-16 11:37:06 +08:00
|
|
|
|
result[index++] = ((b & 0xF8) << 8) | ((g & 0xFC) << 3) | (r >> 3);
|
2025-08-27 10:32:13 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
result[index++] = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-17 15:21:20 +08:00
|
|
|
|
|
2025-11-14 17:28:20 +08:00
|
|
|
|
|
2025-08-27 10:32:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let instance = null;
|
|
|
|
|
|
export default {
|
|
|
|
|
|
getBleTool: function(found, receive) {
|
|
|
|
|
|
if (!instance) {
|
|
|
|
|
|
instance = new BleHelper();
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
////console.log("调用现有实例");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return instance;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|