You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

嵌入式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,适配性更强。

三、临时调试建议

  1. 在嵌入式系统上执行dbus-send --system --type=method_call --print-reply --dest=org.bluez /org/bluez/hci0 org.freedesktop.DBus.Introspectable.Introspect,查看hci0适配器的DBus接口列表,确认是否存在LEAdvertisingManager1和GattManager1。
  2. 如果接口不存在,说明BlueZ版本不支持或未启用,必须重新编译BlueZ。
  3. 检查蓝牙硬件是否支持BLE:执行hciconfig hci0,查看是否有LE相关标识。

内容的提问来源于stack exchange,提问作者Nguyen Minh Binh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 00:20:55