Tujuannya adalah untuk menulis aplikasi Qt untuk Raspberry Pi 4 yang dapat digunakan untuk beralih di antara jalur akses WLAN yang berbeda dan menyimpan kredensial terkait.
Saya menggunakan gambar raspbian-buster-lite dan instalasi Qt seperti yang dijelaskan dalam Qt pada Raspberry Pi 4 sebagai titik awal.
Selain itu, saya telah menginstal NetworkManager, yang dapat digunakan dengan perintah shell (nmcli ...) Membuat, mengonfigurasi, dan mengelola koneksi jaringan.
Informasi tentang ini dapat ditemukan di bawah https://wiki.debian.org/de/NetworkManager atau https://developer.gnome.org/NetworkManager/stable/nmcli.html.
NetworkManager menawarkan perintah yang dapat digunakan untuk memulai proses pemantauan, yang kemudian mengomentari perubahan pada berbagai antarmuka (wlan0 atau eth0) (misalnya tidak tersedia, terputus, terhubung, terhubung, ...).
Saya ingin menggunakan pemantauan ini untuk menampilkan status yang berbeda dari lokasi jaringan di GUI. 2 masalah muncul:
- jika beberapa perintah nmcli dikeluarkan secara berurutan, maka umpan balik tentang status yang berbeda tiba dengan penundaan waktu dan tidak dapat ditampilkan langsung di GUI.
- Umpan balik dari perintah NMCLI dikirim dalam slot yang berbeda dan dengan demikian dapat dikoordinasikan dengan buruk.
Fungsi pemantauan
Pertama-tama, kita memerlukan fungsi pemantauan (monitorDevices) dan fungsi slot publik, yang mencegat dan mengevaluasi output pemantauan dan kemudian mengirim pesan status ke GUI, misalnya.
Dalam fungsi "monitorDevices", yang dimulai secara otomatis ketika aplikasi dimulai, perintah nmcli dimulai dengan sudo: sudo nmcli monitor
Pernyataan "setProcessChannelMode (QProcess:: MergedChannels)" menyatakan bahwa "Output Standar" dan "Kesalahan Standar" ditampilkan bersama dalam saluran dan dengan demikian dapat dievaluasi dengan fungsi.
Baris "connect(device_monitoring_process, SIGNAL(readyReadStandardOutput()), ini, SLOT(processOutput()))" digunakan setiap kali pesan ditampilkan (readyReadStandardOutput), dikirim 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 evaluasi
Evaluasi pesan kemudian dilakukan dalam fungsi "processOutput". QProcess senderProcess mencegat semua pesan dari semua perintah nmcli - bukan hanya perintah 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:>
Mulai proses nmcli lainnya
Jika Anda sekarang memulai perintah nmcli lain dengan fungsi di bawah ini, output dicegat oleh fungsi pemantauan di atas dan kemudian dapat dievaluasi dan diproses lebih lanjut dalam "outputProcess".
Fungsi ini beralih ke koneksi jaringan yang ada dan memulainya. Penting untuk tidak menyertakan "set_wifi_process->waitForReadyRead()" atau "set_wifi_process->waitForFinished()", karena output dari semua pesan akan diblokir hingga 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 "connect(set_wifi_process, SIGNAL(readyReadStandardOutput()), this, SLOT(processOutput()))" meneruskan pesan output dari proses ini kembali ke "processOutput" dan dapat dievaluasi di sana lagi di lokasi pusat. </:code3:>