Ang layunin ay upang magsulat ng isang Qt application para sa Raspberry Pi 4 na maaaring magamit upang lumipat sa pagitan ng iba't ibang mga WLAN access point at mag imbak ng mga kaugnay na kredensyal.
Gumamit ako ng isang imahe ng raspbian buster lite at isang pag install ng Qt tulad ng inilarawan sa Qt sa Raspberry Pi 4 bilang isang panimulang punto.
Bilang karagdagan, na install ko ang NetworkManager, na maaaring magamit sa pamamagitan ng shell command (nmcli ...) lumikha, mag configure, at pamahalaan ang mga koneksyon sa network.
Ang impormasyon tungkol dito ay matatagpuan sa ilalim ng https://wiki.debian.org/de/NetworkManager o https://developer.gnome.org/NetworkManager/stable/nmcli.html.
Nag aalok ang NetworkManager ng isang utos na maaaring magamit upang simulan ang isang proseso ng pagsubaybay, na pagkatapos ay magkomento sa mga pagbabago sa iba't ibang mga interface (wlan0 o eth0) (hal. hindi magagamit, disconnected, pagkonekta, konektado, ...).
Gusto kong gamitin ang pagsubaybay na ito upang ipakita ang iba't ibang mga katayuan ng mga lokasyon ng network sa GUI. 2 problema ang lumabas:
- kung ang ilang mga utos ng NMCLI ay inisyu nang mabilis, pagkatapos ay ang feedback tungkol sa iba't ibang mga katayuan ay dumating na may isang oras pagkaantala at hindi maaaring ipakita nang live sa GUI.
- Ang feedback ng mga utos ng NMCLI ay ipinadala sa iba't ibang mga slot at sa gayon ay maaaring maging mahina coordinated.
Pagsubaybay sa function
Una sa lahat, kailangan namin ang pagsubaybay function (monitorDevices) at ang pampublikong slot function, na intercepts at sinusuri ang pagsubaybay output at pagkatapos ay ipadala ang mga mensahe ng katayuan sa GUI, halimbawa.
Sa function na "monitorDevices", na awtomatikong nagsisimula kapag nagsimula ang application, ang utos ng nmcli ay sinimulan sa sudo: sudo nmcli monitor
Ang pahayag na "setProcessChannelMode(QProcess::MergedChannels)" ay nagsasaad na ang "Standard Output" at "Standard Error" ay ipinapakita nang magkasama sa isang channel at sa gayon ay maaaring masuri na may isang function.
Ang linya "connect(device_monitoring_process, SIGNAL(readyReadStandardOutput()), ito, SLOT (processOutput()))" ay ginagamit sa tuwing ang isang mensahe ay ipinapakita (readyReadStandardOutput), ito ay ipinadala sa slot "processOutput".
void CmdLauncher::monitorDevices() {
QStringList device_monitoring_on = {"nmcli", "monitor"};
device_monitoring_process = new QProcess(this);
device_monitoring_process->setProcessChannelMode(QProcess::MergedChannels);
device_monitoring_process->start("sudo", device_monitoring_on);
connect(device_monitoring_process, SIGNAL(readyReadStandardOutput()), this, SLOT(processOutput()));
}
</:code1:>
Pag andar ng pagsusuri
Ang pagsusuri ng mga mensahe ay pagkatapos ay isinasagawa sa "processOutput" function. Ang QProcess senderProcess ay humaharang sa lahat ng mensahe ng lahat ng nmcli command - hindi lamang sa mga ng monitoring command.
void CmdLauncher::processOutput() {
QProcess* senderProcess = qobject_cast<QProcess*>(sender());
senderProcess->setReadChannel(QProcess::StandardOutput);
QString message = QString::fromLocal8Bit(senderProcess->readAllStandardOutput());
qDebug() << "CmdLauncher::processOutput message: " << message << endl;
if (message.contains("Error:")) {
message.remove(QString("\n"));
error_messages = message;
emit getErrorMessagesChanged();
if (message.contains(QString("Error: unknown connection"))) {
secrets_required = true;
emit getSecretsRequiredChanged();
}
}
// wifi
if (message.contains("wlan0: connected") || message.contains("wlan0:connected")) {
wifi_device_state = "Wifi-Connected";
emit getWifiDeviceStateChanged();
error_messages = "";
emit getErrorMessagesChanged();
rescanWifi();
testInternetConnection();
}
}
</:code2:>
Simulan ang isa pang proseso ng nmcli
Kung ngayon ay magsisimula ka ng isa pang utos ng nmcli na may function sa ibaba, ang output ay na intercept sa pamamagitan ng pag andar ng pagsubaybay sa itaas at pagkatapos ay maaaring masuri at karagdagang naproseso sa "outputProcess".
Ang function na ito ay lumilipat sa isang umiiral na koneksyon sa network at sinisimulan ito. Mahalagang huwag isama ang "set_wifi_process->waitForReadyRead()" o "set_wifi_process->waitForFinished()", dahil pagkatapos ay ma-block ang output ng lahat ng mensahe hanggang sa matapos ang prosesong ito.
void CmdLauncher::setWifi(QString ssid) {
error_messages = "";
emit getErrorMessagesChanged();
QString uuid = "";
for (int i = 0 ; i networkConnections.length() ; i++) {
QStringList connections = networkConnections[i].split(":");
if (connections[1] == ssid)
{
uuid = connections[2];
}
}
QStringList args_wifi_exist = {"nmcli", "connection", "up", uuid};
set_wifi_process = new QProcess(this);
set_wifi_process->setProcessChannelMode(QProcess::MergedChannels);
set_wifi_process->start("sudo", args_wifi_exist);
connect(set_wifi_process, SIGNAL(readyReadStandardOutput()), this, SLOT(processOutput()));
}
Ang linya na "connect(set_wifi_process, SIGNAL(readyReadStandardOutput()), this, SLOT(processOutput()))" ay nagpapasa ng mga output message ng prosesong ito pabalik sa "processOutput" at maaaring masuri doon muli sa isang sentral na lokasyon. </:code3:>