|
|
|
@ -5,8 +5,8 @@ set -Eeuo pipefail
|
|
|
|
# НАСТРОЙКИ
|
|
|
|
# НАСТРОЙКИ
|
|
|
|
############################
|
|
|
|
############################
|
|
|
|
|
|
|
|
|
|
|
|
# ЗАМЕНИ на реальную точку монтирования nvme1n1
|
|
|
|
# Точка сохранения, по умолчанию nvme/data.
|
|
|
|
BASE_DIR="/mnt/data/noise"
|
|
|
|
BASE_DIR="${BASE_DIR:-/mnt/data/noise}"
|
|
|
|
|
|
|
|
|
|
|
|
# Путь к python из venv
|
|
|
|
# Путь к python из venv
|
|
|
|
PYTHON_BIN="${PYTHON_BIN:-$PWD/.venv-sdr/bin/python}"
|
|
|
|
PYTHON_BIN="${PYTHON_BIN:-$PWD/.venv-sdr/bin/python}"
|
|
|
|
@ -14,11 +14,14 @@ PYTHON_BIN="${PYTHON_BIN:-$PWD/.venv-sdr/bin/python}"
|
|
|
|
# Путь к headless скрипту
|
|
|
|
# Путь к headless скрипту
|
|
|
|
SCRIPT_PATH="${SCRIPT_PATH:-$PWD/scripts_nn/data_saver_headless.py}"
|
|
|
|
SCRIPT_PATH="${SCRIPT_PATH:-$PWD/scripts_nn/data_saver_headless.py}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Env-файл читается точечно: source .env небезопасен из-за сложных NN_* строк.
|
|
|
|
|
|
|
|
ENV_FILE="${ENV_FILE:-$PWD/.env}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Лимиты
|
|
|
|
# Лимиты
|
|
|
|
PER_FREQ_LIMIT_BYTES=$((3 * 1024 * 1024 * 1024)) # 3 GiB на частоту за запуск
|
|
|
|
PER_FREQ_LIMIT_BYTES=$((3 * 1024 * 1024 * 1024)) # 3 GiB на частоту за запуск
|
|
|
|
TOTAL_LIMIT_BYTES=$((128 * 1024 * 1024 * 1024)) # общий лимит 512 GiB
|
|
|
|
TOTAL_LIMIT_BYTES=$((128 * 1024 * 1024 * 1024)) # общий лимит 512 GiB
|
|
|
|
CYCLE_SECONDS=36 # один цикл в час
|
|
|
|
CYCLE_SECONDS="${CYCLE_SECONDS:-36}" # один цикл в час
|
|
|
|
|
|
|
|
|
|
|
|
# Параметры SDR
|
|
|
|
# Параметры SDR
|
|
|
|
SAMP_RATE="20e6"
|
|
|
|
SAMP_RATE="20e6"
|
|
|
|
@ -28,6 +31,16 @@ RF_GAIN="12"
|
|
|
|
IF_GAIN="30"
|
|
|
|
IF_GAIN="30"
|
|
|
|
BB_GAIN="36"
|
|
|
|
BB_GAIN="36"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Моки для server-to-master на время capture.
|
|
|
|
|
|
|
|
CAPTURE_MOCK_SEND_ENABLED="${CAPTURE_MOCK_SEND_ENABLED:-1}"
|
|
|
|
|
|
|
|
CAPTURE_MOCK_HOST="${CAPTURE_MOCK_HOST:-127.0.0.1}"
|
|
|
|
|
|
|
|
CAPTURE_MOCK_INTERVAL_SECONDS="${CAPTURE_MOCK_INTERVAL_SECONDS:-1}"
|
|
|
|
|
|
|
|
CAPTURE_MOCK_TIMEOUT_SECONDS="${CAPTURE_MOCK_TIMEOUT_SECONDS:-0.3}"
|
|
|
|
|
|
|
|
CAPTURE_MOCK_LOG_SUCCESS="${CAPTURE_MOCK_LOG_SUCCESS:-0}"
|
|
|
|
|
|
|
|
MOCK_SENDER_PID=""
|
|
|
|
|
|
|
|
ACTIVE_CAPTURE_PID=""
|
|
|
|
|
|
|
|
ACTIVE_MOCK_PID=""
|
|
|
|
|
|
|
|
|
|
|
|
############################
|
|
|
|
############################
|
|
|
|
# ЧАСТОТЫ И SERIAL ИЗ ENV
|
|
|
|
# ЧАСТОТЫ И SERIAL ИЗ ENV
|
|
|
|
############################
|
|
|
|
############################
|
|
|
|
@ -76,6 +89,122 @@ log() {
|
|
|
|
printf '[%s] %s\n' "$(date '+%F %T')" "$*"
|
|
|
|
printf '[%s] %s\n' "$(date '+%F %T')" "$*"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
env_get() {
|
|
|
|
|
|
|
|
local key="$1"
|
|
|
|
|
|
|
|
local default="${2:-}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if [[ ! -f "$ENV_FILE" ]]; then
|
|
|
|
|
|
|
|
printf '%s\n' "$default"
|
|
|
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
awk -v key="$key" -v default="$default" '
|
|
|
|
|
|
|
|
BEGIN { found = 0 }
|
|
|
|
|
|
|
|
$0 ~ "^[[:space:]]*" key "=" {
|
|
|
|
|
|
|
|
value = $0
|
|
|
|
|
|
|
|
sub("^[[:space:]]*" key "=", "", value)
|
|
|
|
|
|
|
|
sub("[[:space:]]+#.*$", "", value)
|
|
|
|
|
|
|
|
gsub("^[[:space:]]+|[[:space:]]+$", "", value)
|
|
|
|
|
|
|
|
if ((substr(value, 1, 1) == "\"" && substr(value, length(value), 1) == "\"") ||
|
|
|
|
|
|
|
|
(substr(value, 1, 1) == "'"'"'" && substr(value, length(value), 1) == "'"'"'")) {
|
|
|
|
|
|
|
|
value = substr(value, 2, length(value) - 2)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
print value
|
|
|
|
|
|
|
|
found = 1
|
|
|
|
|
|
|
|
exit
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
END {
|
|
|
|
|
|
|
|
if (!found) {
|
|
|
|
|
|
|
|
print default
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
' "$ENV_FILE"
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mock_bool_enabled() {
|
|
|
|
|
|
|
|
case "${1,,}" in
|
|
|
|
|
|
|
|
1|true|yes|on) return 0 ;;
|
|
|
|
|
|
|
|
*) return 1 ;;
|
|
|
|
|
|
|
|
esac
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mock_url() {
|
|
|
|
|
|
|
|
local port endpoint
|
|
|
|
|
|
|
|
port="${CAPTURE_MOCK_PORT:-$(env_get locport "$(env_get GENERAL_SERVER_PORT 5010)")}"
|
|
|
|
|
|
|
|
endpoint="${CAPTURE_MOCK_ENDPOINT:-$(env_get freq_endpoint process_data)}"
|
|
|
|
|
|
|
|
endpoint="${endpoint#/}"
|
|
|
|
|
|
|
|
printf 'http://%s:%s/%s' "$CAPTURE_MOCK_HOST" "$port" "$endpoint"
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
start_mock_sender() {
|
|
|
|
|
|
|
|
local band="$1"
|
|
|
|
|
|
|
|
local log_file="$2"
|
|
|
|
|
|
|
|
local url
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MOCK_SENDER_PID=""
|
|
|
|
|
|
|
|
if ! mock_bool_enabled "$CAPTURE_MOCK_SEND_ENABLED"; then
|
|
|
|
|
|
|
|
log "Mock sender отключен CAPTURE_MOCK_SEND_ENABLED=$CAPTURE_MOCK_SEND_ENABLED"
|
|
|
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
url="$(mock_url)"
|
|
|
|
|
|
|
|
log "Старт mock sender band=$band url=$url amplitude=0 interval=${CAPTURE_MOCK_INTERVAL_SECONDS}s"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"$PYTHON_BIN" - "$url" "$band" "$CAPTURE_MOCK_INTERVAL_SECONDS" "$CAPTURE_MOCK_TIMEOUT_SECONDS" <<'PY' >>"$log_file" 2>&1 &
|
|
|
|
|
|
|
|
import json
|
|
|
|
|
|
|
|
import os
|
|
|
|
|
|
|
|
import sys
|
|
|
|
|
|
|
|
import time
|
|
|
|
|
|
|
|
import urllib.error
|
|
|
|
|
|
|
|
import urllib.request
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
url = sys.argv[1]
|
|
|
|
|
|
|
|
freq = str(sys.argv[2])
|
|
|
|
|
|
|
|
interval = float(sys.argv[3])
|
|
|
|
|
|
|
|
timeout = float(sys.argv[4])
|
|
|
|
|
|
|
|
payload = json.dumps({"freq": freq, "amplitude": 0}).encode("utf-8")
|
|
|
|
|
|
|
|
headers = {"Content-Type": "application/json"}
|
|
|
|
|
|
|
|
log_success = os.getenv("CAPTURE_MOCK_LOG_SUCCESS", "0").lower() in {"1", "true", "yes", "on"}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
print(f"[capture-mock] started url={url} freq={freq} amplitude=0 interval={interval}", flush=True)
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
req = urllib.request.Request(url, data=payload, headers=headers, method="POST")
|
|
|
|
|
|
|
|
with urllib.request.urlopen(req, timeout=timeout) as response:
|
|
|
|
|
|
|
|
if log_success:
|
|
|
|
|
|
|
|
print(f"[capture-mock] sent status={response.status}", flush=True)
|
|
|
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
|
|
|
print(f"[capture-mock] send failed: {exc}", flush=True)
|
|
|
|
|
|
|
|
time.sleep(interval)
|
|
|
|
|
|
|
|
PY
|
|
|
|
|
|
|
|
MOCK_SENDER_PID=$!
|
|
|
|
|
|
|
|
log "Mock sender PID=$MOCK_SENDER_PID"
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stop_mock_sender() {
|
|
|
|
|
|
|
|
local pid="${1:-}"
|
|
|
|
|
|
|
|
if [[ -z "$pid" ]]; then
|
|
|
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
if kill -0 "$pid" 2>/dev/null; then
|
|
|
|
|
|
|
|
log "Останавливаю mock sender PID=$pid"
|
|
|
|
|
|
|
|
kill -TERM "$pid" 2>/dev/null || true
|
|
|
|
|
|
|
|
wait "$pid" 2>/dev/null || true
|
|
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cleanup_active_jobs() {
|
|
|
|
|
|
|
|
local rc=$?
|
|
|
|
|
|
|
|
if [[ -n "${ACTIVE_CAPTURE_PID:-}" ]] && kill -0 "$ACTIVE_CAPTURE_PID" 2>/dev/null; then
|
|
|
|
|
|
|
|
log "Останавливаю active capture PID=$ACTIVE_CAPTURE_PID"
|
|
|
|
|
|
|
|
kill -TERM "$ACTIVE_CAPTURE_PID" 2>/dev/null || true
|
|
|
|
|
|
|
|
wait "$ACTIVE_CAPTURE_PID" 2>/dev/null || true
|
|
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
stop_mock_sender "${ACTIVE_MOCK_PID:-}"
|
|
|
|
|
|
|
|
exit "$rc"
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
dir_size_bytes() {
|
|
|
|
dir_size_bytes() {
|
|
|
|
local path="$1"
|
|
|
|
local path="$1"
|
|
|
|
if [[ -e "$path" ]]; then
|
|
|
|
if [[ -e "$path" ]]; then
|
|
|
|
@ -135,7 +264,12 @@ run_one_freq() {
|
|
|
|
>"$log_file" 2>&1 &
|
|
|
|
>"$log_file" 2>&1 &
|
|
|
|
|
|
|
|
|
|
|
|
local pid=$!
|
|
|
|
local pid=$!
|
|
|
|
|
|
|
|
local mock_pid=""
|
|
|
|
log "PID=$pid"
|
|
|
|
log "PID=$pid"
|
|
|
|
|
|
|
|
ACTIVE_CAPTURE_PID="$pid"
|
|
|
|
|
|
|
|
start_mock_sender "$band" "$log_file"
|
|
|
|
|
|
|
|
mock_pid="$MOCK_SENDER_PID"
|
|
|
|
|
|
|
|
ACTIVE_MOCK_PID="$mock_pid"
|
|
|
|
|
|
|
|
|
|
|
|
while kill -0 "$pid" 2>/dev/null; do
|
|
|
|
while kill -0 "$pid" 2>/dev/null; do
|
|
|
|
local cur_dir_size cur_total_size
|
|
|
|
local cur_dir_size cur_total_size
|
|
|
|
@ -146,6 +280,9 @@ run_one_freq() {
|
|
|
|
log "Достигнут общий лимит 512 GiB. Останавливаю PID=$pid"
|
|
|
|
log "Достигнут общий лимит 512 GiB. Останавливаю PID=$pid"
|
|
|
|
kill -TERM "$pid" 2>/dev/null || true
|
|
|
|
kill -TERM "$pid" 2>/dev/null || true
|
|
|
|
wait "$pid" 2>/dev/null || true
|
|
|
|
wait "$pid" 2>/dev/null || true
|
|
|
|
|
|
|
|
stop_mock_sender "$mock_pid"
|
|
|
|
|
|
|
|
ACTIVE_CAPTURE_PID=""
|
|
|
|
|
|
|
|
ACTIVE_MOCK_PID=""
|
|
|
|
return 2
|
|
|
|
return 2
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
@ -166,12 +303,18 @@ run_one_freq() {
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
wait "$pid" 2>/dev/null || true
|
|
|
|
wait "$pid" 2>/dev/null || true
|
|
|
|
|
|
|
|
stop_mock_sender "$mock_pid"
|
|
|
|
|
|
|
|
ACTIVE_CAPTURE_PID=""
|
|
|
|
|
|
|
|
ACTIVE_MOCK_PID=""
|
|
|
|
break
|
|
|
|
break
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
sleep 1
|
|
|
|
sleep 1
|
|
|
|
done
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stop_mock_sender "$mock_pid"
|
|
|
|
|
|
|
|
ACTIVE_CAPTURE_PID=""
|
|
|
|
|
|
|
|
ACTIVE_MOCK_PID=""
|
|
|
|
log "Завершен band=$band, размер=$(du -sh "$out_dir" | awk '{print $1}')"
|
|
|
|
log "Завершен band=$band, размер=$(du -sh "$out_dir" | awk '{print $1}')"
|
|
|
|
return 0
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -216,5 +359,8 @@ main_loop() {
|
|
|
|
done
|
|
|
|
done
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if [[ "${CAPTURE_HOURLY_SOURCE_ONLY:-0}" != "1" ]]; then
|
|
|
|
|
|
|
|
trap cleanup_active_jobs INT TERM
|
|
|
|
ensure_requirements
|
|
|
|
ensure_requirements
|
|
|
|
main_loop
|
|
|
|
main_loop
|
|
|
|
|
|
|
|
fi
|
|
|
|
|