Orodje za konfiguracijo Raspberry Pi 4 NetworkManager

Cilj je bil napisati Qt aplikacijo za Raspberry Pi 4, ki se lahko uporablja za preklapljanje med različnimi WLAN dostopnimi točkami in shranjevanje povezanih poverilnic.
Uporabil sem raspbian-buster-lite sliko in Qt namestitev, kot je opisano v Qt na Raspberry Pi 4 kot izhodišče.
Poleg tega sem namestil NetworkManager, ki se lahko uporablja z ukazom shell (nmcli ...) ustvarjanje, konfiguriranje in upravljanje omrežnih povezav.
Informacije o tem lahko najdete pod https://wiki.debian.org/de/NetworkManager ali https://developer.gnome.org/NetworkManager/stable/nmcli.html.
NetworkManager ponuja ukaz, ki ga je mogoče uporabiti za začetek postopka spremljanja, ki nato komentira spremembe različnih vmesnikov (wlan0 ali eth0) (npr. nedosegljiv, odklopljen, povezan, povezan, ...).
Želel sem uporabiti to spremljanje za prikaz različnih statusov omrežnih lokacij v GUI. Pojavili sta se dve težavi:

  • če je bilo več nmcli ukazov izdanih v hitrem zaporedju, potem so povratne informacije o različnih statusih prispele s časovno zamudo in jih ni bilo mogoče prikazati v živo v GUI.
  • povratna informacija ukazov nmcli je bila poslana v različnih režah in se je tako lahko slabo usklajevala.

Funkcija spremljanja

Najprej potrebujemo funkcijo spremljanja (monitorDevices) in funkcijo javne reže, ki prestreže in oceni izhod spremljanja in nato pošlje sporočila o stanju gui, na primer.
V funkciji "monitorDevices", ki se začne samodejno ob zagonu aplikacije, se zažene ukaz nmcli z sudo: sudo nmcli monitor
V izjavi »setProcessChannelMode(QProcess::MergedChannels)« je navedeno, da sta »Standardni izhod« in »Standardna napaka« prikazana skupaj v kanalu in jo je tako mogoče oceniti s funkcijo.
Linija "connect(device_monitoring_process, SIGNAL(readyReadStandardOutput()), this, SLOT(processOutput()))" se uporablja vedno, ko se prikaže sporočilo (readyReadStandardOutput), se pošlje v režo "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 vrednotenja

Evalvacija sporočil se nato izvede v funkciji »processOutput«. QProcess pošiljateljProcess prestreže vsa sporočila vseh nmcli ukazov - ne samo tistih iz ukaza za spremljanje.

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

Zaženite drug nmcli postopek

Če zdaj zaženete drug ukaz nmcli s spodnjo funkcijo, izhod prestreže zgoraj navedena funkcija spremljanja, nato pa ga je mogoče oceniti in nadalje obdelati v "outputProcess".
Ta funkcija preklopi na obstoječo omrežno povezavo in jo zažene. Pomembno je, da ne vključite »set_wifi_process->waitForReadyRead()« ali »set_wifi_process->waitForFinished()«, ker bo potem izhod vseh sporočil blokiran, dokler se ta postopek ne konča.

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

Linija "connect(set_wifi_process, SIGNAL(readyReadStandardOutput()), this, SLOT(processOutput()))" posreduje izhodna sporočila tega procesa nazaj na "processOutput" in ga je mogoče ponovno oceniti tam na osrednji lokaciji. </:code3:>