Небольшой командный бот для сети Meshtastic. Приложение подключается к локальной ноде через USB/serial или Bluetooth, принимает текстовые команды из mesh-сети, проверяет отправителя по whitelist и отправляет ответ личным сообщением.
Сейчас поддерживаются команды /start, /help и /ping. Бот построен на Python в стиле
Layered Clean Architecture + feature modules + CQRS-lite.
- Python 3.14 или новее;
- uv для установки зависимостей;
- Meshtastic-устройство с установленной прошивкой;
- USB-кабель с поддержкой передачи данных или Bluetooth-адаптер;
- отдельная Meshtastic-нода, с которой будут отправляться команды боту.
uv syncДля Heltec, подключённого как COM3:
meshtastic --port COM3 --infoЧтобы увидеть известные ноды и их ID:
meshtastic --port COM3 --nodesNode ID имеет вид !a1b2c3d4. В whitelist нужно добавить ID удалённой ноды, которая будет
отправлять команды, а не ID Heltec, к которому подключён бот.
Скопируйте .env.example в .env и выберите транспорт. Для USB/serial:
$env:MESHTASTIC_CONNECTION_TYPE = "serial"
$env:MESHTASTIC_PORT = "COM3"
$env:MESHTASTIC_ALLOWED_NODE_IDS = "!a1b2c3d4,!11223344"Для Bluetooth сначала найдите адрес ноды:
meshtastic --ble-scanЗатем задайте:
$env:MESHTASTIC_CONNECTION_TYPE = "bluetooth"
$env:MESHTASTIC_BLE_ADDRESS = "AA:BB:CC:DD:EE:FF"
$env:MESHTASTIC_ALLOWED_NODE_IDS = "!a1b2c3d4,!11223344"Несколько разрешённых нод перечисляются через запятую. Пустой whitelist запрещён.
python -m srcПриложение работает, пока запущен процесс Python и Heltec подключён к компьютеру. Для остановки
нажмите Ctrl+C.
Не держите этот же COM-порт открытым в Meshtastic CLI, Web Client, Arduino Serial Monitor или другой программе одновременно с ботом.
| Переменная | Обязательна | Пример | Назначение |
|---|---|---|---|
MESHTASTIC_CONNECTION_TYPE |
Нет, по умолчанию serial |
bluetooth |
Транспорт: serial или bluetooth |
MESHTASTIC_PORT |
Только для serial |
COM3 |
Последовательный порт локальной ноды |
MESHTASTIC_BLE_ADDRESS |
Только для bluetooth |
AA:BB:CC:DD:EE:FF |
Bluetooth-адрес или имя ноды |
MESHTASTIC_ALLOWED_NODE_IDS |
Да | !a1b2c3d4,!11223344 |
Разрешённые отправители |
Настройки читаются pydantic-settings из переменных окружения и файла .env. Переменные
окружения имеют приоритет. При неизвестном типе подключения, пустом whitelist или отсутствии
параметра выбранного транспорта приложение завершится с ошибкой конфигурации.
Каждый node ID должен состоять из ! и восьми шестнадцатеричных символов. Регистр символов
не учитывается.
Пример запуска в Linux:
export MESHTASTIC_PORT=/dev/ttyUSB0
export MESHTASTIC_CONNECTION_TYPE=serial
export MESHTASTIC_ALLOWED_NODE_IDS='!a1b2c3d4'
python -m src| Команда | Ответ |
|---|---|
/start |
Сообщает, что бот готов, и предлагает открыть справку |
/help |
Показывает список команд |
/ping |
Возвращает pong |
Любая другая команда с / |
Предлагает использовать /help |
Обычный текст без / игнорируется. Команды от нод вне whitelist также игнорируются без ответа.
Ответ разрешённому отправителю всегда уходит личным сообщением через destinationId.
Meshtastic text packet
↓
infrastructure/meshtastic/gateway.py
↓
presentation/meshtastic/handler.py
↓ HandleTextCommand
application/bot/handlers.py
↓ проверка whitelist
domain/bot/access.py
↓
MessageSender port → личный ответ отправителю
- Выбранный serial или Bluetooth gateway подписывается на событие
meshtastic.receive.text. - Presentation валидирует структуру пакета Pydantic-схемой и создаёт
HandleTextCommand. - Application handler проверяет отправителя через domain-политику доступа.
- Разрешённая команда выполняется, после чего handler вызывает
MessageSender. - Infrastructure-адаптер отправляет ответ через Meshtastic Python API.
src/
domain/
bot/ # Правила и нормализация whitelist
application/
bot/ # Commands и handlers
ports/ # Контракты внешних адаптеров
infrastructure/
meshtastic/ # Работа с Meshtastic Python API через serial/Bluetooth
presentation/
meshtastic/ # Преобразование пакетов в application commands
config/ # Pydantic Settings и logging
bootstrap/ # Composition root
__main__.py # Точка входа
Направление зависимостей:
presentation → application → domain
infrastructure → application/domain
bootstrap → все слои и config
Repository и Unit of Work пока отсутствуют намеренно: бот не хранит состояние и не использует базу данных. Подробности находятся в спецификации бота и описании архитектуры.
Запуск всех тестов:
.\.venv\Scripts\python.exe -m unittest discover -s tests -vПроверка Ruff, если он установлен:
ruff check src testsТесты разделены по назначению:
tests/
unit/ # Domain, application, config и bootstrap
integration/ # Meshtastic infrastructure adapter с fake interface
api/ # Контракт presentation-слоя
Автоматические тесты не открывают реальный COM-порт и не устанавливают Bluetooth-соединение.
- Добавьте ветку команды в
HandleTextCommandHandler._execute():src/application/bot/handlers.py. - Добавьте сценарий в
tests/unit/application/bot/test_handlers.py. - Запустите тесты и Ruff.
Если команда требует БД, HTTP API, файловой системы или другого внешнего сервиса, сначала
определите контракт в application/ports/, а конкретную реализацию разместите в
infrastructure/.
- Whitelist по node ID является логической фильтрацией, а не криптографической аутентификацией.
- Отправитель, имеющий доступ к ключу канала и модифицированной прошивке, потенциально может подделать node ID.
- Входящий текст не выполняется как Python-код или команда операционной системы.
- Бот пока не требует PKI-шифрования, не ограничивает частоту сообщений и не выполняет автоматическое переподключение после потери соединения.
- Для строгого контроля доступа следует принимать только PKI-зашифрованные личные сообщения.
- убедитесь, что в whitelist указан ID отправляющей ноды;
- отправляйте команду с отдельного Meshtastic-устройства;
- проверьте, что сообщение начинается с
/; - убедитесь, что COM-порт не занят другой программой;
- проверьте соединение командой
meshtastic --port COM3 --infoпосле остановки бота.
При Bluetooth-подключении дополнительно проверьте, что нода видна в meshtastic --ble-scan,
адрес или имя совпадает с MESHTASTIC_BLE_ADDRESS, а другой клиент не удерживает соединение.
ACPI\PNP0501 обычно является встроенным последовательным портом материнской платы, а не
Meshtastic-устройством. Используйте исправный USB-кабель с передачей данных и найдите порт
Silicon Labs CP210x USB to UART Bridge в диспетчере устройств.
