Matlamatnya adalah untuk menulis aplikasi Qt untuk Raspberry Pi 4 yang boleh digunakan untuk bertukar antara titik akses WLAN yang berbeza dan menyimpan kelayakan yang berkaitan.
Saya menggunakan imej raspbian-buster-lite dan pemasangan Qt seperti yang diterangkan dalam Qt pada Raspberry Pi 4 sebagai titik permulaan.
Di samping itu, saya telah memasang NetworkManager, yang boleh digunakan oleh arahan shell (nmcli ...) Mencipta, mengkonfigurasi dan menguruskan sambungan rangkaian.
Maklumat mengenai perkara ini boleh didapati di bawah https://wiki.debian.org/de/NetworkManager atau https://developer.gnome.org/NetworkManager/stable/nmcli.html.
NetworkManager menawarkan arahan yang boleh digunakan untuk memulakan proses pemantauan, yang kemudian memberi komen mengenai perubahan pada pelbagai antara muka (wlan0 atau eth0) (contohnya tidak tersedia, terputus, menyambung, disambungkan, ...).
Saya mahu menggunakan pemantauan ini untuk memaparkan status lokasi rangkaian yang berbeza di GUI. 2 masalah muncul:

  • jika beberapa arahan nmcli dikeluarkan berturut-turut, maka maklum balas mengenai status yang berbeza tiba dengan kelewatan masa dan tidak dapat dipaparkan secara langsung di GUI.
  • Maklum balas arahan NMCLI dihantar dalam slot yang berbeza dan dengan itu boleh diselaraskan dengan buruk.

Fungsi pemantauan

Pertama sekali, kita memerlukan fungsi pemantauan (monitorDevices) dan fungsi slot awam, yang memintas dan menilai output pemantauan dan kemudian menghantar mesej status kepada GUI, sebagai contoh.
Dalam fungsi "monitorDevices", yang bermula secara automatik apabila aplikasi bermula, arahan nmcli dimulakan dengan sudo: sudo nmcli monitor
Kenyataan "setProcessChannelMode(QProcess::MergedChannels)" menyatakan bahawa "Output Standard" dan "Ralat Standard" dipaparkan bersama-sama dalam saluran dan dengan itu boleh dinilai dengan fungsi.
Baris "sambung(device_monitoring_process, SIGNAL (readyReadStandardOutput()), ini, SLOT(processOutput()))" digunakan apabila mesej dipaparkan (readyReadStandardOutput), ia dihantar ke slot "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:>

Fungsi penilaian

Penilaian mesej kemudiannya dijalankan dalam fungsi "processOutput". QProcess senderProcess memintas semua mesej semua arahan nmcli - bukan hanya arahan pemantauan.

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

Mulakan proses nmcli yang lain

Jika anda kini memulakan satu lagi arahan nmcli dengan fungsi di bawah, output dipintas oleh fungsi pemantauan di atas dan kemudian boleh dinilai dan diproses selanjutnya dalam "outputProcess".
Fungsi ini bertukar kepada sambungan rangkaian sedia ada dan memulakannya. Adalah penting untuk tidak memasukkan "set_wifi_process->waitForReadyRead()" atau "set_wifi_process->waitForFinished()", kerana kemudian output semua mesej akan disekat sehingga proses ini selesai.

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

Baris "sambung(set_wifi_process, SIGNAL (readyReadStandardOutput()), ini, SLOT(processOutput()))" memajukan mesej output proses ini kembali ke "processOutput" dan boleh dinilai semula di lokasi pusat. </:code3:>

Walter Prechtl

Walter Prechtl

Dikemas kini pada: 12. March 2024
Masa membaca: 4 minutes