目標は、異なるWLANアクセスポイントを切り替え、関連する資格情報を保存するために使用できるRaspberry Pi 4用のQtアプリケーションを作成することでした。 ラズベリー パイ4の Qtで説明されているように、ラスビアンバスターライトイメージとQtインストールを出発点として使用しました。 さらに、シェルコマンドで使用できる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:>

評価関数

メッセージの評価は、"プロセス出力" 関数で実行されます。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. 3月 2024
読書時間: 4 分