diff --git a/src/pages/mixer/mixer.vue b/src/pages/mixer/mixer.vue index 5b96318..f2a8439 100644 --- a/src/pages/mixer/mixer.vue +++ b/src/pages/mixer/mixer.vue @@ -553,6 +553,9 @@ const showDeviceInfo = () => { const updateRunValue = (channelId, value) => { const channel = channels.value.find(c => c.id === channelId) if (channel) { + console.log(`🏚️ ${channel.name} 设置速度: ${channel.runValue} -> ${value}`) + addDebugLog(`🏚️ ${channel.name} 设置速度: ${value}`, 'info') + // ✅ 不立即修改状态,只发送命令 // 等待蓝牙设备反馈后,通过 onBLECharacteristicValueChange 监听器更新速度 sendBluetoothCommand('setRunValue', channelId, value) @@ -594,6 +597,9 @@ const setTimer = (channelId) => { return } + console.log(`⏰ ${channel.name} 设置定时: ${channel.timerMinutes} -> ${minutes}分钟`) + addDebugLog(`⏰ ${channel.name} 设置定时: ${minutes}分钟`, 'info') + // ✅ 不立即修改状态,只发送命令 // 等待蓝牙设备反馈后,通过 onBLECharacteristicValueChange 监听器更新定时设置 sendBluetoothCommand('setTimer', channelId, minutes) @@ -684,8 +690,18 @@ const batchStart = () => { cancelText: 'Cancel', success: (res) => { if (res.confirm) { - // ✅ 不立即修改状态,只发送批量启动命令 - // 等待蓝牙设备反馈后,通过 onBLECharacteristicValueChange 监听器更新状态 + // 🔧 乐观更新:立即修改所有选中通道的状态 + selectedChannels.value.forEach(channelId => { + const channel = channels.value.find(c => c.id === channelId) + if (channel) { + const oldStatus = channel.status + channel.status = 'running' + console.log(`🚀 批量启动: ${channel.name} ${oldStatus} -> running`) + addDebugLog(`🚀 ${channel.name} 批量启动: ${oldStatus} -> running`, 'info') + } + }) + + // 发送批量启动命令 sendBluetoothCommand('batchStart', null, null) uni.showToast({ @@ -715,8 +731,20 @@ const batchStop = () => { cancelText: 'Cancel', success: (res) => { if (res.confirm) { - // ✅ 不立即修改状态,只发送批量停止命令 - // 等待蓝牙设备反馈后,通过 onBLECharacteristicValueChange 监听器更新状态 + // 🔧 乐观更新:立即修改所有选中通道的状态 + selectedChannels.value.forEach(channelId => { + const channel = channels.value.find(c => c.id === channelId) + if (channel) { + const oldStatus = channel.status + channel.status = 'stopped' + console.log(`🛑 批量停止: ${channel.name} ${oldStatus} -> stopped`) + addDebugLog(`🛑 ${channel.name} 批量停止: ${oldStatus} -> stopped`, 'info') + // 停止定时器 + stopTimer(channelId) + } + }) + + // 发送批量停止命令 sendBluetoothCommand('batchStop', null, null) uni.showToast({ @@ -737,6 +765,9 @@ const startTimer = (channelId) => { // 清除旧定时器 stopTimer(channelId) + console.log(`⏱️ 启动定时器: ${channel.name}, 剩余时间: ${channel.remainingTime}秒`) + addDebugLog(`⏱️ ${channel.name} 启动定时器: ${Math.floor(channel.remainingTime / 60)}分钟`, 'info') + // 创建新定时器(后台倒计时,不显示给用户) timerIntervals.value[channelId] = setInterval(() => { if (channel.remainingTime > 0) { @@ -744,7 +775,11 @@ const startTimer = (channelId) => { // 定时到期 if (channel.remainingTime === 0) { + console.log(`⏰ ${channel.name} 定时到期,自动停止`) + addDebugLog(`⏰ ${channel.name} 定时到期,自动停止`, 'warn') + stopTimer(channelId) + // 🔧 立即更新UI状态为stopped channel.status = 'stopped' // 发送停止命令 @@ -933,119 +968,87 @@ const writeBLEData = (characteristicUUID, buffer) => { // 验证必需参数 if (!deviceId.value) { console.error('❌ 错误:deviceId 为空,无法写入数据') - uni.showModal({ - title: '写入失败', - content: 'deviceId 为空,请重新连接设备', - showCancel: false + addDebugLog('❌ 错误:deviceId 为空', 'error') + uni.showToast({ + title: 'Device ID empty', + icon: 'error', + duration: 2000 }) return } if (!serviceId.value) { console.error('❌ 错误:serviceId 为空,无法写入数据') - uni.showModal({ - title: '写入失败', - content: 'serviceId 为空,请检查蓝牙连接', - showCancel: false + addDebugLog('❌ 错误:serviceId 为空', 'error') + uni.showToast({ + title: 'Service ID empty', + icon: 'error', + duration: 2000 }) return } if (!characteristicUUID) { console.error('❌ 错误:characteristicUUID 为空,无法写入数据') - uni.showModal({ - title: '写入失败', - content: '特征值UUID为空,请检查蓝牙配置', - showCancel: false + addDebugLog('❌ 错误:characteristicUUID 为空', 'error') + uni.showToast({ + title: 'Characteristic UUID empty', + icon: 'error', + duration: 2000 }) return } - // 将 buffer 转换为可读格式用于显示 + // 将 buffer 转换为可读格式用于日志 const dataView = new Uint8Array(buffer) const hexArray = Array.from(dataView).map(b => '0x' + b.toString(16).toUpperCase().padStart(2, '0')) const decArray = Array.from(dataView) - // 构建详细的数据信息 - const dataInfo = `Device ID: ${deviceId.value} -Service ID: ${serviceId.value} -(${serviceId.value?.length} chars) - -Characteristic: ${characteristicUUID} -(${characteristicUUID?.length} chars) - -Data Length: ${buffer.byteLength} bytes - -Hex: -${hexArray.join(' ')} - -Decimal: -${decArray.join(', ')} - -Binary: -${Array.from(dataView).map(b => b.toString(2).padStart(8, '0')).join(' ')}` - - console.log(`📤 准备发送蓝牙数据:\n${dataInfo}`) + console.log(`📤 准备发送蓝牙数据:`) + console.log(` Device ID: ${deviceId.value}`) + console.log(` Service ID: ${serviceId.value}`) + console.log(` Characteristic: ${characteristicUUID}`) + console.log(` Data Length: ${buffer.byteLength} bytes`) + console.log(` Hex: ${hexArray.join(' ')}`) + console.log(` Decimal: ${decArray.join(', ')}`) console.log('==========================================') - // 显示确认对话框 - uni.showModal({ - title: 'Confirm Send BLE Data', - content: dataInfo, - confirmText: 'Send', - cancelText: 'Cancel', + addDebugLog(`📤 发送: ${hexArray.slice(0, 4).join(' ')}... (${buffer.byteLength}bytes)`, 'info') + + // 直接发送,不显示确认对话框 + uni.writeBLECharacteristicValue({ + deviceId: deviceId.value, + serviceId: serviceId.value, + characteristicId: characteristicUUID, + value: buffer, success: (res) => { - if (res.confirm) { - // 用户确认,执行真正的发送 - console.log(`✅ 用户确认发送,开始写入数据到 ${characteristicUUID}`) - - uni.writeBLECharacteristicValue({ - deviceId: deviceId.value, - serviceId: serviceId.value, - characteristicId: characteristicUUID, - value: buffer, - success: (res) => { - console.log(`✅ Successfully wrote to ${characteristicUUID}`) - uni.showToast({ - title: 'Send Success', - icon: 'success', - duration: 1500 - }) - }, - fail: (err) => { - console.error(`❌ Failed to write to ${characteristicUUID}:`, err) - - // 构建错误信息 - const errorInfo = `Device ID: ${deviceId.value} -Service ID: ${serviceId.value} -Characteristic: ${characteristicUUID} - -Error Code: ${err.errCode || 'Unknown'} -Error Message: ${err.errMsg || 'Unknown error'} - -Full Error: -${JSON.stringify(err, null, 2)}` - - console.error('发送失败详情:', errorInfo) - - // 弹出详细错误信息 - uni.showModal({ - title: 'Send Failed', - content: errorInfo, - showCancel: false, - confirmText: 'OK' - }) - } - }) - } else { - // 用户取消 - console.log('❌ 用户取消发送') - uni.showToast({ - title: 'Send Cancelled', - icon: 'none', - duration: 1000 - }) - } + console.log(`✅ Successfully wrote to ${characteristicUUID}`) + addDebugLog(`✅ 发送成功: ${characteristicUUID.substring(0, 8)}...`, 'success') + + // 🔧 发送成功后立即查询一次设备状态 + console.log('🔄 发送成功,延迟300ms后查询设备状态') + addDebugLog('🔄 发送成功,即将查询设备状态', 'info') + + // 延迟300ms给设备一些处理时间,然后查询最新状态 + setTimeout(() => { + queryAllChannelsData() + }, 300) + }, + fail: (err) => { + console.error(`❌ Failed to write to ${characteristicUUID}:`, err) + addDebugLog(`❌ 发送失败: ${err.errMsg}`, 'error') + + // 构建错误信息 + const errorInfo = `Error: ${err.errMsg || 'Unknown error'}\nCode: ${err.errCode || 'Unknown'}\nCharacteristic: ${characteristicUUID}` + + console.error('发送失败详情:', errorInfo) + + // 简化的错误提示 + uni.showToast({ + title: `Send Failed: ${err.errMsg}`, + icon: 'none', + duration: 2000 + }) } }) } @@ -1399,6 +1402,8 @@ const initBluetoothCommunication = () => { channel.runValue = speed // 保存到本地存储 saveChannelData(channel.id) + } else { + console.log(`${channel.name} 速度未变: ${speed}`) } }) } else if (matchCharacteristic(characteristicIds.value.direction)) { @@ -1559,14 +1564,18 @@ const parseMotorTimer = (dataView, type = 'unknown') => { // 明确是剩余时间(0xFF05) channel.remainingTime = minutes * 60 // 转为秒 console.log(`${channel.name} 剩余时间:`, minutes, '分钟') + addDebugLog(` ${channel.name}: 剩余 ${minutes}分钟`, 'info') } else if (type === 'setup') { // 明确是定时设置(0xFF04)- 根据设备反馈更新本地定时设置 if (channel.timerMinutes !== minutes) { console.log(`${channel.name} 定时设置变化: ${channel.timerMinutes} -> ${minutes} 分钟`) + addDebugLog(` ${channel.name}: 定时 ${channel.timerMinutes} -> ${minutes}分钟`, 'warn') channel.timerMinutes = minutes channel.timerValue = minutes > 0 ? `Set ${minutes} min` : 'Not Set' // 保存到本地存储 saveChannelData(channel.id) + } else { + console.log(`${channel.name} 定时未变: ${minutes}分钟`) } } else { // 未知类型,根据当前状态智能判断(兼容旧逻辑) @@ -1574,10 +1583,12 @@ const parseMotorTimer = (dataView, type = 'unknown') => { // 如果正在定时中且已有剩余时间,优先更新剩余时间 channel.remainingTime = minutes * 60 console.log(`${channel.name} 剩余时间(推测):`, minutes, '分钟') + addDebugLog(` ${channel.name}: 剩余 ${minutes}分钟(推测)`, 'info') } else { // 否则当作定时设置 - 根据设备反馈更新本地定时设置 if (channel.timerMinutes !== minutes) { console.log(`${channel.name} 定时设置变化(推测): ${channel.timerMinutes} -> ${minutes} 分钟`) + addDebugLog(` ${channel.name}: 定时 ${minutes}分钟(推测)`, 'warn') channel.timerMinutes = minutes channel.timerValue = minutes > 0 ? `Set ${minutes} min` : 'Not Set' // 保存到本地存储 @@ -1585,6 +1596,8 @@ const parseMotorTimer = (dataView, type = 'unknown') => { } } } + } else { + console.log(`${channel.name} 定时为0,跳过`) } }) } @@ -1593,6 +1606,8 @@ const parseMotorTimer = (dataView, type = 'unknown') => { const parseMotorAllProperties = (dataView) => { // 格式:6字节状态 + 6字节速度 + 6字节方向 + 12字节定时设置 + 12字节剩余时间 + addDebugLog('📦 解析完整属性数据(42字节)', 'success') + channels.value.forEach((channel, index) => { // 电机状态(0-5字节)- 根据设备反馈更新本地状态 const status = dataView[index] @@ -1601,6 +1616,9 @@ const parseMotorAllProperties = (dataView) => { // 状态变化时才处理定时器 if (channel.status !== newStatus) { + console.log(`${channel.name} 状态变化: ${channel.status} -> ${newStatus}`) + addDebugLog(` ${channel.name}: ${channel.status} -> ${newStatus}`, 'warn') + // 如果从非定时状态变为定时状态,启动定时器 if (newStatus === 'timing' && channel.timerMinutes > 0) { channel.remainingTime = channel.timerMinutes * 60 @@ -1618,6 +1636,8 @@ const parseMotorAllProperties = (dataView) => { // 电机速度(6-11字节)- 根据设备反馈更新本地速度 const speed = dataView[6 + index] if (channel.runValue !== speed) { + console.log(`${channel.name} 速度变化: ${channel.runValue} -> ${speed}`) + addDebugLog(` ${channel.name}: 速度 ${channel.runValue} -> ${speed}`, 'info') channel.runValue = speed // 保存到本地存储 saveChannelData(channel.id) @@ -1630,6 +1650,8 @@ const parseMotorAllProperties = (dataView) => { // 定时设置(18-29字节)- 根据设备反馈更新本地定时设置 const timerMinutes = dataView[18 + index * 2] | (dataView[18 + index * 2 + 1] << 8) if (channel.timerMinutes !== timerMinutes) { + console.log(`${channel.name} 定时设置变化: ${channel.timerMinutes} -> ${timerMinutes}分钟`) + addDebugLog(` ${channel.name}: 定时 ${channel.timerMinutes} -> ${timerMinutes}分钟`, 'info') channel.timerMinutes = timerMinutes channel.timerValue = timerMinutes > 0 ? `Set ${timerMinutes} min` : 'Not Set' // 保存到本地存储