2025-06-06 15:17:30 +08:00
|
|
|
|
Page({
|
|
|
|
|
|
data: {
|
|
|
|
|
|
devices: [],
|
|
|
|
|
|
isSearching: false,
|
|
|
|
|
|
status: '未连接',
|
|
|
|
|
|
connected: false,
|
|
|
|
|
|
skipCount: 0,
|
|
|
|
|
|
connectedDeviceId: null,
|
|
|
|
|
|
deviceServices: [],
|
|
|
|
|
|
deviceCharacteristics: [],
|
2026-04-16 13:38:33 +08:00
|
|
|
|
blueIsOk: false
|
2025-06-06 15:17:30 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 1. 初始化蓝牙模块
|
|
|
|
|
|
startBluetooth() {
|
|
|
|
|
|
const that = this
|
2026-04-16 13:38:33 +08:00
|
|
|
|
wx.closeBluetoothAdapter({
|
|
|
|
|
|
success:()=>{
|
|
|
|
|
|
wx.openBluetoothAdapter({
|
|
|
|
|
|
success: () => {
|
|
|
|
|
|
// console.log('蓝牙初始化成功');
|
|
|
|
|
|
this.setData({
|
|
|
|
|
|
blueIsOk: true
|
|
|
|
|
|
})
|
|
|
|
|
|
that.searchDevices() //开始搜索设备
|
|
|
|
|
|
// wx.showToast({ title: '蓝牙已开启', icon: 'success' });
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (res) => {
|
|
|
|
|
|
console.error('蓝牙初始化失败', res);
|
|
|
|
|
|
wx.showModal({
|
|
|
|
|
|
title: '提示',
|
|
|
|
|
|
content: '请打开手机蓝牙并授权小程序使用',
|
|
|
|
|
|
showCancel: false,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2025-06-06 15:17:30 +08:00
|
|
|
|
});
|
|
|
|
|
|
}
|
2026-04-16 13:38:33 +08:00
|
|
|
|
})
|
2025-06-06 15:17:30 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
2026-04-16 13:38:33 +08:00
|
|
|
|
onLoad(options) {
|
2025-06-06 15:17:30 +08:00
|
|
|
|
this.startBluetooth()
|
2026-04-16 13:38:33 +08:00
|
|
|
|
console.log(options.params)
|
|
|
|
|
|
if (options.params) {
|
|
|
|
|
|
this.setData({
|
|
|
|
|
|
params: options.params.replaceAll('*', '=').replaceAll('@', '&')
|
|
|
|
|
|
})
|
|
|
|
|
|
console.log(this.data.params)
|
|
|
|
|
|
}
|
2025-06-06 15:17:30 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 搜索设备
|
|
|
|
|
|
searchDevices() {
|
2026-04-16 13:38:33 +08:00
|
|
|
|
const that = this
|
|
|
|
|
|
if (!this.data.blueIsOk) return wx.showModal({
|
2025-06-06 15:17:30 +08:00
|
|
|
|
title: '提示',
|
|
|
|
|
|
content: '请打开手机蓝牙并授权小程序使用',
|
|
|
|
|
|
showCancel: false,
|
|
|
|
|
|
});
|
2026-04-16 13:38:33 +08:00
|
|
|
|
this.setData({
|
|
|
|
|
|
isSearching: true,
|
|
|
|
|
|
devices: []
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const last_device_id = wx.getStorageSync('device_id')
|
|
|
|
|
|
const uuid = wx.getStorageSync('uuid')
|
|
|
|
|
|
// if (uuid != '' && device_id != '') {
|
|
|
|
|
|
// wx.getConnectedBluetoothDevices({
|
|
|
|
|
|
// services: [uuid],
|
|
|
|
|
|
// success: ress => {
|
|
|
|
|
|
// console.log('aa', ress)
|
|
|
|
|
|
// console.log('看看有没有', ress)
|
|
|
|
|
|
// console.log('看看有没有', ress)
|
|
|
|
|
|
// console.log('看看有没有', ress)
|
|
|
|
|
|
// console.log('看看有没有', ress)
|
|
|
|
|
|
// if (ress.devices.length > 0) {
|
|
|
|
|
|
// for (let item of ress.devices) {
|
|
|
|
|
|
// if (item.deviceId == device_id) {
|
|
|
|
|
|
// that.setData({
|
|
|
|
|
|
// connectedDeviceId: device_id,
|
|
|
|
|
|
// devices: [item, ...that.data.devices]
|
|
|
|
|
|
// }, () => {
|
|
|
|
|
|
// console.log('nowDevice===========>', that.data.devices)
|
|
|
|
|
|
// console.log('nowDevice===========>', that.data.devices)
|
|
|
|
|
|
// console.log('nowDevice===========>', that.data.devices)
|
|
|
|
|
|
// console.log('nowDevice===========>', that.data.devices)
|
|
|
|
|
|
// })
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
// //尝试链接原来的蓝牙
|
|
|
|
|
|
// wx.closeBLEConnection()
|
|
|
|
|
|
// return
|
|
|
|
|
|
// wx.showModal({
|
|
|
|
|
|
// title: '是否连接上次的设备?',
|
|
|
|
|
|
// content: '',
|
|
|
|
|
|
// complete: (res) => {
|
|
|
|
|
|
// if (res.cancel) {
|
|
|
|
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// if (res.confirm) {
|
|
|
|
|
|
// that.connectDevice({
|
|
|
|
|
|
// currentTarget: {
|
|
|
|
|
|
// dataset: {
|
|
|
|
|
|
// device: {
|
|
|
|
|
|
// deviceId: device_id
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
// })
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
// })
|
|
|
|
|
|
// // that.connectDevice({
|
|
|
|
|
|
// // currentTarget:{
|
|
|
|
|
|
// // dataset:{
|
|
|
|
|
|
// // device:{deviceId:device_id}
|
|
|
|
|
|
// // }
|
|
|
|
|
|
// // }
|
|
|
|
|
|
// // })
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
// })
|
|
|
|
|
|
// }
|
2025-06-06 15:17:30 +08:00
|
|
|
|
|
|
|
|
|
|
// 启动搜索
|
|
|
|
|
|
wx.startBluetoothDevicesDiscovery({
|
|
|
|
|
|
allowDuplicatesKey: false,
|
|
|
|
|
|
success: () => {
|
|
|
|
|
|
console.log('开始搜索设备');
|
|
|
|
|
|
// 监听发现设备事件
|
|
|
|
|
|
wx.onBluetoothDeviceFound((res) => {
|
|
|
|
|
|
console.log('发现新设备', res.devices);
|
|
|
|
|
|
res.devices.forEach(device => {
|
2026-04-16 13:38:33 +08:00
|
|
|
|
if (device.name == 'YD-Jump' || device.name == 'YD_Jump' || device.name == 'YD-O1' || device.localName == 'YD-O1' || device.localName == 'YD-Jump' || device.localName == 'YD_Jump') {
|
2025-06-06 15:17:30 +08:00
|
|
|
|
const exists = this.data.devices.find(d => d.deviceId === device.deviceId);
|
|
|
|
|
|
if (!exists) {
|
2026-04-16 13:38:33 +08:00
|
|
|
|
if (device.deviceId == last_device_id) {
|
|
|
|
|
|
that.connectDevice({
|
|
|
|
|
|
currentTarget: {
|
|
|
|
|
|
dataset: {
|
|
|
|
|
|
device: device
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
2025-06-06 15:17:30 +08:00
|
|
|
|
this.setData({
|
|
|
|
|
|
devices: [...this.data.devices, device]
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
|
console.error('搜索设备失败', err);
|
2026-04-16 13:38:33 +08:00
|
|
|
|
wx.showToast({
|
|
|
|
|
|
title: '搜索失败',
|
|
|
|
|
|
icon: 'error'
|
|
|
|
|
|
});
|
|
|
|
|
|
this.setData({
|
|
|
|
|
|
isSearching: false
|
|
|
|
|
|
});
|
2025-06-06 15:17:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 设置超时自动停止
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
wx.stopBluetoothDevicesDiscovery();
|
2026-04-16 13:38:33 +08:00
|
|
|
|
this.setData({
|
|
|
|
|
|
isSearching: false
|
|
|
|
|
|
});
|
2025-06-06 15:17:30 +08:00
|
|
|
|
console.log('停止搜索');
|
|
|
|
|
|
}, 9000); // 10秒后停止
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 连接设备
|
|
|
|
|
|
connectDevice(e) {
|
2026-04-16 13:38:33 +08:00
|
|
|
|
if (this.data.connectedDeviceId) { //如果已经链接先断开连接
|
|
|
|
|
|
this.disconnectDevice()
|
|
|
|
|
|
}
|
2025-06-06 15:17:30 +08:00
|
|
|
|
const device = e.currentTarget.dataset.device;
|
|
|
|
|
|
console.log('尝试连接设备', device);
|
|
|
|
|
|
wx.showLoading({
|
|
|
|
|
|
title: '连接中...',
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
wx.createBLEConnection({
|
|
|
|
|
|
deviceId: device.deviceId,
|
|
|
|
|
|
success: () => {
|
|
|
|
|
|
console.log('连接成功', device.deviceId);
|
2026-04-16 13:38:33 +08:00
|
|
|
|
console.log('连接成功', device);
|
|
|
|
|
|
wx.showToast({
|
|
|
|
|
|
title: '连接成功',
|
|
|
|
|
|
icon: 'success'
|
|
|
|
|
|
});
|
2025-06-06 15:17:30 +08:00
|
|
|
|
|
|
|
|
|
|
this.setData({
|
|
|
|
|
|
status: '已连接',
|
|
|
|
|
|
connected: true,
|
|
|
|
|
|
connectedDeviceId: device.deviceId
|
|
|
|
|
|
});
|
|
|
|
|
|
wx.setStorageSync('device_id', device.deviceId)
|
|
|
|
|
|
wx.setStorageSync('device_name', device.name)
|
2026-04-16 13:38:33 +08:00
|
|
|
|
if (device.name == 'YD-O1') {
|
2025-06-06 15:17:30 +08:00
|
|
|
|
wx.setStorageSync('uuid', device.advertisServiceUUIDs[0])
|
2026-04-16 13:38:33 +08:00
|
|
|
|
} else {
|
2025-06-06 15:17:30 +08:00
|
|
|
|
// 获取设备的服务
|
|
|
|
|
|
wx.getBLEDeviceServices({
|
|
|
|
|
|
deviceId: device.deviceId,
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
console.log('设备服务', res.services);
|
|
|
|
|
|
wx.setStorageSync('uuid', res.services[0].uuid)
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
|
console.error('获取服务失败', err);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2026-04-16 13:38:33 +08:00
|
|
|
|
if (this.data.params) {
|
|
|
|
|
|
wx.redirectTo({
|
|
|
|
|
|
url: '/subpackage/train/bluetooth/train?' + this.data.params,
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
2025-06-06 15:17:30 +08:00
|
|
|
|
},
|
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
|
console.error('连接失败', err);
|
2026-04-16 13:38:33 +08:00
|
|
|
|
wx.showToast({
|
|
|
|
|
|
title: '连接失败',
|
|
|
|
|
|
icon: 'error'
|
|
|
|
|
|
});
|
2025-06-06 15:17:30 +08:00
|
|
|
|
},
|
2026-04-16 13:38:33 +08:00
|
|
|
|
complete: () => {
|
2025-06-06 15:17:30 +08:00
|
|
|
|
wx.hideLoading()
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 获取设备的服务
|
|
|
|
|
|
getDeviceServices(deviceId) {
|
|
|
|
|
|
wx.getBLEDeviceServices({
|
|
|
|
|
|
deviceId: deviceId,
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
console.log('设备服务', res.services);
|
|
|
|
|
|
this.setData({
|
|
|
|
|
|
deviceServices: res.services
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
wx.getConnectedBluetoothDevices({
|
2026-04-16 13:38:33 +08:00
|
|
|
|
services: [res.services[0].uuid],
|
|
|
|
|
|
success: res => {
|
|
|
|
|
|
console.log('aaaaa333333===>', res)
|
2025-06-06 15:17:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
wx.getConnectedBluetoothDevices({
|
2026-04-16 13:38:33 +08:00
|
|
|
|
services: [res.services[1].uuid],
|
|
|
|
|
|
success: res => {
|
|
|
|
|
|
console.log('aaaaa444444===>', res)
|
2025-06-06 15:17:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// 获取第一个服务的特征值
|
|
|
|
|
|
// if (res.services.length > 0) {
|
|
|
|
|
|
// this.getDeviceCharacteristics(deviceId, res.services[0].uuid);
|
|
|
|
|
|
// }
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
|
console.error('获取服务失败', err);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 获取第一个服务的特征值
|
|
|
|
|
|
getDeviceCharacteristics(deviceId, serviceId) {
|
|
|
|
|
|
wx.getBLEDeviceCharacteristics({
|
|
|
|
|
|
deviceId: deviceId,
|
|
|
|
|
|
serviceId: serviceId,
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
console.log('服务特征值', res.characteristics);
|
|
|
|
|
|
this.setData({
|
|
|
|
|
|
deviceCharacteristics: res.characteristics
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 启动接收数据通知
|
|
|
|
|
|
this.startNotify(deviceId, serviceId);
|
|
|
|
|
|
|
|
|
|
|
|
// 发送启动自由跳绳的命令
|
|
|
|
|
|
this.startFreeJumpRope(deviceId, serviceId);
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
|
console.error('获取特征值失败', err);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 启动接收数据通知
|
|
|
|
|
|
startNotify(deviceId, serviceId) {
|
|
|
|
|
|
const characteristics = this.data.deviceCharacteristics;
|
|
|
|
|
|
characteristics.forEach(characteristic => {
|
|
|
|
|
|
if (characteristic.properties.notify) {
|
|
|
|
|
|
wx.notifyBLECharacteristicValueChange({
|
|
|
|
|
|
deviceId: deviceId,
|
|
|
|
|
|
serviceId: serviceId,
|
|
|
|
|
|
characteristicId: characteristic.uuid,
|
|
|
|
|
|
state: true,
|
|
|
|
|
|
success: () => {
|
|
|
|
|
|
console.log('启动数据通知');
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
|
console.error('启动通知失败', err);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
// 接收数据
|
|
|
|
|
|
wx.onBLECharacteristicValueChange((res) => {
|
|
|
|
|
|
console.log('接收到数据', res.value);
|
|
|
|
|
|
if (res.deviceId === deviceId && res.characteristicId === characteristic.uuid) {
|
|
|
|
|
|
console.log('接收到数据', res.value);
|
|
|
|
|
|
this.handleReceivedData(res.value);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 发送启动自由跳绳命令
|
|
|
|
|
|
startFreeJumpRope(deviceId, serviceId) {
|
2026-04-16 13:38:33 +08:00
|
|
|
|
const command = 3; // 启动自由跳绳的命令
|
|
|
|
|
|
const code = 1;
|
|
|
|
|
|
const parameter = 0; // 启动自由跳绳,参数为0
|
2025-06-06 15:17:30 +08:00
|
|
|
|
// 获取蓝牙设备的特征值(特征值应是你已经连接的蓝牙设备的写入特征值)
|
|
|
|
|
|
const characteristic = this.data.deviceCharacteristics.find(c => c.properties.write);
|
|
|
|
|
|
if (!characteristic) {
|
|
|
|
|
|
console.error('没有可写的特征值');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 构建命令数据
|
2026-04-16 13:38:33 +08:00
|
|
|
|
const commandData = new ArrayBuffer(4);
|
2025-06-06 15:17:30 +08:00
|
|
|
|
const dataView = new DataView(commandData);
|
2026-04-16 13:38:33 +08:00
|
|
|
|
dataView.setUint8(0, 0x03);
|
|
|
|
|
|
dataView.setUint8(1, 0x01);
|
|
|
|
|
|
dataView.setUint8(2, 0x00);
|
|
|
|
|
|
dataView.setUint8(3, 0x00);
|
|
|
|
|
|
|
2025-06-06 15:17:30 +08:00
|
|
|
|
// 发送命令到设备
|
|
|
|
|
|
wx.writeBLECharacteristicValue({
|
|
|
|
|
|
deviceId: deviceId,
|
|
|
|
|
|
serviceId: serviceId,
|
|
|
|
|
|
characteristicId: characteristic.uuid,
|
|
|
|
|
|
value: commandData,
|
|
|
|
|
|
success: () => {
|
|
|
|
|
|
console.log("自由跳绳已启动!");
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (error) => {
|
|
|
|
|
|
console.error("启动自由跳绳失败", error);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
// 处理接收到的数据
|
|
|
|
|
|
handleReceivedData(arrayBuffer) {
|
|
|
|
|
|
// 1. 创建 Int16Array 视图(从 ArrayBuffer 读取)
|
|
|
|
|
|
const int16Array = new Int16Array(arrayBuffer);
|
|
|
|
|
|
// 2. 检查长度是否足够(至少 3 个元素)
|
|
|
|
|
|
if (int16Array.length < 3) {
|
2026-04-16 13:38:33 +08:00
|
|
|
|
console.error("Int16Array length is too short!");
|
|
|
|
|
|
return;
|
2025-06-06 15:17:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
// 3. 读取索引 2 的值
|
|
|
|
|
|
const value = int16Array[2];
|
|
|
|
|
|
// 4. 更新数据
|
2026-04-16 13:38:33 +08:00
|
|
|
|
this.setData({
|
|
|
|
|
|
skipCount: value
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
2025-06-06 15:17:30 +08:00
|
|
|
|
|
|
|
|
|
|
// 4. 断开连接
|
2026-04-16 13:38:33 +08:00
|
|
|
|
disconnectDevice(id) {
|
2025-06-06 15:17:30 +08:00
|
|
|
|
wx.closeBLEConnection({
|
2026-04-16 13:38:33 +08:00
|
|
|
|
deviceId: id || this.data.connectedDeviceId,
|
2025-06-06 15:17:30 +08:00
|
|
|
|
success: () => {
|
|
|
|
|
|
console.log('断开连接');
|
|
|
|
|
|
this.setData({
|
|
|
|
|
|
status: '未连接',
|
|
|
|
|
|
connected: false
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2026-04-16 13:38:33 +08:00
|
|
|
|
});
|