diff --git a/selfdrive/ui/qt/offroad/networking.cc b/selfdrive/ui/qt/offroad/networking.cc index a5af1662f9..bb35bead36 100644 --- a/selfdrive/ui/qt/offroad/networking.cc +++ b/selfdrive/ui/qt/offroad/networking.cc @@ -47,7 +47,7 @@ void Networking::attemptInitialization() { } connect(wifi, &WifiManager::wrongPassword, this, &Networking::wrongPassword); - connect(wifi, &WifiManager::refreshSignal, this, &Networking::refreshSlot); + connect(wifi, &WifiManager::refreshSignal, this, &Networking::refresh); QWidget* wifiScreen = new QWidget(this); QVBoxLayout* vlayout = new QVBoxLayout(wifiScreen); @@ -106,19 +106,24 @@ void Networking::requestScan() { wifi->requestScan(); } -void Networking::refreshSlot() { - wifiWidget->refresh(); - an->refresh(); +void Networking::refresh() { + if (this->isVisible() || firstRefresh) { + wifiWidget->refresh(); + an->refresh(); + firstRefresh = false; + } } void Networking::connectToNetwork(const Network &n) { - if (wifi->isKnownNetwork(n.ssid)) { + if (wifi->isKnownConnection(n.ssid)) { wifi->activateWifiConnection(n.ssid); } else if (n.security_type == SecurityType::OPEN) { wifi->connect(n); } else if (n.security_type == SecurityType::WPA) { QString pass = InputDialog::getText("Enter password for \"" + n.ssid + "\"", 8); - wifi->connect(n, pass); + if (!pass.isEmpty()) { + wifi->connect(n, pass); + } } } @@ -126,7 +131,9 @@ void Networking::wrongPassword(const QString &ssid) { for (Network n : wifi->seen_networks) { if (n.ssid == ssid) { QString pass = InputDialog::getText("Wrong password for \"" + n.ssid +"\"", 8); - wifi->connect(n, pass); + if (!pass.isEmpty()) { + wifi->connect(n, pass); + } return; } } @@ -214,7 +221,7 @@ void WifiUI::refresh() { ssid_label->setStyleSheet("font-size: 55px;"); hlayout->addWidget(ssid_label, 1, Qt::AlignLeft); - if (wifi->isKnownNetwork(network.ssid) && !wifi->tetheringEnabled()) { + if (wifi->isKnownConnection(network.ssid) && !wifi->tetheringEnabled()) { QPushButton *forgetBtn = new QPushButton(); QPixmap pix("../assets/offroad/icon_close.svg"); diff --git a/selfdrive/ui/qt/offroad/networking.h b/selfdrive/ui/qt/offroad/networking.h index 2ca2050ec9..cb681392df 100644 --- a/selfdrive/ui/qt/offroad/networking.h +++ b/selfdrive/ui/qt/offroad/networking.h @@ -69,6 +69,7 @@ private: AdvancedNetworking* an = nullptr; bool ui_setup_complete = false; bool show_advanced; + bool firstRefresh = true; WifiUI* wifiWidget; WifiManager* wifi = nullptr; @@ -76,7 +77,7 @@ private: void requestScan(); public slots: - void refreshSlot(); + void refresh(); private slots: void connectToNetwork(const Network &n); diff --git a/selfdrive/ui/qt/offroad/wifiManager.cc b/selfdrive/ui/qt/offroad/wifiManager.cc index acdf28b2ca..5007b59b4f 100644 --- a/selfdrive/ui/qt/offroad/wifiManager.cc +++ b/selfdrive/ui/qt/offroad/wifiManager.cc @@ -80,6 +80,9 @@ WifiManager::WifiManager(QWidget* parent) : QWidget(parent) { bus.connect(nm_service, adapter, device_iface, "StateChanged", this, SLOT(stateChange(unsigned int, unsigned int, unsigned int))); bus.connect(nm_service, adapter, props_iface, "PropertiesChanged", this, SLOT(propertyChange(QString, QVariantMap, QStringList))); + bus.connect(nm_service, nm_settings_path, nm_settings_iface, "ConnectionRemoved", this, SLOT(connectionRemoved(QDBusObjectPath))); + bus.connect(nm_service, nm_settings_path, nm_settings_iface, "NewConnection", this, SLOT(newConnection(QDBusObjectPath))); + QDBusInterface device_props(nm_service, adapter, props_iface, bus); device_props.setTimeout(dbus_timeout); QDBusMessage response = device_props.call("Get", device_iface, "State"); @@ -243,7 +246,6 @@ void WifiManager::connect(const QByteArray &ssid, const QString &username, const nm_settings.setTimeout(dbus_timeout); nm_settings.call("AddConnection", QVariant::fromValue(connection)); - activateWifiConnection(QString(ssid)); } void WifiManager::deactivateConnection(const QString &ssid) { @@ -282,12 +284,12 @@ QVector WifiManager::get_active_connections() { return conns; } -bool WifiManager::isKnownNetwork(const QString &ssid) { - return !pathFromSsid(ssid).path().isEmpty(); +bool WifiManager::isKnownConnection(const QString &ssid) { + return !getConnectionPath(ssid).path().isEmpty(); } void WifiManager::forgetConnection(const QString &ssid) { - QDBusObjectPath path = pathFromSsid(ssid); + const QDBusObjectPath &path = getConnectionPath(ssid); if (!path.path().isEmpty()) { QDBusInterface nm2(nm_service, path.path(), nm_settings_conn_iface, bus); nm2.call("Delete"); @@ -369,6 +371,7 @@ QString WifiManager::get_adapter() { void WifiManager::stateChange(unsigned int new_state, unsigned int previous_state, unsigned int change_reason) { raw_adapter_state = new_state; if (new_state == state_need_auth && change_reason == reason_wrong_password) { + knownConnections.remove(getConnectionPath(connecting_to_network)); emit wrongPassword(connecting_to_network); } else if (new_state == state_connected) { connecting_to_network = ""; @@ -380,11 +383,23 @@ void WifiManager::stateChange(unsigned int new_state, unsigned int previous_stat // https://developer.gnome.org/NetworkManager/stable/gdbus-org.freedesktop.NetworkManager.Device.Wireless.html void WifiManager::propertyChange(const QString &interface, const QVariantMap &props, const QStringList &invalidated_props) { if (interface == wireless_device_iface && props.contains("LastScan")) { - refreshNetworks(); + if (knownConnections.isEmpty()) { + knownConnections = listConnections(); + } + refreshNetworks(); // TODO: only refresh on first scan, then use AccessPointAdded and Removed signals emit refreshSignal(); } } +void WifiManager::connectionRemoved(const QDBusObjectPath &path) { + knownConnections.remove(path); +} + +void WifiManager::newConnection(const QDBusObjectPath &path) { + knownConnections[path] = getConnectionSsid(path); + activateWifiConnection(knownConnections[path]); +} + void WifiManager::disconnect() { QString active_ap = get_active_ap(); if (active_ap != "" && active_ap != "/") { @@ -392,46 +407,36 @@ void WifiManager::disconnect() { } } -QDBusObjectPath WifiManager::pathFromSsid(const QString &ssid) { - QDBusObjectPath path; // returns uninitialized path if network is not known - for (auto const& [conn_ssid, conn_path] : listConnections()) { - if (conn_ssid == ssid) { - path = conn_path; +QDBusObjectPath WifiManager::getConnectionPath(const QString &ssid) { + for (const QString &conn_ssid : knownConnections) { + if (ssid == conn_ssid) { + return knownConnections.key(conn_ssid); } } - return path; + return QDBusObjectPath(); // unknown ssid, return uninitialized path } -QVector> WifiManager::listConnections() { - QVector> connections; - QDBusInterface nm(nm_service, nm_settings_path, nm_settings_iface, bus); +QString WifiManager::getConnectionSsid(const QDBusObjectPath &path) { + QDBusInterface nm(nm_service, path.path(), nm_settings_conn_iface, bus); nm.setTimeout(dbus_timeout); + const QDBusReply result = nm.call("GetSettings"); + return result.value().value("802-11-wireless").value("ssid").toString(); +} - QDBusMessage response = nm.call("ListConnections"); - QVariant first = response.arguments().at(0); - const QDBusArgument &args = first.value(); - args.beginArray(); - while (!args.atEnd()) { - QDBusObjectPath path; - args >> path; - - // Get ssid - QDBusInterface nm2(nm_service, path.path(), nm_settings_conn_iface, bus); - nm2.setTimeout(dbus_timeout); - - QDBusMessage response = nm2.call("GetSettings"); - const QDBusArgument &dbusArg = response.arguments().at(0).value(); - QMap> map; - dbusArg >> map; +QMap WifiManager::listConnections() { + QMap connections; + QDBusInterface nm(nm_service, nm_settings_path, nm_settings_iface, bus); + nm.setTimeout(dbus_timeout); - const QString ssid = map.value("802-11-wireless").value("ssid").toString(); - connections.push_back(qMakePair(ssid, path)); + const QDBusReply> response = nm.call("ListConnections"); + for (const QDBusObjectPath &path : response.value()) { + connections[path] = getConnectionSsid(path); } return connections; } void WifiManager::activateWifiConnection(const QString &ssid) { - QDBusObjectPath path = pathFromSsid(ssid); + const QDBusObjectPath &path = getConnectionPath(ssid); if (!path.path().isEmpty()) { connecting_to_network = ssid; QString devicePath = get_adapter(); @@ -475,7 +480,7 @@ void WifiManager::addTetheringConnection() { } void WifiManager::enableTethering() { - if (!isKnownNetwork(tethering_ssid.toUtf8())) { + if (!isKnownConnection(tethering_ssid.toUtf8())) { addTetheringConnection(); } activateWifiConnection(tethering_ssid.toUtf8()); diff --git a/selfdrive/ui/qt/offroad/wifiManager.h b/selfdrive/ui/qt/offroad/wifiManager.h index 1ee129e5e1..00f6617a83 100644 --- a/selfdrive/ui/qt/offroad/wifiManager.h +++ b/selfdrive/ui/qt/offroad/wifiManager.h @@ -32,11 +32,12 @@ public: void requestScan(); QVector seen_networks; + QMap knownConnections; QString ipv4_address; void refreshNetworks(); void forgetConnection(const QString &ssid); - bool isKnownNetwork(const QString &ssid); + bool isKnownConnection(const QString &ssid); void connect(const Network &ssid); void connect(const Network &ssid, const QString &password); @@ -72,8 +73,9 @@ private: QByteArray get_property(const QString &network_path, const QString &property); unsigned int get_ap_strength(const QString &network_path); SecurityType getSecurityType(const QString &path); - QDBusObjectPath pathFromSsid(const QString &ssid); - QVector> listConnections(); + QDBusObjectPath getConnectionPath(const QString &ssid); + QMap listConnections(); + QString getConnectionSsid(const QDBusObjectPath &path); signals: void wrongPassword(const QString &ssid); @@ -82,4 +84,6 @@ signals: private slots: void stateChange(unsigned int new_state, unsigned int previous_state, unsigned int change_reason); void propertyChange(const QString &interface, const QVariantMap &props, const QStringList &invalidated_props); + void connectionRemoved(const QDBusObjectPath &path); + void newConnection(const QDBusObjectPath &path); };