Zana ya Usanidi wa Raspberry Pi 4 NetworkManager

Lengo lilikuwa kuandika programu ya Qt kwa Raspberry Pi 4 ambayo inaweza kutumika kubadili kati ya pointi tofauti za ufikiaji wa WLAN na kuhifadhi hati zinazohusiana.
Nilitumia picha ya raspbian-buster-lite na usakinishaji wa Qt kama ilivyoelezwa katika Qt kwenye Raspberry Pi 4 kama hatua ya kuanzia.
Kwa kuongeza, nimesakinisha NetworkManager, ambayo inaweza kutumika na amri ya ganda (nmcli ...) kuunda, kusanidi, na kudhibiti miunganisho ya mtandao.
Habari juu ya hili inaweza kupatikana chini ya https://wiki.debian.org/de/NetworkManager au https://developer.gnome.org/NetworkManager/stable/nmcli.html.
NetworkManager inatoa amri ambayo inaweza kutumika kuanza mchakato wa ufuatiliaji, ambayo kisha maoni juu ya mabadiliko ya interfaces mbalimbali (wlan0 au eth0) (kwa mfano haipatikani, kukatwa, kuunganisha, kushikamana, ...).
Nilitaka kutumia ufuatiliaji huu kuonyesha hali tofauti za maeneo ya mtandao katika GUI. 2 Matatizo ya kujitokeza:

  • ikiwa amri kadhaa za nmcli zilitolewa kwa mfululizo wa haraka, basi maoni juu ya hali tofauti yalifika na kuchelewa kwa wakati na haikuweza kuonyeshwa moja kwa moja kwenye GUI.
  • Maoni ya amri za NMCLI yalitumwa katika nafasi tofauti na kwa hivyo inaweza kuratibiwa vibaya.

Kazi ya ufuatiliaji

Kwanza kabisa, tunahitaji kazi ya ufuatiliaji (monitorDevices) na kazi ya yanayopangwa ya umma, ambayo inaingilia na kutathmini matokeo ya ufuatiliaji na kisha kutuma ujumbe wa hali kwa GUI, kwa mfano.
Katika kazi ya "monitorDevices", ambayo huanza kiotomatiki wakati programu inapoanza, amri ya nmcli inaanza na sudo: sudo nmcli monitor
Taarifa "setProcessChannelMode (QProcess::MergedChannels)" inasema kuwa "Standard Output" na "Kosa la Kawaida" huonyeshwa pamoja katika kituo na kwa hivyo inaweza kutathminiwa na kazi.
Mstari "unganisha(device_monitoring_process, SIGNAL(readyReadStandardOutput()), hii, SLOT (processOutput()))" hutumiwa wakati wowote ujumbe unapoonyeshwa (tayariReadStandardOutput), hutumwa kwa yanayopangwa "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:>

Kazi ya tathmini

Tathmini ya ujumbe huo inafanywa katika kazi ya "processOutput". QProcess mtumajiProcess huingilia ujumbe wote wa amri zote za nmcli - sio tu zile za amri ya ufuatiliaji.

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

Anzisha mchakato mwingine wa nmcli

Ikiwa sasa unaanza amri nyingine ya nmcli na kazi hapa chini, pato limezuiwa na kazi ya ufuatiliaji hapo juu na kisha inaweza kutathminiwa na kusindika zaidi katika "toleoProcess".
Kazi hii inabadilisha muunganisho wa mtandao uliopo na kuianzisha. Ni muhimu kutojumuisha "set_wifi_process->waitForReadyRead()" au "set_wifi_process->waitForFinished()", kwa sababu basi matokeo ya ujumbe wote yatazuiwa hadi mchakato huu utakapokamilika.

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

Mstari "unganisha(set_wifi_process, SIGNAL (readyReadStandardOutput()), hii, SLOT (processOutput()))" inasambaza ujumbe wa pato wa mchakato huu nyuma kwa "processOutput" na inaweza kutathminiwa tena huko katika eneo la kati. </:code3:>