Raspberry Pi 4 NetworkManager-konfigurasie-instrument

Die doel was om 'n Qt-toepassing vir die Raspberry Pi 4 te skryf wat gebruik kan word om tussen verskillende WLAN-toegangspunte te wissel en die gepaardgaande geloofsbriewe te stoor.
Ek het 'n raspbian-buster-lite-beeld en 'n Qt-installasie gebruik soos beskryf in Qt op die Raspberry Pi 4 as 'n beginpunt.
Daarbenewens het ek die NetworkManager geïnstalleer, wat gebruik kan word deur shell-opdrag (nmcli ...) Skep, konfigureer en bestuur netwerkverbindings.
Inligting hieroor kan gevind word onder https://wiki.debian.org/de/NetworkManager of https://developer.gnome.org/NetworkManager/stable/nmcli.html.
Die NetworkManager bied 'n opdrag aan wat gebruik kan word om 'n moniteringsproses te begin, wat dan kommentaar lewer op veranderinge aan die verskillende koppelvlakke (wlan0 of eth0) (bv. nie beskikbaar nie, ontkoppel, verbind, gekoppel, ...).
Ek wou hierdie monitering gebruik om die verskillende statusse van die netwerklokasies in die GUI te vertoon. 2 probleme het na vore gekom:

  • as verskeie nmcli-opdragte vinnig agtereenvolgens uitgereik is, het die terugvoer oor die verskillende statusse met 'n tydsvertraging aangekom en kon dit nie regstreeks in die GUI vertoon word nie.
  • Die terugvoer van die NMCLI-opdragte is in verskillende gleuwe gestuur en kon dus swak gekoördineer word.

Monitering funksie

In die eerste plek het ons die moniteringsfunksie (monitorDevices) en die openbare gleuffunksie nodig, wat die moniteringsuitset onderskep en evalueer en dan byvoorbeeld die statusboodskappe na die GUI stuur.
In die "monitorDevices" -funksie, wat outomaties begin wanneer die toepassing begin, word die nmcli-opdrag begin met sudo: sudo nmcli monitor
Die stelling "setProcessChannelMode (QProcess: : MergedChannels)" lui dat "Standard Output" en "Standard Error" saam in 'n kanaal vertoon word en dus met 'n funksie geëvalueer kan word.
Die lyn "connect (device_monitoring_process, SIGNAL (readyReadStandardOutput ()), hierdie, SLOT (processOutput ()))" word gebruik wanneer 'n boodskap vertoon word (readyReadStandardOutput), dit word na die gleuf gestuur "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:>

Evalueringsfunksie

Die evaluering van die boodskappe word dan uitgevoer in die "processOutput" -funksie. Die QProcess-senderProcess onderskep alle boodskappe van alle nmcli-opdragte - nie net dié van die moniteringsopdrag nie.

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

Begin nog 'n nmcli-proses

As u nou 'n ander nmcli-opdrag begin met die onderstaande funksie, word die uitvoer onderskep deur die bogenoemde moniteringsfunksie en kan dit dan geëvalueer en verder verwerk word in die "outputProcess".
Hierdie funksie skakel oor na 'n bestaande netwerkverbinding en begin dit. Dit is belangrik om nie 'n "set_wifi_process->waitForReadyRead ()" of "set_wifi_process->waitForFinished ()" in te sluit nie, want dan sal die uitvoer van alle boodskappe geblokkeer word totdat hierdie proses voltooi is.

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

Die reël "connect (set_wifi_process, SIGNAL (readyReadStandardOutput ()), hierdie, SLOT (processOutput ()))" stuur die uitvoerboodskappe van hierdie proses terug na die "processOutput" en kan weer daar op 'n sentrale plek geëvalueer word. </:code3:>