เป้าหมายคือการเขียนแอปพลิเคชัน Qt สําหรับ Raspberry Pi 4 ที่สามารถใช้เพื่อสลับระหว่างจุดเชื่อมต่อ WLAN ต่างๆและจัดเก็บข้อมูลรับรองที่เกี่ยวข้อง
ฉันใช้อิมเมจ raspbian-buster-lite และการติดตั้ง Qt ตามที่อธิบายไว้ใน Qt บน Raspberry Pi 4 เป็นจุดเริ่มต้น
นอกจากนี้ฉันได้ติดตั้ง NetworkManager ซึ่งสามารถใช้โดยคําสั่งเชลล์ (nmcli ... ) สร้าง กําหนดค่า และจัดการการเชื่อมต่อเครือข่าย
ข้อมูลเกี่ยวกับเรื่องนี้สามารถพบได้ภายใต้ https://wiki.debian.org/de/NetworkManager หรือ https://developer.gnome.org/NetworkManager/stable/nmcli.html
NetworkManager เสนอคําสั่งที่สามารถใช้เพื่อเริ่มกระบวนการตรวจสอบซึ่งจะแสดงความคิดเห็นเกี่ยวกับการเปลี่ยนแปลงอินเทอร์เฟซต่างๆ (wlan0 หรือ eth0) (เช่นไม่พร้อมใช้งานตัดการเชื่อมต่อเชื่อมต่อเชื่อมต่อ ... )
ฉันต้องการใช้การตรวจสอบนี้เพื่อแสดงสถานะต่างๆ ของตําแหน่งเครือข่ายใน GUI 2 ปัญหาที่เกิดขึ้น:

  • หากมีการออกคําสั่ง nmcli หลายคําสั่งติดต่อกันอย่างรวดเร็วข้อเสนอแนะเกี่ยวกับสถานะที่แตกต่างกันมาพร้อมกับการหน่วงเวลาและไม่สามารถแสดงสดใน GUI ได้
  • ข้อเสนอแนะของคําสั่ง NMCLI ถูกส่งในสล็อตที่แตกต่างกันและอาจประสานงานได้ไม่ดี

ฟังก์ชั่นการตรวจสอบ

ก่อนอื่นเราต้องการฟังก์ชั่นการตรวจสอบ (monitorDevices) และฟังก์ชั่นสล็อตสาธารณะซึ่งสกัดกั้นและประเมินเอาต์พุตการตรวจสอบจากนั้นส่งข้อความสถานะไปยัง GUI เป็นต้น
ในฟังก์ชัน "monitorDevices" ซึ่งเริ่มต้นโดยอัตโนมัติเมื่อแอปพลิเคชันเริ่มทํางานคําสั่ง nmcli จะเริ่มต้นด้วย sudo: sudo nmcli monitor
คําสั่ง "setProcessChannelMode(QProcess::MergedChannels)" ระบุว่า "เอาต์พุตมาตรฐาน" และ "ข้อผิดพลาดมาตรฐาน" จะแสดงร่วมกันในแชนเนลและสามารถประเมินได้ด้วยฟังก์ชัน
บรรทัด "connect(device_monitoring_process, SIGNAL(readyReadStandardOutput()), this, SLOT(processOutput()))" จะถูกใช้เมื่อใดก็ตามที่ข้อความปรากฏขึ้น (readyReadStandardOutput) จะถูกส่งไปยังสล็อต "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:>

ฟังก์ชั่นการประเมินผล

การประเมินข้อความจะดําเนินการในฟังก์ชัน "processOutput" QProcess senderProcess สกัดกั้นข้อความทั้งหมดของคําสั่ง nmcli ทั้งหมด - ไม่ใช่แค่คําสั่งตรวจสอบเท่านั้น

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

เริ่มกระบวนการ nmcli อื่น

หากคุณเริ่มคําสั่ง nmcli อื่นด้วยฟังก์ชันด้านล่างเอาต์พุตจะถูกสกัดกั้นโดยฟังก์ชันการตรวจสอบข้างต้นและสามารถประเมินและประมวลผลเพิ่มเติมใน "outputProcess"
ฟังก์ชันนี้จะสลับไปยังการเชื่อมต่อเครือข่ายที่มีอยู่และเริ่มต้น สิ่งสําคัญคือต้องไม่รวม "set_wifi_process->waitForReadyRead()" หรือ "set_wifi_process->waitForFinished()" เนื่องจากผลลัพธ์ของข้อความทั้งหมดจะถูกบล็อกจนกว่ากระบวนการนี้จะเสร็จสิ้น

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

บรรทัด "connect(set_wifi_process, SIGNAL(readyReadStandardOutput()), this, SLOT(processOutput()))" จะส่งต่อข้อความเอาต์พุตของกระบวนการนี้กลับไปยัง "processOutput" และสามารถประเมินได้อีกครั้งที่ตําแหน่งศูนย์กลาง </:code3:>

Walter Prechtl

Walter Prechtl

อัพเดทเมื่อ: 12. March 2024
เวลาอ่านหนังสือ: 4 minutes