#!/usr/bin/env bash # test_fdd_fwd.sh — e2e-тест форвард-линка ПОД FDD (этап 1, §10 п.7). # Данные A→B на 915; обе платы открывают оба cf-девайса (флаг -F). Обратного # трафика ещё нет (этап 2) — feedback-TX приёмника лишь СКОНФИГУРИРОВАН. # Цель теста: доказать, что форвард-линк выживает, когда оба чипа в FDD и оба # LO активны, и замерить самоглушение (NOTES §2) свипом FBGAIN. # # Использование: scripts/test_fdd_fwd.sh [ipA] [ipB] [размер_КБ] # FBGAIN=-89 (дефолт) — feedback-TX платы B практически заглушён (базовый прогон) # FBGAIN=-20 — штатное усиление обратного канала (проверка десенса RX B) # FBFREQ, PAUSE, TXGAIN, FEC, GROUPFEC — как в test_file_link.sh # ВНИМАНИЕ: сначала кабель + аттенюатор 30–40 дБ! set -euo pipefail source "$(dirname "$0")/../toolchain.env" A="${1:-$PLUTO_A}" # передатчик данных (TX 915 / fb-RX 868) B="${2:-$PLUTO_B}" # приёмник данных (RX 915 / fb-TX 868) SIZE_KB="${3:-1024}" FREQ=915000000 # несущая данных FBFREQ="${FBFREQ:-868000000}" # несущая обратного канала (fb-RX у A, fb-TX у B) RATE=1920000 # НЕ поднимать: бюджет CPU, docs/BENCHMARK.md BW=1500000 TXGAIN="${TXGAIN:--30}" # усиление TX данных на плате A FBGAIN="${FBGAIN:--89}" # усиление feedback-TX на плате B. −89 ≈ выкл (база), # −20 — штатный обратный канал (гипотеза самоглушения) FEC="${FEC:-rs8}" PAUSE="${PAUSE:-4000}" # §12.7: соук/маргинальный канал — только 4000, не 3000 GROUPFEC="${GROUPFEC:-1}" [ "$GROUPFEC" = 1 ] && GFLAG="-G" || GFLAG="" if [ "$GROUPFEC" = 1 ]; then TIMEOUT=$(( SIZE_KB / 85 + 20 )); else TIMEOUT=$(( SIZE_KB / 95 + 20 )); fi if command -v sshpass >/dev/null; then SSH=(sshpass -p "$PLUTO_PASS" ssh -o StrictHostKeyChecking=no) SCP=(sshpass -p "$PLUTO_PASS" scp -O -o StrictHostKeyChecking=no) else SSH=(ssh); SCP=(scp -O) echo "подсказка: apt install sshpass — и пароль вводить не придётся" fi echo "=== FDD форвард-линк: A=$A (TX $((FREQ/1000000))/fb-RX $((FBFREQ/1000000))) → B=$B (RX данных) ===" echo " FBGAIN=$FBGAIN дБ PAUSE=$PAUSE GROUPFEC=$GROUPFEC FEC=$FEC" echo "=== [1/6] Тестовый файл ${SIZE_KB} КБ ===" dd if=/dev/urandom of=/tmp/fdd_test.bin bs=1024 count="$SIZE_KB" status=none MD5_SRC=$(md5sum /tmp/fdd_test.bin | cut -d' ' -f1) echo "md5: $MD5_SRC" echo "=== [2/6] Зачистка хвостов на обеих платах ===" "${SSH[@]}" "root@$A" "killall -9 transmitter receiver 2>/dev/null || true" "${SSH[@]}" "root@$B" "killall -9 transmitter receiver 2>/dev/null || true" echo "=== [3/6] Заливка файла на Pluto A ($A) ===" "${SCP[@]}" /tmp/fdd_test.bin "root@$A:/tmp/" echo "=== [4/6] Старт приёмника на Pluto B ($B) в FDD, таймаут ${TIMEOUT}с ===" # busybox без `timeout` → сторожевой sleep+kill на самой плате. # Приёмник данных на 915 + feedback-TX 868 сконфигурирован (-F/-g). "${SSH[@]}" "root@$B" \ "rm -f /tmp/out.bin; /tmp/receiver -f $FREQ -r $RATE -b $BW -c $FEC \ -F $FBFREQ -g $FBGAIN -u local: > /tmp/out.bin 2>/tmp/rx_fdd.log & \ RXP=\$!; (sleep $TIMEOUT; kill \$RXP 2>/dev/null) & wait \$RXP" & RX_PID=$! sleep 4 # дать RX прогреться (FDD-инициализация двух трактов дольше) echo "=== [5/6] Передача с Pluto A в FDD ===" "${SSH[@]}" "root@$A" \ "cat /tmp/fdd_test.bin | /tmp/transmitter -f $FREQ -r $RATE -b $BW \ -g $TXGAIN -p $PAUSE -c $FEC $GFLAG -F $FBFREQ -u local: 2>/tmp/tx_fdd.log" sleep 3 # дохлебать хвост эфира "${SSH[@]}" "root@$B" "killall receiver 2>/dev/null || true" wait "$RX_PID" 2>/dev/null || true echo "=== [6/6] Сверка ===" MD5_DST=$("${SSH[@]}" "root@$B" "md5sum /tmp/out.bin 2>/dev/null | cut -d' ' -f1" || echo "нет_файла") SIZE_DST=$("${SSH[@]}" "root@$B" "wc -c < /tmp/out.bin 2>/dev/null" || echo 0) echo "источник: $MD5_SRC ($((SIZE_KB*1024)) байт)" echo "приёмник: $MD5_DST ($SIZE_DST байт)" # Ридбэк LO обеих плат — подтверждение, что FDD-тракты поднялись echo "--- FDD-ридбэк ---" "${SSH[@]}" "root@$A" "grep 'FDD ридбэк' /tmp/tx_fdd.log 2>/dev/null | sed 's/^/A: /'" || true "${SSH[@]}" "root@$B" "grep 'FDD ридбэк' /tmp/rx_fdd.log 2>/dev/null | sed 's/^/B: /'" || true # Обратный канал (этап 2): сколько STATUS B отправил и сколько A декодировал. # Доля доставки — метрика gate самоглушения (§10 п.7). echo "--- Обратный канал STATUS (B→A) ---" SENT=$("${SSH[@]}" "root@$B" "grep -o 'отправлено STATUS: [0-9]*' /tmp/rx_fdd.log 2>/dev/null | grep -o '[0-9]*'" || echo "") RECV=$("${SSH[@]}" "root@$A" "grep -o 'принято STATUS: [0-9]*' /tmp/tx_fdd.log 2>/dev/null | grep -o '[0-9]*'" || echo "") SENT=${SENT:-0}; RECV=${RECV:-0} if [ "$SENT" -gt 0 ]; then echo "B отправил: $SENT | A принял: $RECV | доставка ≈ $(( RECV * 100 / SENT ))%" else echo "B отправил: $SENT | A принял: $RECV" fi # Итоговая RX-статистика — источник PER (Потери seq / Байт), нужна каждый прогон, # особенно при GROUPFEC=0 (сырой PER без маскировки групповым FEC). echo "--- RX-статистика (PER) ---" "${SSH[@]}" "root@$B" "grep '^Кадров:' /tmp/rx_fdd.log 2>/dev/null | tail -1" || true if [ "$MD5_SRC" = "$MD5_DST" ]; then echo "РЕЗУЛЬТАТ: OK — форвард-линк под FDD цел (FBGAIN=$FBGAIN)" else echo "РЕЗУЛЬТАТ: FAIL (FBGAIN=$FBGAIN)" echo "Диагностика:" echo " - размер 0 → RX под FDD не декодит: самоглушение? Прогони FBGAIN=-89." echo " - размер < исходного → потери кадров (ARQ ещё нет, этап 3)." echo " - EVM в хвосте rx_fdd.log ниже −10 дБ → десенс RX: снизь FBGAIN/RX gain." echo "--- хвост rx_fdd.log (B) ---" "${SSH[@]}" "root@$B" "tail -6 /tmp/rx_fdd.log" || true fi