使用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", ¤t_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
相关产品推荐
相关产品推荐

