2***@qq.com
2***@qq.com
  • 发布:2025-10-25 18:59
  • 更新:2025-10-25 18:59
  • 阅读:8

我写了一个连接蓝牙设备读取传感器数据的APP,但是现在现在读取数据了数据解析不会搞了 ,错了很多错误,新手求教

分类:uni-app

<template>  
  <view class="container">  
    <!-- 蓝牙连接状态(仅文档设备状态) -->  
    <view class="status-bar" :class="statusClass">  
      <text class="status-text">{{ currentStatus }}</text>  
    </view>  

    <!-- 蓝牙基础操作(仅文档关联功能) -->  
    <view class="bt-operation">  
      <button   
        class="btn-scan"   
        :disabled="currentStatus === BT_STATUS.CONNECTING"  
        @click="handleScanConnect"  
      >  
        {{ currentStatus === BT_STATUS.DISCONNECTED ? '扫描连接设备' : '重新扫描' }}  
      </button>  
      <button   
        class="btn-disconnect"   
        v-if="currentStatus === BT_STATUS.CONNECTED"  
        @click="handleDisconnect"  
      >  
        断开连接  
      </button>  
    </view>  

    <!-- 核心功能按钮(基于文档) -->  
    <view class="func-btns" v-if="currentStatus === BT_STATUS.CONNECTED">  
      <button class="func-btn" @click="showSamplingConfig = !showSamplingConfig">  
        {{ showSamplingConfig ? '隐藏参数配置' : '采样参数配置' }}  
      </button>  
      <button class="func-btn" @click="handleInspectionFeature">巡检特征值测量</button>  
      <button class="func-btn" @click="handleWaveform">波形</button>  
      <button class="func-btn" @click="handleRemoteTemperatureMeasurement">远距离测温</button>  
    </view>  

    <!-- 采样参数配置区域 -->  
    <view class="config-area" v-if="showSamplingConfig && currentStatus === BT_STATUS.CONNECTED">  
      <view class="config-title">采样参数配置</view>  

      <!-- 采样系数选择 -->  
      <view class="config-item">  
        <text class="config-label">采样系数:</text>  
        <picker @change="onSamplingFactorChange" :value="samplingFactorIndex" :range="samplingFactors">  
          <view class="picker">  
            {{ samplingFactors[samplingFactorIndex] }}  
          </view>  
        </picker>  
      </view>  

      <!-- 高通滤波系数选择 -->  
      <view class="config-item">  
        <text class="config-label">高通滤波系数:</text>  
        <picker @change="onHighPassFilterChange" :value="highPassFilterIndex" :range="highPassFilters">  
          <view class="picker">  
            {{ highPassFilters[highPassFilterIndex] }}  
          </view>  
        </picker>  
      </view>  

      <!-- 参数选择提示 -->  
      <view class="config-info">  
        <text class="info-text">当前配置:采样率 {{ currentSamplingRate }}Hz,截止频率 {{ currentCutoffFreq }}Hz</text>  
      </view>  
    </view>  

    <!-- 巡检特征值展示区(默认Z轴3个参数,文档READ通道推送) -->  
    <view class="inspection-area" v-if="showInspectionArea">  
      <view class="area-title">巡检特征值(设备采样完成后推送,默认Z轴)</view>  

      <!-- 交互状态提示(响应/采样/推送) -->  
      <view class="interact-status" :class="interactStatusClass">  
        <text>{{ interactStatusText }}</text>  
      </view>  

      <!-- 数据展示表格 -->  
      <view class="feature-table" v-if="inspectionData.length > 0">  
        <view class="table-header">  
          <view class="table-col">参数类型</view>  
          <view class="table-col">数值</view>  
          <view class="table-col">单位</view>  
        </view>  
        <view class="table-body">  
          <view class="table-row" v-for="(item, idx) in inspectionData" :key="idx">  
            <view class="table-col">{{ item.type }}</view>  
            <view class="table-col">  
              {{ item.value !== undefined && item.value !== null ? item.value.toFixed(4) :   
                 (item.zValue !== null && item.zValue !== undefined && !isNaN(item.zValue) ? item.zValue.toFixed(4) : '-') }}  
            </view>  
            <view class="table-col">{{ item.unit }}</view>  
          </view>  
        </view>  
      </view>  

      <!-- 原始数据调试区域 -->  
      <view class="debug-area" v-if="rawData.length > 0">  
        <view class="debug-title">原始数据(调试用)</view>  
        <text class="debug-data">{{ rawDataText }}</text>  
      </view>  
    </view>  
  </view>  
</template>  

<script>  
// 仅导入《蓝牙服务配置.docx》的参数常量,无其他依赖  
import { ref, computed, onUnmounted } from 'vue';  
import { BT_CONFIG, BT_STATUS } from '@/common/bt-config.js';  

