# Добавление флоуграфа и режима Рецепт на примере нового декодера спутника. Ни один из шагов не выполняется автоматически: списки в CMake явные, таблицы режимов — руками. ## 1. Создать `.grc` Отправная точка — ближайший по смыслу существующий декодер, а не пустой лист: | Задача | С чего копировать | |---|---| | ЧМн с фреймингом AX.25 | `generic/fsk_ax25.grc` | | ЧМн с дефреймером gr-satellites | `satellites/geoscan_gfsk_decoder.grc` | | Фазовая манипуляция | `generic/bpsk.grc` | | Только аудио | `generic/fm.grc` | | Минимальный каркас | `generic/example_flowgraph.grc` | Положить в `satellites/` (декодер конкретного аппарата) или `generic/` (модуляция или протокол общего назначения). Обязательное при копировании: - поменять `id` на `satnogs_<имя файла>` — по нему называется выходной скрипт; - сохранить общий набор параметров и фрагмент `rig_pathname`; - сохранить три ответвления ZMQ, водопад и UDP-сток. Всё это подробно — в [](grc-conventions.md). ## 2. Внести файл в CMake ```cmake set(flowgraphs … my_decoder.grc ) ``` `satellites/CMakeLists.txt` или `generic/CMakeLists.txt`. **Списки явные, не по маске** — без этой строки файл не соберётся и никакой ошибки не будет. Проверить, что цель появилась: ```sh cd build && cmake .. && make my_decoder ``` ## 3. Зарегистрировать скрипт и режим В `flowgraph_dispatcher/flowgraph_dispatcher.py` — две таблицы. ```python SATNOGS_FLOWGRAPH_SCRIPTS = { # … существующие режимы … 'MY_MODE': 'satnogs_my_decoder.py', } SATNOGS_FLOWGRAPH_MODES = { # … существующие режимы … 'MY_MODE': { 'script_name': SATNOGS_FLOWGRAPH_SCRIPTS['MY_MODE'], 'has_baudrate': True, 'has_framing': False, 'outputs_frames': True, }, } ``` Что означают флаги: `has_baudrate` : принимать `--baud` и передавать его как `--baudrate`. Если `False`, значение клиента отбрасывается с предупреждением в `stderr`. `has_framing` : диспетчер сам подставит `--framing` из ключа `framing` того же словаря (добавьте его, если ставите `True`). Значение клиента отбрасывается всегда, поэтому при `False` во флоуграфе параметра `framing` быть не должно. `outputs_frames` : поднять подписчика кадров. Ставьте `True`, только если во флоуграфе действительно есть `zeromq_pub_msg_sink`, иначе процесс будет висеть впустую. Строка режима — это то, что пришлёт `soniks-client-new`; согласуйте её с сетью. Пробелы допустимы (`GMSK USP`), но потребуют кавычек в командной строке. ## 4. Новый параметр — в две стороны Если флоуграфу нужен параметр, которого нет в общем наборе, недостаточно объявить его в `.grc`. Добавьте соответствующий аргумент в `client_argument_parser()`: ```python parser.add_argument('--frame-size', type=int, help='Set frame size in bytes') ``` Имена обязаны совпадать: `--frame-size` ↔ блок `parameter` с именем `frame_size`. Иначе либо флоуграф завершится с кодом 2 на неизвестном аргументе, либо тихо возьмёт значение по умолчанию — то и другое ловит `tests/test_dispatcher.py`, см. [](architecture.md#контракт-2-имена-аргументов). Если параметр нужен только одному режиму и не приходит от клиента, его можно подставлять в конструкторе диспетчера — так сделано для `GFSK Pkst` (`frame-size=192`). ## 5. Собрать и проверить Сначала тесты — они не требуют ни GNU Radio, ни приёмника и сразу скажут, если `.grc` разошёлся с CMake, диспетчером или соглашениями по портам: ```sh python3 tests/test_flowgraphs.py python3 tests/test_dispatcher.py flake8 flowgraph_dispatcher tests ``` Затем сборка и прогон: ```sh cd build && cmake .. && make && sudo make install # набор параметров сгенерированного скрипта satnogs_my_decoder.py --help # прогон целиком, через диспетчер mkdir -p /tmp/.satnogs/data rigctld -m 1 & flowgraph_dispatcher --mode MY_MODE --baud 9600 \ --soapy-rx-device=driver=rtlsdr --rx-freq=435000000 \ --file-path=/tmp/.satnogs/data/audio.ogg \ --decoded-data-file-path=/tmp/.satnogs/data/data ``` Без эфира сигнал можно подать по петле генераторами из [`test_flowgraphs/`](../flowgraphs/index.md#тестовые-флоуграфы) или скормить ранее записанный IQ-файл. Само дерево процессов — подписчики, разведение по портам, код возврата и завершение по сигналу — проверяется без приёмника и без `gr-satnogs`: ```sh python3 tests/e2e_check.py ``` Скрипт подставляет вместо флоуграфа заглушку, публикующую в те же три порта, и поднимает два диспетчера с разными `--zmq-base-port`. Нужны `pmt` из GNU Radio, `pyzmq`, `numpy` и `soundfile` — поэтому в CI он идёт в джобе `flowgraphs`, а не в `test`: `python:3.11-slim` этого не даёт, образ GNU Radio даёт. На станции с реальными флоуграфами те же проверки прогоняются по установленным скриптам: `E2E_FLOWGRAPH_BIN=/usr/bin python3 tests/e2e_check.py`. ## 6. Обновить документацию Изменение поведения без правки документации не принимается. Что затрагивается: | Что сделали | Что править | |---|---| | новый `.grc` | [](../flowgraphs/index.md) — сводная таблица; плюс разбор в `generic.md`, `satellites.md` или на отдельной странице | | новый режим | [](../modes.md) — таблица режимов | | новый аргумент | [](../dispatcher.md) — таблица аргументов | | новый формат выхода | [](../outputs.md) | | новый инвариант `.grc` | `tests/test_flowgraphs.py` | | новая зависимость | [](../install.md) **и** `debian/control` | ## 7. Закоммитить Требования CI — в [](contributing.md). Коротко: атомарные коммиты, императивный заголовок не длиннее 50 символов, обязательный `Signed-off-by:`. Никаких бинарников и сгенерированных `.py`. Разумное разбиение: отдельный коммит на `.grc` вместе со строкой в CMake, отдельный — на регистрацию режима в диспетчере, отдельный — на документацию.