Cilj je bio napisati Qt aplikaciju za Raspberry Pi 4 koja se može koristiti za prebacivanje između različitih WLAN pristupnih točaka i pohranu povezanih vjerodajnica.
Koristio sam raspbian-buster-lite sliku i Qt instalaciju kako je opisano u Qt na Raspberry Pi 4 kao početnu točku.
Osim toga, instalirao sam NetworkManager, koji se može koristiti naredbom ljuske (nmcli ...) Stvaranje, konfiguriranje i upravljanje mrežnim vezama.
Informacije o tome mogu se pronaći pod https://wiki.debian.org/de/NetworkManager ili https://developer.gnome.org/NetworkManager/stable/nmcli.html.
NetworkManager nudi naredbu koja se može koristiti za pokretanje postupka praćenja, koja zatim komentira promjene različitih sučelja (wlan0 ili eth0) (npr. Nedostupno, odspojeno, povezivanje, povezano, ...).
Želio sam koristiti ovaj nadzor za prikaz različitih statusa mrežnih mjesta u GUI-ju. Pojavila su se 2 problema:

  • ako je nekoliko nmcli naredbi izdano u brzom slijedu, povratne informacije o različitim statusima stigle su s vremenskim odmakom i nisu se mogle prikazati uživo u GUI-ju.
  • Povratne informacije o nmcli naredbama poslane su u različitim utorima i stoga su mogle biti loše koordinirane.

Funkcija nadzora

Prije svega, potrebna nam je funkcija praćenja (monitorDevices) i funkcija javnog utora, koja presreće i procjenjuje izlaz praćenja, a zatim šalje poruke o statusu GUI-ju, na primjer.
U funkciji "monitorDevices", koja se automatski pokreće kada se aplikacija pokrene, naredba nmcli pokreće se sa sudo: sudo nmcli monitor
Izjava "setProcessChannelMode(QProcess::MergedChannels)" navodi da se "Standardni izlaz" i "Standardna pogreška" prikazuju zajedno u kanalu i stoga se mogu procijeniti funkcijom.
Redak "connect(device_monitoring_process, SIGNAL(readyReadStandardOutput()), ovo, SLOT(processOutput()))" koristi se kad god se prikaže poruka (readyReadStandardOutput), šalje se u utor "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:>

Funkcija vrednovanja

Procjena poruka se zatim provodi u funkciji "processOutput". QProcess senderProcess presreće sve poruke svih nmcli naredbi - ne samo one naredbe za praćenje.

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:>

Započnite još jedan nmcli proces

Ako sada pokrenete drugu nmcli naredbu s donjom funkcijom, izlaz se presreće gore navedenom funkcijom nadzora, a zatim se može procijeniti i dalje obraditi u "outputProcess".
Ova se funkcija prebacuje na postojeću mrežnu vezu i pokreće je. Važno je ne uključiti "set_wifi_process->waitForReadyRead()" ili "set_wifi_process->waitForFinished()", jer će tada izlaz svih poruka biti blokiran dok se taj proces ne završi.

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()));
}

Redak "connect(set_wifi_process, SIGNAL(readyReadStandardOutput()), ovaj, SLOT(processOutput()))" prosljeđuje izlazne poruke ovog procesa natrag na "processOutput" i tamo se može ponovno procijeniti na središnjem mjestu. </:code3:>

Walter Prechtl

Walter Prechtl

Ažurirano na: 12. March 2024
Vrijeme čitanja: 4 minutes