Add RTL-SDR mode switcher, DVB-T to Kodi pipeline, FM radio
Mode switcher (rtl_mode_switch.sh) handles exclusive dongle access between DVB-T, FM, SDR scanner, ADS-B, spectrum, and HackRF modes. DVB-T pipeline: RTL-SDR -> GNU Radio demod -> MPEG-TS -> HTTP -> Kodi. Kodi setup script generates M3U playlist for PVR IPTV Simple Client. Includes dvbt_rx.py and sdr_tv.py from dvbt-rx project. WebUI updated with mode switcher, channel selector, and Kodi controls.
This commit is contained in:
235
scripts/rtl_mode_switch.sh
Executable file
235
scripts/rtl_mode_switch.sh
Executable file
@@ -0,0 +1,235 @@
|
||||
#!/system/bin/sh
|
||||
# RTL-SDR Mode Switcher
|
||||
# Switches between DVB-T (digital TV), FM Radio, and SDR scanner modes
|
||||
# Manages the userspace process that controls the RTL-SDR dongle
|
||||
#
|
||||
# Only one mode can use the dongle at a time. This script kills
|
||||
# the active process before starting a new one.
|
||||
|
||||
MODDIR="/data/adb/modules/driver-manager"
|
||||
CONFDIR="$MODDIR/config"
|
||||
LOGFILE="$MODDIR/driver-manager.log"
|
||||
PIDDIR="$MODDIR/run"
|
||||
TERMUX="/data/data/com.termux/files/usr/bin"
|
||||
STREAMDIR="$MODDIR/streams"
|
||||
|
||||
mkdir -p "$PIDDIR" "$STREAMDIR"
|
||||
|
||||
mlog() {
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') [rtl_switch] $1" >> "$LOGFILE"
|
||||
}
|
||||
|
||||
# Kill any running RTL process that holds the dongle
|
||||
kill_rtl() {
|
||||
for pidfile in "$PIDDIR"/rtl_*.pid; do
|
||||
[ -f "$pidfile" ] || continue
|
||||
PID=$(cat "$pidfile")
|
||||
if [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null; then
|
||||
kill "$PID" 2>/dev/null
|
||||
sleep 1
|
||||
kill -9 "$PID" 2>/dev/null
|
||||
mlog "Killed PID $PID ($(basename "$pidfile" .pid))"
|
||||
fi
|
||||
rm -f "$pidfile"
|
||||
done
|
||||
# Also catch any strays
|
||||
pkill -f rtl_tcp 2>/dev/null
|
||||
pkill -f rtl_fm 2>/dev/null
|
||||
pkill -f rtl_adsb 2>/dev/null
|
||||
pkill -f rtl_power 2>/dev/null
|
||||
pkill -f dvbt_rx 2>/dev/null
|
||||
pkill -f sdr_tv 2>/dev/null
|
||||
sleep 1
|
||||
}
|
||||
|
||||
# Start rtl_tcp server — base layer for all modes
|
||||
# Apps connect to localhost:1234 for I/Q data
|
||||
start_rtl_tcp() {
|
||||
PORT=$(cat "$CONFDIR/rtl_tcp_port" 2>/dev/null || echo "1234")
|
||||
GAIN=$(cat "$CONFDIR/rtl_gain" 2>/dev/null || echo "0")
|
||||
SRATE=$(cat "$CONFDIR/rtl_samplerate" 2>/dev/null || echo "2048000")
|
||||
FREQ=$(cat "$CONFDIR/rtl_freq" 2>/dev/null || echo "100000000")
|
||||
|
||||
if [ -x "$TERMUX/rtl_tcp" ]; then
|
||||
"$TERMUX/rtl_tcp" -a 127.0.0.1 -p "$PORT" -f "$FREQ" -s "$SRATE" -g "$GAIN" &
|
||||
echo $! > "$PIDDIR/rtl_tcp.pid"
|
||||
mlog "rtl_tcp started on port $PORT (freq=$FREQ srate=$SRATE gain=$GAIN)"
|
||||
else
|
||||
mlog "ERROR: rtl_tcp not found — install in Termux: pkg install rtl-sdr"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
MODE="$1"
|
||||
[ -z "$MODE" ] && MODE=$(cat "$CONFDIR/rtl_mode" 2>/dev/null || echo "off")
|
||||
|
||||
case "$MODE" in
|
||||
|
||||
# =================================================================
|
||||
# DVB-T Digital TV Mode
|
||||
# =================================================================
|
||||
# Receives DVB-T signal, outputs MPEG-TS stream
|
||||
# Stream is served via HTTP on port 8554 for Kodi to consume
|
||||
dvbt)
|
||||
kill_rtl
|
||||
FREQ=$(cat "$CONFDIR/dvbt_freq" 2>/dev/null || echo "506000000")
|
||||
BW=$(cat "$CONFDIR/dvbt_bandwidth" 2>/dev/null || echo "8")
|
||||
TXMODE=$(cat "$CONFDIR/dvbt_txmode" 2>/dev/null || echo "8k")
|
||||
CONSTELLATION=$(cat "$CONFDIR/dvbt_constellation" 2>/dev/null || echo "64qam")
|
||||
CODERATE=$(cat "$CONFDIR/dvbt_coderate" 2>/dev/null || echo "2/3")
|
||||
GUARD=$(cat "$CONFDIR/dvbt_guard" 2>/dev/null || echo "1/32")
|
||||
KODI_PORT=$(cat "$CONFDIR/kodi_stream_port" 2>/dev/null || echo "8554")
|
||||
|
||||
# Use the sdr_tv.py DVB-T receiver if available
|
||||
SDR_TV="$MODDIR/scripts/sdr_tv.py"
|
||||
DVBT_RX="$MODDIR/scripts/dvbt_rx.py"
|
||||
|
||||
if [ -x "$TERMUX/python3" ] && [ -f "$SDR_TV" ]; then
|
||||
# Pipe MPEG-TS to a local HTTP server for Kodi
|
||||
# Using socat or a simple netcat HTTP wrapper
|
||||
FIFO="$STREAMDIR/dvbt.ts"
|
||||
rm -f "$FIFO"
|
||||
mkfifo "$FIFO" 2>/dev/null
|
||||
|
||||
# Start DVB-T receiver, output MPEG-TS to FIFO
|
||||
"$TERMUX/python3" "$SDR_TV" dvbt \
|
||||
--freq "$FREQ" \
|
||||
--bandwidth "$BW" \
|
||||
--transmission-mode "$TXMODE" \
|
||||
--constellation "$CONSTELLATION" \
|
||||
--code-rate "$CODERATE" \
|
||||
--guard-interval "$GUARD" \
|
||||
> "$FIFO" 2>>"$LOGFILE" &
|
||||
echo $! > "$PIDDIR/rtl_dvbt.pid"
|
||||
|
||||
# HTTP stream server — serves MPEG-TS on port for Kodi
|
||||
# Kodi connects to http://127.0.0.1:8554/dvbt.ts
|
||||
(while true; do
|
||||
cat "$FIFO" | {
|
||||
read -r _ # wait for connection
|
||||
echo -e "HTTP/1.1 200 OK\r\nContent-Type: video/mp2t\r\nConnection: close\r\n\r"
|
||||
cat
|
||||
} | nc -l -p "$KODI_PORT" 2>/dev/null
|
||||
done) &
|
||||
echo $! > "$PIDDIR/rtl_dvbt_http.pid"
|
||||
|
||||
mlog "DVB-T started: freq=$FREQ bw=${BW}MHz mode=$TXMODE"
|
||||
mlog "Kodi stream: http://127.0.0.1:$KODI_PORT"
|
||||
|
||||
elif [ -x "$TERMUX/rtl_tcp" ]; then
|
||||
# Fallback: just start rtl_tcp, let an Android DVB app handle it
|
||||
echo "$FREQ" > "$CONFDIR/rtl_freq"
|
||||
start_rtl_tcp
|
||||
mlog "DVB-T fallback: rtl_tcp on port 1234, use SDR Touch or rtl_tcp_andro"
|
||||
else
|
||||
mlog "ERROR: no DVB-T tools found"
|
||||
fi
|
||||
|
||||
echo "dvbt" > "$CONFDIR/rtl_mode"
|
||||
;;
|
||||
|
||||
# =================================================================
|
||||
# FM Radio Mode
|
||||
# =================================================================
|
||||
fm)
|
||||
kill_rtl
|
||||
FREQ=$(cat "$CONFDIR/fm_freq" 2>/dev/null || echo "100000000")
|
||||
GAIN=$(cat "$CONFDIR/rtl_gain" 2>/dev/null || echo "0")
|
||||
|
||||
if [ -x "$TERMUX/rtl_fm" ]; then
|
||||
# Demodulate FM and pipe to audio output
|
||||
"$TERMUX/rtl_fm" -f "$FREQ" -M wbfm -s 200000 -r 48000 -g "$GAIN" - 2>>"$LOGFILE" | \
|
||||
"$TERMUX/play" -r 48000 -b 16 -c 1 -e signed-integer -t raw - 2>/dev/null &
|
||||
echo $! > "$PIDDIR/rtl_fm.pid"
|
||||
mlog "FM radio started: freq=$FREQ gain=$GAIN"
|
||||
else
|
||||
mlog "ERROR: rtl_fm not found — install in Termux: pkg install rtl-sdr"
|
||||
fi
|
||||
|
||||
echo "fm" > "$CONFDIR/rtl_mode"
|
||||
;;
|
||||
|
||||
# =================================================================
|
||||
# SDR Scanner Mode
|
||||
# =================================================================
|
||||
# Starts rtl_tcp server for any SDR app to connect
|
||||
sdr)
|
||||
kill_rtl
|
||||
start_rtl_tcp
|
||||
echo "sdr" > "$CONFDIR/rtl_mode"
|
||||
;;
|
||||
|
||||
# =================================================================
|
||||
# ADS-B Aircraft Tracking
|
||||
# =================================================================
|
||||
adsb)
|
||||
kill_rtl
|
||||
if [ -x "$TERMUX/rtl_adsb" ]; then
|
||||
"$TERMUX/rtl_adsb" -g 50 > "$STREAMDIR/adsb_output.txt" 2>>"$LOGFILE" &
|
||||
echo $! > "$PIDDIR/rtl_adsb.pid"
|
||||
mlog "ADS-B tracking started (1090 MHz)"
|
||||
else
|
||||
mlog "ERROR: rtl_adsb not found"
|
||||
fi
|
||||
echo "adsb" > "$CONFDIR/rtl_mode"
|
||||
;;
|
||||
|
||||
# =================================================================
|
||||
# Spectrum Scanner
|
||||
# =================================================================
|
||||
spectrum)
|
||||
kill_rtl
|
||||
RANGE=$(cat "$CONFDIR/spectrum_range" 2>/dev/null || echo "24M:1800M")
|
||||
if [ -x "$TERMUX/rtl_power" ]; then
|
||||
"$TERMUX/rtl_power" -f "$RANGE" -g 50 -i 1 "$STREAMDIR/spectrum_data.csv" 2>>"$LOGFILE" &
|
||||
echo $! > "$PIDDIR/rtl_spectrum.pid"
|
||||
mlog "Spectrum scan started: $RANGE"
|
||||
else
|
||||
mlog "ERROR: rtl_power not found"
|
||||
fi
|
||||
echo "spectrum" > "$CONFDIR/rtl_mode"
|
||||
;;
|
||||
|
||||
# =================================================================
|
||||
# HackRF TX/RX Mode
|
||||
# =================================================================
|
||||
hackrf)
|
||||
kill_rtl
|
||||
# HackRF uses its own USB interface, doesn't conflict with RTL-SDR
|
||||
# Just set the mode flag — apps handle the rest
|
||||
mlog "HackRF mode set — use hackrf_transfer or rtl_tcp_andro"
|
||||
echo "hackrf" > "$CONFDIR/rtl_mode"
|
||||
;;
|
||||
|
||||
# =================================================================
|
||||
# Off
|
||||
# =================================================================
|
||||
off)
|
||||
kill_rtl
|
||||
mlog "All SDR processes stopped"
|
||||
echo "off" > "$CONFDIR/rtl_mode"
|
||||
;;
|
||||
|
||||
# =================================================================
|
||||
# Status
|
||||
# =================================================================
|
||||
status)
|
||||
CURRENT=$(cat "$CONFDIR/rtl_mode" 2>/dev/null || echo "off")
|
||||
echo "Mode: $CURRENT"
|
||||
for pidfile in "$PIDDIR"/rtl_*.pid; do
|
||||
[ -f "$pidfile" ] || continue
|
||||
PID=$(cat "$pidfile")
|
||||
NAME=$(basename "$pidfile" .pid)
|
||||
if kill -0 "$PID" 2>/dev/null; then
|
||||
echo " $NAME: running (PID $PID)"
|
||||
else
|
||||
echo " $NAME: dead"
|
||||
fi
|
||||
done
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Usage: rtl_mode_switch.sh {dvbt|fm|sdr|adsb|spectrum|hackrf|off|status}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user