分享

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

 守常_1 2020-02-16

嵌入式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。

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

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

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

头文件:

  1. #ifndef WIFICONNECTTEST_H
  2. #define WIFICONNECTTEST_H
  3. #include <QWidget>
  4. #include <QFile>
  5. #include <QDebug>
  6. #include <QGridLayout>
  7. #include <QPainter>
  8. #include <QPixmap>
  9. #include <QPen>
  10. #include <QDialog>
  11. #include <QFormLayout>
  12. #include <QLineEdit>
  13. #include <QPushButton>
  14. #include <QMouseEvent>
  15. #include <QNetworkConfigurationManager>
  16. #include <QDesktopWidget>
  17. #include <QLabel>
  18. #include "inputpassworddialog.h"
  19. #define WIFINUM 10 //最多显示10个wifi
  20. class WifiConnectTest : public QWidget
  21. {
  22. Q_OBJECT
  23. public:
  24. WifiConnectTest(QWidget *parent = 0);
  25. ~WifiConnectTest();
  26. private slots:
  27. void wifiListInit();
  28. protected:
  29. bool eventFilter(QObject *obj, QEvent *event);
  30. private:
  31. QLabel *iconLabel[WIFINUM]; //显示wifi信号强度
  32. QLabel *connectLabel[WIFINUM]; //显示wifi连接状态
  33. QLabel *wifiNameLabel[WIFINUM]; //wifi名
  34. QWidget *wifiWidget[WIFINUM]; //包含wifi成员的widget
  35. QPushButton *connectButton[WIFINUM]; //wifi连接按钮
  36. };
  37. #endif // WIFICONNECTTEST_H
  1. #include "wificonnecttest.h"
  2. const QString wifiStrList = QString("/Settings/WiFi/wifi.ini");
  3. WifiConnectTest::WifiConnectTest(QWidget *parent)
  4. : QWidget(parent)
  5. {
  6. this->wifiListInit();
  7. QDesktopWidget desktop;
  8. this->setFixedSize(desktop.width()/2,desktop.height());
  9. }
  10. WifiConnectTest::~WifiConnectTest()
  11. {
  12. }
  13. void WifiConnectTest::wifiListInit()
  14. {
  15. QFile file(wifiStrList);
  16. if(!file.open(QIODevice::ReadOnly)){
  17. qDebug()<<"No such file!";
  18. return;
  19. }
  20. int curLine = 0;
  21. QString line;
  22. QVBoxLayout *vLayout = new QVBoxLayout;
  23. if(file.size()!=0){
  24. QTextStream in(&file);
  25. QString signalFlag = "SIGNAL"; //表示wifi信号字符
  26. QString wifiFlag = "SSID"; //wifi名字符
  27. QString modeFlag = "MODE"; //wifi连接模式
  28. line = in.readLine();
  29. if(!line.isEmpty()){
  30. int signalIndex = line.indexOf(signalFlag); //文件对应的wifi信号强度索引值
  31. int wifiIndex = line.indexOf(wifiFlag); //文件对应的wifi名索引值
  32. int modeIndex = line.indexOf(modeFlag);
  33. while (curLine < WIFINUM) {
  34. line = in.readLine();
  35. QString tmpStr = line;
  36. QString curConnection = line.left(1); //已连接wifi判断
  37. QString wifiName = line.mid(wifiIndex,(modeIndex-wifiIndex)).simplified(); //获取wifi名称
  38. int signalValue = tmpStr.mid(signalIndex,3).simplified().toInt(); //获取wifi的信号强度
  39. if(!wifiName.isEmpty()){
  40. QGridLayout *gridLayout = new QGridLayout();
  41. wifiWidget[curLine] = new QWidget(this); //wifi对应的属性栏
  42. wifiWidget[curLine]->setObjectName(QString("wifiName*%1*%2").arg(QString::number(curLine)).arg(wifiName));
  43. wifiWidget[curLine]->installEventFilter(this); //安装事件过滤器,选中wifi后弹出连接wifi的接口按钮
  44. wifiWidget[curLine]->setStyleSheet(QString("QWidget::hover{background-color:darkgray}").append(QString("QWidget{background-color:transparent;}")));
  45. wifiNameLabel[curLine] = new QLabel(wifiWidget[curLine]);
  46. wifiNameLabel[curLine]->setText(wifiName); //显示wifi名
  47. QPixmap pix = QPixmap(60,40); //根据wifi信号强度绘制wifi信号
  48. pix.fill(Qt::transparent);
  49. QPainter paint(&pix);
  50. QPen pen = QPen();
  51. pen.setColor(Qt::darkGreen);
  52. pen.setWidth(4);
  53. paint.setPen(pen);
  54. for(int k=2;k<7;k++){
  55. if(k == (signalValue/20+3)){
  56. QPen penGray = QPen();
  57. penGray.setColor(Qt::gray);
  58. penGray.setWidth(4);
  59. paint.setPen(penGray);
  60. }
  61. paint.drawLine(8*k,48-7*k,8*k,35);
  62. }
  63. paint.end();
  64. iconLabel[curLine] = new QLabel(wifiWidget[curLine]);
  65. iconLabel[curLine]->setPixmap(pix); //添加wifi信号强度图标
  66. connectLabel[curLine] = new QLabel(wifiWidget[curLine]);
  67. if(curConnection=="*") //wifi连接状态,wifi名前如果有"*",表示当前wifi处于连接状态
  68. connectLabel[curLine]->setText("已连接");
  69. connectButton[curLine] = new QPushButton(wifiWidget[curLine]);
  70. connectButton[curLine]->setStyleSheet(QString("QPushButton{background-color:lightgray;}").append(QString("QPushButton::pressed{background-color:darkgray;}")));
  71. connectButton[curLine]->setText(tr("连接"));
  72. connectButton[curLine]->setVisible(false);
  73. gridLayout->addWidget(wifiNameLabel[curLine],0,0,1,3); //在wifi属性框中添加wifi对应的属性信息
  74. gridLayout->addWidget(connectLabel[curLine],0,3,1,1);
  75. gridLayout->addWidget(iconLabel[curLine],0,4,1,1);
  76. gridLayout->addWidget(connectButton[curLine],1,3,1,1);
  77. gridLayout->setMargin(0);
  78. gridLayout->setSpacing(0);
  79. wifiWidget[curLine]->setLayout(gridLayout);
  80. vLayout->addWidget(wifiWidget[curLine]);
  81. vLayout->setMargin(2);
  82. vLayout->setSpacing(0);
  83. }
  84. curLine++;
  85. }
  86. }
  87. }
  88. file.close();
  89. this->setLayout(vLayout);
  90. }

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

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

  1. bool WifiConnectTest::eventFilter(QObject *obj, QEvent *event)
  2. {
  3. QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
  4. if(mouseEvent->type() == QEvent::MouseButtonPress){
  5. if(mouseEvent->button()==Qt::LeftButton){
  6. if(obj->objectName().contains("wifiName")){
  7. QString wifiName = obj->objectName().section('*',-1);
  8. static int curLine = 0;
  9. connectButton[curLine]->setVisible(false); //隐藏所有wifi连接button
  10. curLine = obj->objectName().section('*',1,1).toInt();
  11. connectButton[curLine]->setVisible(true); //选中当前wifi属性框后,显示wifi连接按钮
  12. connect(connectButton[curLine],&QPushButton::clicked,[=](){
  13. InputPasswordDialog *inputPassword = new InputPasswordDialog(); //实例化wifi密码输入窗口
  14. inputPassword->show();
  15. connect(inputPassword,&InputPasswordDialog::confirmPassword,[=](QString password){
  16. QString connectNetWorkStr = QString("nmcli dev wifi connect %1 password %2");
  17. QByteArray array = connectNetWorkStr.arg(wifiName).arg(password).toLatin1();
  18. char *cmdStr = array.data(); //QString 转 char*
  19. if(-1!=system(cmdStr)){
  20. QNetworkConfigurationManager mgr;
  21. if(mgr.isOnline()){ //wifi已连接
  22. qDebug("wifi is online!");
  23. connectButton[curLine]->setText(tr("已连接"));
  24. }
  25. else{
  26. qDebug("wifi is offline!");
  27. connectButton[curLine]->setText(tr("offline"));
  28. }
  29. }
  30. });
  31. });
  32. return true;
  33. }
  34. }
  35. }
  36. return QWidget::eventFilter(obj, event);
  37. }

效果图如下:

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

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多