flowgraph_dispatcher

Единственный бинарник, который вызывает клиент станции. Выбирает флоуграф по режиму, переписывает часть аргументов, поднимает процессы и следит за ними.

flowgraph_dispatcher --mode <MODE> [аргументы приёмника, rigctl и путей]

Аргументы командной строки

Все аргументы необязательны и по умолчанию равны None. Значение по умолчанию задаёт не диспетчер, а сам флоуграф: аргумент со значением None просто не передаётся дальше, и .grc использует своё значение.

Каждый аргумент уходит во флоуграф как --ключ=значение без изменений, поэтому имя параметра в .grc обязано совпадать с именем аргумента (дефисы против подчёркиваний — единственная разница).

Управление режимом

Аргумент

Тип

Назначение

--mode

строка

режим модуляции, см. Справочник режимов. Во флоуграф не передаётся

--baud

строка

скорость передачи; превращается в --baudrate либо в --wpm для CW. Во флоуграф под своим именем не передаётся

--framing

строка

принимается для совместимости с клиентом и игнорируется: фрейминг задаёт таблица режимов. Переданное значение вызывает предупреждение

Приёмник (SoapySDR)

Аргумент

Тип

Назначение

--soapy-rx-device

строка

строка устройства, например driver=rtlsdr

--samp-rate-rx

float

частота дискретизации приёмника, Гц

--rx-freq

float

центральная частота приёма, Гц

--lo-offset

строка

смещение гетеродина, Гц (по умолчанию во флоуграфах 100 кГц)

--bb-freq

float

частота CORDIC основной полосы

--bw

float

полоса аналогового фильтра, Гц

--gain

float

суммарное усиление, дБ

--gain-mode

строка

режим АРУ устройства (Overall по умолчанию)

--antenna

строка

имя антенного входа устройства

--ppm

float

поправка опорного генератора, ppm

--dc-removal

int

автоматическое подавление постоянной составляющей

--dev-args

строка

аргументы устройства SoapySDR

--stream-args

строка

аргументы потока

--tune-args

строка

аргументы перестройки

--other-settings

строка

прочие настройки канала

Доплеровская компенсация

Аргумент

Тип

Назначение

--rigctl-host

строка

адрес rigctld

--rigctl-port

int

порт rigctld (обычно 4532)

--doppler-correction-per-sec

int

число коррекций в секунду

Выходные файлы

Аргумент

Тип

Кто использует

--waterfall-file-path

строка

сам флоуграф, блок satnogs_waterfall_sink

--decoded-data-file-path

строка

подписчик zmq_frame_decoder_sub, как префикс имени

--file-path

строка

подписчик zmq_audio_sub, как полный путь к OGG

--iq-file-path

строка

подписчик zmq_iq_sub, как префикс имени

--enable-iq-dump

int

диспетчер: 1 включает подписчика IQ

Живой поток

Аргумент

Тип

Назначение

--udp-dump-host

строка

адрес назначения UDP-потока IQ

--udp-dump-port

int

порт назначения

Каналы ZMQ

Аргумент

Тип

Назначение

--zmq-base-port

int

первый из трёх портов ZMQ, по умолчанию 16887. Кадры уходят на него, IQ на +1, аудио на +2. Передаётся во флоуграф как --zmq-base-port, флоуграф собирает те же три адреса сам

Аргумент нужен, чтобы поднять две станции на одной машине: второй экземпляр запускается с --zmq-base-port=17887.

Примечание

--waterfall-file-path — единственный путь, который обрабатывает сам флоуграф. Три остальных пути ему передаются, но ни к чему не подключены: запись файлов живёт в процессах-подписчиках. См. Рудиментарные параметры.

Правила переписывания аргументов

Порядок действий в конструкторе диспетчера:

  1. Скопировать все аргументы как есть.

  2. Запомнить mode, baud и framing, затем обнулить mode, baud, wpm и framing, чтобы они не ушли во флоуграф.

  3. Неизвестный режим заменить на UNKNOWN.

  4. Взять скрипт из таблицы режимов.

  5. Для UNKNOWN без --baud подставить 48000.

  6. Если --baud задан и режим принимает бодрейт:

    • CW → добавить wpm, остальные → добавить baudrate;

    • FSK на 50000 или 400000 бод → подменить скрипт на PHASMA.

  7. GFSK Pkst → добавить frame-size=192.

  8. Если у режима собственный фрейминг → выставить framing значением из таблицы.

