C++:使用迭代器遍历 DBUS 消息以查找 BlueZ 5 适配器
Posted
技术标签:
【中文标题】C++:使用迭代器遍历 DBUS 消息以查找 BlueZ 5 适配器【英文标题】:C++: Traverse DBUS message to find BlueZ 5 adapter using iterator 【发布时间】:2014-05-06 17:34:27 【问题描述】:我正在尝试使用 BlueZ 5 更新的 Dbus API 查找可用的蓝牙适配器。
与 BlueZ 4 不同,BlueZ 4 有专门的方法(即 org.bluez.Manager.FindAdapter()),BlueZ 5 使用 FreeDesktop ObjectManager 接口和 GetManagedObjects() 方法。此方法返回一个非常大的结果数组:
array [
dict entry(
object path "/org/bluez"
array [
dict entry(
string "org.freedesktop.DBus.Introspectable"
array [
]
)
dict entry(
string "org.bluez.AgentManager1"
array [
]
)
dict entry(
string "org.bluez.ProfileManager1"
array [
]
)
]
)
dict entry(
object path "/org/bluez/hci0"
array [
dict entry(
string "org.freedesktop.DBus.Introspectable"
array [
]
)
dict entry(
string "org.bluez.Adapter1"
array [
dict entry(
string "Address"
variant string "XX:XX:XX:XX:XX:XX"
)
dict entry(
string "Name"
variant string "My_Adapter"
)
dict entry(
string "Alias"
variant string "kubuntu-0"
)
dict entry(
string "Class"
variant uint32 0
)
dict entry(
string "Powered"
variant boolean false
)
dict entry(
string "Discoverable"
variant boolean true
)
dict entry(
string "DiscoverableTimeout"
variant uint32 0
)
dict entry(
string "Pairable"
variant boolean true
)
dict entry(
string "PairableTimeout"
variant uint32 0
)
dict entry(
string "Discovering"
variant boolean false
)
dict entry(
string "UUIDs"
variant array [
string "00001200-0000-1000-8000-00805f9b34fb"
string "00001800-0000-1000-8000-00805f9b34fb"
string "00001801-0000-1000-8000-00805f9b34fb"
string "0000110e-0000-1000-8000-00805f9b34fb"
string "0000110c-0000-1000-8000-00805f9b34fb"
]
)
dict entry(
string "Modalias"
variant string "usb:sdfasdfsadf"
)
]
)
dict entry(
string "org.freedesktop.DBus.Properties"
array [
]
)
dict entry(
string "org.bluez.Media1"
array [
]
)
dict entry(
string "org.bluez.NetworkServer1"
array [
]
)
]
)
.
.etc.
. ]
The BlueZ 5 API Intro and Porting Guide 说,“默认适配器的概念总是有点模糊,并且值无法更改,因此如果应用程序需要类似的东西,他们可以选择他们遇到的第一个适配器GetManagedObjects 回复。"
我已经使用迭代器编写了 C++ 代码来执行此操作(我没有使用 Python 的经验),但是对于看起来如此简单的事情来说真的很长:
if (dbus_message_iter_init(reply, &rootIter) && //point iterator to reply message
DBUS_TYPE_ARRAY == dbus_message_iter_get_arg_type(&rootIter)) //get the type of message that iter points to
debug_print("Type Array.\n");
DBusMessageIter arrayElementIter;
dbus_message_iter_recurse(&rootIter, &arrayElementIter); //assign new iterator to first element of array
debug_print("-->Descending into Array (recursing).\n");
while(!adapterFound)
if (DBUS_TYPE_DICT_ENTRY == dbus_message_iter_get_arg_type(&arrayElementIter))
debug_print(" Type Dict_Entry.\n");
DBusMessageIter dictEntryIter;
dbus_message_iter_recurse(&arrayElementIter,&dictEntryIter ); //assign new iterator to first element of
debug_print(" -->Descending into Dict_Entry (recursing).\n");
if (DBUS_TYPE_OBJECT_PATH == dbus_message_iter_get_arg_type(&dictEntryIter))
debug_print(" Type DBUS_TYPE_OBJECT_PATH.\n");
dbus_message_iter_get_basic(&dictEntryIter, &adapter_path);
if(device && strstr(adapter_path,device))
adapterFound = TRUE;
debug_print(" Adapter %s FOUND!\n",device);
dbus_message_iter_next(&dictEntryIter);
if (DBUS_TYPE_ARRAY == dbus_message_iter_get_arg_type(&dictEntryIter))
debug_print(" Type DBUS_TYPE_ARRAY.\n");
DBusMessageIter innerArrayIter;
dbus_message_iter_recurse(&dictEntryIter, &innerArrayIter);
dbus_message_iter_next(&innerArrayIter);
debug_print(" -->Descending into Array (recursing).\n");
if (DBUS_TYPE_DICT_ENTRY == dbus_message_iter_get_arg_type(&innerArrayIter))
debug_print(" Type Dict_Entry.\n");
DBusMessageIter innerDictEntryIter;
dbus_message_iter_recurse(&innerArrayIter,&innerDictEntryIter ); //assign new iterator to first element of
debug_print(" -->Descending into Dict_Entry (recursing).\n");
if (DBUS_TYPE_STRING == dbus_message_iter_get_arg_type(&innerDictEntryIter))
debug_print(" Type DBUS_TYPE_STRING.\n");
char *dbusObject;
dbus_message_iter_get_basic(&innerDictEntryIter, &dbusObject);
debug_print(" This is an object of type:%s.\n", dbusObject);
if(strncmp(dbusObject,adapterString,strCmpLimit))
debug_print(" Not an adapter.\n");
else
if(!device)
debug_print(" No adapter given, so using first available: %s\n", adapter_path);
adapterFound = TRUE;
debug_print(" Adapter.\n");
debug_print(" <--Ascending from Dict_Entry.\n");
debug_print(" <--Ascending from Array (top layer).\n");
//dbus_message_iter_get_basic(&dictEntryIter, &adapter_path);
debug_print(" <--Ascending from Dict_Entry.\n");
debug_print("<--Ascending from Array (top layer).\n");
if(!dbus_message_iter_has_next(&arrayElementIter)) break; //check to see if end of array
else dbus_message_iter_next(&arrayElementIter);
//while loop end --used to traverse array
//end if - outer arrray
else return 0;
换句话说,我必须为树的每个分支定义一个新的迭代器,只是为了每次都找到一个位于固定位置的字符串。 (array[x]->secondfield[2]->firstfieldstring) 我的问题(最后,我知道)是有人能指出一个更优雅/更快的解决方案吗?
【问题讨论】:
【参考方案1】:您可以使用应由 BLuez 5 Adapter 对象实现的 org.freedesktop.DBus.Properties 接口来获取适配器属性。
据我所知,您仍然需要遍历数组,直到找到适配器对象路径,但从那里开始,您可以执行以下操作:
DBusMessage *msg = dbus_message_new_method_call(
"org.bluez",
adapter_object_path,
"org.freedesktop.DBus.Properties", "Get");
const char *property = "Powered"; // (e.g.)
dbus_message_append_args(msg,
DBUS_TYPE_STRING, &property,
DBUS_TYPE_INVALID);
//...
这样,您可以只在数组中查找适配器对象路径,而忽略其余所有内容。使用此对象路径,您可以请求所需的属性和/或开始发送方法调用。
我不确定这是否可以被认为更“优雅”,而且它可能也不会更快,因为我认为额外的方法调用会比数组遍历慢。 它应该/可以减少代码量并使其更具可读性...
【讨论】:
以上是关于C++:使用迭代器遍历 DBUS 消息以查找 BlueZ 5 适配器的主要内容,如果未能解决你的问题,请参考以下文章