I have been using QtDBus and NetworkManager for a while but have run into a problem. I need to access the Wi-Fi devices IP address and the way to obtain it is to get the Wi-Fi device object, get its IP4Config property (a QDbusObjectPath object) and then to get the AddressData. The problem is that as soon as I try to obtain the AddressData using the interfaces property method, my application crashes.
I believe I need to register a meta type (I have done this for other types) but can't seem to figure out how to unpack the aa{sv} data returned from the property. Using qdbusviewer I can see the data for the IP address.
How can I get this information from the property?
Here is a snippet of the code which is encountering the problem. It seems I can get the QString property of Gateway but as soon as I try to get the AddressData my process crashes (as shown below).
cout << wifi_args.size() << endl;
cout << wifi_args[0].path().toStdString() << endl;
if (wifi_args.size() > 0) {
QDBusInterface wifi_device(NM_DBUS_SERVICE, wifi_args[0].path(),
NM_DBUS_INTERFACE_DEVICE,
QDBusConnection::systemBus());
const auto wifiInterface = wifi_device.property("Interface").toString();
// auto wifiIPv4 = wifi_device.property("Ip4Address").toInt();
auto ip4_config_path =
qdbus_cast<QDBusObjectPath>(wifi_device.property("Ip4Config"));
cout << "config path = " << ip4_config_path.path().toStdString()
<< endl;
QDBusInterface wifi_ip4_if(NM_DBUS_SERVICE, ip4_config_path.path(),
NM_DBUS_INTERFACE_IP4_CONFIG,
QDBusConnection::systemBus());
auto gateway = wifi_ip4_if.property("Gateway").toString();
auto ipv4 = wifi_ip4_if.property("AddressData");
// for (auto item : wifiIPv4) {
// cout << "Item";
// }
cout << "Interface = " << wifiInterface.toStdString() << endl;
cout << "Gateway = " << gateway.toStdString() << endl;
// cout << "Address = " << int_to_ipv4(wifiIPv4) << endl;
} else {
cerr << "ERROR: Multiple wifi devices found!" << endl;
}
Here is the output from the run:
michael_uman@ThinkPad-X1-Carbon-7th ~/gitroot/UXHUB-development (development)$ ./build-host/app/kylixctl/kylixctl list wifi
1
/org/freedesktop/NetworkManager/Devices/3
config path = /org/freedesktop/NetworkManager/IP4Config/8
Cannot construct placeholder type QDBusRawType
Aborted (core dumped)
You can safely get the property in question by using org.freedesktop.DBus.Properties.Get and then manually demarshall the response, similar to Fatal error when trying to get a DBus property with custom type
// Required operator for demarshalling aa{sv} signature
const QDBusArgument &operator>>(const QDBusArgument &argument, QList<QVariantMap> &varMapList)
{
argument.beginArray();
varMapList.clear();
while(!argument.atEnd()) {
QVariantMap map;
argument >> map;
varMapList.append(map);
}
argument.endArray();
return argument;
}
// Use generic property interface.
QDBusInterface getter(NM_DBUS_SERVICE, wifi_args[0].path(), "org.freedesktop.DBus.Properties", QDBusConnection::systemBus());
// Use the Get function to manually access the AddressData property.
auto reply = getter.call("Get", NM_DBUS_INTERFACE_IP4_CONFIG, "AddressData");
// Extract the needed argument from the reply.
auto arg = reply.arguments().first();
// Demarshall the argument into Qt's aa{sv} equivalent.
QList<QVariantMap> list;
arg.value<QDBusVariant>().variant().value<QDBusArgument>() >> list;
// Access the address data.
cout << "Address = " << list.first()["address"].toString().toStdString();
This should be sufficient to get the required data without crashing Qt.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With