Предупреждения

Раньше подмены происходили молча — теперь каждая пишет жёлтую строку в stderr:

  • --framing=<значение> ignored, framing follows --mode;

  • --baud=<значение> ignored, mode <режим> has no baudrate — для AFSK, DUV, APT, FM, SSTV, SSTV_PD120;

  • FSK at 50000 baud decoded as PHASMA;

  • unknown mode '<строка>', falling back to UNKNOWN;

  • ignored unknown arguments: <список>.

Аргументы, которых диспетчер не знает

Разбор идёт через parse_known_args(), а не parse_args(). Клиент новее диспетчера больше не глушит станцию: раньше лишний аргумент завершал диспетчер с кодом 2 до запуска графа, и в лог станции это приходило как проход, закончившийся досрочно, — без единой строки об ошибке. Теперь это жёлтое предупреждение, а наблюдение продолжается.

--norad-cat-id и --lo-transverter парсер принимает явно, но никуда не передаёт: ни один .grc их не объявляет, а flowgraph_argv() передаёт всё вслепую. Это позволяет клиенту слать их уже сегодня. --norad-cat-id начнёт что-то значить, когда будет подключён gr-satellites: он выбирает декодер по NORAD через satyaml.

Примечание

Обнуление framing — не косметика. grcc генерирует parse_args(), поэтому неизвестный аргумент завершает флоуграф с кодом 2. Параметра framing нет в 13 из 20 флоуграфов, и раньше --framing от клиента ронял их все.

Подмена FSK → PHASMA происходит после подстановки бодрейта, поэтому PHASMA получает исходные 50000 или 400000.

Жизненный цикл процессов

Подписчики стартуют раньше флоуграфа — иначе первые сообщения ZMQ пропадут:

  1. если режим отдаёт кадры → zmq_frame_decoder_sub --zmq-dump-host=127.0.0.1 --zmq-dump-port=<base> --decoded-data-file-path=…

  2. если --enable-iq-dump истинно → zmq_iq_sub --zmq-dump-host=127.0.0.1 --zmq-dump-port=<base+1> --iq-file-path=…

  3. всегдаzmq_audio_sub --zmq-dump-host=127.0.0.1 --zmq-dump-port=<base+2> --file-path=…

  4. сам флоуграф: satnogs_<имя>.py --ключ=значение

Здесь <base> — значение --zmq-base-port, по умолчанию 16887. См. Выходные данные.

Затем main() крутится в цикле, опрашивая процесс флоуграфа каждые 250 мс.

Завершение

SIGINT (Ctrl+C) и SIGTERM обрабатываются диспетчером одинаково. Сначала SIGINT получает флоуграф, и диспетчер дожидается именно его: пока флоуграф жив, подписчики продолжают дочитывать сокеты. Затем SIGINT уходит всем подписчикам сразу, и только потом диспетчер ждёт каждого из них. Ожидание — 2 секунды (TERMINATION_GRACE_SEC), дальше SIGKILL. В худшем случае завершение занимает 4 секунды.

Сигнал и ожидание разнесены намеренно. Пока диспетчер сигналил и ждал каждого подписчика по очереди, две секунды первого из них тратились на общем с остальными процессоре, и подписчик аудио — единственный, у кого закрытие делает реальную работу (сброс OGG-кодировщика) — под нагрузкой не успевал и получал SIGKILL посреди записи. Воспроизводилось tests/e2e_check.py примерно раз на три прогона.

Если процесс пришлось убить, в вывод идёт предупреждение — например, «Flowgraph script did not close properly! Some data might be missing».

Остановка гарантирована блоком try/finally в main(), а не сборщиком мусора: подписчики гасятся даже при исключении в самом диспетчере.

Код возврата

Диспетчер возвращает код завершения флоуграфа. Убитый сигналом флоуграф даёт 128 + номер сигнала по соглашению оболочки. Ноль означает, что флоуграф отработал и корректно остановился, — по коду возврата можно отличить отказ приёма от пустого пролёта.

Ошибки запуска

Если скрипт флоуграфа не удалось запустить (нет файла, нет прав), диспетчер гасит уже поднятые подписчики и выходит с сообщением:

Error starting flowgraph: <причина>
Aborting Observation!

Разбор типовых причин — Диагностика неисправностей.