export default {  
  setup() {  
    // 1. 基础状态(仅关联《蓝牙服务配置.docx》设备)  
    const currentStatus = ref(BT_STATUS.DISCONNECTED);  
    const deviceList = ref([]);  
    const connectedDeviceId = ref('');  
    const showInspectionArea = ref(false); // 数据展示区开关  
    const showSamplingConfig = ref(false); // 采样参数配置区开关  

    // 采样参数配置  
    const samplingFactors = ref([2, 3, 4, 5, 6, 8, 10, 15, 18, 20, 26, 30, 35, 40, 50, 60, 80, 100, 101, 255]);  
    const highPassFilters = ref([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 15, 20, 25, 50, 77, 102, 128, 154, 179, 205, 230, 255]);  
    const samplingFactorIndex = ref(0);  
    const highPassFilterIndex = ref(3); // 默认值为4  

    // 采样参数映射表  
    const samplingConfigMap = {  
      2: { rate: 13333, maxPoints: 16384 },  
      3: { rate: 8888.67, maxPoints: 16384 },  
      4: { rate: 6666.5, maxPoints: 16384 },  
      5: { rate: 5333.2, maxPoints: 16384 },  
      6: { rate: 4444.33, maxPoints: 16384 },  
      8: { rate: 3333.25, maxPoints: 16384 },  
      10: { rate: 2666.6, maxPoints: 16384 },  
      15: { rate: 1777.73, maxPoints: 16384 },  
      18: { rate: 1481.44, maxPoints: 16384 },  
      20: { rate: 1333.3, maxPoints: 16384 },  
      26: { rate: 1025.62, maxPoints: 8192 },  
      30: { rate: 888.87, maxPoints: 8192 },  
      35: { rate: 761.89, maxPoints: 8192 },  
      40: { rate: 666.65, maxPoints: 8192 },  
      50: { rate: 533.32, maxPoints: 8192 },  
      60: { rate: 444.43, maxPoints: 4096 },  
      80: { rate: 333.33, maxPoints: 4096 },  
      100: { rate: 266.66, maxPoints: 4096 },  
      101: { rate: 264.09, maxPoints: 4096 },  
      255: { rate: 104.57, maxPoints: 4096 }  
    };  

    // 高通滤波系数映射表  
    const highPassFilterMap = {  
      1: 2.604,  
      2: 5.208,  
      3: 7.812,  
      4: 10.416,  
      5: 13.021,  
      6: 15.625,  
      7: 18.229,  
      8: 20.833,  
      9: 23.437,  
      10: 26.041,  
      12: 31.249,  
      15: 39.062,  
      20: 52.082,  
      25: 65.103,  
      50: 130.205,  
      77: 200.516,  
      102: 265.618,  
      128: 333.325,  
      154: 401.032,  
      179: 466.134,  
      205: 533.841,  
      230: 598.943,  
      255: 664.046  
    };  

    // 2. 设备交互状态(匹配“请求→响应→采样→推送”逻辑)  
    const interactStatusText = ref(''); // 交互状态提示(如“等待设备响应...”)  
    const interactStatusType = ref(''); // 状态类型:waiting/success/error  

    // 3. 测量数据存储  
    const inspectionData = ref([]);  
    // 存储当前请求序号(匹配设备响应/推送的序号,确保数据对应)  
    let currentReqSeq = 0;  
    // 存储当前测量类型  
    let currentMeasurementType = '';  
    // 存储原始数据(用于调试)  
    const rawData = ref([]);  
    // 存储实际连接的服务和特征值信息  
    let connectedServiceInfo = {  
      serviceId: '',  
      writeCharId: '',  
      readCharId: ''  
    };  
    // 原始数据文本显示  
    const rawDataText = computed(() => {  
      return rawData.value.length > 0 ?   
        Array.from(rawData.value).map(b => '0x' + b.toString(16).padStart(2, '0').toUpperCase()).join(', ') :   
        '';  
    });  

    // 当前采样率计算  
    const currentSamplingRate = computed(() => {  
      const factor = samplingFactors.value[samplingFactorIndex.value];  
      return samplingConfigMap[factor]?.rate || 13333;  
    });  

    // 当前截止频率计算  
    const currentCutoffFreq = computed(() => {  
      const filter = highPassFilters.value[highPassFilterIndex.value];  
      return highPassFilterMap[filter] || 10.416;  
    });  

    // 采样系数变更处理  
    const onSamplingFactorChange = (e) => {  
      samplingFactorIndex.value = e.detail.value;  
      uni.showToast({   
        title: `已设置采样系数: ${samplingFactors.value[samplingFactorIndex.value]}`,   
        icon: 'none'   
      });  
    };  

    // 高通滤波系数变更处理  
    const onHighPassFilterChange = (e) => {  
      highPassFilterIndex.value = e.detail.value;  
      uni.showToast({   
        title: `已设置高通滤波系数: ${highPassFilters.value[highPassFilterIndex.value]}`,   
        icon: 'none'   
      });  
    };  

    // 状态样式(仅UI区分)  
    const statusClass = computed(() => ({  
      'status-bar': true,  
      'status-disconnected': currentStatus.value === BT_STATUS.DISCONNECTED,  
      'status-connecting': currentStatus.value === BT_STATUS.CONNECTING,  
      'status-connected': currentStatus.value === BT_STATUS.CONNECTED  
    }));  

    // 交互状态样式(提示响应/采样/推送状态)  
    const interactStatusClass = computed(() => ({  
      'interact-status': true,  
      'status-waiting': interactStatusType.value === 'waiting',  
      'status-success': interactStatusType.value === 'success',  
      'status-error': interactStatusType.value === 'error',  
      'status-warning': interactStatusType.value === 'warning'  
    }));  

    // ---------------------- 基础蓝牙逻辑(严格文档参数) ----------------------  
    /**  
     * 扫描设备(仅匹配《蓝牙服务配置.docx》服务ID:0000fff0的设备)  
     */  
    const handleScanConnect = async () => {  
      if (currentStatus.value === BT_STATUS.CONNECTING) return;  
      try {  
        // 打开蓝牙适配器(文档功能前置操作)  
        await uni.openBluetoothAdapter({  
          fail: (err) => {  
            uni.showToast({ title: err.errCode === 10001 ? '请开启蓝牙' : `初始化失败:${err.errMsg}`, icon: 'none' });  
            throw err;  
          }  
        });  

        // 扫描设备(过滤无效设备)  
        deviceList.value = [];  
        currentStatus.value = BT_STATUS.CONNECTING;  
        await uni.startBluetoothDevicesDiscovery({ allowDuplicatesKey: false });  

        // 监听扫描结果(仅保留有效设备)  
        uni.onBluetoothDeviceFound((res) => {  
          res.devices.forEach(device => {  
            if (device.deviceId && (device.name || device.localName)) {  
              !deviceList.value.some(item => item.deviceId === device.deviceId) && deviceList.value.push({  
                deviceId: device.deviceId,  
                name: device.name || device.localName  
              });  
            }  
          });  
        });  

        // 3秒后弹窗选择文档关联设备  
        setTimeout(async () => {  
          await uni.stopBluetoothDevicesDiscovery();  
          currentStatus.value = BT_STATUS.DISCONNECTED;  
          if (deviceList.value.length === 0) {  
            uni.showToast({ title: '未扫描到设备', icon: 'none' });  
            return;  
          }  

          // 原生弹窗选择设备(仅提示文档服务ID)  
          uni.showActionSheet({  
            title: `选择设备`,  
            itemList: deviceList.value.map(d => d.name),  
            success: (res) => selectDevice(deviceList.value[res.tapIndex])  
          });  
        }, 2000);  
      } catch (err) {  
        currentStatus.value = BT_STATUS.DISCONNECTED;  
      }  
    };  

    /**  
     * 连接设备(文档MTU=131,稳定连接后设置)  
     */  
    const selectDevice = async (device) => {  
      if (!device.deviceId) return;  
      currentStatus.value = BT_STATUS.CONNECTING;  
      try {  
        // 发起连接(仅《蓝牙服务配置.docx》关联设备)  
        await uni.createBLEConnection({  
          deviceId: device.deviceId,  
          fail: (err) => {  
            uni.showToast({ title: `连接失败:${err.errMsg}`, icon: 'none' });  
            currentStatus.value = BT_STATUS.DISCONNECTED;  
            throw err;  
          }  
        });  
const bleAdapter = {  
  // 存储当前注册的监听器  
  listeners: {},  

  // 注册特征值变化监听器  
  onCharacteristicValueChange(callback) {  
    // 保存监听器引用  
    this.listeners.valueChange = callback;  
    // 调用原生API  
    uni.onBLECharacteristicValueChange(callback);  
  },  

  // 移除特征值变化监听器  
  offCharacteristicValueChange() {  
    // 优先使用原生方法  
    if (typeof uni.offBLECharacteristicValueChange === 'function') {  
      uni.offBLECharacteristicValueChange();  
    } else {  
      // 不支持时,通过覆盖监听器实现"移除"效果  
      if (this.listeners.valueChange) {  
        uni.onBLECharacteristicValueChange(() => {}); // 覆盖为空函数  
        this.listeners.valueChange = null; // 清空引用  
      }  
    }  
  }  
};  

// 在代码中使用封装后的方法  
// 注册监听器时  
bleAdapter.onCharacteristicValueChange((res) => {  
  parseDeviceData(res.value);  
});  

// 需要移除监听器时  
bleAdapter.offCharacteristicValueChange();  
        // 监听连接状态,稳定后设置MTU(文档最大值131)  
        const connectionListener = (res) => {  
          if (res.deviceId !== device.deviceId) return;  
          if (res.connected) {  
            connectedDeviceId.value = device.deviceId;  
            currentStatus.value = BT_STATUS.CONNECTED;  
            uni.showToast({ title: `已连接:${device.name}` });  

            // 设置MTU=131(严格遵循《蓝牙服务配置.docx》)  
            uni.setBLEMTU({  
              deviceId: device.deviceId,  
              mtu: BT_CONFIG.MAX_MTU,  
              success: () => console.log(`MTU=${BT_CONFIG.MAX_MTU}(文档要求)`),  
              fail: (err) => uni.showToast({ title: `MTU设置失败:${err.errMsg}`, icon: 'none' })  
            });  

            // 启用文档READ通道通知(接收设备响应/推送,ID:0000fff1)  
            enableReadNotify(device.deviceId);  
            uni.offBLEConnectionStateChange(connectionListener);  
          } else {  
            uni.showToast({ title: '设备断开连接', icon: 'none' });  
            currentStatus.value = BT_STATUS.DISCONNECTED;  
            uni.offBLEConnectionStateChange(connectionListener);  
          }  
        };  
        uni.onBLEConnectionStateChange(connectionListener);  
      } catch (err) {  
        currentStatus.value = BT_STATUS.DISCONNECTED;  
      }  
    };  

    /**  
     * 启用READ通道通知(文档READ_ID=0000fff2,接收响应/推送)  
     */  
    const enableReadNotify = async (deviceId) => {  
      try {  
        // 获取设备所有服务并显示(调试信息)  
        const serviceRes = await uni.getBLEDeviceServices({ deviceId });  
        console.log('设备支持的所有服务ID:', serviceRes.services.map(s => s.uuid));  

        // 显示所有服务ID的弹窗提示(调试用)  
        uni.showModal({  
          title: '设备服务信息',  
          content: `发现 ${serviceRes.services.length} 个服务:\n${serviceRes.services.map(s => s.uuid).join('\n')}\n\n正在尝试连接文档服务...`,  
          showCancel: false  
        });  

        // 重置连接信息  
        connectedServiceInfo = {  
          serviceId: '',  
          writeCharId: '',  
          readCharId: ''  
        };  

        // 匹配《蓝牙服务配置.docx》服务ID:0000fff0  
        // 处理SERVICE_ID可能是数组的情况  
        let targetService = null;  
        if (Array.isArray(BT_CONFIG.SERVICE_ID)) {  
          // 如果是数组,查找数组中任一匹配的服务ID  
          for (const serviceId of BT_CONFIG.SERVICE_ID) {  
            targetService = serviceRes.services.find(  
              s => s.uuid.toLowerCase() === serviceId.toLowerCase()  
            );  
            if (targetService) break;  
          }  
        } else {  
          // 如果是字符串,直接查找匹配  
          targetService = serviceRes.services.find(  
            s => s.uuid.toLowerCase() === BT_CONFIG.SERVICE_ID.toLowerCase()  
          );  
        }  

        if (!targetService) {  
          // 不抛出错误,而是记录警告并尝试使用第一个可用服务  
          console.warn(`未找到文档服务ID:${BT_CONFIG.SERVICE_ID},尝试使用第一个可用服务`);  

          if (serviceRes.services.length > 0) {  
            // 使用第一个可用服务  
            const fallbackService = serviceRes.services[0];  
            console.log(`使用备选服务ID: ${fallbackService.uuid}`);  

            // 尝试获取该服务的所有特征值  
            const characteristics = await uni.getBLEDeviceCharacteristics({  
              deviceId,  
              serviceId: fallbackService.uuid  
            });  

            // 详细记录所有特征值及其属性  
            const charDetails = characteristics.characteristics.map(c => ({  
              uuid: c.uuid,  
              properties: c.properties  
            }));  
            console.log('备选服务的特征值详情:', charDetails);  

            // 查找可读和可写特征值  
            const readChar = findSuitableReadCharacteristic(characteristics.characteristics);  
            const writeChar = findSuitableWriteCharacteristic(characteristics.characteristics);  

            // 先启用读取特征值  
            if (readChar) {  
              await enableCharNotify(deviceId, fallbackService.uuid, readChar.uuid);  
              connectedServiceInfo.serviceId = fallbackService.uuid;  
              connectedServiceInfo.readCharId = readChar.uuid;  
              console.log(`已设置读取特征值: ${readChar.uuid}`);  
            }  

            // 设置写入特征值  
            if (writeChar) {  
              connectedServiceInfo.writeCharId = writeChar.uuid;  
              console.log(`已设置写入特征值: ${writeChar.uuid}`);  
            }  

            // 显示特征值信息  
            showCharacteristicInfo(fallbackService.uuid, charDetails);  
            return;  
          }  

          // 如果没有可用服务或特征值,显示警告但保持连接  
          uni.showToast({   
            title: `未找到文档服务ID,但设备已连接`,   
            icon: 'none',  
            duration: 3000   
          });  
        } else {  
          // 找到文档服务,获取所有特征值  
          const characteristics = await uni.getBLEDeviceCharacteristics({  
            deviceId,  
            serviceId: targetService.uuid  
          });  

          // 详细记录所有特征值及其属性  
          const charDetails = characteristics.characteristics.map(c => ({  
            uuid: c.uuid,  
            properties: c.properties  
          }));  
          console.log('文档服务的特征值详情:', charDetails);  

          // 查找可读和可写特征值  
          const readChar = findSuitableReadCharacteristic(characteristics.characteristics);  
          const writeChar = findSuitableWriteCharacteristic(characteristics.characteristics);  

          // 先启用读取特征值  
          if (readChar) {  
            await enableCharNotify(deviceId, targetService.uuid, readChar.uuid);  
            connectedServiceInfo.serviceId = targetService.uuid;  
            connectedServiceInfo.readCharId = readChar.uuid;  
            console.log(`已设置读取特征值: ${readChar.uuid}`);  
          }  

          // 设置写入特征值  
          if (writeChar) {  
            connectedServiceInfo.writeCharId = writeChar.uuid;  
            console.log(`已设置写入特征值: ${writeChar.uuid}`);  
          }  

          // 显示特征值信息  
          showCharacteristicInfo(targetService.uuid, charDetails);  
        }  
      } catch (err) {  
        console.error('启用READ通道失败:', err);  

        // 显示更详细的错误信息  
        const errorMsg = `启用READ通道失败:\n${err.message || '未知错误'}\n\n设备可能不支持通知功能,已设置基本数据监听。`;  

        // 记录详细错误  
        console.error('蓝牙通知错误详情:', {  
          errType: err.name,  
          errMsg: err.message,  
          error: err  
        });  

        // 显示错误信息但不中断连接  
        uni.showModal({  
          title: '蓝牙数据接收配置',  
          content: errorMsg,  
          showCancel: false,  
          success: () => {  
            // 即使失败也继续,用户可以尝试发送命令  
            console.log('用户已确认错误信息,继续操作');  
          }  
        });  
      }  
    };  

    /**  
     * 启用特定特征值的数据接收(通知或读取)  
     */  
    const enableCharNotify = async (deviceId, serviceId, characteristicId) => {  
      try {  
        // 先尝试获取特征值的属性信息  
        const charInfo = await uni.getBLEDeviceCharacteristics({  
          deviceId,  
          serviceId,  
          characteristicId  
        });  

        console.log(`特征值信息:`, charInfo.characteristics[0]);  

        // 尝试多种数据接收方式  
        try {  
          // 方式1: 尝试启用通知(已在enableNotification中处理了描述符不支持的情况)  
          await enableNotification(deviceId, serviceId, characteristicId);  
          return;  
        } catch (notifyErr) {  
          console.warn('启用通知失败,尝试其他方式:', notifyErr);  

          // 方式2: 如果特征值支持读取,设置周期性读取  
          if (charInfo.characteristics[0].properties.read) {  
            console.log('特征值支持读取,设置周期性读取');  
            startPeriodicReading(deviceId, serviceId, characteristicId, charInfo.characteristics[0].properties);  
            return;  
          } else {  
            // 方式3: 注册数据变化监听器(即使通知失败,某些设备仍可能推送数据)  
            console.log('注册数据变化监听器作为备选方案');  
            registerDataChangeListener(deviceId, serviceId, characteristicId);  
          }  
        }  

        // 显示成功消息  
        uni.showToast({   
          title: `已设置数据接收通道`,   
          icon: 'success',  
          duration: 2000   
        });  
      } catch (err) {  
        console.error('启用数据接收失败:', err);  
        // 不抛出错误,而是设置基本的监听器  
        registerDataChangeListener(deviceId, serviceId, characteristicId);  
        throw new Error(`启用通知失败:${err.errMsg}`);  
      }  
    };  

    /**  
     * 尝试启用通知(方式1)  
     */  
    const enableNotification = async (deviceId, serviceId, characteristicId) => {  
      try {  
        // 当前环境不支持获取描述符,直接尝试启用通知  
        // 跳过描述符查询,避免环境兼容性问题  
        console.log('当前环境不支持获取描述符,直接尝试启用通知');  

        // 尝试启用通知  
        await uni.notifyBLECharacteristicValueChange({  
          deviceId,  
          serviceId,  
          characteristicId,  
          state: true  
        });  

        console.log(`已启用通知 - 服务:${serviceId},特征值:${characteristicId}`);  

        // 注册数据变化监听器  
        registerDataChangeListener(deviceId, serviceId, characteristicId);  
      } catch (err) {  
        console.error('启用通知失败:', err);  
        throw err;  
      }  
    };  

    /**  
     * 设置周期性读取(方式2)  
     */  
    let readTimer = null;  
    let isPeriodicReadingActive = false;  

    const startPeriodicReading = (deviceId, serviceId, characteristicId, charProperties = null) => {  
      // 清除之前的定时器  
      if (readTimer) {  
        clearInterval(readTimer);  
      }  

      console.log(`开始周期性读取 - 服务:${serviceId},特征值:${characteristicId}`);  

      // 检查是否需要获取特征值属性信息  
      const checkAndStartReading = async () => {  
        let actualProperties = charProperties;  

        // 如果没有提供属性信息,尝试获取  
        if (!actualProperties) {  
          try {  
            const charInfo = await uni.getBLEDeviceCharacteristics({  
              deviceId,  
              serviceId,  
              characteristicId  
            });  
            if (charInfo.characteristics && charInfo.characteristics.length > 0) {  
              actualProperties = charInfo.characteristics[0].properties;  
              console.log('获取到特征值属性:', actualProperties);  
            }  
          } catch (err) {  
            console.warn('获取特征值属性失败,将尝试其他方式:', err);  
          }  
        }  

        // 如果确认不支持读取操作,切换到通知模式  
        if (actualProperties && !actualProperties.read) {  
          console.log('特征值不支持读取操作,尝试切换到通知模式');  

          // 尝试直接启用通知(跳过描述符检查)  
          try {  
            await uni.notifyBLECharacteristicValueChange({  
              deviceId,  
              serviceId,  
              characteristicId,  
              state: true  
            });  
            console.log(`成功启用通知 - 服务:${serviceId},特征值:${characteristicId}`);  
            isPeriodicReadingActive = false;  

            // 注册数据变化监听器  
            registerDataChangeListener(deviceId, serviceId, characteristicId);  

            // 更新状态提示  
            if (interactStatusType.value === '' || interactStatusType.value === 'waiting') {  
              interactStatusType.value = 'info';  
              interactStatusText.value = '已启用数据通知模式';  
            }  
            return;  
          } catch (notifyErr) {  
            console.warn('启用通知也失败,将采用宽松的数据接收策略:', notifyErr);  
          }  
        }  

        // 如果支持读取或无法确认属性,继续使用周期性读取作为备选  
        isPeriodicReadingActive = true;  

        // 仅在等待状态时更新UI,避免覆盖重要状态提示  
        if (interactStatusType.value === '' || interactStatusType.value === 'waiting') {  
          interactStatusType.value = 'info';  
          interactStatusText.value = '已启用数据接收模式';  
        }  

        // 设置数据变化监听器作为主要数据接收方式  
        registerDataChangeListener(deviceId, serviceId, characteristicId);  

        // 设置定时器,减少读取频率,避免重复失败  
        readTimer = setInterval(() => {  
          if (isPeriodicReadingActive && currentStatus.value === BT_STATUS.CONNECTED) {  
            // 只有在非success状态或数据为空时才尝试读取  
            if (interactStatusType.value !== 'success' || inspectionData.value.length === 0) {  
              readCharacteristicValue(deviceId, serviceId, characteristicId);  
            }  
          }  
        }, 8000); // 增加间隔时间,减少失败尝试  
      };  

      // 启动异步检查和读取  
      checkAndStartReading();  
    };  

    const stopPeriodicReading = () => {  
      if (readTimer) {  
        clearInterval(readTimer);  
        readTimer = null;  
        isPeriodicReadingActive = false;  
        console.log('已停止周期性读取');  
      }  
    };  

    /**  
     * 读取特征值  
     */  
    const readCharacteristicValue = async (deviceId, serviceId, characteristicId) => {  
        try {  
          // 添加详细的读取特征值信息日志  
          console.log(`尝试读取特征值: 设备=${deviceId}, 服务=${serviceId}, 特征值=${characteristicId}`);  

          // 避免在交互状态为success或error时打印过多日志  
          const logLevel = ['success', 'error'].includes(interactStatusType.value) ? 'debug' : 'info';  

          // 优化状态提示,避免一直显示"尝试主动读取特征值"  
          if (interactStatusType.value === '' || interactStatusType.value === 'waiting') {  
            interactStatusType.value = 'waiting';  
            interactStatusText.value = '正在读取设备数据...';  
          }  

          // 先检查特征值是否支持读取  
          const charRes = await uni.getBLEDeviceCharacteristics({  
            deviceId,  
            serviceId,  
            characteristicId  
          });  

          const char = charRes.characteristics[0];  
          if (!char) {  
            console.error('未找到指定的特征值');  
            // 更新状态提示  
            if (inspectionData.value.length === 0 && interactStatusType.value !== 'success') {  
              interactStatusType.value = 'warning';  
              interactStatusText.value = '特征值未找到,请检查通道设置';  
            }  
            return;  
          }  

          if (!char.properties.read) {  
            console.warn(`特征值 ${characteristicId} 不支持读取操作,属性:`, char.properties);  

            // 如果支持通知,提示用户  
            if (char.properties.notify) {  
              console.log('该特征值支持通知,尝试启用通知模式');  
              if (inspectionData.value.length === 0 && interactStatusType.value !== 'success') {  
                interactStatusType.value = 'warning';  
                interactStatusText.value = '特征值不支持读取,请尝试启用通知模式';  
              }  
            }  

            return;  
          }  

          console.log(`特征值支持读取操作: ${characteristicId}`);  

          // 执行读取操作  
          await uni.readBLECharacteristicValue({  
            deviceId,  
            serviceId,  
            characteristicId  
          });  

          // 读取命令发送成功后,记录日志  
          if (logLevel === 'info' && interactStatusType.value !== 'success') {  
            console.log('数据读取命令已发送,等待响应');  
          }  
        } catch (err) {  
          console.error('读取特征值失败:', err);  
          console.error('错误详情:', { errCode: err.errCode, errMsg: err.errMsg, deviceId, serviceId, characteristicId });  

          // 更详细的错误状态处理  
          if (inspectionData.value.length === 0 && interactStatusType.value !== 'success') {  
            interactStatusType.value = 'warning';  

            // 根据错误码提供更具体的提示  
            if (err.errCode === 10004) {  
              interactStatusText.value = '设备未连接,请重新连接';  
            } else if (err.errCode === 10009) {  
              interactStatusText.value = '特征值不存在,请检查通道设置';  
            } else {  
              interactStatusText.value = '数据读取中,请稍候...';  
            }  
          }  

          // 如果连接已断开,停止周期性读取  
          if (err.errCode === 10018 || err.errCode === 10004) {  
            stopPeriodicReading();  
            return;  
          }  

          // 3秒后尝试重新读取  
          setTimeout(() => {  
            if (currentStatus.value === BT_STATUS.CONNECTED && isPeriodicReadingActive) {  
              readCharacteristicValue(deviceId, serviceId, characteristicId);  
            }  
          }, 3000);  
        }  
      };  

    /**  
     * 注册数据变化监听器(通用)  
     */  
    const registerDataChangeListener = (deviceId, serviceId, characteristicId) => {  
      // 先移除之前可能存在的监听器  
      uni.offBLECharacteristicValueChange();  

      // 注册新的监听器  
      uni.onBLECharacteristicValueChange((res) => {  
        console.log('收到特征值变化通知:', {  
          serviceId: res.serviceId,  
          characteristicId: res.characteristicId,  
          expectedCharId: characteristicId  
        });  

        // 处理所有收到的数据,不严格匹配特征值ID,提高兼容性  
        if (res.value) {  
          parseDeviceData(res.value);  
        }  
      });  
    };  

    /**  
     * 断开连接(释放文档设备资源)  
     */  
    const handleDisconnect = async () => {  
      if (currentStatus.value !== BT_STATUS.CONNECTED || !connectedDeviceId.value) return;  
      try {  
        await uni.closeBLEConnection({ deviceId: connectedDeviceId.value });  
        currentStatus.value = BT_STATUS.DISCONNECTED;  
        connectedDeviceId.value = '';  
        showInspectionArea.value = false;  
        inspectionData.value = [];  
        uni.showToast({ title: '已断开连接' });  
      } catch (err) {  
        uni.showToast({ title: `断开失败:${err.errMsg}`, icon: 'none' });  
      }  
    };  

    // ---------------------- 核心:巡检特征值逻辑(匹配设备交互流程) ----------------------  
    /**  
     * 查找合适的读取特征值  
     */  
    const findSuitableReadCharacteristic = (characteristics) => {  
      // 优先查找包含fff1的特征值(根据用户提供的信息,fff1是读特征值)  
      const fff1Char = characteristics.find(  
        c => c.uuid.toLowerCase().includes('fff1') && (c.properties.read || c.properties.notify)  
      );  
      if (fff1Char) {  
        console.log('找到fff1读取特征值:', fff1Char.uuid);  
        return fff1Char;  
      }  

      // 然后查找文档中指定的READ特征值(支持完整UUID格式)  
      const docReadChar = characteristics.find(  
        c => c.uuid.toLowerCase().includes(BT_CONFIG.CHARACTERISTIC_ID.READ.toLowerCase().split('-')[0])  
      );  
      if (docReadChar) return docReadChar;  

      // 查找支持通知或读取的特征值  
      const notifyChar = characteristics.find(c => c.properties.notify);  
      if (notifyChar) return notifyChar;  

      // 查找支持读取的特征值  
      const readChar = characteristics.find(c => c.properties.read);  
      if (readChar) return readChar;  

      // 返回第一个特征值作为备选  
      return characteristics[0] || null;  
    };  

    /**  
     * 为指定服务查找合适的读取特征值  
     */  
    const findSuitableReadCharacteristicForService = async (serviceId) => {  
      try {  
        console.log(`尝试为服务 ${serviceId} 查找读取特征值`);  

        // 获取服务的所有特征值  
        const charRes = await uni.getBLEDeviceCharacteristics({  
          deviceId: connectedDeviceId.value,  
          serviceId  
        });  

        // 查找合适的读取特征值  
        const readChar = findSuitableReadCharacteristic(charRes.characteristics);  

        if (readChar) {  
          console.log(`找到读取特征值: ${readChar.uuid}`);  
          connectedServiceInfo.readCharId = readChar.uuid;  

          // 如果支持通知,尝试启用通知  
          if (readChar.properties.notify) {  
            console.log('尝试启用通知模式');  
            await uni.notifyBLECharacteristicValueChange({  
              deviceId: connectedDeviceId.value,  
              serviceId,  
              characteristicId: readChar.uuid,  
              state: true,  
              success: () => {  
                console.log('通知模式已启用');  
                interactStatusType.value = 'info';  
                interactStatusText.value = '已启用通知模式,等待数据推送';  
              },  
              fail: (err) => {  
                console.warn('启用通知模式失败:', err);  
                // 继续使用读取模式  
                readCharacteristicValue(connectedDeviceId.value, serviceId, readChar.uuid);  
              }  
            });  
          } else {  
            // 如果不支持通知,尝试读取  
            readCharacteristicValue(connectedDeviceId.value, serviceId, readChar.uuid);  
          }  
        } else {  
          console.warn('未找到合适的读取特征值');  
          interactStatusType.value = 'warning';  
          interactStatusText.value = '未找到可用的读取特征值';  
        }  
      } catch (err) {  
        console.error('查找读取特征值失败:', err);  
      }  
    };  

    /**  
     * 查找合适的写入特征值  
     */  
    const findSuitableWriteCharacteristic = (characteristics) => {  
      // 优先查找包含fff2的特征值(根据用户提供的信息,fff2是写特征值)  
      const fff2Char = characteristics.find(  
        c => c.uuid.toLowerCase().includes('fff2') && (c.properties.write || c.properties.writeNoResponse)  
      );  
      if (fff2Char) {  
        console.log('找到fff2写入特征值:', fff2Char.uuid);  
        return fff2Char;  
      }  

      // 然后查找文档中指定的WRITE特征值(支持完整UUID格式)  
      const docWriteChar = characteristics.find(  
        c => c.uuid.toLowerCase().includes(BT_CONFIG.CHARACTERISTIC_ID.WRITE.toLowerCase().split('-')[0])  
      );  
      if (docWriteChar) return docWriteChar;  

      // 查找支持写入的特征值  
      const writeChar = characteristics.find(c => c.properties.write);  
      if (writeChar) return writeChar;  

      // 查找支持无响应写入的特征值  
      const writeNoRespChar = characteristics.find(c => c.properties.writeNoResponse);  
      if (writeNoRespChar) return writeNoRespChar;  

      // 返回第一个特征值作为备选  
      return characteristics[0] || null;  
    };  

    /**  
     * 显示特征值信息  
     */  
    const showCharacteristicInfo = (serviceId, characteristics) => {  
      const charInfo = characteristics.map(c => {  
        const props = [];  
        if (c.properties.read) props.push('读');  
        if (c.properties.write) props.push('写');  
        if (c.properties.notify) props.push('通知');  
        if (c.properties.writeNoResponse) props.push('无响应写');  
        return `${c.uuid} [${props.join(', ')}]`;  
      }).join('\n');  

      uni.showModal({  
        title: '特征值信息',  
        content: `服务: ${serviceId}\n\n特征值详情:\n${charInfo}\n\n已选择:\n读: ${connectedServiceInfo.readCharId}\n写: ${connectedServiceInfo.writeCharId}`,  
        showCancel: false  
      });  
    };  

    /**  
     * 发送测量指令到设备  
     * @param {number} funcCode - 功能码  
     * @param {string} requestText - 请求提示文本  
     * @param {string} measurementType - 测量类型标识  
     */  
    // 存储超时定时器ID  
    let responseTimeoutId = null;  

    // 清除超时定时器的函数  
    const clearResponseTimeout = () => {  
      if (responseTimeoutId) {  
        clearTimeout(responseTimeoutId);  
        responseTimeoutId = null;  
      }  
    };  

    // 设置响应超时处理  
    const setResponseTimeout = () => {  
      // 清除之前可能存在的定时器  
      clearResponseTimeout();  

      // 设置10秒超时(增加超时时间)  
      responseTimeoutId = setTimeout(() => {  
        interactStatusType.value = 'warning';  
        interactStatusText.value = '设备未响应,请检查连接或重试';  
        console.log('设备响应超时,请求序号:', currentReqSeq, '测量类型:', currentMeasurementType);  
        console.log('当前使用的服务和特征值:', connectedServiceInfo);  
        responseTimeoutId = null;  

        // 主动读取一次特征值,看是否能获取数据  
        if (connectedServiceInfo.serviceId && connectedServiceInfo.readCharId) {  
          console.log('超时后尝试主动读取特征值');  
          readCharacteristicValue(connectedDeviceId.value, connectedServiceInfo.serviceId, connectedServiceInfo.readCharId);  
        }  
      }, 10000);  
    };  

    const sendMeasurementCommand = async (funcCode, requestText, measurementType) => {  
      console.log("===== 开始发送测量指令 =====");  
      console.log("指令参数:", {  
        funcCode: '0x' + funcCode.toString(16).toUpperCase(),  
        requestText,  
        measurementType,  
        currentStatus: currentStatus.value,  
        deviceConnected: currentStatus.value === BT_STATUS.CONNECTED  
      });  

      if (currentStatus.value !== BT_STATUS.CONNECTED) {  
        console.error("发送失败: 设备未连接");  
        uni.showToast({ title: '请先连接设备', icon: 'none' });  
        return;  
      }  

      // 初始化交互状态+展示区  
      showInspectionArea.value = true;  
      interactStatusType.value = 'waiting';  
      interactStatusText.value = requestText;  
      inspectionData.value = [];  
      currentMeasurementType = measurementType;  
      // 生成请求序号(确保与设备响应/推送序号匹配)  
      currentReqSeq = (currentReqSeq + 1) % 256;  
      console.log(`生成请求序号: ${currentReqSeq}`);  

      try {  
        // 根据测量类型组装不同的指令  
        let fullCmd;  

        if (measurementType === 'vibration') {  
          console.log("构建振动测量指令");  
          // 振动测量时添加采样参数配置  
          const samplingFactor = samplingFactors.value[samplingFactorIndex.value];  
          const highPassFilter = highPassFilters.value[highPassFilterIndex.value];  
          // 功能掩码 - 设置bit6为1启用近距离测温(第7位,从0开始计数)  
          const featureMask = 0x40; // 0b01000000,bit6为1  

          // 组装带参数的指令:前导+长度+序号+功能码+功能掩码+采样系数+高通滤波系数+校验和  
          // 注意:长度需要增加1以包含功能掩码参数  
          const cmd = new Uint8Array([0x5A, 0x05, currentReqSeq, funcCode, featureMask, samplingFactor, highPassFilter]);  
          const checksum = cmd.reduce((a, b) => a + b, 0) & 0xFF; // 校验和(累加取低8位)  
          fullCmd = new Uint8Array([...cmd, checksum]);  

          console.log('功能掩码设置:', {  
            featureMask: '0x' + featureMask.toString(16).toUpperCase(),  
            bit6Enabled: (featureMask & 0x40) === 0x40 ? '是' : '否',  
            description: '近距离测温已启用'  
          });  

          console.log('发送带参数的振动测量指令:', {  
            samplingFactor,  
            highPassFilter,  
            expectedSamplingRate: currentSamplingRate.value,  
            expectedCutoffFreq: currentCutoffFreq.value  
          });  
        } else {  
          console.log("构建标准测量指令");  
          // 其他测量类型使用标准指令  
          const cmd = new Uint8Array([0x5A, 0x02, currentReqSeq, funcCode]);  
          const checksum = cmd.reduce((a, b) => a + b, 0) & 0xFF; // 校验和(累加取低8位)  
          fullCmd = new Uint8Array([...cmd, checksum]);  
        }  

        const cmdBuffer = fullCmd.buffer;  

        // 详细的指令发送日志  
        console.log('发送测量指令:', {  
          measurementType,  
          functionCode: '0x' + funcCode.toString(16).toUpperCase(),  
          sequence: currentReqSeq,  
          commandBytes: Array.from(fullCmd),  
          commandHex: Array.from(fullCmd).map(b => '0x' + b.toString(16).padStart(2, '0').toUpperCase()).join(', ')  
        });  

        // 优先使用已知的传感器服务和正确的特征值映射(fff1为读,fff2为写)  
        let serviceId = connectedServiceInfo.serviceId;  
        let writeCharId = connectedServiceInfo.writeCharId;  
        let readCharId = connectedServiceInfo.readCharId;  

        console.log("当前连接信息:", {  
          deviceId: connectedDeviceId.value,  
          serviceId: serviceId || '未设置',  
          writeCharId: writeCharId || '未设置',  
          readCharId: readCharId || '未设置'  
        });  

        // 改进的特征值组合查找逻辑  
        let foundSuitableChars = false;  

        // 首先检查现有配置是否合适  
        if (writeCharId && readCharId) {  
          const hasValidWriteChar = writeCharId.toLowerCase().includes('fff2');  
          const hasValidReadChar = readCharId.toLowerCase().includes('fff1');  

          if (hasValidWriteChar && hasValidReadChar) {  
            foundSuitableChars = true;  
            console.log("发现有效特征值组合,已包含fff2(写)和fff1(读)");  
          } else {  
            console.log("现有特征值组合不满足要求:", {  
              writeCharValid: hasValidWriteChar,  
              readCharValid: hasValidReadChar  
            });  
          }  
        }  

        // 如果未设置正确的读写特征值组合,尝试查找  
        if (!foundSuitableChars) {  
          console.log('未找到正确的读写特征值组合,尝试查找最佳匹配...');  

          // 记录查找前的状态  
          console.log("查找前的特征值状态:", {  
            hasServiceId: !!serviceId,  
            hasWriteCharId: !!writeCharId,  
            hasReadCharId: !!readCharId  
          });  

          // 调用优化后的查找函数  
          await findAndUseAlternativeWriteChar();  

          // 更新使用的ID  
          serviceId = connectedServiceInfo.serviceId;  
          writeCharId = connectedServiceInfo.writeCharId;  
          readCharId = connectedServiceInfo.readCharId;  

          console.log("查找后的特征值状态:", {  
            serviceId: serviceId || '未找到',  
            writeCharId: writeCharId || '未找到',  
            readCharId: readCharId || '未找到'  
          });  
        }  

        // 如果仍然没有找到合适的特征值,使用默认配置  
        console.log("应用默认配置检查...");  
        if (!serviceId) {  
          // 处理SERVICE_ID可能是数组的情况,优先使用第一个服务ID  
          serviceId = Array.isArray(BT_CONFIG.SERVICE_ID) ? BT_CONFIG.SERVICE_ID[0] : BT_CONFIG.SERVICE_ID;  
          console.log(`使用默认服务ID: ${serviceId}`);  
        }  

        if (!writeCharId) {  
          writeCharId = BT_CONFIG.CHARACTERISTIC_ID.WRITE;  
          console.log(`使用默认写入特征值: ${writeCharId}`);  
        }  

        if (!readCharId) {  
          readCharId = BT_CONFIG.CHARACTERISTIC_ID.READ;  
          console.log(`使用默认读取特征值: ${readCharId}`);  
        }  

        console.log(`最终使用的参数:`, {  
          deviceId: connectedDeviceId.value,  
          serviceId,  
          writeCharId,  
          readCharId,  
          fullCommand: Array.from(fullCmd).map(b => b.toString(16).padStart(2, '0').toUpperCase()).join(' ')  
        });  

        // 发送前先尝试获取特征值属性,确保可写  
        try {  
          console.log("开始检查特征值属性...");  
          const charRes = await uni.getBLEDeviceCharacteristics({  
            deviceId: connectedDeviceId.value,  
            serviceId,  
            characteristicId: writeCharId  
          });  

          if (charRes.characteristics && charRes.characteristics.length > 0) {  
            const char = charRes.characteristics[0];  
            console.log('写入特征值属性检查结果:', char.properties);  

            // 如果特征值不支持写入,尝试查找其他可写特征值  
            if (!char.properties.write && !char.properties.writeNoResponse) {  
              console.warn('当前特征值不支持写入,尝试查找其他可写特征值');  
              await findAndUseAlternativeWriteChar();  
              // 使用新的写入特征值  
              const newWriteCharId = connectedServiceInfo.writeCharId;  
              const newReadCharId = connectedServiceInfo.readCharId;  
              if (newWriteCharId) writeCharId = newWriteCharId;  
              if (newReadCharId) readCharId = newReadCharId;  
              console.log('更新后的特征值:', { newWriteCharId, newReadCharId });  
            }  
          } else {  
            console.error('未找到指定的特征值');  
          }  
        } catch (checkErr) {  
          console.warn('特征值属性检查失败:', checkErr);  
          // 继续尝试发送,不中断流程  
        }  

        // 先检查特征值是支持write还是writeNoResponse  
        try {  
          console.log("开始检查写入特征值属性类型...");  
          const charRes = await uni.getBLEDeviceCharacteristics({  
            deviceId: connectedDeviceId.value,  
            serviceId,  
            characteristicId: writeCharId  
          });  

          if (charRes.characteristics && charRes.characteristics.length > 0) {  
            const char = charRes.characteristics[0];  
            console.log('写入特征值可用属性:', char.properties);  

            // 确定写入类型  
            const writeType = char.properties.writeNoResponse ? 'noResponse' : 'write';  
            console.log(`确定使用写入类型: ${writeType}`);  

            // 发送指令到WRITE通道(优先使用fff2)  
            console.log("准备发送指令...");  
            await uni.writeBLECharacteristicValue({  
              deviceId: connectedDeviceId.value,  
              serviceId,  
              characteristicId: writeCharId,  
              value: cmdBuffer,  
              writeType: writeType,  
              success: () => {  
                console.log('✅ 指令发送成功,等待设备响应...');  
                // 设置超时处理  
                setResponseTimeout();  

                // 发送成功后立即尝试读取一次,看是否有即时响应  
                setTimeout(() => {  
                  if (readCharId) {  
                    console.log('尝试主动读取特征值(fff1),检查即时响应');  
                    readCharacteristicValue(connectedDeviceId.value, serviceId, readCharId);  
                  } else {  
                    console.log('未设置读取特征值,尝试查找合适的读取特征值');  
                    // 如果没有设置读取特征值,尝试查找一个  
                    findSuitableReadCharacteristicForService(serviceId);  
                  }  
                }, 300);  
              },  
              fail: (err) => {  
                console.error('❌ 指令发送失败(高级写入模式):', err);  
                // 处理失败情况  
                throw new Error(`高级写入模式失败: ${err.errMsg}`);  
              }  
            });  
          } else {  
            console.error('特征值不存在,使用默认写入方式');  
            throw new Error('特征值不存在');  
          }  
        } catch (checkErr) {  
          console.warn('特征值属性检查失败,降级使用默认写入方式:', checkErr.message);  

          // 如果检查失败,使用默认方式发送指令  
          console.log("尝试使用默认方式发送指令...");  
          await uni.writeBLECharacteristicValue({  
            deviceId: connectedDeviceId.value,  
            serviceId,  
            characteristicId: writeCharId,  
            value: cmdBuffer,  
            success: () => {  
              console.log('✅ 指令发送成功(默认写入方式),等待设备响应...');  
              setResponseTimeout();  

              setTimeout(() => {  
                if (readCharId) {  
                  readCharacteristicValue(connectedDeviceId.value, serviceId, readCharId);  
                } else {  
                  findSuitableReadCharacteristicForService(serviceId);  
                }  
              }, 300);  
            },  
            fail: async (err) => {   
              console.error('❌ 指令发送失败(默认方式):', JSON.stringify(err, null, 2));  
              // 更友好的错误提示和处理  
              let errorMessage = `发送失败:${err.errMsg || '未知错误'}`;  

              if (err.errCode === 10009 || err.errMsg?.includes('property not support')) {  
                // 特征值不存在或不支持写入,尝试查找正确的fff2写入特征值  
                console.warn('⚠️ 特征值不存在或不支持写入,尝试查找正确的fff2写入特征值');  
                await findAndUseAlternativeWriteChar();  
                // 强制更新连接信息  
                serviceId = connectedServiceInfo.serviceId;  
                writeCharId = connectedServiceInfo.writeCharId;  
                readCharId = connectedServiceInfo.readCharId;  
                console.log('更新后的特征值信息:', { serviceId, writeCharId, readCharId });  
                errorMessage = '特征值不支持写入,已尝试查找正确通道,请重试';  
              } else if (err.errCode === 10004) {  
                errorMessage = '设备未连接,请重新连接';  
              }  

              console.error(`最终错误信息: ${errorMessage}`);  
              throw new Error(errorMessage);  
            }  
          });  
      }   
      } catch (err) {  
        console.error('❌ 测量指令发送流程失败:', JSON.stringify(err, null, 2));  
        interactStatusType.value = 'warning';  
        interactStatusText.value = `请求发送失败:${err.message}`;  
        clearResponseTimeout();  

        // 如果发送失败且未使用备选方案,尝试查找替代写入特征值  
        if (!connectedServiceInfo.writeCharId) {  
          console.log('未找到写入特征值,尝试查找替代方案...');  
          findAndUseAlternativeWriteChar();  
        }  
      } finally {  
        console.log("===== 测量指令发送流程结束 =====");  
      }  
    };  

    /**  
     * 查找并使用替代的写入特征值和读取特征值  
     */  
    const findAndUseAlternativeWriteChar = async () => {  
      try {  
        console.log('? 开始查找最佳特征值组合...');  

        // 确保设备已连接  
        if (!connectedDeviceId.value) {  
          console.error('❌ 设备未连接,无法查找特征值');  
          uni.showToast({   
            title: '设备未连接',   
            icon: 'none'   
          });  
          return;  
        }  

        // 清除之前的连接信息,确保重新查找  
        connectedServiceInfo.serviceId = null;  
        connectedServiceInfo.writeCharId = null;  
        connectedServiceInfo.readCharId = null;  
        console.log('✅ 已清除之前的连接信息,准备重新查找');  

        // 获取设备的所有服务  
        const serviceRes = await uni.getBLEDeviceServices({   
          deviceId: connectedDeviceId.value   
        });  

        console.log(`? 发现设备服务数量: ${serviceRes.services.length}`);  
        console.log('? 设备服务列表:', serviceRes.services.map(s => s.uuid));  

        // 优先遍历已知的传感器服务  
        let servicesToCheck = [];  

        // 确保SENSOR_SERVICE_IDS是数组  
        if (Array.isArray(BT_CONFIG.SENSOR_SERVICE_IDS)) {  
          servicesToCheck = [...BT_CONFIG.SENSOR_SERVICE_IDS];  
        } else {  
          servicesToCheck = [BT_CONFIG.SENSOR_SERVICE_IDS];  
        }  

        // 添加设备实际支持的所有服务(去重)  
        const deviceServices = serviceRes.services.map(s => s.uuid);  
        servicesToCheck = [...new Set([...servicesToCheck, ...deviceServices])];  

        // 优先检查文档中指定的服务(fff0)  
        const fff0Service = servicesToCheck.find(s => s.toLowerCase().includes('fff0'));  
        if (fff0Service) {  
          const index = servicesToCheck.indexOf(fff0Service);  
          servicesToCheck.splice(index, 1);  
          servicesToCheck.unshift(fff0Service); // 移到最前面优先检查  
          console.log('? 找到fff0服务,优先检查');  
        }  

        console.log('? 将检查的服务列表:', servicesToCheck);  

        // 记录找到的最佳组合  
        let bestWriteChar = null;  
        let bestReadChar = null;  
        let bestServiceId = null;  
        let bestScore = 0;  

        // 服务评分函数  
        const scoreCharacteristicPair = (writeChar, readChar, serviceId) => {  
          let score = 0;  

          // 基础分:有写入特征值+10,有读取特征值+10  
          if (writeChar) score += 10;  
          if (readChar) score += 10;  

          // 额外分:如果包含特定标识符  
          if (writeChar && writeChar.uuid.toLowerCase().includes('fff2')) score += 20;  
          if (readChar && readChar.uuid.toLowerCase().includes('fff1')) score += 20;  

          // 额外分:如果是fff0服务  
          if (serviceId.toLowerCase().includes('fff0')) score += 15;  

          // 额外分:支持更多属性  
          if (writeChar && writeChar.properties.writeNoResponse) score += 5;  
          if (readChar && readChar.properties.notify) score += 5;  

          return score;  
        };  

        // 为每个服务评分  
        const serviceScores = [];  

        for (const serviceId of servicesToCheck) {  
          try {  
            console.log(`? 正在检查服务: ${serviceId}`);  

            // 获取服务的所有特征值  
            const charRes = await uni.getBLEDeviceCharacteristics({  
              deviceId: connectedDeviceId.value,  
              serviceId  
            });  

            console.log(`? 服务 ${serviceId} 特征值数量: ${charRes.characteristics.length}`);  

            // 详细记录所有特征值信息  
            const charDetails = [];  
            charRes.characteristics.forEach((c, idx) => {  
              const props = [];  
              if (c.properties.read) props.push('read');  
              if (c.properties.write) props.push('write');  
              if (c.properties.notify) props.push('notify');  
              if (c.properties.writeNoResponse) props.push('writeNoResponse');  

              charDetails.push({  
                index: idx + 1,  
                uuid: c.uuid,  
                properties: props  
              });  

              console.log(`  特征值 ${idx + 1}:`, {  
                uuid: c.uuid,  
                properties: c.properties  
              });  
            });  

            // 全面查找读写特征值  
            let writeChar = null;  
            let readChar = null;  

            // 1. 优先使用专业查找函数  
            writeChar = findSuitableWriteCharacteristic(charRes.characteristics);  
            // 查找合适的读取特征值  
            readChar = charRes.characteristics.find(  
              c => c.uuid.toLowerCase().includes('fff1') && (c.properties.read || c.properties.notify)  
            ) || charRes.characteristics.find(c => c.properties.read || c.properties.notify);  

            // 计算分数  
            const score = scoreCharacteristicPair(writeChar, readChar, serviceId);  
            serviceScores.push({  
              serviceId,  
              score,  
              writeChar: writeChar?.uuid,  
              readChar: readChar?.uuid  
            });  

            // 记录特征值找到情况  
            console.log(`? 服务 ${serviceId} 特征值匹配结果:`, {  
              writeCharFound: !!writeChar,  
              readCharFound: !!readChar,  
              writeCharId: writeChar?.uuid || '未找到',  
              readCharId: readChar?.uuid || '未找到',  
              score  
            });  

            // 更新最佳组合  
            if (score > bestScore) {  
              bestWriteChar = writeChar;  
              bestReadChar = readChar;  
              bestServiceId = serviceId;  
              bestScore = score;  
              console.log(`⭐ 找到更好的特征值组合 (分数: ${score}),更新最佳选择`);  
            }  

            // 如果找到完美组合,立即返回  
            if (writeChar && readChar &&   
                writeChar.uuid.toLowerCase().includes('fff2') &&   
                readChar.uuid.toLowerCase().includes('fff1')) {  
              console.log(`? 找到完美匹配的特征值组合,立即使用`);  
              bestWriteChar = writeChar;  
              bestReadChar = readChar;  
              bestServiceId = serviceId;  
              break; // 找到完美组合,立即返回  
            }  
          } catch (serviceError) {  
            console.warn(`⚠️ 服务 ${serviceId} 访问失败,跳过:`, serviceError);  
          }  
        }  

        // 打印所有服务的评分结果  
        console.log('? 所有服务评分结果:', serviceScores.sort((a, b) => b.score - a.score));  

        // 处理找到的最佳组合  
        if (bestWriteChar && bestReadChar) {  
          console.log(`✅ 找到最佳特征值组合: 服务=${bestServiceId} (分数: ${bestScore})`);  
          console.log(`  写入特征值: ${bestWriteChar.uuid} [${Object.keys(bestWriteChar.properties).filter(p => bestWriteChar.properties[p]).join(', ')}]`);  
          console.log(`  读取特征值: ${bestReadChar.uuid} [${Object.keys(bestReadChar.properties).filter(p => bestReadChar.properties[p]).join(', ')}]`);  

          // 更新连接信息  
          connectedServiceInfo.serviceId = bestServiceId;  
          connectedServiceInfo.writeCharId = bestWriteChar.uuid;  
          connectedServiceInfo.readCharId = bestReadChar.uuid;  

          // 通知用户  
          uni.showModal({  
            title: '✅ 已找到匹配的读写通道',  
            content: `已切换到最佳通道组合:\n服务: ${bestServiceId}\n写入特征值: ${bestWriteChar.uuid}\n读取特征值: ${bestReadChar.uuid}\n匹配分数: ${bestScore}\n\n请尝试发送测量指令`,  
            showCancel: false  
          });  

          // 尝试启用通知  
          if (bestReadChar.properties.notify) {  
            try {  
              console.log('? 尝试启用读取特征值的通知模式');  
              await uni.notifyBLECharacteristicValueChange({  
                deviceId: connectedDeviceId.value,  
                serviceId: bestServiceId,  
                characteristicId: bestReadChar.uuid,  
                state: true  
              });  
              console.log('✅ 通知模式已成功启用');  
            } catch (notifyErr) {  
              console.warn('⚠️ 启用通知模式失败:', notifyErr);  
            }  
          }  
        } else if (bestWriteChar) {  
          // 只有写入特征值的情况  
          console.log(`⚠️ 找到写入特征值: 服务=${bestServiceId}, 写入特征值=${bestWriteChar.uuid}`);  

          connectedServiceInfo.serviceId = bestServiceId;  
          connectedServiceInfo.writeCharId = bestWriteChar.uuid;  
          connectedServiceInfo.readCharId = bestReadChar?.uuid || null;  

          uni.showModal({  
            title: '⚠️ 已找到写入通道',  
            content: `已切换到替代通道:\n服务: ${bestServiceId}\n写入特征值: ${bestWriteChar.uuid}\n读取特征值: ${bestReadChar?.uuid || '未找到'}\n\n请尝试发送测量指令`,  
            showCancel: false  
          });  
        } else {  
          // 如果没有找到可写入的特征值  
          console.error('❌ 未找到任何可用的特征值');  

          // 尝试极端方案:遍历所有服务的所有特征值  
          console.log('? 尝试极端方案:遍历所有服务的所有特征值...');  

          for (const service of serviceRes.services) {  
            try {  
              const charRes = await uni.getBLEDeviceCharacteristics({  
                deviceId: connectedDeviceId.value,  
                serviceId: service.uuid  
              });  

              const anyWriteChar = charRes.characteristics.find(c => c.properties.write || c.properties.writeNoResponse);  
              cons
2025-10-25 18:59 负责人:无 分享
已邀请:

要回复问题请先登录注册