Привет, Хабр! Меня зовут Иван Куликов, я руководитель направления backend разработки в VK Tech, и хочу поделиться своим путем боли и преодолений по запуску DMR Хотспота на базе MMDVMHost и DMRGateway на российском аналоге RaspberryPi — RepkaPi
Ссылка на GitHub → r2bln/repka-star

Что такое DMR
DMR (Digital Mobile Radio) — это стандарт цифровой радиосвязи, разработанный ETSI (European Telecommunications Standards Institute) для профессиональной радиосвязи.
Работает в диапазонах УКВ (обычно 144–148 МГц, 430–440 МГц и других).
Использует TDMA — это когда один частотный канал делится на два временных слота и два человека могут говорить одновременно на одной частоте.
Звук кодируется в цифру (кодек AMBE+2), поэтому меньше шумов и искажений, чем в аналоге.
Есть ID-идентификаторы (как номера телефонов), система групп (комнат) и зон, что позволяет гибко управлять большими парками устройств через программное обеспечение диспетчера. Например, таксопарком или отрядами пожарных.
Ретрансляторы можно объединять друг с другом с помощью сети интернет.
Как тут оказались радиолюбители
Кто-то придумал поднять собственный DMR-сервер и пускать в него только лицензированных радиолюбителей. По сути, это такой закрытый Discord, для входа в который нужна лицензия.
Сначала сеть была совсем небольшой, но благодаря особенностям стандарта к ней можно было доставлять новые и новые сегменты. Сейчас самая большая сеть — это BrandMeister, она насчитывает почти 300к пользователей.
Что такое хотспот и зачем так сложно
DMR-хотспот — это узел распределенной сети. Обычно это одноплатный компьютер (99% случаев это Raspberry Pi) с радиомодулем, воткнутый в интернет. Используя свою цифровую DMR-радиостанцию, вы шлёте посылки (голос и данные) на радиомодуль, а он проксирует это в сеть. И наоборот, при общении в группе в интернете трафик будет поступать на одноплатник, а затем через радиомодуль транслироваться в окружающее пространство, где вы, находясь неподалеку с DMR-радиостанцией, можете этот трафик принять, декодировать и услышать.
Зачем тут вообще рация? Зачем одноплатник? Нельзя это всё решить одним андроид-смартфоном?
Да можно. Такие решения есть.
Тогда зачем?
Сложно сказать. Скорее всего, это опыт общения с настоящей физической рацией, с кнопкой PTT и всем прочим. Может быть, дух DIY. Нейронка еще наглючила, что «в некоторых странах передача голоса через интернет-приложения требует лицензии (VoIP), а работа через хотспот с лицензированной рацией легальна (если частота разрешена)».
Ок, а почему «Репка»?
Репка просто была под рукой.
Погнали.
Железки
MMDVM_HS_HAT c Aliexpress
Repka Pi 3 v. 1.3 2Gb
Конфигурируем Репку
Предполагаем, что вы накатили на Репку родную операционную систему, она запустилась и вы получили доступ в терминал.
1. Распиновка GPIO
По умолчанию у Репки отличается и выглядит так, но с помощью поставляемой вместе с ОС утилиты repka-config её необходимо поменять. Нам нужен вариант 2.
2. UART
[!CAUTION] По умолчанию у Репки включен вывод на UART, что неизбежно приведет к проблемам в работе модема (шляпы). Его необходимо отключить!
В версии v1.0.18_d16.02.24
пункт конфигуратора называется 1 console-UART0-on/off
Прошиваем модем
Возможно, модем с Алиэкспресса уже приходит прошитым — я не знал, как это проверить, и поэтому занялся прошивкой. Но проверить это можно. Статья в этом блоге говорит, что прошитый модем мигает красным светодиодом с интервалом в 1 секунду. Что похоже на правду. Или чтобы наверняка — прочитать прошивку и посмотреть, что внутри.
Чтобы прошить модем или прочитать его прошивку, нужно перевести его в режим прошивки по UART. Для этого необходимо в определенной последовательности переключить состояние определенных GPIO-пинов (20 и 21). Stm32flash
, по идее, может сделать это и сама, но файлы, за которые надо дергать GPIO, у Репки расположены в других местах. Так что выхода два: хачить исходники stm32flash
, либо перемапить пины с помощью библиотеки и шить две команды. Я выбрал последнее.
Устанавливаем stm32flash
Эта штука просто есть в репозитории — качаем:
sudo apt install stm32flash
Устанавливаем библиотеку для работы с GPIO
Для совместимости с Raspberry Pi Репке нужно переключать пины программным способом. Ставим зависимости:
sudo apt update
sudo apt install python3-dev python3-setuptools git
Качаем библиотеку:
git clone https://gitflic.ru/project/repka_pi/repkapigpiofs.git
Устанавливаем:
cd repkapigpiofs
sudo python3 setup.py install
Далее либо пишем сами, либо запускаем скрипт из этого репозитория:
root@Repka-Pi:~/sources/repka-star# python3 repka-hat.py enter
Repka Pi 3
enter bootloader mode
Это переведет модем в режим прошивки, и тогда можно будет посмотреть данные о нём:
root@Repka-Pi:~/sources/repka-star# stm32flash /dev/ttyS0
stm32flash 0.5
http://stm32flash.sourceforge.net/
Interface serial_posix: 57600 8E1
Version : 0x10
Option 1 : 0x00
Option 2 : 0x00
Device ID : 0x0410 (STM32F10xxx Medium-density)
- RAM : 20KiB (512b reserved by bootloader)
- Flash : 128KiB (size first sector: 4x1024)
- Option RAM : 16b
- System RAM : 2KiB
Читаем прошивку в файл:
root@Repka-Pi:~/sources/repka-star# stm32flash -r dump.bin /dev/ttyS0
stm32flash 0.5
http://stm32flash.sourceforge.net/
Interface serial_posix: 57600 8E1
Version : 0x10
Option 1 : 0x00
Option 2 : 0x00
Device ID : 0x0410 (STM32F10xxx Medium-density)
- RAM : 20KiB (512b reserved by bootloader)
- Flash : 128KiB (size first sector: 4x1024)
- Option RAM : 16b
- System RAM : 2KiB
Memory read
Read address 0x08020000 (100.00%) Done.
Смотрим, есть ли в ней что-нибудь про MMDVM
root@Repka-Pi:~/sources/repka-star# strings dump.bin | grep -i mmdvm
MMDVM_HS FW configuration:
MMDVM_HS_Hat-v1.5.2 20201108 14.7456MHz ADF7021 FW by CA6JAU GitID #89daa20
Если да, то шить ничего не надо. Если нет — надо шить. Можно сделать с тем же скриптом с командой flash:
python3 repka-hat.py flash
Он делает следующее:
Качает прошивку из https://github.com/juribeparada/MMDVM_HS/.
Перетыкает GPIO пины, так же как и
enter,
чтобы попасть в режим прошивки.Запускает
stm32flash
и заливает скачанную прошивку.Перетыкает GPIO пины для выхода из режима прошивки и перезапускает модем.
Собираем софт
Клонируем репозитории MMDVMHost и DMRGateway и собираем — у обоих в описании есть инструкция, но, по сути, все сводится к запуску make
, и оно все собирается. Получаем на выходе 2 бинаря.
Конфигурируем софт
В этом репозитории лежит два конфига:
Из этих конфигов выкинуто все лишнее (по крайней мере, на мой взгляд. Ну и то, что точно не работает). Их можно открыть и подрихтовать под себя: поменять частоту работы, описание хотспота, позывной и прочее.
Запускаем
Никакого pistar на Repka Pi не предвидится как минимум потому, что исходников в открытом доступе нет, так что будем запускать руками.
Я сделал systemd
-файлы mmdvmhost.service и dmrgateway.service, чтобы их использовать:
Внутри можно поменять пути для pid-файлов и расположения бинарей туда, где все лежит на вашей системе.
Скопировать файлы *.service в /etc/systemd/system.
Инициализировать: systemctl enable mmdvmhost
systemctl enable dmrgateway
Перезагрузиться.
Сервисы должны запуститься самостоятельно; проверить это можно с помощью команды status
:
> systemctl status mmdvmhost
mmdvmhost.service — MMDVMHost
Loaded: loaded (/etc/systemd/system/mmdvmhost.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2024-03-09 20:47:25 MSK; 18min ago
Main PID: 390 (MMDVMHost)
Tasks: 2 (limit: 2230)
Memory: 3.2M
CGroup: /system.slice/mmdvmhost.service
└─390 /etc/mmdvmhost /etc/mmdvmhost.cfg
...
> systemctl status dmrgateway
dmrgateway.service — DMRGateway
Loaded: loaded (/etc/systemd/system/dmrgateway.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2024-03-09 20:47:25 MSK; 19min ago
Main PID: 388 (DMRGateway)
Tasks: 1 (limit: 2230)
Memory: 1.5M
CGroup: /system.slice/dmrgateway.service
└─388 /etc/dmrgateway /etc/dmrgateway.cfg
Выводы
Сделать хотспот на Repka Pi можно — всё работает.
Установку и запуск автоматизировать несложно — начал тут.
Компилировать программы MMDVMHost и DMRGateway самостоятельно не обязательно, можно собрать и распространять уже готовые бинари.
Единственная проблема — конфигурирование на лету через веб-интерфейс, который предоставляет pistar. Портировать его невозможно, так как нет доступа к исходникам. Остается только писать свой. Но на самом деле проще сделать одноклеточного бота для tg — вот так.
Все то же самое можно провернуть и на Raspberry Pi Model B Rev 2 — я проверил.