HMI
Configuratietool Raspberry Pi 4 NetworkManager

Het doel was om een Qt-applicatie voor de Raspberry Pi 4 te schrijven, waarmee men kan schakelen tussen verschillende WLAN-toegangspunten en de bijbehorende inloggegevens kan opslaan. Ik gebruikte als uitgangspunt een raspbian-buster-lite-afbeelding en een Qt-installatie zoals beschreven in Qt op de Raspberry Pi 4. Daarnaast heb ik de NetworkManager geïnstalleerd, waarmee men via de shell-opdracht (nmcli...) netwerkverbindingen kan maken, configureren en beheren. Informatie hierover vindt u op https://wiki.debian.org/de/NetworkManager of https://developer.gnome.org/NetworkManager/stable/nmcli.html. De NetworkManager biedt een commando waarmee men een monitoringproces kan starten, dat vervolgens commentaar geeft op veranderingen aan de verschillende interfaces (wlan0 of eth0) (bijv. niet beschikbaar, losgekoppeld, aan het verbinden, verbonden,...). Ik wilde deze monitoring gebruiken om de verschillende statussen van de netwerkpunten in de GUI weer te geven. Er deden zich twee problemen voor:

  • als snel achter elkaar meerdere nmcli-opdrachten werden gegeven, kwam de feedback over de verschillende statussen met een vertraging en kon deze niet live in de GUI worden weergegeven.

    • de feedback van de nmcli-opdrachten werd in verschillende slots verzonden en kon op die manier niet goed gecoördineerd worden.

    Bewakingsfunctie

    Ten eerste hebben we de bewakingsfunctie (monitorDevices) en de openbare slotfunctie nodig, die de bewakingsoutput onderschept en evalueert en vervolgens de statusberichten naar bijvoorbeeld de GUI verzendt. In de functie "monitorDevices", die automatisch wordt gestart wanneer de toepassing wordt gestart, wordt de opdracht nmcli gestart met sudo: sudo nmcli monitor De instructie "setProcessChannelMode (QProcess::MergedChannels)" stelt dat "Standard-Output" en "Standard-Error" samen in een kanaal worden weergegeven en dus met één functie geëvalueerd kunnen worden. Via de regel "connect(device_monitoring_process, SIGNAL(readyReadStandardOutput()), this, SLOT(processOutput()))" wordt een bericht altijd naar de slot "processOutput" gestuurd wanneer het wordt weergegeven (readyReadStandardOutput).

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

## Evaluatiefunctie De evaluatie van de berichten wordt dan uitgevoerd in de functie "processOutput". De QProcess senderProcess onderschept hier alle berichten van alle nmcli-opdrachten - niet alleen die van de monitoringopdracht.

void CmdLauncher::processOutput() {
    QProcess* senderProcess = qobject_cast(sender());
    senderProcess->setReadChannel(QProcess::StandardOutput);

    QString message = QString::fromLocal8Bit(senderProcess->readAllStandardOutput());

    qDebug() 

Een ander nmcli-proces starten

Als men nu een ander nmcli-commando start met de onderstaande functie, wordt de uitvoer onderschept door de bovenstaande bewakingsfunctie en kan deze vervolgens worden geëvalueerd en verder verwerkt in het "outputProcess". Deze functie schakelt over naar een bestaande netwerkverbinding en start deze. Het is belangrijk om geen "set_wifi_process->waitForReadyRead()" oder "set_wifi_process->waitForFinished()" te installeren, omdat dan de uitvoer van alle berichten wordt geblokkeerd totdat dit proces is voltooid.

void CmdLauncher::setWifi(QString ssid) {
    error_messages = "";
    emit getErrorMessagesChanged();

    QString uuid = "";
    for (int i = 0 ; i setProcessChannelMode(QProcess::MergedChannels);
    set_wifi_process->start("sudo", args_wifi_exist);
    connect(set_wifi_process, SIGNAL(readyReadStandardOutput()), this, SLOT(processOutput()));
}

De regel "connect(set_wifi_process, SIGNAL(readyReadStandardOutput()), this, SLOT(processOutput()))" stuurt de outputberichten van dit proces terug naar de "processOutput" en kan daar op een centraal punt opnieuw worden geëvalueerd.