纪炎呀
纪炎呀
  • 发布:2024-12-03 17:50
  • 更新:2024-12-03 18:50
  • 阅读:33

【报Bug】app蓝牙notifyBLECharacteristicValueChange无法订阅

分类:uni-app

产品分类: uniapp/App

PC开发环境操作系统: Mac

PC开发环境操作系统版本号: M1

HBuilderX类型: 正式

HBuilderX版本号: 4.29

手机系统: Android

手机系统版本号: Android 10

手机厂商: OPPO

手机机型: A72n 5G

页面类型: vue

vue版本: vue3

打包方式: 云端

项目创建方式: HBuilderX

操作步骤:
  <view>  
    <uni-popup ref="popup" type="dialog">  
        <uni-popup-dialog mode="input" v-model="bobaoContent" message="成功消息" :duration="2000" :before-close="true" @close="closePopup" @confirm="confirmPopup"></uni-popup-dialog>  
    </uni-popup>  
    <!-- <button @click="textToSpeech(1)">A播报内容<button>  
    <button @click="textToSpeech(2)">B播报内容</button>  
    <button @click="textToSpeech(3)">C播报内容</button> -->  
    <button @click="startBluetooth">启动蓝牙</button>  
    <button @click="closeBluetooth">关闭蓝牙</button>  
    <button @click="scanBluetooth" :disabled="isScanning">扫描蓝牙设备</button>  
    <!-- 显示扫描到的设备列表 -->  
    <scroll-view scroll-y="true" style="height: 400px;">  
      <view v-for="device in devices" :key="device.deviceId" class="device-item">  
        <text>{{ device.name || device.localName || '未知设备' }}</text>  
        <button @click="connectToDevice(device)">连接</button>  
      </view>  
    </scroll-view>  

    <view v-if="connectedDevice">  
      <text>已连接到蓝牙设备: {{ connectedDevice }}</text>  
      <button @click="disconnectDevice">断开连接</button>  
    </view>  

    <view v-if="receivedData">  
      <text>接收到的数据: {{ receivedData }}</text>  
    </view>  

  </view>  
</template>  

