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

使用sd-bus在C语言中控制蓝牙开关异常的技术求助

问题:sd-bus控制蓝牙Powered属性异常(开启正常,关闭无效)

我需要用C语言通过sd-bus实现以下busctl命令的功能:

busctl set-property org.bluez /org/bluez/hci0 org.bluez.Adapter1 Powered b true
busctl set-property org.bluez /org/bluez/hci0 org.bluez.Adapter1 Powered b false

尝试了两种实现方式,但均出现异常:设置powered = true时蓝牙能正常开启,但设置powered = false时无法关闭蓝牙;甚至在蓝牙已关闭的情况下,执行设置false的代码会意外开启蓝牙。

代码片段1:使用sd_bus_set_property()函数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <systemd/sd-bus.h>

int main(int argc, char *argv[]) {
    sd_bus_error error = SD_BUS_ERROR_NULL;
    sd_bus *bus = NULL;
    int r;
    bool powered = true;  /* to turn on*/
    //bool powered = false;  /* to turn off*/

    /* Connect to the system bus */
    r = sd_bus_open_system(&bus);
    if (r < 0) {
        fprintf(stderr, "Failed to connect to system bus: %s\n", strerror(-r));
        goto finish;
    }
    printf("Connected to system bus\n");

    /* Set the property value */
    r = sd_bus_set_property(bus,
                            "org.bluez",        /* service to contact */
                            "/org/bluez/hci0",  /* object path */
                            "org.bluez.Adapter1",/* interface name */
                            "Powered",          /* property name */
                            &error,             /* object to return error in */
                            "b",                /* type */
                            &powered            /* pointer to boolean variable */
                           );
    if (r < 0) {
        fprintf(stderr, "Failed to set property: %s\n", error.message);
        goto finish;
    }
    printf("Successfully turned off\n");

finish:
    sd_bus_error_free(&error);
    sd_bus_unref(bus);

    return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}

代码片段2:直接调用org.freedesktop.DBus.Properties.Set方法

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <systemd/sd-bus.h>

int main(int argc, char *argv[]) {
    sd_bus *bus = NULL;
    sd_bus_message *m = NULL;
    sd_bus_error error = SD_BUS_ERROR_NULL; 
    int r;
    bool powered = true;  /* to turn on*/
    //bool powered = false;  /* to turn off*/
    
    r = sd_bus_open_system(&bus);
    if (r < 0) {
        fprintf(stderr, "Failed to connect to system bus: %s\n", strerror(-r));
        goto finish;
    }
    printf("Connected to system bus\n");
    
    r = sd_bus_message_new_method_call(bus, &m, "org.bluez", "/org/bluez/hci0",
                                       "org.freedesktop.DBus.Properties", "Set");
    if (r < 0) {
        fprintf(stderr, "Failed to create method call: %s\n", strerror(-r));
        goto finish;
    }
    
    r = sd_bus_message_append(m, "ss", "org.bluez.Adapter1", "Powered");
    if (r < 0) {
        fprintf(stderr, "Failed to append message: %s\n", strerror(-r));
        goto finish;
    }
    
    r = sd_bus_message_open_container(m, 'v', "b");
    if (r < 0) {
        fprintf(stderr, "Failed to open container: %s\n", strerror(-r));
        goto finish;
    }
    
    r = sd_bus_message_append_basic(m, 'b', &powered);
     if (r < 0) {
        fprintf(stderr, "Failed append_basic: %s\n", strerror(-r));
        goto finish;
    }
    
    r = sd_bus_message_close_container(m);
     if (r < 0) {
        fprintf(stderr, "Failed to close container: %s\n", strerror(-r));
        goto finish;
    }
    
    r = sd_bus_call(bus, m, 0, &error, NULL);
    if (r < 0) {
        fprintf(stderr, "Failed to make method call: %s\n", error.message);
        goto finish;
    }
    
finish:
    sd_bus_error_free(&error);
    sd_bus_message_unref(m);
    sd_bus_unref(bus);

    return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}

问题分析与解决建议

1. 检查运行权限

修改蓝牙适配器的电源状态通常需要root权限或加入bluetooth用户组。普通用户可能仅能执行开启操作,但关闭操作需要更高权限。建议使用sudo运行程序测试:

sudo ./your_compiled_program

2. 验证属性设置结果

在代码中添加读取属性的逻辑,确认设置操作是否真正生效。例如在设置成功后添加以下代码:

bool current_power;
sd_bus_error error_get = SD_BUS_ERROR_NULL;
r = sd_bus_get_property(bus,
                        "org.bluez",
                        "/org/bluez/hci0",
                        "org.bluez.Adapter1",
                        "Powered",
                        &error_get,
                        "b",
                        &current_power);
if (r < 0) {
    fprintf(stderr, "Failed to get property: %s\n", error_get.message);
} else {
    printf("Current Powered state: %s\n", current_power ? "true" : "false");
}
sd_bus_error_free(&error_get);

如果读取结果和设置值不符,说明bluez服务没有正确处理请求,需排查服务状态。

3. 检查bluez服务状态与版本

  • 查看bluetooth服务状态:systemctl status bluetooth,确保服务正常运行,无报错。
  • 确认bluez版本:bluetoothctl --version,部分旧版本bluez对Powered属性的写入逻辑可能存在限制,可尝试更新到最新稳定版。

4. 排查蓝牙占用情况

若有其他进程或设备正在使用蓝牙,可能导致无法关闭适配器。可先断开所有蓝牙设备,关闭蓝牙相关程序(如bluetoothctl)后再测试代码。

内容的提问来源于stack exchange,提问作者its_me_mak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 19:24:55