获取Linux中可用的WiFi连接列表

问题描述 投票:0回答:1

我尝试使用Qt5通过D-Bus消息在Fedora 31 Linux中获取SSID列表。

我正在检查许多教程,但是仍然无法通过D-Bus进行通信,而且我仍然不了解接口,路径和服务之间的差异。借助文档帮助(https://developer.gnome.org/NetworkManager/stable/spec.html)和Internet,我写道:

QDBusInterface nm("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager", "org.freedesktop.NetworkManager.Device.Wireless", QDBusConnection::systemBus());

  if(nm.isValid()) {
      QDBusMessage msg = nm.call("GetAllAccessPoints");

  }

但是变量“ msg”收到一个参数:

"No interface „org.freedesktop.NetworkManager.Device.Wireless” in  object at path /org/freedesktop/NetworkManager"

我如何连接到D-Bus?

qt qt5 fedora dbus qdbus
1个回答
2
投票

您的困惑是有道理的,因为该过程并不是很直观。基本上,您需要做的是首先创建一个代表NetworkManager本身的QDBusInterface。通过该对象,您需要获取网络接口列表,对其进行迭代,过滤出WiFi接口,创建相应的QDBusInterface,指示该接口扫描可用网络,然后请求可见访问点列表。然后,您将获得每个访问点对象的SSID属性。这是一个简单的示例,演示了使用普通Qt的过程:

list_ssid.pro:

QT -= gui
QT += dbus

SOURCES += list_ssid.cpp

list_ssid.cpp:

#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QStringList>
#include <QtDBus/QtDBus>
#include <QDebug>
#include <QThread>

int main(int argc, char **argv)
{
    QCoreApplication app(argc, argv);

    // get the interface to nm    
    QDBusInterface nm("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager",
            "org.freedesktop.NetworkManager", QDBusConnection::systemBus());
    if(!nm.isValid())
    {
        qFatal("Failed to connect to the system bus");
    }

    // get all devices
    QDBusMessage msg = nm.call("GetDevices");
    qDebug() << "GetDevices reply: " << msg << endl;
    QDBusArgument arg = msg.arguments().at(0).value<QDBusArgument>();

    if(arg.currentType() != QDBusArgument::ArrayType)
    {
        qFatal("Something went wrong with getting the device list");
    }
    QList<QDBusObjectPath> pathsLst = qdbus_cast<QList<QDBusObjectPath> >(arg);
    foreach(QDBusObjectPath p, pathsLst)
    {
        qDebug() << "DEV PATH: " << p.path();
        // creating an interface used to gather this devices properties
        QDBusInterface device("org.freedesktop.NetworkManager", p.path(),
        "org.freedesktop.NetworkManager.Device", QDBusConnection::systemBus());
        // 2 is WiFi dev, see https://people.freedesktop.org/~lkundrak/nm-docs/nm-dbus-types.html#NMDeviceType
        if (device.property("DeviceType").toInt() != 2) 
        {
            continue;
        }
        // we got a wifi device, let's get an according dbus interface
        QDBusInterface wifi_device("org.freedesktop.NetworkManager", p.path(),
        "org.freedesktop.NetworkManager.Device.Wireless", QDBusConnection::systemBus());
        // we need to call scan on the inteface prior to request the list of interfaces
        QMap<QString, QVariant> argList;
        QDBusMessage msg = wifi_device.call("RequestScan", argList);
        QThread::sleep(2); // not the best solution, but here we just wait for the scan

        // doing the actual call
        msg = wifi_device.call("GetAllAccessPoints");
        qDebug()<< "Answer for GetAllAccessPoints:  " << msg << endl << endl;
        // dig out the paths of the Access Point objects:
        QDBusArgument ap_list_arg = msg.arguments().at(0).value<QDBusArgument>();
        QList<QDBusObjectPath> ap_path_list = qdbus_cast<QList<QDBusObjectPath> >(ap_list_arg);
        // and iterate through the list
        foreach(QDBusObjectPath p ,ap_path_list)
        {
            // for each Access Point we create an interface
            QDBusInterface ap_interface("org.freedesktop.NetworkManager", p.path(),
            "org.freedesktop.NetworkManager.AccessPoint", QDBusConnection::systemBus());
            // and getting the name of the SSID
            qDebug() << "SSID: " << ap_interface.property("Ssid").toString();
        }
    }



    return 0;
}

为了比较,使用networkmanager-qt也是如此:

CMakeLists.txt:

project(ssid_list LANGUAGES CXX)

set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Qt5 REQUIRED COMPONENTS
    Core
    Gui
    Network
    DBus
)
find_package(KF5NetworkManagerQt REQUIRED)

add_executable(ssid_list
  ssid_list.cpp
)
target_link_libraries(ssid_list Qt5::Core Qt5::DBus Qt5::Network KF5::NetworkManagerQt)

ssid_list.cpp

#include <arpa/inet.h>
#include <QThread>

#include <NetworkManagerQt/Manager>
#include <NetworkManagerQt/Device>
#include <NetworkManagerQt/WirelessDevice>
#include <NetworkManagerQt/AccessPoint>

int main()
{
    // getting all of the devices, and iterate through them
    NetworkManager::Device::List list = NetworkManager::networkInterfaces();
    Q_FOREACH (NetworkManager::Device::Ptr dev, list)
    {
        if(dev->type() != NM_DEVICE_TYPE_WIFI)
        {
            //skipping non-wifi interfaces
            continue;
        }
        // creating a Wifi device with this object path
        NetworkManager::WirelessDevice wifi_dev(dev->uni());
        wifi_dev.requestScan();
        QThread::sleep(2); // still not the best solution:w
        //get the Object Path of all the visible access points
        // and iterate through
        foreach(QString ap_path, wifi_dev.accessPoints())
        {
            // creating an AccessPoint object with this path
            NetworkManager::AccessPoint ap(ap_path);
            // and finally get the SSID
            qDebug() << "SSID:" << ap.ssid();

        }
    }
}
热门问题
推荐问题
最新问题