<script>  
export default {  
  data() {  
    return {  
      connectedDevice: null, // 当前连接的设备ID  
      devices: [], // 扫描到的设备列表  
      isScanning: false, // 扫描状态  
      receivedData: null, // 接收到的数据  
      deviceServices: [], // 设备的服务  
      deviceCharacteristics: [] ,// 设备的特征值  
      // ==================  
      cachedValueA:'',  
      cachedValueB:'',  
      cachedValueC:'',  
      bobaoContent:'', //播报内容输入框  
    };  
  },  
  mounted() {  
    this.cachedValueA = uni.getStorageSync(`inputValue_1`) || '';  
    this.cachedValueB = uni.getStorageSync(`inputValue_2`) || '';  
    this.cachedValueC = uni.getStorageSync(`inputValue_3`) || '';  
  },  
  methods: {  
    // 启动蓝牙适配器  
    startBluetooth() {  
      uni.openBluetoothAdapter({  
        success: () => {  
          console.log('蓝牙适配器启动成功');  
           uni.showToast({ title: '蓝牙适配器启动成功', icon: 'none' });  
        },  
        fail: (err) => {  
          console.error('启动蓝牙适配器失败:', err);  
          uni.showToast({ title: '启动蓝牙适配器失败', icon: 'none' });  
        }  
      });  
    },  

    // 扫描蓝牙设备  
    scanBluetooth() {  
      this.isScanning = true;  
      uni.startBluetoothDevicesDiscovery({  
        success: () => {  
          console.log('开始扫描蓝牙设备...');  
          uni.showToast({ title: '开始扫描设备' ,icon: 'none'});  
          this.listenForDeviceFound();  
        },  
        fail: (err) => {  
          console.error('扫描失败:', err);  
          uni.showToast({ title: '扫描失败', icon: 'none' });  
          this.isScanning = false;  
        }  
      });  
    },  
    ab2hex(buffer) {  
      const hexArr = Array.prototype.map.call(  
        new Uint8Array(buffer),  
        function (bit) {  
          return ('00' + bit.toString(16)).slice(-2)  
        }  
      )  
      return hexArr.join('')  
    },  
    // 监听扫描到的蓝牙设备  
    listenForDeviceFound() {  
      uni.onBluetoothDeviceFound((res) => {  
        console.log('扫描到设备:', res.devices);  
        res.devices.forEach((device) => {  
             // 检查设备是否已经在列表中  
             const isDeviceExist = this.devices.some(d => d.deviceId === device.deviceId);  
             if (!isDeviceExist && device.name=="BT4.0 Mouse") {  
               this.devices.push(device);  
               this.isScanning = false;  
              uni.stopBluetoothDevicesDiscovery({  
                success(res) {  
                  console.log(res,"停止搜索成功")  
                }  
              })  
             }  
        });  
      });  
    },  

    // 连接到蓝牙设备  
    connectToDevice(device) {  
        uni.showLoading({  
            title: '连接中'  
        });  
      uni.createBLEConnection({  
        deviceId: device.deviceId,  
        success: () => {  
          console.log('成功连接到设备:', device.name);  
          this.connectedDevice = device.deviceId;  
          uni.hideLoading();  
          uni.showToast({ title: '连接成功', icon: 'none' });  
          setTimeout(() => this.getDeviceServices(device.deviceId), 1000); // 延迟1秒获取服务  
        },  
        fail: (err) => {  
          uni.hideLoading();  
          console.error('连接失败:', err);  
          uni.showToast({ title: '连接失败', icon: 'none' });  
        }  
      });  
    },  

    // 获取设备的服务  
    getDeviceServices(deviceId) {  
      uni.getBLEDeviceServices({  
        deviceId,  
        success: (res) => {  
          console.log('设备服务:', res);  
          this.deviceServices = res.services;  
          // 假设我们选择第一个服务进行后续操作  
          if (res.services && res.services.length > 0) {  
           this.serviceId = this.deviceServices.find(service => service.isPrimary).uuid;   
            this.getDeviceCharacteristics(deviceId, this.serviceId);  
          }  
        },  
        fail: (err) => {  
          console.error('获取服务失败:', err);  
          uni.showToast({ title: '获取服务失败请重新连接蓝牙', icon: 'none' });  
        }  
      });  
    },  

    // 获取设备的特征值  
    getDeviceCharacteristics(deviceId, serviceId) {  
      uni.getBLEDeviceCharacteristics({  
        deviceId,  
        serviceId,  
        success: (res) => {  
          console.log('设备特征值列表:', res.characteristics);  
          this.characteristics = res.characteristics;  
          // 假设我们订阅第一个特征值来接收数据  
          if (this.characteristics.length >0) {  
            const readCharacteristicuuid = this.characteristics.find(c => c.properties.read).uuid;  // 找到读特征值  
            if(readCharacteristicuuid){  
                console.log('可读特征值:', readCharacteristicuuid);  
                this.notifyDevice(deviceId, serviceId, readCharacteristicuuid);  
            }else{  
               uni.showToast({ title: '获取读特征值失败', icon: 'none' });  
            }  
          }  
        },  
        fail: (err) => {  
          console.error('获取特征值失败:', err);  
          uni.showToast({ title: '获取特征值失败', icon: 'none' });  
        }  
      });  
    },  

    // 启用特征值的通知  
    notifyDevice(deviceId, serviceId, characteristicId) {  
      uni.notifyBLECharacteristicValueChange({  
        state: true, // 开启通知  
        deviceId:deviceId,  
        serviceId:serviceId,  
        characteristicId:characteristicId,  
        success: () => {  
          console.log('订阅成功');  
          uni.showToast({ title: '订阅成功', icon: 'none' });  
          // this.listenForNotifications(deviceId, serviceId, characteristicId);  
        },  
        fail: (err) => {  
          console.error('订阅失败:', err);  
          uni.showToast({ title: '订阅失败', icon: 'none' });  
        }  
      });  
    },  

    // 监听设备通知  
    listenForNotifications(deviceId, serviceId, characteristicId) {  
      uni.onBLECharacteristicValueChange((res) => {  
        console.log('接收到设备返回的数据:', res);  
        if (res.deviceId === deviceId && res.serviceId === serviceId && res.characteristicId === characteristicId) {  
          // 解析设备返回的数据  
          this.receivedData = this.ab2str(res.value);  
           console.log('解析后的数据:', this.receivedData);  
        }  
      });  
    },  

    // 断开蓝牙设备连接  
    disconnectDevice() {  
      if (this.connectedDevice) {  
        uni.closeBLEConnection({  
          deviceId: this.connectedDevice,  
          success: () => {  
            console.log('已断开连接');  
            this.connectedDevice = null;  
            uni.showToast({ title: '已断开连接' });  
          },  
          fail: (err) => {  
            console.error('断开连接失败:', err);  
            uni.showToast({ title: '断开连接失败', icon: 'none' });  
          }  
        });  
      }  
    },  

    // 关闭蓝牙适配器  
    closeBluetooth() {  
    uni.onBluetoothAdapterStateChange(function (res) {  
      console.log('adapterState changed, now is', res)  
    })  
      uni.closeBluetoothAdapter({  
        success: () => {  
          console.log('蓝牙适配器已关闭');  
          uni.showToast({ title: '蓝牙适配器已关闭', icon: 'none' });  
        },  
        fail: (err) => {  
          console.error('关闭蓝牙适配器失败:', err);  
          uni.showToast({ title: '关闭蓝牙适配器失败', icon: 'none' });  
        }  
      });  
    },  

    // 辅助方法:将 ArrayBuffer 转换为字符串  
    ab2str(buf) {  
      return String.fromCharCode.apply(null, new Uint8Array(buf));  
    },  
    closePopup(){  
        this.bobaoContent = "";  
        this.$refs.popup.close()  
    },  
    confirmPopup(val){  
        this.bobaoContent = val;  
        if(val){  
                uni.setStorage({  
                key: `inputValue_${this.bobaoType}`,  
                 data: val,  
                  success: () => {  
                    uni.showToast({ title: '播报内容保存成功', icon: 'none' });  
                  },  
                  fail: (err) => {  
                    uni.showToast({ title: '播报内容保存失败', icon: 'none' });  
                  }  
                });  
                this.$refs.popup.close()  
        }else{  
            uni.showToast({ title: '请输入播报内容', icon: 'none' });  
        }  
    },  
    // 点击按钮输入需要播报的内容  
    textToSpeech(type){  
        // 根据 type 获取缓存内容  
        const cachedValue = uni.getStorageSync(`inputValue_${type}`) || '';  
        this.bobaoType = type;  
        this.bobaoContent = cachedValue;  
        this.$refs.popup.open();  
    }  
  },  

  onUnload() {  
    // 页面卸载时关闭蓝牙连接  
    this.closeBluetooth();  
  }  
};  
</script>  

<style scoped>  
button {  
  margin: 10px;  
  padding: 10px;  
  background-color: #007aff;  
  color: white;  
  border-radius: 5px;  
}  

.device-item {  
  margin: 10px;  
  padding: 10px;  
  border: 1px solid #ddd;  
  border-radius: 5px;  
  background-color: #f9f9f9;  
  display: flex;  
  justify-content: space-between;  
}  

.scroll-view {  
  max-height: 300px;  
}  
</style>  

预期结果:

1

实际结果:

1

bug描述:

{
"errMsg": "notifyBLECharacteristicValueChange:fail no descriptor",
"code": 10008
}报错提示,换了好几个设备都是一样的

2024-12-03 17:50 负责人:无 分享
已邀请:
dennyjiang

dennyjiang

查找特定的特征值才可以,通过characteristics[].properties.notify / characteristics[].properties.indicate 属性判断

  • 纪炎呀 (作者)

    [

    {

    "uuid": "00002A05-0000-1000-8000-00805F9B34FB",

    "properties": {

    "read": true,

    "write": true,

    "notify": true,

    "indicate": true

    }

    }

    ]都有的哈

    2024-12-03 19:17

要回复问题请先登录注册