BluetoothGatt.writeCharacteristic返回201错误,ESP32未收到BLE写入数据
问题分析与解决方案
错误码201对应GATT_INVALID_ATTRIBUTE_LENGTH,说明写入的数据长度超出了BLE特征允许的最大长度限制,以下是针对性排查和解决步骤:
1. 调整ESP32特征的长度配置
ESP32默认BLE特征的最大数据长度为20字节(MTU默认23,扣除3字节ATT协议头),如果加密后的会话密钥长度超过这个值,会直接触发201错误。
修改ESP32端代码,手动设置特征的最大支持长度:
caracteristicRecive=service->createCharacteristic(CHARACTERISTIC_UUID_2 , BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE| BLECharacteristic::PROPERTY_NOTIFY | BLECharacteristic::PROPERTY_INDICATE); // 设置特征最大支持长度,示例为64字节,可按需调整 caracteristicRecive->setLength(64); BLE2902 * desc= new BLE2902(); desc->setNotifications(true); caracteristicRecive->addDescriptor(desc); caracteristicRecive->setCallbacks(new MyCharacteristicCallback());
2. 主动协商BLE MTU
Android默认不会自动协商更大的MTU,需要主动请求扩展MTU以支持更大数据传输:
- 在连接成功后(比如
onConnectionStateChange回调中状态为BluetoothProfile.STATE_CONNECTED时)调用MTU请求:btGatt.requestMtu(256); // 请求256字节MTU,可根据需求调整 - 重写
onMtuChanged回调,确认MTU协商成功后再执行写入操作:@Override public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { super.onMtuChanged(gatt, mtu, status); if (status == BluetoothGatt.GATT_SUCCESS) { // MTU协商成功后执行写入逻辑 if(!aes.createSessionKey()) disconnect(); int res=btGatt.writeCharacteristic(characteristicSend, aes.encrypt(aes.sesKey), BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE); Log.d("data",String.valueOf(res)); } }
3. 检查加密后数据的实际长度
计算aes.encrypt(aes.sesKey)返回的字节数组长度,确保不超过MTU - 3(ATT协议头占用3字节)。比如MTU为256时,最大可写入253字节数据。
4. 验证ESP32端回调实现
确认MyCharacteristicCallback的onWrite方法正确重写,避免因回调未实现导致误以为未收到数据:
class MyCharacteristicCallback : public BLECharacteristicCallbacks { void onWrite(BLECharacteristic *pCharacteristic) override { std::string receivedData = pCharacteristic->getValue(); Serial.print("Received data length: "); Serial.println(receivedData.length()); Serial.print("Received data: "); for (uint8_t c : receivedData) { Serial.printf("%02X ", c); } Serial.println(); } };
5. 尝试切换写入类型
暂时将写入类型改为带响应的WRITE_TYPE_DEFAULT,获取更明确的错误反馈,排查无响应写入的兼容性问题:
int res=btGatt.writeCharacteristic(characteristicSend, aes.encrypt(aes.sesKey), BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
内容的提问来源于stack exchange,提问作者Andrei S.
相关产品推荐
相关产品推荐

