Наземные станции

Станция (Station) — точка приёма в сети. Принадлежит пользователю, имеет координаты, набор антенн и настройки планирования.

Статусы

Состояние станции не хранится: оно выводится из трёх величин — last_seen, is_available и testing — каждый раз, когда его спрашивают, и потому не может разъехаться с сердцебиением. Station.status_badge возвращает слаг состояния, Station.status_label — его название.

Слаг

Значение

Условие

online

На связи и открыта сети

last_seen свежее STATION_HEARTBEAT_TIME, is_available, не testing

testing

Работает, наблюдения считаются тестовыми

то же плюс testing

unavailable

На связи, но владелец закрыл приём

то же плюс is_available = False

offline

Не выходила на связь дольше сердцебиения

last_seen устарел

never

Ни разу не выходила на связь

last_seen пуст

unavailable — состояние, которым владелец закрывает станцию для чужих наблюдений, оставаясь на связи: свои наблюдения он планирует как обычно, собственное расписание станции продолжает работать, сетевое автопланирование её не трогает. Флажок — в настройках станции.

Переходы пишутся в StationStatusLog (три булевых: is_connected, is_available, testing). Строка появляется при сохранении станции, если состояние действительно изменилось; уход станции со связи никто не сохраняет, поэтому его раз в час дописывает задача station_log_disconnect.

В API v1 (/api/stations/) поле status по-прежнему отдаёт три слова Online/Testing/Offline, и unavailable в них читается как Offline — станция, которая никогда не обновится, продолжает видеть тот же словарь. Фильтр ?status=2|1|0 работает по тем же правилам.

Основные поля

Поле

Назначение

owner

Владелец, network.users.User

name

Отображаемое имя

lat, lng, alt

Широта (−90…90), долгота (−180…180), высота над уровнем моря в метрах (от −500: станция ниже уровня моря — реальный случай)

qthlocator

QTH-локатор. Не колонка: считается из координат тем же gridsquare(), что и приём SiDS

horizon

Минимальный угол места в градусах, ниже которого наблюдения не планируются

target_utilization

Целевой коэффициент загрузки станции, 0…100

client_version, client_id

Версия и идентификатор клиента

reported_status, reported_status_at

Что станция сообщила о себе через POST /api/v2/stations/<id>/status/ или MQTT — слияние по ключам верхнего уровня: modes и client_version (клиент), config (итог применения конфигурации и фактические значения), sdr (найденные приёмники и их возможности), calibration (свип по усилению и рекомендованное значение), scheduling (за сколько секунд до начала станции нужно задание — порог планирования, пока она на связи), connection (мост MQTT). Планирование предлагает станции только заявленные режимы; без modes станция планируется на все

desired_config, config_generation, config_updated_at

Конфигурация, сохранённая владельцем в форме «Настройки станции»: плоский словарь с именами переменных окружения клиента, номер сохранения, время. 0 — не сохранялась, станция на своём .env

commands

Разовые просьбы к станции из формы настроек — rescan_sdr, calibrate_gain с отметкой at и частотами; уходят в документе state/, станция выполняет раз на отметку между проходами

release_channel, update_mode

Канал релизов (canary/stable, digest образа — в ReleaseChannel, правят администраторы) и разрешение агенту обновлять станцию самому (managed) или только сообщать (notify)

violator_scheduling

Кому разрешено планировать спутники-нарушители: «Никто» (0), «Только операторы» (1), «Все» (2)

featured_date

Дата вывода станции в подборку

Конфигурация с портала

