diff --git a/capture_hourly.sh b/capture_hourly.sh index 975748b..d1956c5 100755 --- a/capture_hourly.sh +++ b/capture_hourly.sh @@ -1,31 +1,46 @@ +# echo 'RUN_ONCE=1 CAPTURE_ORDER=433 /home/sergei/work/DroneDetector/DroneDetector/capture_hourly.sh >> /home/sergei/capture_hourly_night.log 2>&1' | sudo at 15:00 2026-07-22 + #!/usr/bin/env bash set -Eeuo pipefail +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SCRIPT_OWNER="${CAPTURE_USER:-$(stat -c %U "$SCRIPT_DIR")}" +SCRIPT_OWNER_HOME="$(getent passwd "$SCRIPT_OWNER" | cut -d: -f6)" +cd "$SCRIPT_DIR" + +source "$SCRIPT_DIR/.env" ############################ # НАСТРОЙКИ ############################ -# ЗАМЕНИ на реальную точку монтирования nvme1n1 -BASE_DIR="/mnt/nvme1/dataset" +BASE_DIR="/mnt/nvme1/dataset/noise2" # Путь к python из venv -PYTHON_BIN="${PYTHON_BIN:-$PWD/.venv-sdr/bin/python}" +PYTHON_BIN="${PYTHON_BIN:-$SCRIPT_DIR/.venv-sdr/bin/python}" # Путь к headless скрипту -SCRIPT_PATH="${SCRIPT_PATH:-$PWD/scripts_nn/data_saver_headless.py}" +SCRIPT_PATH="${SCRIPT_PATH:-$SCRIPT_DIR/scripts_nn/data_saver_headless.py}" + +RUN_ONCE="${RUN_ONCE:-0}" +CAPTURE_LOG_FILE="${CAPTURE_LOG_FILE:-$BASE_DIR/capture_hourly.log}" + +SYSTEMCTL_BIN=(systemctl) +CURRENT_CAPTURE_PID="" +CURRENT_SERVICE_UNIT="" + -# Проверка, что каталог реально на nvme1n1 -EXPECTED_DEVICE_PREFIX="/dev/nvme1n1" # Лимиты -PER_FREQ_LIMIT_BYTES=$((3 * 1024 * 1024 * 1024)) # 3 GiB на частоту за запуск -TOTAL_LIMIT_BYTES=$((128 * 1024 * 1024 * 1024)) # общий лимит 512 GiB -CYCLE_SECONDS=36 # один цикл в час + +lim_all=48 +PER_FREQ_LIMIT_BYTES=$((12 * 1024 * 1024 * 1024)) # GiB на частоту за запуск +TOTAL_LIMIT_BYTES=$((lim_all * 1024 * 1024 * 1024)) # общий лимит GiB +CYCLE_SECONDS=1 # один цикл в час # Параметры SDR SAMP_RATE="20e6" SPLIT_SIZE="400000" -DELAY="0.1" +DELAY="0.04" RF_GAIN="12" IF_GAIN="30" BB_GAIN="36" @@ -34,41 +49,51 @@ BB_GAIN="36" # ЧАСТОТЫ И SERIAL ИЗ ENV ############################ -ORDER=(433 750 915 1200 2400 3300 4500 5200 5800) +ORDER=(2400) + declare -A SERIAL declare -A FREQ_HZ +declare -A SERVICE_UNIT -SERIAL[433]="0000000000000000114864dc382a8e1b" +SERIAL[433]="$hack_433" FREQ_HZ[433]="433000000" -SERIAL[750]="0000000000000000114864dc383d0d1b" +SERIAL[750]="$hack_750" FREQ_HZ[750]="750000000" -SERIAL[868]="000000000000000026a468dc36066b63" -FREQ_HZ[868]="868000000" -SERIAL[915]="000000000000000026a468dc36066b63" +SERIAL[915]="$hack_915" FREQ_HZ[915]="915000000" -SERIAL[1200]="0000000000000000518864dc32660d83" +SERIAL[1200]="$hack_1200" FREQ_HZ[1200]="1200000000" -SERIAL[2400]="0000000000000000919068dc3437b31f" +SERIAL[2400]="$hack_2400" FREQ_HZ[2400]="2400000000" -SERIAL[3300]="0000000000000000114864dc325069a3" +SERIAL[3300]="$hack_3300" FREQ_HZ[3300]="3300000000" -SERIAL[4500]="0000000000000000518864dc33833183" +SERIAL[4500]="$hack_4500" FREQ_HZ[4500]="4500000000" -SERIAL[5200]="0000000000000000874461dc241c7857" +SERIAL[5200]="$hack_5200" FREQ_HZ[5200]="5200000000" -SERIAL[5800]="0000000000000000919068dc35781c1f" +SERIAL[5800]="$hack_5800" FREQ_HZ[5800]="5800000000" +SERVICE_UNIT[433]="dronedetector-sdr-433.service" +SERVICE_UNIT[750]="dronedetector-sdr-750.service" +SERVICE_UNIT[915]="dronedetector-sdr-915.service" +SERVICE_UNIT[1200]="dronedetector-sdr-1200.service" +SERVICE_UNIT[2400]="dronedetector-sdr-2400.service" +SERVICE_UNIT[3300]="dronedetector-sdr-3300.service" +SERVICE_UNIT[4500]="dronedetector-sdr-4500.service" +SERVICE_UNIT[5200]="dronedetector-sdr-5200.service" +SERVICE_UNIT[5800]="dronedetector-sdr-5800.service" + ############################ # ВСПОМОГАТЕЛЬНОЕ ############################ @@ -77,6 +102,65 @@ log() { printf '[%s] %s\n' "$(date '+%F %T')" "$*" } +systemctl_run() { + "${SYSTEMCTL_BIN[@]}" "$@" +} + +service_exists() { + local unit="$1" + systemctl_run show "$unit" >/dev/null 2>&1 +} + +stop_band_service() { + local band="$1" + local unit="${SERVICE_UNIT[$band]:-}" + + if [[ -z "$unit" ]]; then + log "Для band=$band не найден service unit" + return 0 + fi + + if ! service_exists "$unit"; then + log "Service unit $unit не установлен, пропускаю stop/start" + return 0 + fi + + log "Останавливаю service $unit перед записью band=$band" + systemctl_run stop "$unit" + CURRENT_SERVICE_UNIT="$unit" +} + +start_current_service() { + if [[ -z "$CURRENT_SERVICE_UNIT" ]]; then + return 0 + fi + + log "Запускаю service $CURRENT_SERVICE_UNIT после записи" + systemctl_run start "$CURRENT_SERVICE_UNIT" + CURRENT_SERVICE_UNIT="" +} + +cleanup_capture() { + if [[ -n "$CURRENT_CAPTURE_PID" ]] && kill -0 "$CURRENT_CAPTURE_PID" 2>/dev/null; then + log "Останавливаю текущий PID=$CURRENT_CAPTURE_PID при завершении скрипта" + kill -TERM "$CURRENT_CAPTURE_PID" 2>/dev/null || true + wait "$CURRENT_CAPTURE_PID" 2>/dev/null || true + fi + CURRENT_CAPTURE_PID="" + + if [[ -n "$CURRENT_SERVICE_UNIT" ]]; then + log "Восстанавливаю service $CURRENT_SERVICE_UNIT при завершении скрипта" + systemctl_run start "$CURRENT_SERVICE_UNIT" || true + CURRENT_SERVICE_UNIT="" + fi +} + +on_signal() { + local sig="$1" + log "Получен сигнал $sig, завершаю работу" + exit 130 +} + dir_size_bytes() { local path="$1" if [[ -e "$path" ]]; then @@ -101,16 +185,41 @@ ensure_requirements() { exit 1 fi + if ! command -v systemctl >/dev/null 2>&1; then + echo "Не найден systemctl" >&2 + exit 1 + fi + + if [[ "${EUID}" -ne 0 ]]; then + if command -v sudo >/dev/null 2>&1; then + SYSTEMCTL_BIN=(sudo systemctl) + else + echo "Для управления service нужен root или sudo" >&2 + exit 1 + fi + fi + mkdir -p "$BASE_DIR" + mkdir -p "$(dirname "$CAPTURE_LOG_FILE")" - local dev - dev="$(df -P "$BASE_DIR" | awk 'NR==2 {print $1}')" + if [[ -n "${CAPTURE_ORDER:-}" ]]; then + ORDER=() + local band + for band in ${CAPTURE_ORDER//,/ }; do + ORDER+=("$band") + done + fi - if [[ "$dev" != ${EXPECTED_DEVICE_PREFIX}* ]]; then - echo "BASE_DIR=$BASE_DIR сейчас находится на $dev, а ожидался ${EXPECTED_DEVICE_PREFIX}*" >&2 - echo "Исправь BASE_DIR на точку монтирования nvme1n1" >&2 + if [[ "${#ORDER[@]}" -eq 0 ]]; then + echo "ORDER пустой. Укажите частоты в ORDER или задайте CAPTURE_ORDER." >&2 exit 1 fi + + log "Рабочая директория: $SCRIPT_DIR" + log "BASE_DIR: $BASE_DIR" + log "ORDER: ${ORDER[*]}" + log "RUN_ONCE: $RUN_ONCE" + } run_one_freq() { @@ -118,14 +227,23 @@ run_one_freq() { local serial="${SERIAL[$band]}" local freq="${FREQ_HZ[$band]}" + if [[ -z "$serial" ]]; then + log "Для band=$band пустой serial, пропускаю" + return 0 + fi + local ts out_dir log_file ts="$(date '+%F_%H-%M-%S')" out_dir="$BASE_DIR/$band/$ts" log_file="$out_dir/run.log" - mkdir -p "$out_dir" - log "Старт band=$band serial=$serial freq=$freq dir=$out_dir" + if ! mkdir -p "$out_dir"; then + log "Не удалось создать каталог $out_dir" + return 1 + fi + + stop_band_service "$band" "$PYTHON_BIN" "$SCRIPT_PATH" \ --serial "$serial" \ @@ -141,6 +259,7 @@ run_one_freq() { >"$log_file" 2>&1 & local pid=$! + CURRENT_CAPTURE_PID="$pid" log "PID=$pid" while kill -0 "$pid" 2>/dev/null; do @@ -149,9 +268,11 @@ run_one_freq() { cur_total_size="$(total_size_bytes)" if (( cur_total_size >= TOTAL_LIMIT_BYTES )); then - log "Достигнут общий лимит 512 GiB. Останавливаю PID=$pid" + log "Достигнут общий лимит $lim_all GiB. Останавливаю PID=$pid" kill -TERM "$pid" 2>/dev/null || true wait "$pid" 2>/dev/null || true + CURRENT_CAPTURE_PID="" + start_current_service return 2 fi @@ -178,6 +299,8 @@ run_one_freq() { sleep 1 done + CURRENT_CAPTURE_PID="" + start_current_service log "Завершен band=$band, размер=$(du -sh "$out_dir" | awk '{print $1}')" return 0 } @@ -188,7 +311,7 @@ main_loop() { total_before="$(total_size_bytes)" if (( total_before >= TOTAL_LIMIT_BYTES )); then - log "Общий размер уже >= 512 GiB, выхожу" + log "Общий размер уже >= GiB, выхожу" break fi @@ -206,10 +329,18 @@ main_loop() { if [[ $rc -eq 2 ]]; then log "Остановка по общему лимиту" return 0 + else + log "Ошибка записи band=$band rc=$rc" + return "$rc" fi } done + if [[ "$RUN_ONCE" == "1" ]]; then + log "RUN_ONCE=1, завершаю работу после одного цикла" + break + fi + elapsed=$(( $(date +%s) - cycle_start )) sleep_left=$(( CYCLE_SECONDS - elapsed )) @@ -222,5 +353,9 @@ main_loop() { done } +trap cleanup_capture EXIT +trap 'on_signal INT' INT +trap 'on_signal TERM' TERM + ensure_requirements -main_loop \ No newline at end of file +main_loop diff --git a/train_scripts/ImageDatasetCreate_spec_imag_real_915.ipynb b/train_scripts/ImageDatasetCreate_spec_imag_real_915.ipynb index e5a98e9..db535b4 100644 --- a/train_scripts/ImageDatasetCreate_spec_imag_real_915.ipynb +++ b/train_scripts/ImageDatasetCreate_spec_imag_real_915.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 2, + "execution_count": 11, "id": "4fdb98fc-65bb-467e-be0c-168fee9b0fca", "metadata": {}, "outputs": [ @@ -16,10 +16,10 @@ { "data": { "text/plain": [ - "" + "" ] }, - "execution_count": 2, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -64,7 +64,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 12, "id": "4848b066-2e09-4c1c-b8fa-8e3fa84d907a", "metadata": {}, "outputs": [], @@ -74,7 +74,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 13, "id": "9267fbe1", "metadata": {}, "outputs": [], @@ -147,20 +147,20 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "id": "448da74a-e0ae-44d8-9877-8dd1f257a24f", "metadata": {}, "outputs": [], "source": [ - "selected_freq=750\n", + "selected_freq=915\n", "\n", - "path_to_binaries = f'/mnt/nvme1/dataset/{selected_freq}'\n", - "path_to_pictures = f'/mnt/nvme1/dataset_img/noise/{selected_freq}_jpg'" + "path_to_binaries = f'/mnt/nvme1/dataset/noise2/{selected_freq}'\n", + "path_to_pictures = f'/mnt/nvme1/dataset_img/noise2/{selected_freq}_jpg'" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 15, "id": "ac4945a8-29c4-4da4-945f-08658953e3e5", "metadata": {}, "outputs": [], @@ -170,7 +170,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 22, "id": "6f226f86-5d72-4573-8af6-750128b70263", "metadata": {}, "outputs": [ @@ -178,287 +178,14 @@ "name": "stderr", "output_type": "stream", "text": [ - "2026-03-25_16-59-25: 0%| | 0/40 [00:00" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "filename=\"/home/sibscience-4/from_ssh/DroneDetector/HackA5.npy\"\n", + "filename=\"/mnt/nvme1/dataset/drone/2400/2026-04-25_13-23-11/A5_2.45_drone_100_1700_147.npy\"\n", + "with open(filename, 'rb') as file:\n", + " tmp = np.frombuffer(file.read(), dtype=np.complex64)\n", + " signal = tmp\n", + "\n", + "%matplotlib inline\n", + "signal\n", + "specT = T.Spectrogram(nperseg=1024)\n", + "figsize=(16,16)\n", + "dpi=16\n", + "resize = None\n", + "\n", + "\n", + "spectr = np.array(F.spectrogram(signal, fft_size=specT.fft_size, fft_stride=specT.fft_stride)[:, :figsize[0] * dpi])\n", + "#print(\"VSE OK\")\n", + "mag = np.abs(signal)\n", + "real = signal.real\n", + "\n", + "fig2 = plt.figure(figsize = figsize)\n", + "\n", + "fig2\n", + "\n", + "plt.axes(ylim=(-1, 1))\n", + "\n", + "plt.plot(real)\n", + "\n", + "real[:100]\n" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "c7eea9ad", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([2.2366853e+08+1.2387478e-40j, 3.4833497e-15+4.4898648e+21j,\n", + " 1.5767864e-19+2.1442303e-07j, 2.2228396e-15+7.6830766e+31j,\n", + " 1.7177136e+19+6.7425655e+22j, 1.5767864e-19+1.8727951e+31j,\n", + " 2.2228527e-15+2.7904159e+29j, 1.5767847e-19+1.4585893e-19j,\n", + " 2.5893285e-12+2.7000278e-06j, 1.3306611e+37+1.3563156e-19j,\n", + " 1.3563156e-19+1.3563156e-19j, 1.3563156e-19+1.3563156e-19j,\n", + " 1.3563156e-19+1.3563156e-19j, 1.3563156e-19+1.3563156e-19j,\n", + " 1.3563156e-19+1.3563156e-19j, 1.3563156e-19+7.7097618e-33j,\n", + " 0.0000000e+00+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+1.8900000e+02j, 0.0000000e+00+0.0000000e+00j,\n", + " 0.0000000e+00+0.0000000e+00j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+1.8600000e+02j, 0.0000000e+00+0.0000000e+00j,\n", + " 0.0000000e+00+0.0000000e+00j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.4700000e+02+0.0000000e+00j,\n", + " 0.0000000e+00+0.0000000e+00j, 0.0000000e+00+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 1.7900000e+02+0.0000000e+00j,\n", + " 0.0000000e+00+0.0000000e+00j, 9.7000000e+01+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j,\n", + " 2.5500000e+02+2.5500000e+02j, 2.5500000e+02+2.5500000e+02j],\n", + " dtype=complex64)" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "signal[:100]" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "ea2676be", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Agg\n" + ] + } + ], + "source": [ + "print(matplotlib.get_backend())" + ] } ], "metadata": { "kernelspec": { - "display_name": ".venv-train (3.12.3)", + "display_name": ".venv-train", "language": "python", "name": "python3" },