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()获取的数据,然后去手动编写最开始的characteristic、descriptor等数据,然后再发送请求。
蓝牙设备能够正常进行ble连接,发送的指令也能够正常的执行,但是就是无法获取设备的回调。
gattClient.setCharacteristicChangeNotification方法的回调没有报错,应该是正常设置了特征值变化通知能力,**gattClient.on(‘BLECharacteristicChange’)**方法也没有报错,但是没有任何反应。请问为什么无法获取设备的回调呢?
更多关于HarmonyOS鸿蒙Next中ble订阅蓝牙低功耗设备的特征值变化事件BLECharacteristicChange,发送指令并操作成功后,没有得到设备的回调的实战教程也可以访问 https://www.itying.com/category-93-b0.html
我也是,请问解决了吗
更多关于HarmonyOS鸿蒙Next中ble订阅蓝牙低功耗设备的特征值变化事件BLECharacteristicChange,发送指令并操作成功后,没有得到设备的回调的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
解决了吗
我也是,请问解决了吗
在HarmonyOS Next中,订阅BLE特征值变化事件后未收到回调,可能原因包括:特征值未正确启用通知或指示;设备端未正确配置或发送数据;订阅操作与设备通信时序不同步;或设备连接不稳定。请检查设备端的特征值属性配置,并确保在订阅后设备已发送数据更新。
根据你提供的代码和服务发现数据,问题很可能出在订阅的特征值对象与设备实际支持的特征值不匹配。
从 getServices() 返回的数据看,服务 xxxxxx00-aaaa-bbbb-cccc-dddddddddddd 下有两个特征值:
xxxxxx01-aaaa-bbbb-cccc-dddddddddddd:属性为write和writeNoResponse,不支持notify或indicate。xxxxxx02-aaaa-bbbb-cccc-dddddddddddd:属性为read和notify,支持notify。
你的代码逻辑存在一个关键错误:
你正在尝试对不支持通知(notify)的特征值(xxxxxx01)进行订阅。
具体分析如下:
-
特征值对象构建错误:
- 你代码中构建的
characteristic对象使用了xxxxxx01这个 UUID。 - 你同时为这个对象添加了一个描述符(Descriptor),其
characteristicUuid指向了xxxxxx02,并且描述符的 UUID 是客户端特征值配置描述符(CCCD,00002902-...)。这个描述符通常用于启用/禁用notify或indicate。 - 然而,根据服务发现结果,
xxxxxx01这个特征值根本没有描述符数组("descriptors": [])。CCCD 描述符是属于xxxxxx02特征值的。
- 你代码中构建的
-
操作对象与目标对象不匹配:
- 你调用
setCharacteristicChangeNotification(characteristic, true, ...)时,传入的characteristic对象是xxxxxx01。 - 但
setCharacteristicChangeNotification方法的作用是向 BLE 设备写入 CCCD 描述符的值(例如0x0001开启通知)。这个操作只能对支持notify或indicate属性的特征值进行。 - 由于
xxxxxx01不支持notify/indicate,它就没有对应的 CCCD 描述符。因此,即使系统调用没有返回错误,这个操作在协议层也是无效的,设备端不会为此特征值启用通知。
- 你调用
-
订阅了错误的特征值变化事件:
- 你通过
on('BLECharacteristicChange', ...)订阅了特征值变化事件。 - 但是,这个事件只会在你已成功为其调用
setCharacteristicChangeNotification且设备主动发送了通知/指示的特征值上触发。 - 由于你对
xxxxxx01的启用通知操作实质无效,设备永远不会发送该特征值的通知,因此你订阅的回调永远不会被触发。
- 你通过
解决方案:
你需要将操作目标更正为支持 notify 的特征值 xxxxxx02。
- 修正特征值对象:构建
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; } - 使用正确的对象进行操作:将
targetCharacteristic用于后续的setCharacteristicChangeNotification和on('BLECharacteristicChange')逻辑。gattClient.setCharacteristicChangeNotification(targetCharacteristic, true, (err, data) => { // ... 处理回调 }); // 订阅事件 gattClient.on('BLECharacteristicChange', (characteristicChangeReq) => { // 这里 characteristicChangeReq.characteristicUuid 应该是 xxxxxx02 // ... 处理数据 }); - 确保写入操作针对正确的特征值:你的
writeCharacteristicValue操作看起来是想向xxxxxx01发送指令,这可能是正确的,因为它是可写的。但接收响应的通知应该来自xxxxxx02。请确认你的设备协议:是否是通过写入xxxxxx01发送命令,然后设备通过xxxxxx02的通知返回数据?这是BLE设备一种常见的“命令-响应”模式。
总结: 无法收到回调的根本原因是代码逻辑混淆了两个不同属性(write 与 notify)的特征值。请根据设备实际的服务和特征值定义,确保对支持 notify 的特征值进行订阅和启用通知操作。

