Raspberry Pi 4 NetworkManager konfigurációs eszköz

A cél egy Qt alkalmazás írása volt a Raspberry Pi 4-hez, amely használható a különböző WLAN hozzáférési pontok közötti váltásra és a kapcsolódó hitelesítő adatok tárolására.
Kiindulási pontként egy raspbian-buster-lite képet és egy Qt telepítést használtam a Qt-ben leírtak szerint a Raspberry Pi 4-en .
Ezenkívül telepítettem a NetworkManager-t, amelyet shell paranccsal (nmcli ...) lehet használni Hálózati kapcsolatok létrehozása, konfigurálása és kezelése.
Az erre vonatkozó információk a https://wiki.debian.org/de/NetworkManager vagy https://developer.gnome.org/NetworkManager/stable/nmcli.html alatt találhatók.
A NetworkManager egy olyan parancsot kínál, amellyel elindítható egy figyelési folyamat, amely ezután megjegyzéseket fűz a különböző interfészek (wlan0 vagy eth0) változásaihoz (pl. nem elérhető, leválasztott, csatlakozás, csatlakozás, ...).
Ezzel a figyeléssel szerettem volna megjeleníteni a hálózati helyek különböző állapotait a grafikus felhasználói felületen. 2 probléma merült fel:

  • ha gyors egymásutánban több nmcli parancsot adtak ki, akkor a különböző állapotokról szóló visszajelzések időbeli késéssel érkeztek, és nem jeleníthetők meg élőben a grafikus felhasználói felületen.
  • Az nmcli parancsok visszajelzését különböző résidőkben küldték, és így rosszul koordinálhatók.

Felügyeleti funkció

Először is szükségünk van a monitoring funkcióra (monitorDevices) és a public slot funkcióra, amely elfogja és kiértékeli a felügyeleti kimenetet, majd elküldi az állapotüzeneteket például a grafikus felhasználói felületnek.
A "monitorDevices" funkcióban, amely automatikusan elindul az alkalmazás indításakor, az nmcli parancs a következővel indul el: sudo nmcli monitor
A "setProcessChannelMode(QProcess::MergedChannels)" utasítás azt állítja, hogy a "Standard Output" és a "Standard Error" együtt jelenik meg egy csatornán, és így egy függvénnyel értékelhető.
A "connect(device_monitoring_process, SIGNAL(readyReadStandardOutput()), this, SLOT(processOutput()))" sor kerül használatba, amikor egy üzenet megjelenik (readyReadStandardOutput), és a "processOutput" nyílásba kerül.

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

Kiértékelési funkció

Az üzenetek kiértékelése ezután a "processOutput" függvényben történik. A QProcess senderProcess elfogja az összes nmcli parancs összes üzenetét - nem csak a monitoring parancsot.

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

Indítson el egy másik nmcli folyamatot

Ha most elindít egy másik nmcli parancsot az alábbi függvénnyel, a kimenetet a fenti figyelési függvény elfogja, majd kiértékelheti és tovább feldolgozhatja az "outputProcess" -ben.
Ez a funkció átvált egy meglévő hálózati kapcsolatra, és elindítja azt. Fontos, hogy ne szerepeljen "set_wifi_process->waitForReadyRead()" vagy "set_wifi_process->waitForFinished ()", mert akkor az összes üzenet kimenete blokkolva lesz, amíg ez a folyamat be nem fejeződik.

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

A "connect(set_wifi_process, SIGNAL(readyReadStandardOutput()), this, SLOT(processOutput()))" sor továbbítja a folyamat kimeneti üzeneteit a "processOutput" -nak, és ott ismét kiértékelhető egy központi helyen. </:code3:>