嵌入式Linux下BlueZ_inc蓝牙外设程序报错问题求助
蓝牙外设应用在QCS404DK嵌入式Linux上的BlueZ适配问题
我是嵌入式编程新手,正在开发一款运行在外设设备上的蓝牙应用:需广播指定UUID的蓝牙服务,供手机扫描配对后发送指令触发功能。初期为简化开发,基于BlueZ和DBus的BlueZ_inc库,参考示例peripheral.c编写代码,程序在Ubuntu 22.04编译运行正常,手机可连接并通过on_local_char_write回调交互。但交叉编译至QCS404DK嵌入式Linux(内核版本:Linux nf-64 4.14.117-perf #1 SMP PREEMPT Wed Aug 25 08:30:19 UTC 2021 aarch64)运行时,抛出如下错误:
2021-08-25 08:00:32:993 DEBUG [Adapter] failed to register advertisement (error 19: GDBus.Error:org.freedesktop.DBus.Error.UnknownMethod: Unknown method 'RegisterAdvertisement' or interface 'org.bluez.LEAdvertisingManager1'.) 2021-08-25 08:00:32:995 DEBUG [Adapter] failed to register application (error 19: GDBus.Error:org.freedesktop.DBus.Error.UnknownMethod: Unknown method 'RegisterApplication' or interface 'org.bluez.GattManager1'.)
请问是否是嵌入式Linux未部署BlueZ导致?有没有更适合该场景的库?
附适配Ubuntu与嵌入式Linux的源码:
#include <glib.h> #include <stdio.h> #include <signal.h> #include "adapter.h" #include "device.h" #include "logger.h" #include "agent.h" #include "application.h" #include "advertisement.h" #include "utility.h" #include "parser.h" #define TAG "Main" #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" GMainLoop *loop = NULL; Adapter *default_adapter = NULL; Advertisement *advertisement = NULL; Application *app = NULL; void on_central_state_changed(Adapter *adapter, Device *device) { log_debug(TAG, "remote central %s is %s", binc_device_get_address(device), binc_device_get_connection_state_name(device)); // ConnectionState state = binc_device_get_connection_state(device); // if (state == CONNECTED) { // binc_adapter_stop_advertising(adapter, advertisement); // } else if (state == DISCONNECTED){ // binc_adapter_start_advertising(adapter, advertisement); // } } const char *on_local_char_read(const Application *application, const char *address, const char *service_uuid, const char *char_uuid) { if (g_str_equal(service_uuid, HTS_SERVICE_UUID) && g_str_equal(char_uuid, TEMPERATURE_CHAR_UUID)) { const guint8 bytes[] = {0x06, 0x6f, 0x01, 0x00, 0xff, 0xe6, 0x07, 0x03, 0x03, 0x10, 0x04, 0x00, 0x01}; GByteArray *byteArray = g_byte_array_sized_new(sizeof(bytes)); g_byte_array_append(byteArray, bytes, sizeof(bytes)); binc_application_set_char_value(application, service_uuid, char_uuid, byteArray); return NULL; } return BLUEZ_ERROR_REJECTED; } const char *on_local_char_write(const Application *application, const char *address, const char *service_uuid, const char *char_uuid, GByteArray *byteArray) { log_debug(TAG, "On Char Write. UUID = %s", char_uuid); Parser *parser = parser_create(byteArray, LITTLE_ENDIAN); if(g_str_equal( char_uuid, TEMPERATURE_CHAR_UUID)){ GString *settings = parser_get_string(parser); log_debug(TAG, "Settings = %s", settings->str); g_string_free(settings, TRUE); }else{ log_debug(TAG, "Unknown Characteristic %s", char_uuid); } parser_free(parser); return NULL; } void on_local_char_start_notify(const Application *application, const char *service_uuid, const char *char_uuid) { log_debug(TAG, "on start notify"); if (g_str_equal(service_uuid, HTS_SERVICE_UUID) && g_str_equal(char_uuid, TEMPERATURE_CHAR_UUID)) { const guint8 bytes[] = {0x06, 0x6A, 0x01, 0x00, 0xff, 0xe6, 0x07, 0x03, 0x03, 0x10, 0x04, 0x00, 0x01}; GByteArray *byteArray = g_byte_array_sized_new(sizeof(bytes)); g_byte_array_append(byteArray, bytes, sizeof(bytes)); binc_application_notify(application, service_uuid, char_uuid, byteArray); g_byte_array_free(byteArray, TRUE); } } void on_local_char_stop_notify(const Application *application, const char *service_uuid, const char *char_uuid) { log_debug(TAG, "on stop notify"); } gboolean callback(gpointer data) { if (app != NULL) { binc_adapter_unregister_application(default_adapter, app); binc_application_free(app); app = NULL; } if (advertisement != NULL) { binc_adapter_stop_advertising(default_adapter, advertisement); binc_advertisement_free(advertisement); } if (default_adapter != NULL) { binc_adapter_free(default_adapter); default_adapter = NULL; } g_main_loop_quit((GMainLoop *) data); return FALSE; } gboolean on_request_confirmation(Device *device) { log_debug(TAG, "requesting Confirmation for '%s", binc_device_get_name(device)); return TRUE; } static void cleanup_handler(int signo) { if (signo == SIGINT) { log_error(TAG, "received SIGINT"); callback(loop); } } void advertise_new_service() { binc_adapter_discoverable_on(default_adapter); log_debug(TAG, "Adapter name: %s", binc_adapter_get_name(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, "SleepHub Anywhere"); binc_advertisement_set_services(advertisement, adv_service_uuids); g_ptr_array_free(adv_service_uuids, TRUE); binc_adapter_start_advertising(default_adapter, advertisement); Agent *agent = NULL; agent = binc_agent_create(default_adapter, "/org/bluez/BincAgent", DISPLAY_YES_NO); binc_agent_set_request_confirmation_cb(agent, &on_request_confirmation); // 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_READ | GATT_CHR_PROP_INDICATE | GATT_CHR_PROP_WRITE | GATT_CHR_PROP_NOTIFY); 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_adapter_register_application(default_adapter, app); } void on_powered_state_changed(Adapter *adapter, gboolean state) { log_debug(TAG, "powered '%s' (%s)", state ? "on" : "off", binc_adapter_get_path(adapter)); if( state) { advertise_new_service(); } } 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 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); log_debug(TAG, "Power status = %d", binc_adapter_get_powered_state(default_adapter)); if (!binc_adapter_get_powered_state(default_adapter)) { binc_adapter_power_on(default_adapter); log_debug(TAG, "Power on adapter %s", binc_adapter_get_path(default_adapter)); } else { advertise_new_service(); } } else { log_debug("MAIN", "No default_adapter found"); } // Bail out after some time g_timeout_add_seconds(600, callback, loop); // Start the mainloop g_main_loop_run(loop); // Clean up mainloop g_main_loop_unref(loop); // Disconnect from DBus g_dbus_connection_close_sync(dbusConnection, NULL, NULL); g_object_unref(dbusConnection); return 0; }
补充说明:程序可在嵌入式系统编译执行,但运行时触发上述错误。
问题分析与解决方案
一、错误原因判断
不是未部署BlueZ,而是嵌入式系统上的BlueZ版本过低或编译时未启用相关功能:
- 错误提示的
org.bluez.LEAdvertisingManager1和org.bluez.GattManager1是BlueZ 5.40+才稳定提供的DBus接口,你的嵌入式系统内核是2021年的4.14,配套的BlueZ版本大概率低于这个要求,或者编译BlueZ时没有开启--enable-experimental或--enable-gatt、--enable-le等关键配置项。 - 另外,检查嵌入式系统上的BlueZ服务是否正常运行:执行
systemctl status bluetooth(如果用systemd)或/etc/init.d/bluetooth status,确认蓝牙服务已启动,且DBus接口正常暴露。
二、适合嵌入式场景的替代方案
1. 升级/重新编译BlueZ
如果硬件支持,建议重新编译适配QCS404DK的BlueZ版本:
- 选择BlueZ 5.50+的稳定版本,编译时添加
--enable-experimental --enable-gatt --enable-le --enable-dbus等参数,确保GATT和LE广告管理接口被编译进去。 - 替换嵌入式系统上的BlueZ二进制文件和配置,重启蓝牙服务后再测试你的程序。
2. 使用更轻量的蓝牙库
如果不想依赖BlueZ+DBus的复杂架构,可考虑以下轻量库:
- Zephyr Bluetooth Stack:适合资源受限的嵌入式设备,支持BLE peripheral角色,提供直接的API操作,无需DBus,可直接集成到应用中。
- Btstack:轻量级、可移植的蓝牙协议栈,支持BLE peripheral,可直接在用户空间运行,无需系统级BlueZ服务,适合嵌入式场景。
- 芯片厂商专属SDK:如果使用的是Nordic、ST等品牌的蓝牙芯片,对应的nRF5 SDK、BlueNRG-MS SDK等提供原生BLE API,无需依赖BlueZ,适配性更强。
三、临时调试建议
- 在嵌入式系统上执行
dbus-send --system --type=method_call --print-reply --dest=org.bluez /org/bluez/hci0 org.freedesktop.DBus.Introspectable.Introspect,查看hci0适配器的DBus接口列表,确认是否存在LEAdvertisingManager1和GattManager1。 - 如果接口不存在,说明BlueZ版本不支持或未启用,必须重新编译BlueZ。
- 检查蓝牙硬件是否支持BLE:执行
hciconfig hci0,查看是否有LE相关标识。
内容的提问来源于stack exchange,提问作者Nguyen Minh Binh
相关产品推荐
相关产品推荐

