HarmonyOS 鸿蒙Next中BLE使用ble.GattWriteType.WRITE_NO_RESPONSE分包发送40多个字节数据设备收到成功率低问题
HarmonyOS 鸿蒙Next中BLE使用ble.GattWriteType.WRITE_NO_RESPONSE分包发送40多个字节数据设备收到成功率低问题
发送数据:AA5503001a0300321414000e00009600000190000000000000000000000000AE
代码如下:
// 新增命令队列及发送状态标识
private commandQueue: Uint8Array[] = []; // 发送队列
private isSending: boolean = false; // 是否正在发送中
async sendToBytes(stSent: string) {
console.error(Tag, '=========发送数据:' + stSent);
let bytes = BluHexUtils.hexStringToUint8Array(stSent);
if (this.connectModel != null && this.gattClientDevice != null) {
if (bytes.length > 20) {
// console.error('aa','=============走这里')
let dataArr = this.splitUint8Array(bytes, 20);
// 将数据块加入队列(而不是直接发送)
this.commandQueue.push(...dataArr);
// this.commandQueue.push(bytes)
// 触发队列处理
this.processQueue(ble.GattWriteType.WRITE_NO_RESPONSE);
} else {
// console.error('aa','=============走这里1111')
this.commandQueue.push(bytes);
// 触发队列处理
this.processQueue(ble.GattWriteType.WRITE);
}
}
}
// 将 Uint8Array 按指定 chunkSize 分割成多个子数组
splitUint8Array(data: Uint8Array, chunkSize: number): Uint8Array[] {
const chunks: Uint8Array[] = [];
for (let i = 0; i < data.length; i += chunkSize) {
// 使用 slice 截取当前块(不修改原数组)
const chunk = data.slice(i, i + chunkSize);
chunks.push(chunk);
}
return chunks;
}
private processQueue(writeType: ble.GattWriteType) {
if (this.isSending || this.commandQueue.length === 0) {
return; // 正在发送或队列为空时退出
}
this.isSending = true;
const nextData = this.commandQueue.shift()!; // 取出队列头部数据
this.sendData(nextData, writeType)
.finally(() => {
this.isSending = false;
// 递归处理下一个数据
this.processQueue(writeType);
});
}
private async sendData(data: Uint8Array, writeType: ble.GattWriteType) {
return new Promise<void>((resolve, reject) => {
let write = this.connectModel?.writeCharacteristic;
if (!write) {
reject('Write characteristic not found');
return;
}
let characteristic: ble.BLECharacteristic = {
serviceUuid: write.serviceUuid,
characteristicUuid: write.characteristicUuid,
characteristicValue: this.typedArrayToBuffer(data),
descriptors: write.descriptors
};
let stBytes = BluHexUtils.toHexWithSpaces(data);
// console.error('aa','===============发送:writeType:'+writeType+'================='+stBytes)
this.gattClientDevice?.writeCharacteristicValue(characteristic, writeType, (err) => {
if (err) {
console.error(Tag, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
if(writeType == ble.GattWriteType.WRITE_NO_RESPONSE){
reject(err);
// console.error('aa','===============发送:wwwwwwwwwwwwww:err')
} else {
// setTimeout(() => {
reject(err);
// }, 300)
}
} else {
console.error(Tag, 'writeCharacteristicValue success');
if(writeType == ble.GattWriteType.WRITE_NO_RESPONSE){
// console.error('aa','===============发送:wwwwwwwwwwwwww:success')
resolve();
} else {
// setTimeout(() => {
resolve();
// }, 300)
}
}
});
});
}
请问要如何处理 才能保证设备收到的成功率 。。 只有长命令成功率低,一般段命令成功率高。。只是偶尔出现成功率低问题
更多关于HarmonyOS 鸿蒙Next中BLE使用ble.GattWriteType.WRITE_NO_RESPONSE分包发送40多个字节数据设备收到成功率低问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS Next中,使用 WRITE_NO_RESPONSE 发送超过40字节数据时,建议将数据拆分为20字节/包进行发送。鸿蒙BLE协议栈对无响应写入有MTU限制,大包可能被底层丢弃。可通过调整发送间隔(建议15-20ms)提升成功率,同时确保设备端MTU配置匹配。若需可靠传输,可改用 WRITE_TYPE_DEFAULT 并在应用层实现确认机制。
更多关于HarmonyOS 鸿蒙Next中BLE使用ble.GattWriteType.WRITE_NO_RESPONSE分包发送40多个字节数据设备收到成功率低问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
针对BLE分包发送成功率低的问题,建议从以下几个方面优化:
- 增加发送间隔
在processQueue
方法中,建议在每次发送后添加50-100ms的延迟,避免蓝牙设备处理不过来:
private processQueue(writeType: ble.GattWriteType) {
if (this.isSending || this.commandQueue.length === 0) {
return;
}
this.isSending = true;
const nextData = this.commandQueue.shift()!;
this.sendData(nextData, writeType)
.finally(() => {
this.isSending = false;
// 增加100ms延迟
setTimeout(() => {
this.processQueue(writeType);
}, 100);
});
}
- 实现重发机制
修改sendData
方法,增加重试逻辑:
private async sendData(data: Uint8Array, writeType: ble.GattWriteType, retryCount = 3) {
return new Promise<void>((resolve, reject) => {
const attemptSend = (attempt = 0) => {
let write = this.connectModel?.writeCharacteristic;
// ...原有发送逻辑...
this.gattClientDevice?.writeCharacteristicValue(characteristic, writeType, (err) => {
if (err && attempt < retryCount) {
setTimeout(() => attemptSend(attempt + 1), 50);
} else if (err) {
reject(err);
} else {
resolve();
}
});
};
attemptSend();
});
}
- 检查MTU大小
确保设备支持足够的MTU大小(建议至少23字节):
// 在连接后检查MTU
this.gattClientDevice?.getBLEMtu((err, mtu) => {
console.log('Current MTU:', mtu);
if (mtu < 23) {
this.gattClientDevice?.setBLEMtu(23);
}
});
- 考虑使用WRITE_WITH_RESPONSE
对于关键数据包,可以混合使用两种写入方式:
// 修改processQueue逻辑
private processQueue() {
// ...
const useResponse = this.commandQueue.length === 1; // 最后一包使用response
this.sendData(nextData, useResponse ? ble.GattWriteType.WRITE : ble.GattWriteType.WRITE_NO_RESPONSE)
// ...
}
这些修改应该能显著提高长数据包的传输成功率。