Владелец настраивает приёмник, усиление, поправки частоты, поворотное устройство, запись IQ и уровни логов в форме «Настройки станции» (stations/edit/<id>/) — той же, где имя, координаты и антенны, с пояснением у каждого поля. Кнопку «Настройки станции» на странице станции видят владелец, модераторы и суперпользователи. Единый список полей — STATION_CONFIG_FIELDS в network/base/station_config.py; ключи совпадают с переменными окружения клиента и с его MANAGED_FIELDS. Сохранение, которое меняет поле конфигурации, — новое поколение: станция забирает документ GET /api/v2/stations/<id>/state/ (и получает его по MQTT сразу), открывает приёмник с новыми параметрами и применяет между проходами; итог возвращается в reported_status.config и показывается на странице как «поколение N применено» или «отклонено: …». Сохранение без правок конфигурации — имя, координаты, антенны — поколения не создаёт. Пока владелец ничего не сохранил, форма предзаполняется фактическими значениями со станции, и станция остаётся на своём .env, пока в конфигурации что-нибудь не изменят; кнопка «Заполнить с станции» подставляет эти значения и позже. Что станция делает с документом — docs/station/configuration.md клиента.

Там же — то, что станция узнала о себе сама. Блок «Найденные приёмники» показывает устройства SoapySDR, которые станция перечислила (на старте, раз в час в простое и по кнопке «Пересканировать»), с входами, диапазоном усиления и частотами дискретизации; «Использовать» подставляет их в поля формы. Блок «Калибровка усиления» по кнопке просит станцию прогнать свип по усилению на частотах антенн (середины диапазонов, можно править) и рисует шумовую полку графиком; «Применить рекомендованное» ставит усиление, на котором полка поднялась на порог станции. Обе кнопки — команды в Station.commands, часть документа state/.

Антенны и диапазоны

Антенна (Antenna) ссылается на тип (AntennaType) и содержит один или несколько диапазонов (FrequencyRange). Ограничения:

  • MAX_ANTENNAS_PER_STATION — антенн на станцию (по умолчанию 4);

  • MAX_FREQUENCY_RANGES_PER_ANTENNA — диапазонов на антенну;

  • MIN_FREQUENCY_FOR_RANGE / MAX_FREQUENCY_FOR_RANGE — допустимые границы.

Диапазон автоматически классифицируется по радиодиапазонам (VHF/UHF/L/S) — границы задаются переменными VHF_MIN_FREQUENCY, VHF_MAX_FREQUENCY, UHF_*, L_*, S_* (см. Конфигурация). Планирование сопоставляет диапазоны антенн с частотами передатчиков спутника.

Список поддерживаемых типов антенн загружается начальными фикстурами (django-admin initialize) и переведён на русский в интерфейсе: диполь, V-дипольная, дисконная, базовая, яги, кросс-яги, спиральная, параболическая, вертикальная, турникетная, квадрифилярная, «взбивалка», линденблад, паразитная линденблад и др.

Регистрация станции

Клиент регистрируется через POST /api/station/register. Дальше он забирает свои задания из /api/jobs/ и отправляет результаты в /api/observations/ и /api/demoddata/ — см. Обзор эндпоинтов.

Проверить состояние станции можно через GET /api/stations/check.

Настройки автопланирования

У станции может быть до двух расписаний и одно общесетевое:

Модель

Связь

Назначение

StationSchedule

one-to-one со станцией

Основное расписание станции

StationScheduleSec

one-to-one со станцией

Дополнительное расписание

NetworkSchedule

одиночная запись

Общесетевое расписание

У всех трёх одинаковая структура: флаг active, список спутников (satellites, JSON) и параметры (param, JSON) — минимальный угол места, азимутальные окна и прочие ограничения. Как эти параметры применяются, описано в Планирование наблюдений.

Статистика

StationStat хранит агрегаты по станции. Пересчитываются задачами calculate_all_station_stat / calculate_station_stat (ежедневно в 03:00 UTC). Суточные метрики по станциям ведёт отдельное приложение — см. Аналитика.

Уведомления о проблемах

Задача notify_for_stations_without_results находит станции, у которых подряд идут наблюдения без результатов (порог — OBS_NO_RESULTS_MIN_COUNT, по умолчанию 3), и отправляет уведомление на EMAIL_FOR_STATIONS_ISSUES. Период проверки — OBS_NO_RESULTS_CHECK_PERIOD.