19 KiB
HTTP-канал управления RF-001
Текущее состояние: HTTP-КАНАЛ РАБОТАЕТ; ВЕРСИОННЫЙ МЕХАНИЗМ ОБНОВЛЕНИЯ
И НЕБЛОКИРУЮЩИЙ STAIRCASE_SEARCH ПРОВЕРЕНЫ БЕЗ НОВОГО ДОСТУПА К РАДИО.
Канал заменяет Git как транспорт между работающими компьютерами. Git остаётся для исходного кода и истории. Старые watcher-ы сохранены как резервный вариант.
Граница этапа 1
Реализованы:
- JSON-сервер на основном ПК;
- исходящее подключение RX-агента с ноутбука к основному ПК;
- подпись каждого запроса HMAC-SHA256;
- защита от повторного использования запроса по времени и nonce;
- ограничение адреса RX-агента на сервере;
- фиксированные задачи
INVENTORY,OFFLINE_VERIFY,RX_CAPTURE_START,RX_CAPTURE_STATUS,CAPTURE_DECODE,CAPTURE_DIAGNOSTICSиSTAIRCASE_SEARCHиUPDATE_AGENT; - чтение
hostname,whoami, состояния Git иhackrf_info; - сохранение результата на основном ПК;
- обязательное поле
rf_tx = 0во всех сообщениях.
На RX-ноутбуке 23 сентября 2026 года автономная проверка завершилась так:
- ветка
video-development; - HEAD
a94f2db4ee8377201a97263166cb09431df5f5d6; - 100 CRC-корректных пакетов из 100;
- 100 точных пакетов из 100;
hardware_accessed = false;- ошибок нет;
rf_tx = 0.
В сеансе RF001A_20260925T125829Z_227EADB4 уже были выполнены:
- один конечный RX-захват с фиксированным профилем;
- проверка READY по фактическому PID, обнаруженному CLKIN и растущему файлу;
- чтение итогового состояния захвата;
- потоковое декодирование принятого IQ;
- полный потоковый поиск эталонной лестницы без обращения к SDR.
Новые захваты и передачи не входят в текущее состояние и требуют отдельного
явного разрешения. Завершённый поиск лестницы сохраняет исходный результат
NOT_DETECTED; последующая диагностика должна записываться отдельно и не
подменять этот результат.
Не входят в управляющий канал:
- запуск
hackrf_transferв режиме TX; - команда или сетевой метод RF TX;
- изменение firmware, CPLD, USB-драйвера или Zadig;
- commit и push.
Для сервера и RX-агента подготовлен пользовательский автозапуск через Планировщик заданий Windows. Службы Windows и права администратора для этого не нужны. Сервер и агент работают постоянно после входа соответствующего пользователя в Windows. Агент не содержит произвольной shell-команды.
Схема
ОСНОВНОЙ ПК 192.168.255.185:8765
HTTP JSON server
очередь только фиксированных типов заданий
^
| исходящее соединение с подписью запроса
|
RX-НОУТБУК 192.168.255.56
polling agent
hostname / whoami / Git / hackrf_info / offline 100/100
RF TX = 0
Сервер не раздаёт каталоги и произвольные пути. Он может выдать только заранее
зарегистрированный архив агента с точным release_id через ограниченный маршрут
обновлений. Произвольной shell-команды в протоколе нет. Неизвестный тип задания
и любое значение rf_tx, отличное от нуля, отклоняются.
Файлы
tools/rf001_http_control.py: сервер, локальная очередь и клиент управления;tools/rf001_rx_http_agent.py: RX-агент с фиксированной инвентаризацией;tools/rf001_offline_decode.py: фиксированный программныйlegacy-декодер;tools/rf001_staircase_search.py: потоковый поиск эталонной лестницы без обращения к SDR;tools/rf001_staircase_job.py: фиксированный дочерний процесс длительного поиска и сохранение результата до сетевого подтверждения;tools/rf001_agent_update.py: строгая проверка состава и распаковка версионного архива;tools/rf001_agent_launcher.py: стабильный запускатель, переключение версии и локальный откат при неудачном запуске;tools/rf001_build_agent_packages.py: воспроизводимая сборка выпусков и первоначального пакета без включения секрета;tools/rf001_rx_capture.py: жёсткие RX-параметры и проверки READY/COMPLETE;tools/rf001_capture_runner.py: один конечный фоновый RX-процесс и журнал;.local/rf001_http_token.txt: общий секрет вне Git;.local/rf001_http_server_state.json: локальное состояние вне Git.
Подготовка общего секрета
На основном ПК из корня проекта один раз выполнить:
python -B tools\rf001_http_control.py init-token
Команда не перезаписывает существующий секрет. Файл
.local\rf001_http_token.txt надо скопировать на RX-ноутбук по доверенному
каналу и не добавлять в Git. Сервер и агент должны читать одинаковое содержимое.
Запуск сервера на основном ПК
python -B tools\rf001_http_control.py serve `
--bind 192.168.255.185 `
--port 8765 `
--allowed-agent-ip 192.168.255.56
Ожидаемый стартовый вывод:
SERVER = http://192.168.255.185:8765
ALLOWED AGENT IP = 192.168.255.56
TASK KINDS = INVENTORY, OFFLINE_VERIFY, RX_CAPTURE_START, RX_CAPTURE_STATUS, CAPTURE_DECODE, CAPTURE_DIAGNOSTICS, STAIRCASE_SEARCH, UPDATE_AGENT
RF TX = 0
Действующее правило Windows Firewall должно оставаться ограниченным программой
Python, TCP-портом 8765, локальным адресом 192.168.255.185, удалённым
адресом 192.168.255.56 и беспроводным интерфейсом.
Постановка задания на основном ПК
python -B tools\rf001_http_control.py enqueue-inventory --agent-id user-pc
Это локальная операция. Сервер принимает её только от собственного адреса и с правильной подписью. Задание не содержит произвольной команды.
Автозапуск агента на RX-ноутбуке
Первоначальный пакет содержит INSTALL_RX_AGENT.cmd. После распаковки его надо
запустить один раз. Установщик проверяет HMAC-манифест существующим секретом,
размеры и SHA256 всех файлов, сохраняет прежнюю установку и XML задания, а
затем меняет только действие существующего пользовательского задания
SDR Rover RX Agent. Пользователь, триггеры, параметры и уровень прав задания
сохраняются. Ожидаемый итог:
BOOTSTRAP_INSTALL=COMPLETE
TASK_STATE=Running
AGENT_VERSION=2026.09.29.1
ARBITRARY_SHELL=DISABLED
RF_TX=0
После этого ручной запуск на ноутбуке для штатных обновлений не требуется. Запускатель хранит выпуски в отдельных каталогах, проверяет запуск по PID, версии и одноразовой метке и при сбое возвращается к предыдущему локальному выпуску. Очередь MAIN, IQ, эталоны, результаты, конфигурация и секрет находятся вне каталога конкретной версии.
Модель доверия обновлений
Манифест каждого выпуска подписывается HMAC-SHA256 из стандартной библиотеки
Python тем же общим секретом, которым уже подписываются HTTP-запросы. Подпись
охватывает отдельный домен RF001-UPDATE-MANIFEST-V1, release_id, версию
агента, совместимую версию протокола, размер и SHA256 архива и хеш внутреннего
манифеста. Разрешение MAIN дополнительно привязано к agent_id и сроку
действия. Сам секрет в ZIP не включается и при установке не заменяется.
Ограничение модели: общий симметричный секрет находится и на MAIN, и на RX-ноутбуке. Компрометация одного из этих узлов позволяет создавать корректные HMAC-подписи. Аппаратного корня доверия и независимой издательской подписи у этого контура нет.
Перед переключением агент скачивает архив не более двух раз за одну
сохранённую попытку обновления, проверяет подпись, размер, SHA256, точный список
файлов, хеш каждого файла, допустимость путей, предел распакованного объёма,
совместимость и свободное место. Затем выполняется программная самопроверка без
SDR. Если агент занят локальной задачей, обновление остаётся в состоянии
WAITING_FOR_IDLE. Наличие файлов само по себе не считается установкой:
фактическую версию MAIN получает из следующего сообщения работающего агента.
Поиск эталонной лестницы
STAIRCASE_SEARCH принимает только идентификатор существующего сеанса и
ожидаемые SHA256 RX-файла и эталона. Агент сам строит пути внутри
%USERPROFILE%\Documents\SDR_Rover_Runtime: запись берётся из каталога
rx_capture, а эталон — из отдельного каталога references. Сетевой запрос не
может передать путь или команду.
Перед запуском агент проверяет оба SHA256. Отчёт сохраняется рядом с записью
под именем staircase_search_report.json. Если подходящий отчёт уже существует,
он проверяется и возвращается без повторного анализа и без перезаписи. Для
задачи всегда заданы hardware_accessed = false, rf_tx = 0 и
automatic_retry = false.
Поиск выполняется отдельным фиксированным процессом. Агент продолжает опрос сервера и сообщает фактическую фазу, число обработанных комплексных отсчётов и общий объём. Эти значения берутся из потокового анализатора, а не оцениваются по времени. Активная аренда продлевается даже после истечения обычного короткого тайм-аута. Указатель задачи записывается до запуска процесса, поэтому перезапуск агента не создаёт второй анализатор. Готовый результат остаётся на диске до подтверждения MAIN и после обрыва сети отправляется без повторного вычисления.
Диагностический однократный запуск агента
Команду выполнять из фактического клона SDR_Rover_Video на ноутбуке. Пути к
репозиторию, секрету и hackrf_info.exe надо подставить по результатам
инвентаризации ноутбука:
python -B tools\rf001_rx_http_agent.py `
--server http://192.168.255.185:8765 `
--token-file <путь-к-rf001_http_token.txt> `
--agent-id user-pc `
--repository <путь-к-SDR_Rover_Video> `
--hackrf-info <путь-к-hackrf_info.exe> `
--hackrf-clock <путь-к-hackrf_clock.exe> `
--hackrf-transfer <путь-к-hackrf_transfer.exe> `
--once
Без --once агент работает постоянно. Этот ручной режим нужен только для
диагностики; при установленном автозапуске его не используют.
Просмотр результата на основном ПК
python -B tools\rf001_http_control.py status
Для завершённой инвентаризации сервер показывает состояние задания
COMPLETE или FAILED, фактические результаты команд и rf_tx = 0.
Автономная проверка 100/100
После подтверждения одинакового HEAD на обоих компьютерах основной ПК ставит фиксированное программное задание:
python -B tools\rf001_http_control.py enqueue-offline-verify `
--agent-id user-pc `
--expected-head a94f2db4ee8377201a97263166cb09431df5f5d6
Агент сверяет ветку и HEAD чтением .git, поэтому git.exe для этой проверки
не нужен. Затем он запускает только два заранее заданных проектных сценария:
создание детерминированной RF-001A волны и её программное декодирование через
встроенный legacy-декодер, не требующий Numba. Рабочие
файлы сохраняются вне Git в Documents\SDR_Rover_Runtime\offline_verify.
Успех требует ровно 100 CRC-корректных и 100 точных пакетов. HackRF при этом не
открывается, hardware_accessed = false, rf_tx = 0.
Подготовленный RX-захват
Сервер не примет постановку RX-захвата без точной локальной фразы
AUTHORIZE RF RX. До отдельного разрешения эту команду не выполнять:
python -B tools\rf001_http_control.py enqueue-rx-capture `
--agent-id user-pc `
--expected-head a94f2db4ee8377201a97263166cb09431df5f5d6 `
--authorize-rx "AUTHORIZE RF RX"
Агент перед захватом проверяет:
- ветку и HEAD без обязательного наличия
git.exe; - отсутствие конфликтующих SDR-процессов;
- серийный номер RX
000000000000000097c063dc2e5327d3; - строку
clock signal detectedотhackrf_clock.exe; - не менее
6000000000свободных байт; - неизменность частоты
1400000000Гц, частоты дискретизации8000000отсчётов/с, LNA/VGA24/24дБ, выключенных RF amp и antenna bias.
Для ручного барьера TX захват длится 300 секунд: 2400000000 комплексных
отсчётов, ожидаемый файл 4800000000 байт. Значение 20 секунд в исходном
профиле проверяется как часть исходных данных, но управляющий контур расширяет
окно до 300 секунд. Это зафиксировано в журнале сеанса. Автоматического повтора
нет.
Фоновый процесс запускает фиксированный Python-runner. Старый
capture_process_runner.ps1 и Git watcher-ы не изменены и остаются резервом.
Состояние конкретного сеанса запрашивается отдельной фиксированной задачей:
python -B tools\rf001_http_control.py enqueue-rx-status `
--agent-id user-pc `
--session-id <SESSION_ID>
TX разрешён только при свежем результате READY, открытом окне захвата и после
точной отдельной фразы AUTHORIZE RF TX. В сетевом протоколе операции TX нет.
После завершения захвата сервер может поставить потоковое декодирование с тремя фактическими временами. Отчёт и IQ остаются на RX-ноутбуке вне Git.
Текущее продолжение
На RX-ноутбуке работает версия агента 2026.09.29.2; штатное обновление через
подписанный HTTP-канал и полный STAIRCASE_SEARCH завершены. Дальнейшая работа
с существующим сеансом является только потоковой офлайн-диагностикой сохранённой
IQ-записи. Новый RX-захват и любой RF TX требуют нового отдельного разрешения;
разрешения, использованные в завершённом сеансе, повторно не применяются.