嵌入式linux管理网络的工具主要有wpa_supplicant 和networkmanager两种方式,它们都各自的工具来管理wifi网络,具体实现细节网上都有很详细的介绍。接下来要介绍的主要是嵌入式linux下使用networkmanager工具来实现wifi网络连接,本人使用的是友善之臂的nanopi S2开发板,已经移植好networkmanager工具。
关于NetworkManager
NetworkManager有自己的CLI工具:nmcli。使用nmcli用户可以查询网络连接的状态,也可以用来管理。优点:原始,语法相对简单;在CLI中使用NetworkManager很容易掌握。
常用命令:
nmcli r wifi on
nmcli dev wifi
nmcli dev wifi connect "SSID" password "PASSWORD" ifname wlan0
nmcli con
nmcli con up id YOUR_VPN_ID
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里面的内容如下:
文件里面很清晰的显示了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列表如下图:
上面已经完成了第一步,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);
}
效果图如下:
好了,到这儿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