Если у вас есть что-то на PHP, что живёт на Raspberry Pi или в коробке под столом и должно само подключаться к Wi-Fi, без человека с клавиатурой, то эта библиотека как раз про это. Называется php-wifi. Ей семь лет, но версия 3.2 первая, которую я не побоюсь оставить работать где-нибудь далеко, без присмотра.

Писал я её из упрямства, хотелось, чтобы PHP тоже так умел. Внутри никакой магии, обычные системные утилиты nmcli, wpa_cli и hostapd. Так устроены многие PHP-библиотеки, тот же php-ffmpeg или gitonomy/gitlib. Утилита даёт стабильный интерфейс, библиотека добавляет типы, исключения и тесты.

composer require sanchescom/php-wifi

Что умеет

Четыре вещи, все через один объект.

Сканировать. Какие сети вокруг, сигнал, канал, диапазон, тип защиты. На выходе объекты, парсить вывод nmcli самому не надо.

use Sanchescom\WiFi\WiFi;

$wifi = WiFi::create();                       // сам выбирает бэкенд под ОС
$strongest = $wifi->scan()->strongest();

printf("%s: %.0f dBm, %s\n", $strongest->ssid, $strongest->signal->dbm, $strongest->security->value);

scan() возвращает обычную Collection из illuminate/collections, к ней добавлено несколько своих методов: ->band(Band::GHz5), ->strongerThan(-70), ->uniqueBySsid(), ->connected(). А filter(), map(), first() работают как везде.

Подключаться и отключаться.

use Sanchescom\WiFi\Value\Credentials;

$wifi->connect($wifi->scan()->bySsid('Home'), Credentials::password('secret123'));
$wifi->disconnect();

Если в SSID опечатка, прилетит NetworkNotFound. Расшифровывать код возврата nmcli не придётся. Когда SSID известен заранее и сканировать незачем, есть connectTo('Home', …). Сохранённые сети можно посмотреть и удалить: knownNetworks(), forget().

Поднимать хотспот. Только Linux, зато с обоими бэкендами.

use Sanchescom\WiFi\Value\HotspotConfig;

$hotspot = $wifi->startHotspot(new HotspotConfig(ssid: 'setup', password: 'change-me-now'));
// ... позже
$wifi->stopHotspot();

Держать устройство на связи. Ради этого всё и затевалось. Pi стоит где-нибудь в углу, монитора и клавиатуры у него нет, и в три часа ночи он теряет Wi-Fi. Зайти по SSH уже нельзя, ввести пароль некому. wifi watch крутится сервисом и раз в несколько секунд проверяет соединение. Если оно пропало, переподключается. Если переподключиться не вышло, поднимает хотспот, чтобы устройство можно было настроить с телефона. Пока к хотспоту кто-то подключён, watchdog его не трогает. Когда все отключились и прошло --retry секунд, он гасит хотспот и снова пробует домашнюю сеть.

$ sudo vendor/bin/wifi watch --ssid=Home --hotspot-ssid=setup \
      --hotspot-password-file=/etc/wifi-setup.pass --interval=5 --retry=20
2026-09-14T09:14:08+00:00 watch: hotspot_raised
2026-09-14T09:14:13+00:00 watch: hotspot_busy
2026-09-14T09:14:40+00:00 watch: recovered
2026-09-14T09:14:45+00:00 watch: connected

Лог настоящий, с моего Pi. --retry здесь короткий, чтобы всё влезло на экран. По умолчанию интервал 30 секунд, повтор через 300. Юнит для systemd лежит в examples/watch/. В examples/provision/ есть и страница настройки. Pi поднимает хотспот, телефон подключается к нему, выбирает домашнюю сеть из списка и вводит пароль.

CLI

Всё то же самое есть в виде команд, поверх того же API, с --json для скриптов:

$ vendor/bin/wifi list --unique
 SSID             BSSID              Channel  Band  Quality  dBm  Frequency  Connected  Security
-------------------------------------------------------------------------------------------------
 BELL340          0e:ac:8a:99:58:5c  1        2.4   100%     -50  2412       false      WPA2
 VTECH_5764_9764  a6:97:5c:b7:97:64  1        2.4   65%      -68  2412       false      WPA2
 -                0e:ac:8a:99:58:5e  157      5     75%      -62  5785       false      WPA2

