DT
April 14, 2025, 3:38 p.m.
Qt 6.8 MinGW - управление подключением WiFi из программы
Всем привет!
На Qt 6.8 MinGW пытаюсь сделать управление подключением WiFi из программы. Пока делаю поддержку Windows, но так же хочу в дальнейшем внедрить и поддержку Linux/MacOS.
Для управления пробрасываю команды в netsh и разбираю результат.
Пока загвоздка в разных локализациях системы, из-за чего или некорректно отображаются названия на русском языке (одни ??????????????), либо ничего не выдается из-за того, что не удается разобрать результат. Хотел бы библиотеку унифицировать.
Есть идеи?
Пока выглядит следующим образом:
wifimanager.h
#ifndef WIFIMANAGER_H #define WIFIMANAGER_H #include <QtNetwork/QtNetwork> #include <QtCore> #include <QtGui> #include <QtWidgets> #include <list> /** * Open - открытая сеть без шифрования * Shared - устаревший режим WEP с общей аутентификацией * WPA-Personal - WPA с использованием PSK (Pre-Shared Key) * WPA-Enterprise - WPA с использованием RADIUS-сервера для аутентификации * WPA2-Personal - WPA2 с PSK (наиболее распространенный сейчас режим) * WPA2-Enterprise - WPA2 с RADIUS-сервером * WPA3-Personal - современный WPA3 с PSK * WPA3-Enterprise - WPA3 с RADIUS-сервером */ typedef enum { AUTH_TYPE_UNKNOWN = 0, AUTH_TYPE_OPEN, AUTH_TYPE_SHARED, AUTH_TYPE_WPA_PERSONAL, AUTH_TYPE_WPA_ENTERPRISE, AUTH_TYPE_WPA2_PERSONAL, AUTH_TYPE_WPA2_ENTERPRISE, AUTH_TYPE_WPA3_PERSONAL, AUTH_TYPE_WPA3_ENTERPRISE, AUTH_TYPE_MAX } auth_type_t; typedef enum { WIFI_BAND_UNKNOWN = 0, WIFI_BAND_2_4_GHZ, WIFI_BAND_5_GHZ, WIFI_BAND_MAX } wifi_band_t; typedef enum { WIFI_STATE_DISCONNECTED = 0, WIFI_STATE_CONNECTED } wifi_state_t; typedef enum { INTERFACE_TYPE_PRIMARY = 0, INTERFACE_TYPE_SECONDARY } interface_type_t; /** * Name : Беспроводная сеть * Description : Intel(R) Wireless-AC 9560 160MHz * GUID : 082bf832-bae3-4933-a678-16e21e1dfb75 * Physical address : 5c:87:9c:94:c2:76 * Interface type : Primary * State : connected * SSID : tp-link * AP BSSID : 78:8c:b5:b7:27:a6 * Band : 5 GHz * Channel : 48 * Network type : Infrastructure * Radio type : 802.11ac * Authentication : WPA2-Personal * Cipher : CCMP * Connection mode : Profile * Receive rate (Mbps) : 780 * Transmit rate (Mbps) : 780 * Signal : 87% * Profile : tp-link */ typedef struct { QString interfaceName; QString interfaceDesc; QString interfaceMAC; interface_type_t interfaceType; wifi_state_t wifiConnected; auth_type_t authType; int signal; QString currentProfileUsed; QString wifiSSIDConnected; wifi_band_t currentBand; } interface_desc_t; typedef struct { QString wifiSSID; QString wifiBSSID; int signal; wifi_band_t band; } wifi_network_t; inline QString wifiBandToStr(wifi_band_t band) { switch (band) { case WIFI_BAND_2_4_GHZ: return "2.4 GHz"; case WIFI_BAND_5_GHZ: return "5 GHz"; default: return "Unknown"; } } class WiFiManager { public: WiFiManager(); ~WiFiManager(); QList<wifi_network_t> scanNetworks(interface_desc_t wifi_interface); QList<wifi_network_t> getLastScannedNetworks() { return wifiNetworks; } interface_desc_t getLastScannedWifiInterface() { return wifiScannedInterface; } QList<interface_desc_t> getWifiInterfaces(); QList<interface_desc_t> getLastCheckedWifiInterfaces() { return interfacesDescriptions; } private: QList<interface_desc_t> interfacesDescriptions; QList<wifi_network_t> wifiNetworks; interface_desc_t wifiScannedInterface; QString tempFolderPath; }; #endif // WIFIMANAGER_H
wifimanager.cpp
#include "wifimanager.h" WiFiManager::WiFiManager() { } WiFiManager::~WiFiManager() { interfacesDescriptions.clear(); } QList<interface_desc_t> WiFiManager::getWifiInterfaces() { QProcess process; qDebug() << "WiFi interfaces getting..."; // Выполняем команду netsh QString cmd = QString("cmd /U /C chcp 437 > nul && netsh wlan show interfaces"); // process.start("netsh", QStringList() << "wlan" << "show" << "interfaces"); process.startCommand(cmd); process.waitForFinished(); QString output = QString::fromLocal8Bit(process.readAllStandardOutput()); QStringList lines = output.split("\n"); interface_desc_t currentInterface; bool parsingInterface = false; // Регулярные выражения для разбора QRegularExpression nameRe("^Name\\s*:\\s*(.+)$"); QRegularExpression descRe("^Description\\s*:\\s*(.+)$"); QRegularExpression macRe("^Physical address\\s*:\\s*([0-9a-fA-F:]+)$"); QRegularExpression typeRe("^Interface type\\s*:\\s*(.+)$"); QRegularExpression stateRe("^State\\s*:\\s*(.+)$"); QRegularExpression ssidRe("^SSID\\s*:\\s*(.+)$"); QRegularExpression bandRe("^Band\\s*:\\s*(.+)$"); QRegularExpression authRe("^Authentication\\s*:\\s*(.+)$"); QRegularExpression signalRe("^Signal\\s*:\\s*(\\d+)%$"); QRegularExpression profileRe("^Profile\\s*:\\s*(.+)$"); for (const QString& line : lines) { QString trimmedLine = line.trimmed(); qDebug() << "Line to be parsed: " << line << ", trimmed: " << trimmedLine; if (trimmedLine.isEmpty()) { if (parsingInterface && currentInterface.interfaceName.length() > 0) { qDebug() << "Interface name to be added: " + currentInterface.interfaceName; interfacesDescriptions.append(currentInterface); parsingInterface = false; } continue; } QRegularExpressionMatch match; if (!parsingInterface) { currentInterface = interface_desc_t(); currentInterface.currentBand = WIFI_BAND_UNKNOWN; currentInterface.signal = 0; currentInterface.authType = AUTH_TYPE_UNKNOWN; parsingInterface = true; qDebug() << "Starting new interface parsing"; } // Парсинг полей if ((match = nameRe.match(trimmedLine)).hasMatch()) { currentInterface.interfaceName = match.captured(1); qDebug() << "Interface name parsed: " << currentInterface.interfaceName; // parsingInterface = true; // continue; } else if ((match = descRe.match(trimmedLine)).hasMatch()) { currentInterface.interfaceDesc = match.captured(1); qDebug() << "Interface desc parsed: " << currentInterface.interfaceDesc; // parsingInterface = true; // continue; } else if ((match = macRe.match(trimmedLine)).hasMatch()) { currentInterface.interfaceMAC = match.captured(1); qDebug() << "Interface MAC parsed: " << currentInterface.interfaceMAC; // parsingInterface = true; // continue; } else if ((match = typeRe.match(trimmedLine)).hasMatch()) { qDebug() << "interface type parsed: " << match.captured(1); currentInterface.interfaceType = match.captured(1) == "Primary" ? INTERFACE_TYPE_PRIMARY : INTERFACE_TYPE_SECONDARY; // parsingInterface = true; // continue; } else if ((match = stateRe.match(trimmedLine)).hasMatch()) { qDebug() << "state parsed: " << match.captured(1); currentInterface.wifiConnected = match.captured(1) == "connected" ? WIFI_STATE_CONNECTED : WIFI_STATE_DISCONNECTED; // parsingInterface = true; // continue; } else if ((match = ssidRe.match(trimmedLine)).hasMatch()) { qDebug() << "current SSID parsed: " << match.captured(1); currentInterface.wifiSSIDConnected = match.captured(1); // parsingInterface = true; // continue; } else if ((match = bandRe.match(trimmedLine)).hasMatch()) { QString band = match.captured(1); qDebug() << "band parsed: " << band; if (band == "2.4 GHz") { currentInterface.currentBand = WIFI_BAND_2_4_GHZ; } else if (band == "5 GHz") { currentInterface.currentBand = WIFI_BAND_5_GHZ; } else { currentInterface.currentBand = WIFI_BAND_UNKNOWN; } // parsingInterface = true; // continue; } else if ((match = authRe.match(trimmedLine)).hasMatch()) { QString auth = match.captured(1); qDebug() << "auth type parsed: " << auth; if (auth == "Open") currentInterface.authType = AUTH_TYPE_OPEN; else if (auth == "Shared") currentInterface.authType = AUTH_TYPE_SHARED; else if (auth == "WPA-Personal") currentInterface.authType = AUTH_TYPE_WPA_PERSONAL; else if (auth == "WPA-Enterprise") currentInterface.authType = AUTH_TYPE_WPA_ENTERPRISE; else if (auth == "WPA2-Personal") currentInterface.authType = AUTH_TYPE_WPA2_PERSONAL; else if (auth == "WPA2-Enterprise") currentInterface.authType = AUTH_TYPE_WPA2_ENTERPRISE; else if (auth == "WPA3-Personal") currentInterface.authType = AUTH_TYPE_WPA3_PERSONAL; else if (auth == "WPA3-Enterprise") currentInterface.authType = AUTH_TYPE_WPA3_ENTERPRISE; else currentInterface.authType = AUTH_TYPE_UNKNOWN; // parsingInterface = true; // continue; } else if ((match = signalRe.match(trimmedLine)).hasMatch()) { qDebug() << "current signal parsed: " << match.captured(1); currentInterface.signal = match.captured(1).toInt(); // parsingInterface = true; // continue; } else if ((match = profileRe.match(trimmedLine)).hasMatch()) { qDebug() << "profile used parsed: " << match.captured(1); currentInterface.currentProfileUsed = match.captured(1); // parsingInterface = true; // continue; } } // Добавляем последний интерфейс, если он есть if (parsingInterface && currentInterface.interfaceName.length() > 0) { qDebug() << "Last interface name to be added: " + currentInterface.interfaceName; interfacesDescriptions.append(currentInterface); parsingInterface = false; } return interfacesDescriptions; } QList<wifi_network_t> WiFiManager::scanNetworks(interface_desc_t wifi_interface) { QProcess process; wifiScannedInterface = wifi_interface; wifiNetworks.clear(); // process.start("netsh", {"wlan", "show", "networks", "mode=bssid"}); QString cmd = QString("cmd /U /C chcp 437 > nul && netsh wlan show networks mode=bssid interface=\"%1\"").arg(wifiScannedInterface.interfaceName); process.startCommand(cmd); process.waitForFinished(); QString output = process.readAllStandardOutput(); QTextStream stream(&output); // Регулярные выражения для парсинга QRegularExpression ssidRegex("\\bSSID\\b (\\d+)( +):((.+)|\\n)"); QRegularExpression bssidRegex("( +)\\bBSSID\\b (\\d+)( +): (.+)"); QRegularExpression signalRegex("( +)\\bSignal\\b( +): (\\d+)(%)"); QRegularExpression bandRegex("( +)\\bBand\\b( +): (.+)"); bool parsingNetwork = false; wifi_network_t currentNetwork; while (!stream.atEnd()) { QString line = stream.readLine(); // Ищем начало новой сети QRegularExpressionMatch ssidMatch = ssidRegex.match(line); if (ssidMatch.hasMatch()) { QString ssid_to_check = ssidMatch.captured(3); currentNetwork.wifiSSID = ssid_to_check; qDebug() << "Got SSID: " << currentNetwork.wifiSSID; parsingNetwork = true; continue; } // Ищем BSSID QRegularExpressionMatch bssidMatch = bssidRegex.match(line); if (bssidMatch.hasMatch()) { currentNetwork.wifiBSSID = bssidMatch.captured(4); qDebug() << "Got BSSID: " << currentNetwork.wifiBSSID; parsingNetwork = true; continue; } // Ищем уровень сигнала QRegularExpressionMatch signalMatch = signalRegex.match(line); if (signalMatch.hasMatch()) { qDebug() << "Got signal: " << signalMatch.captured(3); currentNetwork.signal = signalMatch.captured(3).toInt(); parsingNetwork = true; continue; } // Ищем полосу частот QRegularExpressionMatch bandMatch = bandRegex.match(line); if (bandMatch.hasMatch()) { QString bandStr = bandMatch.captured(3); qDebug() << "Got band: " << bandStr; if (bandStr == "2.4 GHz") currentNetwork.band = WIFI_BAND_2_4_GHZ; else if (bandStr == "5 GHz") currentNetwork.band = WIFI_BAND_5_GHZ; else currentNetwork.band = WIFI_BAND_UNKNOWN; // parsingNetwork = true; // Добавляем сеть в список if (parsingNetwork) { currentNetwork.wifiSSID = currentNetwork.wifiSSID.trimmed(); qDebug() << "WiFi SSID found: " << currentNetwork.wifiSSID << " (" + currentNetwork.wifiBSSID + ")"; // Excluding empty wifi ssids if (!currentNetwork.wifiSSID.isNull()) if (currentNetwork.wifiSSID.length() > 0) wifiNetworks.append(currentNetwork); parsingNetwork = false; } continue; } } return wifiNetworks; }
1
94
Do you like it? Share on social networks!
- Last comments
- AKApril 1, 2025, 11:41 a.m.Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
- VPMarch 9, 2025, 4:14 p.m.Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…
- Now discuss on the forum
- DTApril 14, 2025, 3:38 p.m.Всем привет! На Qt 6.8 MinGW пытаюсь сделать управление подключением WiFi из программы. Пока делаю поддержку Windows, но так же хочу в дальнейшем внедрить и поддержку Linux/MacOS. Для…
- fFeb. 15, 2025, 1:46 p.m.Подскажите, пожалуйста! Как данный класс можно дополнить, чтобы созданные объекты можно было перемещать мышкой по сцене?
- Не запускается компьютер (точнее работает блок , но сам монитор вообще жесть)В общем я ничего с интернета не скачивала в последнее время. На компе никаких левых пр…
- Вопрос решен. Узнать QModelIndex элемента на который мы перетаскиваем другой элемент, можно с помощью функции indexAt(event->position().toPoint()) представления QTreeViev вызываемой в переопр…