ESP32 Arduino写入ANCS控制点特征遇0xA1格式错误求助
问题:ANCS Control Point写入返回0xA1(命令格式错误)
环境与背景
- 使用Arduino ESP32,遵循ANCS规范向Control Point特征写入命令
- 尝试获取通知的App Identifier属性,但写入后返回错误码
0xA1:Invalid command (0xA1). The command was improperly formatted.
命令定义代码
uint8_t notificationAttributesCommand[7]; notificationAttributesCommand[0] = 0x00; // Command ID: Get Notification Attributes notificationAttributesCommand[1] = (uint8_t)(notificationUID >> 24); // Notification UID (Most significant byte) notificationAttributesCommand[2] = (uint8_t)(notificationUID >> 16); // Second byte notificationAttributesCommand[3] = (uint8_t)(notificationUID >> 8); // Third byte notificationAttributesCommand[4] = (uint8_t)(notificationUID); // Least significant byte // Attribute IDs and their maximum length (as per your specification) notificationAttributesCommand[5] = 0x01; // Attribute ID for App Identifier
发送逻辑(loop函数)
void loop() { if (newNotificationFlag) { // Send the command to the Control Point characteristic if (pControlPointCharacteristic != nullptr) { Serial.println("Sending Get Notification Attributes command to Control Point..."); if (pControlPointCharacteristic->canWrite()) { Serial.println("before writing to pControlPointCharacteristic!"); pControlPointCharacteristic->writeValue(notificationAttributesCommand, sizeof(notificationAttributesCommand), true); Serial.println("after writing to pControlPointCharacteristic!"); } else { Serial.println("loop(): Control Point Characteristic cannot be written."); } } else { Serial.println("Control Point characteristic is null"); } // Reset the flag newNotificationFlag = false; } }
修改的日志输出代码(BLERemoteCharacteristic.cpp)
case ESP_GATTC_WRITE_CHAR_EVT: { log_d("case ESP_GATTC_WRITE_CHAR_EVT"); // Determine if this event is for us and, if not, pass onwards. if (evtParam->write.handle != getHandle()) { break; } // Check the write status to confirm if it was successful // Check the write status to confirm if it was successful or if an error occurred if (evtParam->write.status == ESP_GATT_OK) { log_d("Write to Control Point characteristic was successful."); } else { // Handle specific ANCS error codes switch (evtParam->write.status) { case 0xA0: log_d("Write to Control Point characteristic failed. Error: Unknown command (0xA0). The commandID was not recognized by the NP."); break; case 0xA1: log_d("Write to Control Point characteristic failed. Error: Invalid command (0xA1). The command was improperly formatted."); break; case 0xA2: log_d("Write to Control Point characteristic failed. Error: Invalid parameter (0xA2). One of the parameters (e.g., NotificationUID) does not refer to an existing object on the NP."); break; case 0xA3: log_d("Write to Control Point characteristic failed. Error: Action failed (0xA3). The action was not performed."); break; default: log_d("Write to Control Point characteristic failed. Unknown error status: %d", evtParam->write.status); break; } } // There is nothing further we need to do here. This is merely an indication // that the write has completed and we can unlock the caller. m_semaphoreWriteCharEvt.give(); log_d("after m_semaphoreWriteCharEvt.give, There is nothing further we need to do here. This is merely an indication that the write has completed and we can unlock the caller."); break; } // ESP_GATTC_WRITE_CHAR_EVT
核心错误日志
Write to Control Point characteristic failed. Error: Invalid command (0xA1). The command was improperly formatted.
问题分析与修正
错误的核心是Get Notification Attributes命令的格式不符合ANCS规范:
根据ANCS规范,该命令的结构必须包含:
- 1字节:Command ID(0x00)
- 4字节:Notification UID(大端字节序)
- 重复的(Attribute ID + 2字节最大长度) 字段对:每个需要获取的属性,都必须同时指定属性ID和期望返回的最大长度(大端字节序),二者缺一不可。
你的代码只添加了Attribute ID(0x01),但缺失了对应的2字节最大长度字段,导致命令结构不完整,触发0xA1错误。
修正后的命令代码
uint8_t notificationAttributesCommand[9]; notificationAttributesCommand[0] = 0x00; // Command ID: Get Notification Attributes notificationAttributesCommand[1] = (uint8_t)(notificationUID >> 24); // Notification UID MSB notificationAttributesCommand[2] = (uint8_t)(notificationUID >> 16); notificationAttributesCommand[3] = (uint8_t)(notificationUID >> 8); notificationAttributesCommand[4] = (uint8_t)(notificationUID); // Notification UID LSB // Attribute ID + 2字节最大长度(大端字节序) notificationAttributesCommand[5] = 0x01; // Attribute ID: App Identifier notificationAttributesCommand[6] = 0x00; // 最大长度高位(示例:255字节) notificationAttributesCommand[7] = 0xFF; // 最大长度低位 // 若需要获取多个属性,可继续追加(Attribute ID + 2字节长度)的组合
额外注意事项
- 命令总长度计算公式:
1(Command ID) + 4(UID) + N*3,其中N是要获取的属性数量(每个属性占3字节) - 最大长度字段必须使用大端字节序,即使只需要短内容,也不能省略这两个字节
内容的提问来源于stack exchange,提问作者Đức Thanh Nguyễn
相关产品推荐
相关产品推荐