wifi device, wifi connect, wifi disconnect, wifi known, wifi forget, wifi hotspot start|stop|status, wifi watch. Пароль можно передать файлом или через stdin (--password-file=-), тогда в командной строке и в ps его нет.

Где работает

В основном это библиотека для Linux. Бэкенда два, нужный выбирается сам. Если запущен NetworkManager, всё идёт через nmcli. Если нет, через wpa_cli к wpa_supplicant, а хотспот тогда поднимают hostapd и dnsmasq. Второй случай встречается на Raspberry Pi OS Lite и вообще на любом минимальном образе, где NetworkManager не стоит.

Сразу про права, потому что об них спотыкаются первым делом. Сканировать на Debian можно без root, если пользователь в группе netdev. Подключение и хотспот меняют состояние сети, так что либо sudo, либо правило polkit, готовое есть в README. Хотспот на hostapd в любом случае под root: он поднимает интерфейс и запускает dnsmasq.

Всё, что в таблице помечено «проверено», я гонял на своём Pi 4 (Debian 13) перед тем, как ставить тег на релиз. Логи этих прогонов лежат в репозитории, в docs/verified-on.md, вместе с тем, что не заработало.

Linux nmcli

Linux wpa_cli

macOS

Windows

сканирование

проверено

проверено

проверено, SSID скрыты без доступа к геолокации

только тесты

подключение / отключение

проверено

проверено, включая DHCP

только тесты

только тесты

сохранённые сети

проверено

forget проверен, список только тесты

не поддерживается

не поддерживается

хотспот

проверено

проверено

не поддерживается

не поддерживается

watchdog

только тесты

проверено, включая настоящий телефон на хотспоте

не поддерживается

не поддерживается

macOS и Windows нужны, чтобы тот же код запускался на ноутбуке разработчика: сканирование и подключение там работают, остальное бросает UnsupportedOperation. Можно проверить заранее: $wifi->supports(SupportsHotspot::class). Про Windows честно скажу сразу. Первую версию я проверял на ней в 2019 году, и она работала, а третью на живой Windows не запускал ни разу, бэкенд на netsh покрыт только тестами. Если у вас есть Windows под рукой, отчёт о прогоне будет очень кстати.

Два момента, про которые лучше знать заранее

Пароль не светится в argv. nmcli получает его через stdin (--ask), wpa_cli тоже через stdin, скриптом, hostapd читает из конфига с правами 0600, который удаляется, как только демон его прочитал. Я это проверял. Во время живого connect на Pi снимал ps -ww -eo args и искал в нём пароль, причём шаблон для grep читался из файла, чтобы сам grep пароль не нёс. Ноль совпадений. Одно исключение осталось. У NetworkManager команда запуска хотспота принимает пароль только аргументом. Лечится через keyfile, это в планах.

Утилиты ищутся по абсолютному пути. На Debian у непривилегированного пользователя в PATH нет /usr/sbin, а именно там лежат wpa_cli, iw и dnsmasq. При этом proc_open() в PHP ищет программу по PATH родительского процесса, и тот PATH, который вы передаёте в окружении команды, на поиск не влияет. Поэтому библиотека сначала находит каждую утилиту через which по системным каталогам. Если у вас когда-нибудь PHP-скрипт не мог запустить утилиту, которая точно стояла, скорее всего, дело было в этом.

Чего не делает

Веб-панели нет и не планируется. Постоянный веб-интерфейс с правом менять Wi-Fi работает под root и становится главной дырой на устройстве, а кому нужна панель, у того есть RaspAP. Нет хотспота с WPA3. Нет настройки IPv6. На macOS чужие SSID и BSSID видны только подписанному хелперу на CoreWLAN, такого хелпера в библиотеке нет, она отдаёт то, что даёт system_profiler, и помечает имена как скрытые. Полный список с причинами в roadmap.

Что дальше

В 3.3 появится wifi provision. Это одна команда, после которой устройство настраивается с телефона, как умная колонка. Устройство показывает QR-код своего хотспота, телефон подключается и сам открывает страницу настройки (captive portal), страница показывает список сетей и человеческим языком объясняет, почему подключиться не вышло, а устройство после этого доступно как <имя>.local. Большая часть уже есть в examples/provision/, осталось собрать это в команду.

Код, документация и логи с железа: github.com/sanchescom/php-wifi.

Комментарии (0)