#!/bin/bash # Alias splat -> splat-rs (versión nueva) alias splat='splat-rs' shopt -s expand_aliases # Detectar hilos disponibles del procesador NUM_THREADS=$(nproc 2>/dev/null || grep -c ^processor /proc/cpuinfo 2>/dev/null || echo 2) echo "=== SPLAT paralelo | Hilos detectados: $NUM_THREADS | Alias: splat -> splat-rs ===" ruta="." # Copiar archivos base del proyecto cp "$HOME/.splat-gui/projects/$1/prediccion/tx_sitepred.qth" "$ruta/txprofile.qth" cp "$HOME/.splat-gui/projects/$1/prediccion/splat.lrp" "$ruta/splat.lrp" # Constantes de desplazamiento dezp=0.53965407 dezpj=$(echo "scale=8; $dezp/12" | bc) dezp=0 # Leer y convertir coordenadas TX a decimal tx_sitepred=$(sed -n 1p "$ruta/txprofile.qth" | sed 's/ /_/g') lat=$(sed -n 2p "$ruta/txprofile.qth") lon=$(sed -n 3p "$ruta/txprofile.qth") lat_gradopred=$(echo "$lat" | awk '{print $1}') lat_minutopred=$(echo "$lat" | awk '{print $2}') lat_segundopred=$(echo "$lat" | awk '{print $3}') lattx=$(echo "scale=8; $lat_gradopred + $lat_minutopred/60 + $lat_segundopred/3600" | bc) long_gradopred=$(echo "$lon" | awk '{print $1}') long_minutopred=$(echo "$lon" | awk '{print $2}') long_segundopred=$(echo "$lon" | awk '{print $3}') longtx=$(echo "scale=8; $long_gradopred + $long_minutopred/60 + $long_segundopred/3600" | bc) # Reescribir txprofile en formato decimal puro echo "$tx_sitepred" > "$ruta/txprofile.qth" echo "$lattx" >> "$ruta/txprofile.qth" echo "$longtx" >> "$ruta/txprofile.qth" echo "30 m" >> "$ruta/txprofile.qth" # Constantes para direcciones diagonales a=0.269827035 b=0.467354134 aj=$(echo "scale=8; $a/12" | bc) bj=$(echo "scale=8; $b/12" | bc) # === Sistema de progreso global === TOTAL_STEPS=168 # 12 perfiles × (13 atenuaciones + 1 imagen final) PROGRESS_FILE=$(mktemp) echo 0 > "$PROGRESS_FILE" PROGRESS_LOCK="${PROGRESS_FILE}.lock" touch "$PROGRESS_LOCK" update_progress() { local angulo=$1 local paso_local=$2 local total_local=14 ( flock -x 200 local current current=$(cat "$PROGRESS_FILE") current=$((current + 1)) echo "$current" > "$PROGRESS_FILE" local pct_total pct_local pct_total=$(echo "scale=1; $current * 100 / $TOTAL_STEPS" | bc) pct_local=$(echo "scale=1; $paso_local * 100 / $total_local" | bc) printf "\r[Total: %5s%% | Perfil %3s°: %5s%% (%2d/%2d)]" \ "$pct_total" "$angulo" "$pct_local" "$paso_local" "$total_local" >&2 ) 200>"$PROGRESS_LOCK" } # === Función de procesamiento por perfil (ángulo) === procesar_perfil() { local angulo=$1 local rxfile="${ruta}/rxprofile_${angulo}.qth" local attnfile="${ruta}/atenuaciones${angulo}.ttxt" local paso=0 echo "${angulo}º dBuVm" > "$attnfile" local i=1 while [ $i -lt 19 ]; do local latrx longrx case $angulo in 0) latrx=$(echo "scale=8; $lattx+$dezpj*$i" | bc); longrx=$longtx ;; 180) latrx=$(echo "scale=8; $lattx-$dezpj*$i" | bc); longrx=$longtx ;; 90) latrx=$lattx; longrx=$(echo "scale=8; $longtx-$dezpj*$i" | bc) ;; 270) latrx=$lattx; longrx=$(echo "scale=8; $longtx+$dezpj*$i" | bc) ;; 30) latrx=$(echo "scale=8; $lattx+$bj*$i" | bc); longrx=$(echo "scale=8; $longtx-$aj*$i" | bc) ;; 60) latrx=$(echo "scale=8; $lattx+$aj*$i" | bc); longrx=$(echo "scale=8; $longtx-$bj*$i" | bc) ;; 120) latrx=$(echo "scale=8; $lattx-$aj*$i" | bc); longrx=$(echo "scale=8; $longtx-$bj*$i" | bc) ;; 150) latrx=$(echo "scale=8; $lattx-$bj*$i" | bc); longrx=$(echo "scale=8; $longtx-$aj*$i" | bc) ;; 210) latrx=$(echo "scale=8; $lattx-$bj*$i" | bc); longrx=$(echo "scale=8; $longtx+$aj*$i" | bc) ;; 240) latrx=$(echo "scale=8; $lattx-$aj*$i" | bc); longrx=$(echo "scale=8; $longtx+$bj*$i" | bc) ;; 300) latrx=$(echo "scale=8; $lattx+$aj*$i" | bc); longrx=$(echo "scale=8; $longtx+$bj*$i" | bc) ;; 330) latrx=$(echo "scale=8; $lattx+$bj*$i" | bc); longrx=$(echo "scale=8; $longtx+$aj*$i" | bc) ;; esac echo "perfil de ${angulo} grados" > "$rxfile" echo "$latrx" >> "$rxfile" echo "$longrx" >> "$rxfile" echo "10 m" >> "$rxfile" local dist=$((i*5)) if [[ $dist -le 40 || $dist -eq 50 || $dist -eq 60 || $dist -eq 70 || $dist -eq 80 || $dist -eq 90 ]]; then case $angulo in 0) timeout 10 splat -t "$ruta/txprofile.qth" -r "$rxfile" -d /opt/splat/sdf -olditm -metric -l "$ruta/attnprfl${angulo}.png" ;; 30) timeout 10 splat -r "$rxfile" -t "$ruta/txprofile.qth" -d /opt/splat/sdf -olditm -metric -nf -l "$ruta/attnprfl${angulo}.png" ;; *) timeout 10 splat -r "$rxfile" -t "$ruta/txprofile.qth" -d /opt/splat/sdf -olditm -metric -l "$ruta/attnprfl${angulo}.png" ;; esac local attn attn=$(cat "${tx_sitepred}-to-perfil_de_${angulo}_grados.txt" | grep "Field strength" | cut -d " " -f 8 | sed 's/\./,/g') echo "$attn" >> "$attnfile" paso=$((paso + 1)) update_progress "$angulo" "$paso" fi i=$((i + 1)) done # Imagen de perfil final (mismas inversiones TX/RX que el original) case $angulo in 0) splat -r "$ruta/txprofile.qth" -t "$rxfile" -d /opt/splat/sdf -olditm -metric -n -H "$ruta/perfil${angulo}.png" ;; *) splat -t "$rxfile" -r "$ruta/txprofile.qth" -d /opt/splat/sdf -olditm -metric -n -H "$ruta/perfil${angulo}.png" ;; esac paso=$((paso + 1)) update_progress "$angulo" "$paso" # Limpiar archivo temporal de receptor rm -f "$rxfile" } # === Lanzamiento paralelo controlado === ANGULOS=(0 30 60 90 120 150 180 210 240 270 300 330) PIDS=() for angulo in "${ANGULOS[@]}"; do # Limpiar PIDs que ya terminaron new_pids=() for pid in "${PIDS[@]}"; do kill -0 "$pid" 2>/dev/null && new_pids+=("$pid") done PIDS=("${new_pids[@]}") # Respetar límite de hilos while [ ${#PIDS[@]} -ge "$NUM_THREADS" ]; do sleep 0.3 new_pids=() for pid in "${PIDS[@]}"; do kill -0 "$pid" 2>/dev/null && new_pids+=("$pid") done PIDS=("${new_pids[@]}") done procesar_perfil "$angulo" & PIDS+=($!) done # Esperar a que terminen todos los trabajos for pid in "${PIDS[@]}"; do wait "$pid" 2>/dev/null done echo "" >&2 # === Concatenación final en orden === cat "$ruta/atenuaciones0.ttxt" > "$ruta/atenuaciones.ttxt" for angulo in 30 60 90 120 150 180 210 240 270 300 330; do cat "$ruta/atenuaciones${angulo}.ttxt" >> "$ruta/atenuaciones.ttxt" done # Limpieza de temporales de progreso rm -f "$PROGRESS_FILE" "$PROGRESS_LOCK" echo "=== Proceso completado. Resultados en atenuaciones.ttxt y perfil*.png ==="