HarmonyOS鸿蒙Next中ble订阅蓝牙低功耗设备的特征值变化事件BLECharacteristicChange,发送指令并操作成功后,没有得到设备的回调

HarmonyOS鸿蒙Next中ble订阅蓝牙低功耗设备的特征值变化事件BLECharacteristicChange,发送指令并操作成功后,没有得到设备的回调 以下是大致的代码流程:

let descriptors: Array<ble.BLEDescriptor> = [];
let bufferDesc = new ArrayBuffer(8);
let descV = new Uint8Array(bufferDesc);
descV[0] = 0x00;
descV[1] = 0xaa;
descV[2] = 0xbb;
descV[3] = 0xcc;
// 模拟数据
let descriptor: ble.BLEDescriptor = {
  serviceUuid: 'xxxxxx00-aaaa-bbbb-cccc-dddddddddddd',
  characteristicUuid: 'xxxxxx02-aaaa-bbbb-cccc-dddddddddddd',
  descriptorUuid: '00002902-0000-1000-8000-00805F9B34FB',
  descriptorValue: bufferDesc
};
descriptors[0] = descriptor;
let bufferCCC = new ArrayBuffer(8);
let cccV = new Uint8Array(bufferCCC);
cccV[0] = 0x00;
cccV[1] = 0xaa;
cccV[2] = 0xbb;
cccV[3] = 0xcc;
cccV[4] = 0xdd;

let characteristic: ble.BLECharacteristic = {
  serviceUuid: 'xxxxxx00-aaaa-bbbb-cccc-dddddddddddd',
  characteristicUuid: 'xxxxxx01-aaaa-bbbb-cccc-dddddddddddd',
  characteristicValue: bufferCCC,
  descriptors: descriptors
};

