Qt基于networkmanager嵌入式linux的wifi网络连接

嵌入式linux管理网络的工具主要有wpa_supplicant 和networkmanager两种方式,它们都各自的工具来管理wifi网络,具体实现细节网上都有很详细的介绍。接下来要介绍的主要是嵌入式linux下使用networkmanager工具来实现wifi网络连接,本人使用的是友善之臂的nanopi S2开发板,已经移植好networkmanager工具。

关于NetworkManager

NetworkManager有自己的CLI工具:nmcli。使用nmcli用户可以查询网络连接的状态,也可以用来管理。优点:原始,语法相对简单;在CLI中使用NetworkManager很容易掌握。

常用命令:

  • 开启wifi

nmcli r wifi on 

  • 扫描附近wifi热点

nmcli dev wifi

  • 连接到指定wifi热点

nmcli dev wifi connect "SSID" password "PASSWORD" ifname wlan0

  • 查看VPN

nmcli con

  • 连接VPN

nmcli con up id YOUR_VPN_ID

  • 断开VPN

nmcli con down id YOUR_VPN_ID

实现方法

借助上面nmcli工具只需要3步即可通过终端连接一个wifi网络:

开启wifi->扫描wifi热点->连接到指定wifi热点。

那实际上我们只需要借助qt实现类似windows系统下wifi连接的可视化操作界面,具体分为两个步骤:

1.显示wifi列表信息,按照wifi的信号强度排序,预留wifi连接接口。

2.选择指定的wifi,输入wifi密码,连接wifi。

system("sudo nmcli r wifi on");                              //开启wifi
system("sudo nmcli dev wifi > /Settings/WiFi/wifi.ini");     //把扫描到的wifi信息输出到指定文件   
//system("sudo nmcli con > /Settings/WiFi/wifiCon.ini");     //显示当前连接的wifi网络

上面通过调用系统命令开启wifi,并把扫描到的wifi信息定向输出到/Setting/WiFi/wifi.ini文件中,通过解析wifi.ini文件里面的内容来显示wifi列表信息,并依据wifi信号强度进行排序,测试得到wifi.ini里面的内容如下:

Qt基于networkmanager嵌入式linux的wifi网络连接_第1张图片

文件里面很清晰的显示了wifi的相关属性信息,那我们接下来需要做的就是解析这个文件:

头文件:

#ifndef WIFICONNECTTEST_H
#define WIFICONNECTTEST_H

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "inputpassworddialog.h"

#define WIFINUM 10                              //最多显示10个wifi

class WifiConnectTest : public QWidget
{
    Q_OBJECT

public:
    WifiConnectTest(QWidget *parent = 0);
    ~WifiConnectTest();
private slots:
    void wifiListInit();

protected:
    bool eventFilter(QObject *obj, QEvent *event);

private:
    QLabel *iconLabel[WIFINUM];                 //显示wifi信号强度
    QLabel *connectLabel[WIFINUM];              //显示wifi连接状态
    QLabel *wifiNameLabel[WIFINUM];             //wifi名
    QWidget *wifiWidget[WIFINUM];               //包含wifi成员的widget
    QPushButton *connectButton[WIFINUM];        //wifi连接按钮
};

#endif // WIFICONNECTTEST_H

 

#include "wificonnecttest.h"

const QString wifiStrList = QString("/Settings/WiFi/wifi.ini");

WifiConnectTest::WifiConnectTest(QWidget *parent)
    : QWidget(parent)
{
    this->wifiListInit();
    QDesktopWidget desktop;
    this->setFixedSize(desktop.width()/2,desktop.height());
}

WifiConnectTest::~WifiConnectTest()
{

}

