Первый мой брокер прожил три дня на ноутбуке. Я поставил его между делом, проверил — работает, — и ушёл с ноутбуком на кухню писать скетч. Плата в это время честно стучалась в брокер по адресу, который я ей прописал, и не могла пробиться. Тогда я решил, что сломал библиотеку, и перекопал её всю. А сломал я всего-навсего то, о чём предупреждён заранее: брокер должен жить на машине, которая всегда включена и всегда стоит на одном месте. Для этой роли в доме есть ровно один кандидат — Raspberry Pi в кладовке, которая уже год не выключается.
Брокер Mosquitto — открытый проект под лицензией Eclipse, гоняет версии MQTT 3.1, 3.1.1 и 5.0, ставится в одну команду и ест на малине мизер: я не замечал его в top ни разу. Но у него есть один заскок, на котором спотыкаются все, кто читает старые инструкции: начиная с версии 2.0 брокер без конфига слушает только localhost. Установили — из консоли той же машины всё работает, а с платы — тишина. Классический тупик, и именно его мы разберём посреди урока.
План такой: ставим брокер и консольные утилиты, пробуем публикацию двумя терминалами — руками, ещё до скетчей, — потом открываем брокеру дверь в локальную сеть и добавляем пароль. На выходе — рабочий брокер, к которому в следующем уроке подключится первый скетч на PubSubClient.
Ставим и проверяем
На Raspberry Pi или любом Debian-подобном Linux брокер ставится из штатного репозитория: пакет mosquitto — это сам сервер, а пакет mosquitto-clients — консольные утилиты sub и pub, без которых отлаживаться мучительно. После установки сервис стартует сам, и проверить его можно командой systemctl status mosquitto — в ответе ищите слово active (running). На macOS то же самое делает brew install mosquitto, на Linux со снапом — snap install mosquitto, а на Windows есть установщик с сайта проекта: он и сервер, и утилиты ставит в Program Files.
Проверка из консоли — ритуал, который я делаю всегда, на любой машине, даже если буквально вчера делал его на соседней. Терминал номер один подписывается на все топики с решёткой и флагом -v, который печатает не только сообщение, но и имя топика. Терминал номер два публикует тестовую строку. Если в первом терминале мгновенно приехала строка с топиком и текстом — брокер жив, и вся дальнейшая отладка будет иметь опору под ногами.
# ставим сервер и консольные утилитыsudo apt updatesudo apt install mosquitto mosquitto-clients # статус сервиса: ищем active (running)sudo systemctl status mosquitto # терминал 1: слушаем все топики, с печатью имени топикаmosquitto_sub -h localhost -t 'dacha/#' -v # терминал 2: публикуем тестовое сообщениеmosquitto_pub -h localhost -t 'dacha/temp' -m '23.5' # в терминале 1 мгновенно появится:# dacha/temp 23.5Формат вывода mosquitto_sub -v запомните: имя топика, пробел, сообщение. Именно так выглядит сырой поток вашего дома, и когда в будущем дашборд покажет ерунду, первая проверка всегда одна — что видно в этом терминале. Если данные тут есть, виноват дашборд; если нет — виновата плата или сеть.
Полезные флаги утилит, которые я использую еженедельно: -h — адрес брокера, -t — топик, -m — сообщение, -q — уровень QoS (по умолчанию 0), -d — режим отладки, в котором утилита печатает CONNACK и пинги. Ещё два флага экономят время в скриптах: -C 5 — выйти после пяти сообщений, -W 10 — слушать не дольше десяти секунд. Флаг -n у mosquitto_pub означает пустое сообщение — им удобно проверять retained-поведение, стирая значение из топика.
Когда подключится первая плата, загляните в кухню живого брокера: остановите сервис (sudo systemctl stop mosquitto) и запустите его руками — mosquitto -v. В логе появится New connection from 192.168.1.73 на порт 1883, строка CONNACK с кодом подтверждения, дисконнекты и подписки. Я ловил через этот лог половину своих ошибок: клиент с чужим именем, повторные подключения каждую секунду, подписка на опечатанный топик. Чёрный ящик внезапно стал прозрачным.
И сразу о вечном: у mosquitto_pub есть флаг -r, который помечает сообщение как retained. Опубликуйте с ним 'offline' в топик статуса, и каждый новый подписчик будет получать это значение сразу после подключения, не дожидаясь следующей публикации платы. Так дашборды узнают, что плата лежит, ещё до первого отсчёта.
Впускаем плату: конфиг
Теперь тупик из вступления во всей красе. Свежий Mosquitto (2.0 и новее) без конфигурационного файла слушает только loopback: localhost, 127.0.0.1. Из консоли той же машины всё летает, а плата из сети получает отказ на этапе TCP-соединения — и выглядит это как поломка библиотеки. Диагноз ставится одной командой mosquitto -v в терминале: в логе будет строка вида Opening ipv4 listen socket on port 1883 — но адрес там будет привязан к localhost, а не к 0.0.0.0.
Лекарство — две строки в конфиге /etc/mosquitto/conf.d/local.conf (файл можно создать любым редактором от root): listener 1883 0.0.0.0 и allow_anonymous true. Первая говорит: слушай порт 1883 на всех интерфейсах. Вторая: впускай клиентов без пароля. После правки — sudo systemctl restart mosquitto. Анонимный режим для опыта в домашней сети за роутером я считаю приемлемым, но это временная мера: как только в доме появляются гости с Wi-Fi, ставим пароль.
Пароль в Mosquitto делается двумя командами: mosquitto_passwd -c /etc/mosquitto/passwd имя_пользователя создаст файл и спросит пароль дважды, а в конфиг вместо allow_anonymous true пишутся allow_anonymous false и password_file /etc/mosquitto/passwd. После рестарта брокер требует логин и пароль у всех клиентов — и консольные утилиты с флагами -u и -P, и скетчи через client.connect с логином и паролем. Число с условием: пароль в passwd-файле хранится в виде хэша, но по 1883-му порту летит открытым текстом в пакете CONNECT, поэтому для брокера, торчащего в интернет, нужен порт 8883 с TLS; внутри домашней сети за роутером 1883 — норма.
Про сеть вокруг брокера — три бытовых дела. Первое: если на малине включён брандмауэр ufw, откройте порт — sudo ufw allow 1883, иначе конфиг правильный, а плата стучится в закрытую дверь. Второе: проверяйте доступ не с той же машины, а с соседней — mosquitto_pub -h 192.168.1.40 -t 'dacha/test' -m 'ping' с ноутбука; это ровно тот путь, которым пойдёт плата. Третье: прибейте малину статическим адресом в роутере, иначе однажды DHCP выдаст ей другой IP, и все скетчи в доме молча перестанут достукиваться.
# /etc/mosquitto/conf.d/local.conf# этап 1: тест в домашней сетиlistener 1883 0.0.0.0allow_anonymous true # этап 2: включаем пароли# listener 1883 0.0.0.0# allow_anonymous false# password_file /etc/mosquitto/passwd # после правки:# sudo systemctl restart mosquitto# создание пароля:# sudo mosquitto_passwd -c /etc/mosquitto/passwd dacha| Команда | Что делает | Мой типовой вызов |
|---|---|---|
| mosquitto_sub | Слушает топики, печатает поток | mosquitto_sub -h localhost -t 'dacha/#' -v |
| mosquitto_pub | Публикует одно сообщение | mosquitto_pub -h localhost -t 'dacha/temp' -m '23.5' |
| mosquitto_passwd | Создаёт файл паролей | sudo mosquitto_passwd -c /etc/mosquitto/passwd dacha |
| mosquitto -v | Брокер в консоли с логом | mosquitto -v — смотреть CONNACK и отключения клиентов |
| systemctl | Управление сервисом | sudo systemctl restart mosquitto |
- Поменяйте интервал с 2000 на 500 мс и посмотрите на плотность потока: так ощущается разница между polling-опросом и потоком публикаций.
- Добавьте второй publish в топик dacha/status со значением done прямо после первого: в реальном терминале вы увидите две строки подряд — по одной на топик.
- Поменяйте clientId в connect с console-test на rpi-local: имя клиента видно в логе брокера при mosquitto -v, и по нему в логах всегда понятно, кто подключался.
- Пробегитесь по таблице команд и закройте терминалом каждую строку: консольные утилиты — ваш стетоскоп для всей будущей отладки MQTT.
- Пакеты: mosquitto — сервер, mosquitto-clients — утилиты sub и pub; сервис стартует сам
- Первый тест — два терминала: sub с флагом -v слушает dacha/#, pub кладёт сообщение
- Mosquitto 2.0 без конфига слушает только localhost: для платы нужен listener 1883 0.0.0.0
- allow_anonymous true — только для опытов; для постоянной работы — mosquitto_passwd и password_file
- Формат вывода sub -v: топик, пробел, сообщение — первая линия диагностики всей системы
- Брокер живёт на машине, которая всегда включена: малина, а не ноутбук
- 1. Свежий Mosquitto 2.0 установлен без конфига. Кто сможет подключиться?
- 2. Какая команда мгновенно покажет поток данных вашего дома в сыром виде?
- 3. Что делает флаг -r у mosquitto_pub?
- 4. Плата не может соединиться с брокером, а mosquitto_pub с той же машины работает. Первый подозреваемый?
- 5. Почему для брокера в интернете нужен порт 8883, а дома хватает 1883?
Доска стоит, дверь в сеть открыта, пароли придуманы — брокер больше не игрушка, а часть дома. Дальше два пути, и я советую пройти оба. Вперёд — к скетчу: в уроке про первый скетч PubSubClient плата подключается к этому брокеру, публикует и учится читать коды ошибок. Назад — вспомнить, как плата вообще попадает в вашу сеть: WiFi.begin и ожидание подключения из раздела про ESP32, а если сети пока нет вовсе — режим точки доступа выручит и настроючный Wi-Fi. Для брокерских логов в длинных проектах мне пригодился подход из урока про уровни логов — та же привычка разделять шум и сигналы работает и в консоли малины. А если после установки на Linux IDE не видит плату — рядом лежит доступ к последовательному порту в Linux: в той же консоли чинятся и права dialout.
Частые вопросы по теме урока
- Свежий Mosquitto 2.0 установлен без конфига. Кто сможет подключиться?
- Начиная с 2.0 брокер без конфигурации слушает только loopback. Для доступа из сети нужны строки listener 1883 0.0.0.0 и allow_anonymous true либо password_file. Только клиенты с той же машины (localhost)
- Какая команда мгновенно покажет поток данных вашего дома в сыром виде?
- Подписка с -v печатает имя топика и сообщение для каждого входящего: это первая линия диагностики — до дашбордов и логов. mosquitto_sub -h localhost -t 'dacha/#' -v
- Что делает флаг -r у mosquitto_pub?
- Retained-сообщение брокер хранит и отдаёт каждому новому подписчику сразу после подключения — так дашборд видит статус мгновенно. Помечает сообщение как retained
- Плата не может соединиться с брокером, а mosquitto_pub с той же машины работает. Первый подозреваемый?
- Классика Mosquitto 2.0: без listener 1883 0.0.0.0 сервер принимает только локальные подключения, и плата из сети получает отказ. Брокер слушает только localhost
- Почему для брокера в интернете нужен порт 8883, а дома хватает 1883?
- Без TLS пакет CONNECT уходит открытым текстом. В домашней сети за роутером это терпимо, наружу — только 8883 с шифрованием. На 1883 летит открытый текст, в том числе пароль: снаружи нужен TLS