// 创建客户端
gattClient = ble.createGattClientDevice(myDevice.deviceId);
try {
  gattClient.on('BLEConnectionStateChange', (state: ble.BLEConnectionChangeState) => {
    console.info('订阅连接状态变化事件 bluetooth connect state changed');
    let connectState: ble.ProfileConnectionState = state.state;
    console.info('连接状态:' + connectState);
    // 已连接状态,进行以下操作
    if (connectState === 2) {
      // 服务发现
      gattClient.getServices()
        .then((result: Array<ble.GattService>) => {
          console.info('服务发现 getServices successfully:' + JSON.stringify(result));

          // 设置特征值变化通知能力
          try {
            // enable入参: true表示启用,false表示禁用
            gattClient.setCharacteristicChangeNotification(characteristic, true, (err: BusinessError, data) => {
              if (err) {
                console.error('特征值变化通知 setCharacteristicChangeNotification callback failed');
              } else {
                console.info('特征值变化通知 setCharacteristicChangeNotification callback successful --', data);

                try {
                  // 订阅特征值变化事件通知
                  // 需要先调用 setCharacteristicChangeNotification 接口
                  // 或 setCharacteristicChangeIndication 接口才能接收服务端的通知。
                  gattClient.on('BLECharacteristicChange', (characteristicChangeReq: ble.BLECharacteristic) => {
                    let serviceUuids: string = characteristicChangeReq.serviceUuid;
                    let characteristicUuids: string = characteristicChangeReq.characteristicUuid;
                    let values: Uint8Array = new Uint8Array(characteristicChangeReq.characteristicValue);
                    console.log('订阅特征值变化事件', serviceUuids, characteristicUuids, values)
                  })
                } catch (err) {
                  console.error('订阅特征值变化事件 errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
                }
              }
            });
          } catch (err) {
            console.error('特征值变化通知 errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
          }

        }).catch((err: BusinessError) => {
          console.error('服务发现 getServices failed:' + JSON.stringify(err));
        })
    }
  });
  // 发起ble连接
  try {
    gattClient.connect();
  } catch (err) {
    console.error('发起ble建立连接 errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
  }
} catch (err) {
  console.error('订阅连接状态变化事件: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message)
}

// 写入特征值 发送指令
try {
  const TAG: string = '写入特征值 GattClientManager';
  console.warn('character', JSON.stringify(characteristic))
  gattClient.writeCharacteristicValue(characteristic, ble.GattWriteType.WRITE, (err) => {
    if (err) {
      console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
      return;
    }
    console.info(TAG, 'writeCharacteristicValue success');
  });
} catch (err) {
  console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
}

以下是**gattClient.getServices()**拿到的数据:

[
  {
    "serviceUuid":"xxxxxx00-aaaa-bbbb-cccc-dddddddddddd",
    "isPrimary":true,
    "characteristics":[
      {
        "characteristicUuid":"xxxxxx01-aaaa-bbbb-cccc-dddddddddddd",
        "serviceUuid":"xxxxxx00-aaaa-bbbb-cccc-dddddddddddd",
        "characteristicValue":{},
        "properties":{
          "write":true,
          "writeNoResponse":true,
          "read":false,
          "notify":false,
          "indicate":false
        },
        "descriptors":[]
      },
      {
        "characteristicUuid":"xxxxxx02-aaaa-bbbb-cccc-dddddddddddd",
        "serviceUuid":"xxxxxx00-aaaa-bbbb-cccc-dddddddddddd",
        "characteristicValue":{},
        "properties":{
           "write":false,
           "writeNoResponse":false,
           "read":true,
           "notify":true,
           "indicate":false
         },
       "descriptors":[
         {
           "descriptorUuid":"00002902-0000-1000-8000-00805F9B34FB",
           "characteristicUuid":"xxxxxx02-aaaa-bbbb-cccc-dddddddddddd",
           "serviceUuid":"xxxxxx00-aaaa-bbbb-cccc-dddddddddddd",
           "descriptorValue":{}
         }
       ]
      }
    ],
    "includeServices":[]
  }
]

我是通过gattClient.getServices()获取的数据,然后去手动编写最开始的characteristicdescriptor等数据,然后再发送请求。

蓝牙设备能够正常进行ble连接,发送的指令也能够正常的执行,但是就是无法获取设备的回调。

gattClient.setCharacteristicChangeNotification方法的回调没有报错,应该是正常设置了特征值变化通知能力,**gattClient.on(‘BLECharacteristicChange’)**方法也没有报错,但是没有任何反应。请问为什么无法获取设备的回调呢?


更多关于HarmonyOS鸿蒙Next中ble订阅蓝牙低功耗设备的特征值变化事件BLECharacteristicChange,发送指令并操作成功后,没有得到设备的回调的实战教程也可以访问 https://www.itying.com/category-93-b0.html

5 回复

我也是,请问解决了吗

更多关于HarmonyOS鸿蒙Next中ble订阅蓝牙低功耗设备的特征值变化事件BLECharacteristicChange,发送指令并操作成功后,没有得到设备的回调的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


解决了吗

我也是,请问解决了吗

在HarmonyOS Next中,订阅BLE特征值变化事件后未收到回调,可能原因包括:特征值未正确启用通知或指示;设备端未正确配置或发送数据;订阅操作与设备通信时序不同步;或设备连接不稳定。请检查设备端的特征值属性配置,并确保在订阅后设备已发送数据更新。

根据你提供的代码和服务发现数据,问题很可能出在订阅的特征值对象与设备实际支持的特征值不匹配。

getServices() 返回的数据看,服务 xxxxxx00-aaaa-bbbb-cccc-dddddddddddd 下有两个特征值:

  1. xxxxxx01-aaaa-bbbb-cccc-dddddddddddd:属性为 writewriteNoResponse不支持 notifyindicate
  2. xxxxxx02-aaaa-bbbb-cccc-dddddddddddd:属性为 readnotify支持 notify

你的代码逻辑存在一个关键错误:

你正在尝试对不支持通知(notify)的特征值(xxxxxx01)进行订阅。

具体分析如下:

  1. 特征值对象构建错误

    • 你代码中构建的 characteristic 对象使用了 xxxxxx01 这个 UUID。
    • 你同时为这个对象添加了一个描述符(Descriptor),其 characteristicUuid 指向了 xxxxxx02,并且描述符的 UUID 是客户端特征值配置描述符(CCCD,00002902-...)。这个描述符通常用于启用/禁用 notifyindicate
    • 然而,根据服务发现结果,xxxxxx01 这个特征值根本没有描述符数组"descriptors": [])。CCCD 描述符是属于 xxxxxx02 特征值的。
  2. 操作对象与目标对象不匹配

    • 你调用 setCharacteristicChangeNotification(characteristic, true, ...) 时,传入的 characteristic 对象是 xxxxxx01
    • setCharacteristicChangeNotification 方法的作用是向 BLE 设备写入 CCCD 描述符的值(例如 0x0001 开启通知)。这个操作只能对支持 notifyindicate 属性的特征值进行
    • 由于 xxxxxx01 不支持 notify/indicate,它就没有对应的 CCCD 描述符。因此,即使系统调用没有返回错误,这个操作在协议层也是无效的,设备端不会为此特征值启用通知。
  3. 订阅了错误的特征值变化事件

    • 你通过 on('BLECharacteristicChange', ...) 订阅了特征值变化事件。
    • 但是,这个事件只会在你已成功为其调用 setCharacteristicChangeNotification 且设备主动发送了通知/指示的特征值上触发。
    • 由于你对 xxxxxx01 的启用通知操作实质无效,设备永远不会发送该特征值的通知,因此你订阅的回调永远不会被触发。

解决方案:

你需要将操作目标更正为支持 notify 的特征值 xxxxxx02

  1. 修正特征值对象:构建 characteristic 对象时,应使用从 getServices() 获取到的、支持 notify 的那个特征值的数据(即 xxxxxx02)。直接使用发现结果中的对象,而不是手动构建一个错误的对象。
    // 在 getServices 的成功回调中,找到目标特征值
    let targetCharacteristic: ble.BLECharacteristic | undefined = result[0]?.characteristics?.find(c => c.characteristicUuid === 'xxxxxx02-aaaa-bbbb-cccc-dddddddddddd');
    if (!targetCharacteristic) {
        console.error('未找到支持notify的特征值');
        return;
    }
    
  2. 使用正确的对象进行操作:将 targetCharacteristic 用于后续的 setCharacteristicChangeNotificationon('BLECharacteristicChange') 逻辑。
    gattClient.setCharacteristicChangeNotification(targetCharacteristic, true, (err, data) => {
        // ... 处理回调
    });
    // 订阅事件
    gattClient.on('BLECharacteristicChange', (characteristicChangeReq) => {
        // 这里 characteristicChangeReq.characteristicUuid 应该是 xxxxxx02
        // ... 处理数据
    });
    
  3. 确保写入操作针对正确的特征值:你的 writeCharacteristicValue 操作看起来是想向 xxxxxx01 发送指令,这可能是正确的,因为它是可写的。但接收响应的通知应该来自 xxxxxx02。请确认你的设备协议:是否是通过写入 xxxxxx01 发送命令,然后设备通过 xxxxxx02 的通知返回数据?这是BLE设备一种常见的“命令-响应”模式。

总结: 无法收到回调的根本原因是代码逻辑混淆了两个不同属性(writenotify)的特征值。请根据设备实际的服务和特征值定义,确保对支持 notify 的特征值进行订阅和启用通知操作。

回到顶部