本文档为上一个长对话的上下文总结,旨在为开启新对话提供完整的背景信息和代码逻辑参考。
bt_gap_cb 的 ESP_BT_GAP_ACL_DISCONN_CMPL_STAT_EVT 事件中,提取底层的 reason 断开原因。reason 为 0x13, 0x14, 0x15 (User Terminated / Local Host Terminated),视为手动断开,停止回连并开启广播 (ESP_BT_GENERAL_DISCOVERABLE)。0x08 (Link Timeout) 等异常断开,则启动一个后台 FreeRTOS 任务 bt_reconnect_task,每 5 秒尝试调用 esp_a2d_sink_connect() 一次,持续 5 分钟(60次)。bt_reconnect_task 中加入了判断:如果当前音频源正在播放 AirPlay (playback_control_get_source() == PLAYBACK_SOURCE_AIRPLAY),则立刻跳过当前的蓝牙回连动作,保证网络音频流畅。sdkconfig 里改了速度没用,因为 Antigravity IDE (基于 VSCode 插件体系) 烧录时默认使用它自己配置表的 460800。解决: 必须在 .vscode/settings.json 里硬编码 "idf.flashBaudRate": "xxx"。2000000 和 1500000,但在烧录时均出现 A fatal error occurred: Unable to verify flash chip connection (No serial data received)。原因是 CH340K 配合某些数据线、拓展坞或主板走线时,在高频下信号完整性崩溃。921600。虽然没有跑满极限,但比默认快了一倍,且绝不丢包翻车。esp_bt_cod_t cod; 时未清零,导致结构体里的 reserved_2 字段带入了栈空间的随机垃圾值。iOS 收到后发现格式类型不对,直接拒认并降级为普通蓝牙图标。解决: 加上 memset(&cod, 0, sizeof(cod));。esp_bt_gap_set_cod() 写在了 A2DP 初始化的最前面。结果当代码执行到 esp_a2d_sink_init() 和 esp_hf_client_init() (HFP免提) 时,底层 Bluedroid 协议栈会自动去注册设备类型,把我们手动设置的音响图标强行覆盖重置了。memset 及 esp_bt_gap_set_cod 的设置代码,移动到 bt_stack_evt_handler 的最后面(也就是在所有音频协议彻底启动完毕之后),并设置 major = 4, minor = 5, service = (1<<8) | (1<<5) (Audio + Rendering)。图标成功找回。77/127 (大约 60%)。77 且不一定能恢复。0x4D 即 77)。ESP_AVRC_RN_VOLUME_CHANGE 支持,彻底切断手机与音箱硬件音量的绝对同步。两者音量独立控制,互不干涉。esp_avrc_tg_cb 的音量回调逻辑中,特殊拦截并忽略 iOS 恶意下发的 77 这一数值,或者编写更复杂的防抖/音量快照恢复逻辑。