diff --git a/README.md b/README.md index c3463c5..fa205a5 100644 --- a/README.md +++ b/README.md @@ -1,119 +1,85 @@ -# 0DMRMaster -Private DMR master server. Version 0.5. -Copyright ©2025 Alexander Mokrov, UR6LKW. +# 0DMRMaster (форк) -This project is currently in public alpha and is under active development. -Don't use it in production environment, interfaces may change. +Частный DMR-мастер-сервер на Python: реализация протокола Homebrew DMR (того же, что используют BrandMeister и HBlink), к которому подключаются хотспоты и репитеры, плюс декодирующий UDP-прокси для анализа трафика и веб-дашборд. Позволяет поднять собственную закрытую DMR-сеть, не завязанную на публичные мастера. +Это форк проекта **0DMRMaster** Александра Мокрова (UR6LKW), оригинал — `https://github.com/olympy/0DMRMaster`, лицензия GPL-3.0 (файл `LICENSE`). Копия взята для эксплуатации у себя — как мастер-сервер и как инструмент разбора DMR-пакетов рядом с XLX-рефлектором. Документация оригинального проекта (описание протокола, roadmap, список источников ETSI) сохранена в [README.upstream.md](README.upstream.md). -## License -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. +## Отличия от оригинала +- `2025-06-19` — единственный собственный коммит: `localmaster_EXAMPLE.py` переименован в `localmaster.py`. Содержимое файла не изменено (`similarity index 100%`). -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. +Смысл правки: в оригинале `localmaster.py` — локальный конфиг-файл запуска, он перечислен в `.gitignore` (`/localmaster.py`) и в репозитории лежит только пример. В этой копии рабочий файл запуска взят под контроль версий, чтобы разворачивать сервер клонированием без ручного копирования примера. Побочный эффект: любые локальные настройки (в том числе список разрешённых peer ID и паролей в `ListPeerAuth`) при последующих правках попадут в историю git. -You should have received a copy of the GNU General Public License -along with this program. If not, see . +Кода самого проекта (`dmrtools/`, `api/`, `dashboard/`) владелец не менял — он полностью соответствует апстриму по состоянию на 2025-06-01. +## Стек +- Python 3.11+, asyncio (`asyncio.DatagramProtocol` для UDP). +- FastAPI + uvicorn — HTTP API и раздача дашборда; `bitarray`/`bitstring` — разбор битовых полей DMR; `dmr-utils3` (BPTC-декодирование Embedded LC); pydantic. Полный список — `requirements.txt`. +- Дашборд — статический HTML + JS без фреймворков. +- Работает на Linux и Windows. Специального железа (AMBE-чипов) не требуется: голос не транскодируется, кодек AMBE пока не реализован. -## Overview -This project contains: -1. An implementation of homebrew dmr protocol (which is used by brandmeister and hblink). Not yet complete, but sufficient for #2 and #3. -1. Decoding UDP proxy -1. Basic private dmr master server +## Структура +- `localmaster.py` — точка входа: наследник `DMRMaster`, в методе `config()` задаётся авторизация пиров и регистрируются приложения. Здесь же включается «попугай» (`ParrotApp(9990)`). +- `udpproxylogger.py` — второй исполняемый скрипт: UDP-прокси между хотспотом и чужим мастером с hex-логом и декодированием пакетов (L1 MMDVM + L2 ETSI). +- `relog.py` — повторный разбор ранее сохранённого лога (строки `HD: `) тем же декодером. +- `dmrtools/dmrmaster.py` — каркас сервера: разбор аргументов командной строки, логирование, запуск UDP-сервера и API. +- `dmrtools/dispatcher.py` — маршрутизация пакетов между пирами и приложениями. +- `dmrtools/peer.py`, `peer_controller.py` — состояние подключённых репитеров/хотспотов и конечный автомат логина (RPTL/RPTK/RPTC). +- `dmrtools/auth.py` — политики доступа: `AllowAllPeerAuth` (пускать всех), `DenyAllPeerAuth`, `ListPeerAuth({id: 'пароль'})` со сверкой SHA-256 хэша с солью. +- `dmrtools/call.py` — сборка голосового вызова из потока пакетов. +- `dmrtools/parrot_app.py` — приложение-эхо: записывает вызов на свой ID и проигрывает обратно с задержкой. +- `dmrtools/app.py` — базовые интерфейсы приложений (`App`, `IAppCallInterceptor`, `IAppDispatcher`). +- `dmrtools/udpproxy.py` — многоклиентский UDP-прокси (сессия на каждый адрес клиента). +- `dmrtools/network.py`, `asyncnetwork.py` — интерфейсы отправки/приёма датаграмм и их asyncio-реализация. +- `dmrtools/dmrproto/mmdvm_l1.py` — пакеты Homebrew/MMDVM (DMRD, RPTL, RPTPING, DMRA и т.д.), расчёт хэша пароля. +- `dmrtools/dmrproto/etsi_l2.py`, `lc_util.py`, `enums.py`, `base_fields.py`, `factory.py` — разбор внутренней структуры DMR по ETSI TS 102 361: Link Control, тип голосового кадра, Talker Alias. +- `dmrtools/pphex.py` — hexdump для логов. +- `api/dmrapi.py` — FastAPI-приложение: `/api/dashboard`, `/api/peers`, `/api/calls`, монтирование статики. +- `dashboard/index.html`, `dashboard/app.js` — веб-дашборд, опрашивающий API. +- `doc/dashboard-screenshot.png` — скриншот дашборда для README. -### Installation -1. Check basic requirements: - - Linux or Windows - - Python 3.11+ -1. Clone/download the repo. -1. Create environment and install requirements (linux example): +## Как запустить/установить +```sh +python -m venv venv +. venv/bin/activate +python -m pip install --upgrade pip +pip install -r requirements.txt +python localmaster.py ``` -$ python -m venv venv -$ . venv/bin/activate -$ python -m pip install --upgrade pip -$ pip install -r requirements.txt +Остановка — `Ctrl+C`. + +По умолчанию сервер слушает `62031/udp` (DMR) и `8000/tcp` (API и дашборд): +- API: `http://<сервер>:8000/api/dashboard` +- Дашборд: `http://<сервер>:8000/dashboard/index.html` + +UDP-прокси с логом: +```sh +python udpproxylogger.py [-l log.txt] +``` +Повторный разбор лога: +```sh +python relog.py <входной-лог> [-l log.txt] ``` -### Configuration -Copy `localmaster_EXAMPLE.py` to `localmaster.py` and edit. +## Конфигурация +Аргументы `localmaster.py` (обрабатываются в `dmrtools/dmrmaster.py`): +- `-i, --interface` — интерфейс для DMR (по умолчанию `0.0.0.0`); +- `-p, --port` — UDP-порт DMR (по умолчанию `62031`); +- `--web-interface` — интерфейс API (по умолчанию `0.0.0.0`); +- `--web-port` — TCP-порт API (по умолчанию `8000`); +- `-l, --log-file` — файл лога; +- `-d, --ll-debug` — уровень логирования DEBUG вместо INFO. -### Run -``` -$ . venv/bin/activate -$ python localmaster.py -``` -`Ctrl+C` to break and stop. +Настройки в коде `localmaster.py` → `DMRMasterLocal.config()`: +- политика доступа: сейчас активна `AllowAllPeerAuth()` — **подключиться может любой peer ID без пароля**; закомментирована строка с `ListPeerAuth({1: 'pass1', 2: ''})` — вариант со списком разрешённых ID и паролей; +- `self.register_app(ParrotApp(9990))` — ID «попугая»; у `ParrotApp` также есть параметры `repeat_delay` (5 с) и прочие, задаваемые при создании. -The running server listens for `62031/udp` as DMR service (may be changed with `--port` command line argument) -and exposes http API/dashboard on `8000/tcp` (may be changed with `--web-port` command line argument): -- API: http://YOUR-SERVER-IP:8000/api/dashboard -- Web dashboard: http://YOUR-SERVER-IP:8000/dashboard/index.html -![web dashboard](https://github.com/olympy/0DMRMaster/blob/master/doc/dashboard-screenshot.png?raw=true) +Паролей и токенов в репозитории нет: `pass1` в закомментированной строке — заглушка из примера. Реальные пароли пиров при вводе в эксплуатацию следует держать вне репозитория (см. `.env`/локальный незакоммиченный конфиг), тем более что `localmaster.py` здесь отслеживается git. +## Состояние +Рабочий прототип (сам автор оригинала определяет статус как public alpha, версия 0.5, «не использовать в проде, интерфейсы могут меняться»). Последний коммит 2025-06-19 (собственный, переименование файла), последний коммит апстрима — 2025-06-01. Всего 17 коммитов. - -## Roadmap -### What is this for (general TODO) -- Private dmr network (own registration, admintool, dashboard, voice apps, etc) -- Other dmr networks bridge (configurable group/unit routing rules, ID replacements, etc) -- Bridge/proxy with packet modification (substitute IDs, add TA, etc..) -- Voice robots interface at packet level (parrot for group and unit cals, recording/playback as prewritten packets by events) -- Encoding and decoding of AMBE (allows to build advanced voice services, like voice time, agenda, etc) -- Voice call history dump (ambe files or decoded) - - -### Features & TODO -- ✔️ basic apps support -- ✔️ parrot -- ✔️ password check -- ✔️ fastapi api -- ✔️ web dashboard -- ✔️ unit call routing -- ✔️ allow single peer id check -- ✔️ TA support (DMRA packet) -- ✔️ dmr internal structure decoding (get LC, voice data) -- 🥕 routing (1 timeslot == 1 routing entity) -- 🥕 only one call per ts for peer (per routing entity) -- 🥕 dmr internal structure encoding (set LC, generate voice data) -- 🥕 apps unit call routing (routing entity for app) -- 🥕 configuration -- 🥕 users configuration (allowed id and passes per id) -- 🥕 resolve id to callsigns -- 🥕 routing 2: group subscriptions -- 🥕 data calls (messages) -- 🥕 ambe decode/encode -- 🥕 log voice calls as files -- 🥕 TA support 2 (inside DMRD packets) -- 🥕 registration -- 🥕 update radiod list and resolve - -## Sources -- ETSI TS 102 361-1 V1.2.1 (2006-01) -Technical Specification -Electromagnetic compatibility -and Radio spectrum Matters (ERM); -Digital Mobile Radio (DMR) Systems; -Part 1: DMR Air Interface (AI) protocol -https://www.etsi.org/deliver/etsi_ts/102300_102399/10236101/01.02.01_60/ts_10236101v010201p.pdf - -- ETSI TS 102 361-2 V2.3.1 (2016-02) -Electromagnetic compatibility -and Radio spectrum Matters (ERM); -Digital Mobile Radio (DMR) Systems; -Part 2: DMR voice and generic services and facilities -https://www.etsi.org/deliver/etsi_ts/102300_102399/10236102/02.03.01_60/ts_10236102v020301p.pdf - -- MMDVMHost by Jonathan Naylor, G4KLX -https://github.com/g4klx/MMDVMHost - -- HBLink3 by Cortney T. Buffington, N0MJS -https://github.com/n0mjs710/hblink3 - -- IPSC Protocol Specs for homebrew DMR repeater by DL5DI, G4KLX, DG1HT 2015 (partially obsolete) -https://wiki.brandmeister.network/images/5/54/DMRplus_IPSC_Protocol_for_HB_repeater.pdf \ No newline at end of file +## Что не доделано +- Явный TODO в коде один: `dmrtools/dmrproto/lc_util.py:141` — `return None # Not supported; !!TODO: decode 7-bit` (не декодируется 7-битный Talker Alias). +- По roadmap апстрима (см. `README.upstream.md`) не реализованы: файл конфигурации и конфигурация пользователей, полноценная маршрутизация (по слотам, подписки на группы), кодирование внутренних структур DMR, датапакеты/сообщения, кодек AMBE, запись голосовых вызовов в файлы, TA внутри DMRD, регистрация абонентов и резолв ID в позывные. +- Собственных доработок форка нет — расхождение с оригиналом сводится к одному переименованию, поэтому обновление апстрима должно проходить без конфликтов, кроме файла `localmaster.py`. +- `localmaster.py` числится в `.gitignore`, но при этом отслеживается — при правке локальных настроек их легко закоммитить случайно. diff --git a/README.upstream.md b/README.upstream.md new file mode 100644 index 0000000..c3463c5 --- /dev/null +++ b/README.upstream.md @@ -0,0 +1,119 @@ +# 0DMRMaster +Private DMR master server. Version 0.5. +Copyright ©2025 Alexander Mokrov, UR6LKW. + +This project is currently in public alpha and is under active development. +Don't use it in production environment, interfaces may change. + + +## License +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + + +## Overview +This project contains: +1. An implementation of homebrew dmr protocol (which is used by brandmeister and hblink). Not yet complete, but sufficient for #2 and #3. +1. Decoding UDP proxy +1. Basic private dmr master server + +### Installation +1. Check basic requirements: + - Linux or Windows + - Python 3.11+ +1. Clone/download the repo. +1. Create environment and install requirements (linux example): +``` +$ python -m venv venv +$ . venv/bin/activate +$ python -m pip install --upgrade pip +$ pip install -r requirements.txt +``` + +### Configuration +Copy `localmaster_EXAMPLE.py` to `localmaster.py` and edit. + +### Run +``` +$ . venv/bin/activate +$ python localmaster.py +``` +`Ctrl+C` to break and stop. + +The running server listens for `62031/udp` as DMR service (may be changed with `--port` command line argument) +and exposes http API/dashboard on `8000/tcp` (may be changed with `--web-port` command line argument): +- API: http://YOUR-SERVER-IP:8000/api/dashboard +- Web dashboard: http://YOUR-SERVER-IP:8000/dashboard/index.html +![web dashboard](https://github.com/olympy/0DMRMaster/blob/master/doc/dashboard-screenshot.png?raw=true) + + + +## Roadmap +### What is this for (general TODO) +- Private dmr network (own registration, admintool, dashboard, voice apps, etc) +- Other dmr networks bridge (configurable group/unit routing rules, ID replacements, etc) +- Bridge/proxy with packet modification (substitute IDs, add TA, etc..) +- Voice robots interface at packet level (parrot for group and unit cals, recording/playback as prewritten packets by events) +- Encoding and decoding of AMBE (allows to build advanced voice services, like voice time, agenda, etc) +- Voice call history dump (ambe files or decoded) + + +### Features & TODO +- ✔️ basic apps support +- ✔️ parrot +- ✔️ password check +- ✔️ fastapi api +- ✔️ web dashboard +- ✔️ unit call routing +- ✔️ allow single peer id check +- ✔️ TA support (DMRA packet) +- ✔️ dmr internal structure decoding (get LC, voice data) +- 🥕 routing (1 timeslot == 1 routing entity) +- 🥕 only one call per ts for peer (per routing entity) +- 🥕 dmr internal structure encoding (set LC, generate voice data) +- 🥕 apps unit call routing (routing entity for app) +- 🥕 configuration +- 🥕 users configuration (allowed id and passes per id) +- 🥕 resolve id to callsigns +- 🥕 routing 2: group subscriptions +- 🥕 data calls (messages) +- 🥕 ambe decode/encode +- 🥕 log voice calls as files +- 🥕 TA support 2 (inside DMRD packets) +- 🥕 registration +- 🥕 update radiod list and resolve + +## Sources +- ETSI TS 102 361-1 V1.2.1 (2006-01) +Technical Specification +Electromagnetic compatibility +and Radio spectrum Matters (ERM); +Digital Mobile Radio (DMR) Systems; +Part 1: DMR Air Interface (AI) protocol +https://www.etsi.org/deliver/etsi_ts/102300_102399/10236101/01.02.01_60/ts_10236101v010201p.pdf + +- ETSI TS 102 361-2 V2.3.1 (2016-02) +Electromagnetic compatibility +and Radio spectrum Matters (ERM); +Digital Mobile Radio (DMR) Systems; +Part 2: DMR voice and generic services and facilities +https://www.etsi.org/deliver/etsi_ts/102300_102399/10236102/02.03.01_60/ts_10236102v020301p.pdf + +- MMDVMHost by Jonathan Naylor, G4KLX +https://github.com/g4klx/MMDVMHost + +- HBLink3 by Cortney T. Buffington, N0MJS +https://github.com/n0mjs710/hblink3 + +- IPSC Protocol Specs for homebrew DMR repeater by DL5DI, G4KLX, DG1HT 2015 (partially obsolete) +https://wiki.brandmeister.network/images/5/54/DMRplus_IPSC_Protocol_for_HB_repeater.pdf \ No newline at end of file