Målet var å skrive en Qt-applikasjon for Raspberry Pi 4 som kan brukes til å bytte mellom forskjellige WLAN-tilgangspunkter og lagre tilhørende legitimasjon.
Jeg brukte et raspbian-buster-lite bilde og en Qt-installasjon som beskrevet i Qt på Raspberry Pi 4 som utgangspunkt.
I tillegg har jeg installert NetworkManager, som kan brukes av shell kommando (nmcli ...) Opprett, konfigurer og administrer nettverkstilkoblinger.
Informasjon om dette finner du under https://wiki.debian.org/de/NetworkManager eller https://developer.gnome.org/NetworkManager/stable/nmcli.html.
NetworkManager tilbyr en kommando som kan brukes til å starte en overvåkingsprosess, som deretter kommenterer endringer i de ulike grensesnittene (wlan0 eller eth0) (f.eks. utilgjengelig, frakoblet, tilkoblet, tilkoblet, ...).
Jeg ønsket å bruke denne overvåkingen til å vise de forskjellige statusene til nettverksstedene i GUI. 2 problemer dukket opp:
- Hvis flere NMCLI-kommandoer ble utstedt i rask rekkefølge, kom tilbakemeldingen om de forskjellige statusene med en tidsforsinkelse og kunne ikke vises live i GUI.
- Tilbakemeldingene fra NMCLI-kommandoene ble sendt i forskjellige spor og kunne dermed være dårlig koordinert.
Overvåking funksjon
Først og fremst trenger vi overvåkingsfunksjonen (monitorDevices) og den offentlige sporfunksjonen, som fanger opp og evaluerer overvåkingsutgangen og deretter sender statusmeldingene til GUI, for eksempel.
I "monitorDevices" -funksjonen, som starter automatisk når applikasjonen starter, startes nmcli-kommandoen med sudo: sudo nmcli monitor
Setningen "setProcessChannelMode(QProcess::MergedChannels)" sier at "Standard Output" og "Standard Error" vises sammen i en kanal og kan dermed evalueres med en funksjon.
Linjen "connect (device_monitoring_process, SIGNAL (readyReadStandardOutput ()), dette, SSLOT (processOutput ()))" brukes når en melding vises (readyReadStandardOutput), den sendes til sporet "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:>
Evaluering funksjon
Evalueringen av meldingene utføres deretter i "processOutput" -funksjonen. QProcess senderProcess fanger opp alle meldinger fra alle nmcli kommandoer - ikke bare de av overvåking kommandoen.
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:>
Start en annen nmcli prosess
Hvis du nå starter en annen nmcli-kommando med funksjonen nedenfor, fanges utdataene opp av overvåkingsfunksjonen ovenfor og kan deretter evalueres og behandles videre i "outputProcess".
Denne funksjonen bytter til en eksisterende nettverkstilkobling og starter den. Det er viktig å ikke inkludere en "set_wifi_process->waitForReadyRead()" eller "set_wifi_process->waitForFinished()", for da vil utdataene fra alle meldinger bli blokkert til denne prosessen er fullført.
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()));
}
Linjen "connect (set_wifi_process, SIGNAL (readyReadStandardOutput ()), dette, SSLOT (processOutput ()))" videresender utdatameldingene til denne prosessen tilbake til "processOutput" og kan evalueres der igjen på et sentralt sted. </:code3:>