Bluez_inC(binc)外设示例在树莓派4失效,Debian笔记本可正常运行
问题
测试Bluez_in_C(简称binc)外设示例时,该代码在Debian 11/12笔记本上可正常运行,但在树莓派4(Raspbian 12)上无法启动广播,报错日志如下:
2025-03-25 01:19:23:536 DEBUG [Adapter] successfully registered application
2025-03-25 01:19:23:537 ERROR [Adapter] failed to register advertisement (error 36: GDBus.Error:org.bluez.Error.Failed: Failed to parse advertisement.)
核心代码片段如下:
#define HTS_SERVICE_UUID "00001809-0000-1000-8000-00805f9b34fb" #define TEMPERATURE_CHAR_UUID "00002a1c-0000-1000-8000-00805f9b34fb" #define CUD_CHAR "00002901-0000-1000-8000-00805f9b34fb" int main(void) { // Get a DBus connection GDBusConnection *dbusConnection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL); // Setup handler for CTRL+C if (signal(SIGINT, cleanup_handler) == SIG_ERR) log_error(TAG, "can't catch SIGINT"); // Setup mainloop loop = g_main_loop_new(NULL, FALSE); // Get the default adapter default_adapter = binc_adapter_get_default(dbusConnection); if (default_adapter != NULL) { log_debug(TAG, "using default_adapter '%s'", binc_adapter_get_path(default_adapter)); // Make sure the adapter is on binc_adapter_set_powered_state_cb(default_adapter, &on_powered_state_changed); if (!binc_adapter_get_powered_state(default_adapter)) { binc_adapter_power_on(default_adapter); } // Setup remote central connection state callback binc_adapter_set_remote_central_cb(default_adapter, &on_central_state_changed); // Setup advertisement GPtrArray *adv_service_uuids = g_ptr_array_new(); g_ptr_array_add(adv_service_uuids, HTS_SERVICE_UUID); advertisement = binc_advertisement_create(); binc_advertisement_set_local_name(advertisement, "BINC"); binc_advertisement_set_interval(advertisement, 500, 500); binc_advertisement_set_tx_power(advertisement, 5); binc_advertisement_set_services(advertisement, adv_service_uuids); g_ptr_array_free(adv_service_uuids, TRUE); binc_adapter_start_advertising(default_adapter, advertisement); // Start application app = binc_create_application(default_adapter); binc_application_add_service(app, HTS_SERVICE_UUID); binc_application_add_characteristic( app, HTS_SERVICE_UUID, TEMPERATURE_CHAR_UUID, GATT_CHR_PROP_INDICATE | GATT_CHR_PROP_WRITE); binc_application_add_descriptor( app, HTS_SERVICE_UUID, TEMPERATURE_CHAR_UUID, CUD_CHAR, GATT_CHR_PROP_READ | GATT_CHR_PROP_WRITE); const guint8 cud[] = "hello there"; GByteArray *cudArray = g_byte_array_sized_new(sizeof(cud)); g_byte_array_append(cudArray, cud, sizeof(cud)); binc_application_set_desc_value(app, HTS_SERVICE_UUID, TEMPERATURE_CHAR_UUID, CUD_CHAR, cudArray); binc_application_set_char_read_cb(app, &on_local_char_read); binc_application_set_char_write_cb(app, &on_local_char_write); binc_application_set_char_start_notify_cb(app, &on_local_char_start_notify); binc_application_set_char_stop_notify_cb(app, &on_local_char_stop_notify); binc_application_set_char_updated_cb(app, &on_local_char_updated); binc_adapter_register_application(default_adapter, app); }
(注:代码未包含回调及资源销毁逻辑)
问题定位与修复
核心原因
树莓派4的蓝牙硬件及Raspbian 12默认的BlueZ配置对广播参数的限制比Debian笔记本更严格,同时代码的广播启动顺序不符合BlueZ规范:
- TX功率超出硬件支持:树莓派4内置蓝牙模块最大仅支持+4dBm,代码中设置的
5超出范围,导致广播解析失败。 - 广播间隔参数不合法:BlueZ广播间隔单位为0.625ms,代码中
500对应312.5ms,树莓派蓝牙模块不支持该间隔范围。 - 广播启动顺序错误:代码先启动广播再注册GATT应用,但BlueZ要求广播中包含的服务UUID必须先存在于已注册的GATT应用中,否则解析失败。
修复步骤
- 调整TX功率到合法范围:
修改代码中的TX功率设置为4:binc_advertisement_set_tx_power(advertisement, 4); - 修改广播间隔为硬件支持的值:
例如设置为160(对应100ms,符合多数蓝牙硬件要求):binc_advertisement_set_interval(advertisement, 160, 160); - 调整广播启动顺序:
将广播启动代码移到GATT应用注册之后,确保服务UUID已被BlueZ识别:// 先注册GATT应用 binc_adapter_register_application(default_adapter, app); // 再启动广播 binc_adapter_start_advertising(default_adapter, advertisement); - 更新树莓派的BlueZ版本:
执行命令更新到最新稳定版,解决兼容性问题:sudo apt update && sudo apt install --only-upgrade bluez -y - 重启蓝牙服务:
sudo systemctl restart bluetooth
内容的提问来源于stack exchange,提问作者Michel
相关产品推荐
相关产品推荐

