bluetooth — C ++: пройти через сообщение DBUS, чтобы найти адаптер BlueZ 5 с помощью итератора

Я пытаюсь найти доступные адаптеры BlueTooth, используя обновленный Dbus API BlueZ 5.

В отличие от 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.
. ]

Руководство по портированию и использованию BlueZ 5 API говорит «Концепция адаптера по умолчанию всегда была немного нечеткой, и значение не могло быть изменено, поэтому, если приложениям нужно что-то подобное, они могут, например, просто выберите первый адаптер, с которым они сталкиваются в ответе 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

Решение

Вы могли бы использовать org.freedesktop.DBus.Properties интерфейс, который должен быть реализован объектом адаптера BLuez 5 для получения свойств адаптера.

Насколько я знаю, вам все равно придется обходить массив, пока вы не найдете путь к объекту адаптера, но, начиная с него, вы можете сделать что-то вроде:

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);

//...

Таким образом, вы можете просто искать в массиве пути к объектам адаптера и игнорировать все остальное. С помощью этого пути к объекту вы можете запросить необходимые свойства и / или начать отправку вызовов метода.

Я не уверен, что это можно считать более «элегантным», и, вероятно, он тоже не будет быстрее, потому что я думаю, что вызовы дополнительных методов будут медленнее, чем обход массива.
Это должно / могло бы уменьшить объем кода и сделать его более читабельным, хотя …

0

Другие решения

Других решений пока нет …