void WifiConnectTest::wifiListInit()
{
    QFile file(wifiStrList);
    if(!file.open(QIODevice::ReadOnly)){
        qDebug()<<"No such file!";
        return;
    }
    int curLine = 0;
    QString line;

    QVBoxLayout *vLayout = new QVBoxLayout;
    if(file.size()!=0){
        QTextStream in(&file);
        QString signalFlag = "SIGNAL";      //表示wifi信号字符
        QString wifiFlag = "SSID";          //wifi名字符
        QString modeFlag = "MODE";          //wifi连接模式

        line =  in.readLine();
        if(!line.isEmpty()){
            int signalIndex = line.indexOf(signalFlag);     //文件对应的wifi信号强度索引值
            int wifiIndex = line.indexOf(wifiFlag);         //文件对应的wifi名索引值
            int modeIndex = line.indexOf(modeFlag);
            while (curLine < WIFINUM) {
                line =  in.readLine();
                QString tmpStr = line;
                QString curConnection = line.left(1);       //已连接wifi判断
                QString wifiName = line.mid(wifiIndex,(modeIndex-wifiIndex)).simplified();  //获取wifi名称
                int signalValue = tmpStr.mid(signalIndex,3).simplified().toInt();           //获取wifi的信号强度
                if(!wifiName.isEmpty()){
                    QGridLayout *gridLayout = new QGridLayout();
                    wifiWidget[curLine] = new QWidget(this);                                //wifi对应的属性栏
                    wifiWidget[curLine]->setObjectName(QString("wifiName*%1*%2").arg(QString::number(curLine)).arg(wifiName));
                    wifiWidget[curLine]->installEventFilter(this);                          //安装事件过滤器,选中wifi后弹出连接wifi的接口按钮
                    wifiWidget[curLine]->setStyleSheet(QString("QWidget::hover{background-color:darkgray}").append(QString("QWidget{background-color:transparent;}")));

                    wifiNameLabel[curLine] = new QLabel(wifiWidget[curLine]);
                    wifiNameLabel[curLine]->setText(wifiName);                              //显示wifi名

                    QPixmap pix = QPixmap(60,40);       //根据wifi信号强度绘制wifi信号
                    pix.fill(Qt::transparent);
                    QPainter paint(&pix);
                    QPen pen = QPen();
                    pen.setColor(Qt::darkGreen);
                    pen.setWidth(4);
                    paint.setPen(pen);
                    for(int k=2;k<7;k++){
                        if(k == (signalValue/20+3)){
                            QPen penGray = QPen();
                            penGray.setColor(Qt::gray);
                            penGray.setWidth(4);
                            paint.setPen(penGray);
                        }
                        paint.drawLine(8*k,48-7*k,8*k,35);
                    }
                    paint.end();

                    iconLabel[curLine] = new QLabel(wifiWidget[curLine]);
                    iconLabel[curLine]->setPixmap(pix); //添加wifi信号强度图标

                    connectLabel[curLine] = new QLabel(wifiWidget[curLine]);
                    if(curConnection=="*")              //wifi连接状态,wifi名前如果有"*",表示当前wifi处于连接状态
                        connectLabel[curLine]->setText("已连接");

                    connectButton[curLine] = new QPushButton(wifiWidget[curLine]);
                    connectButton[curLine]->setStyleSheet(QString("QPushButton{background-color:lightgray;}").append(QString("QPushButton::pressed{background-color:darkgray;}")));
                    connectButton[curLine]->setText(tr("连接"));
                    connectButton[curLine]->setVisible(false);

                    gridLayout->addWidget(wifiNameLabel[curLine],0,0,1,3);      //在wifi属性框中添加wifi对应的属性信息
                    gridLayout->addWidget(connectLabel[curLine],0,3,1,1);
                    gridLayout->addWidget(iconLabel[curLine],0,4,1,1);
                    gridLayout->addWidget(connectButton[curLine],1,3,1,1);
                    gridLayout->setMargin(0);
                    gridLayout->setSpacing(0);
                    wifiWidget[curLine]->setLayout(gridLayout);

                    vLayout->addWidget(wifiWidget[curLine]);
                    vLayout->setMargin(2);
                    vLayout->setSpacing(0);
                }
                curLine++;
            }
        }
    }
    file.close();
    this->setLayout(vLayout);
}

wifi信息的解析通过上面wifiListInit()来实现,主要是找准wifi.ini文件对应的wifi名以及wifi信号强度的位置信息,并根据信号强度值绘制wifi信号图。最终生成的wifi列表如下图:

Qt基于networkmanager嵌入式linux的wifi网络连接_第2张图片

上面已经完成了第一步,wifi列表信息的显示,接着第二步模仿windows下wifi连接,选中wifi后显示连接wifi的接口按钮,并输入wifi密码,连接wifi。具体实现方法如下:

bool WifiConnectTest::eventFilter(QObject *obj, QEvent *event)
{
    QMouseEvent *mouseEvent = static_cast(event);
    if(mouseEvent->type() == QEvent::MouseButtonPress){
        if(mouseEvent->button()==Qt::LeftButton){
            if(obj->objectName().contains("wifiName")){
                QString wifiName = obj->objectName().section('*',-1);
                static int curLine = 0;
                connectButton[curLine]->setVisible(false);                  //隐藏所有wifi连接button
                curLine = obj->objectName().section('*',1,1).toInt();
                connectButton[curLine]->setVisible(true);                   //选中当前wifi属性框后,显示wifi连接按钮

                connect(connectButton[curLine],&QPushButton::clicked,[=](){
                    InputPasswordDialog *inputPassword = new InputPasswordDialog();     //实例化wifi密码输入窗口
                    inputPassword->show();
                    connect(inputPassword,&InputPasswordDialog::confirmPassword,[=](QString password){
                        QString connectNetWorkStr = QString("nmcli dev wifi connect %1 password %2");
                        QByteArray array = connectNetWorkStr.arg(wifiName).arg(password).toLatin1();
                        char *cmdStr = array.data();        //QString 转 char*
                        if(-1!=system(cmdStr)){
                            QNetworkConfigurationManager mgr;
                            if(mgr.isOnline()){             //wifi已连接
                                qDebug("wifi is online!");
                                connectButton[curLine]->setText(tr("已连接"));
                            }
                            else{
                                qDebug("wifi is offline!");
                                connectButton[curLine]->setText(tr("offline"));
                            }
                        }
                    });
                });
                return true;
            }
        }
    }
    return QWidget::eventFilter(obj, event);
}

效果图如下:

Qt基于networkmanager嵌入式linux的wifi网络连接_第3张图片

Qt基于networkmanager嵌入式linux的wifi网络连接_第4张图片

好了,到这儿wifi的连接基本上已经实现了,至于后续密码输入(输入法实现)就是各位看官自个儿去实现了。当然,到目前为止仅仅只是讲到了基于networkmanager工具实现一个wifi热点的连接,在关于networkmanager上也提到过,networkmanager工具是可以查询当前连接状态的,能够保存连接过的wifi网络信息,通过nmcli con命令可以查看连接过的wifi列表,通过命令nmcli con up id YOUR_VPN_ID可以直接连接。总的来说,通过networkmanager工具来实现wifi网络管理还是比较方便的,实现语法简单,只是相当于用qt简单封装了一次,实现了可视化操作。

 

完整测试Demo下载地址:https://download.csdn.net/download/p154613730/10854608

 

 

你可能感兴趣的:(Qt)