Add rtl_tcp (remote SDR) support v1.1.0

Features:
- Add rtl_tcp support for pager and sensor decoding
  - Connect to remote RTL-SDR via rtl_tcp server
  - New UI toggle and host:port inputs in sidebar
  - Supports rtl_fm and rtl_433 with remote devices

- Add remote dump1090 support for ADS-B tracking
  - Connect to dump1090 SBS output on remote machine
  - New "Remote" checkbox with host:port in ADS-B dashboard

Backend changes:
- Add rtl_tcp_host/port fields to SDRDevice dataclass
- Add is_network property for detecting remote devices
- Update RTLSDRCommandBuilder to use rtl_tcp:host:port format
- Add create_network_device() to SDRFactory
- Add validate_rtl_tcp_host/port validation functions
- Update pager, sensor, and adsb routes to accept remote params

Note: dump1090 doesn't support rtl_tcp directly - use remote
dump1090's SBS output (port 30003) for remote ADS-B tracking.
This commit is contained in:
Smittix
2026-01-05 08:44:58 +00:00
parent 27cbd47a80
commit ba4c6999a6
11 changed files with 279 additions and 16 deletions

View File

@@ -66,6 +66,32 @@ def validate_device_index(device: Any) -> int:
raise ValueError(f"Invalid device index: {device}") from e
def validate_rtl_tcp_host(host: Any) -> str:
"""Validate and return rtl_tcp server hostname or IP address."""
if not host or not isinstance(host, str):
raise ValueError("rtl_tcp host is required")
host = host.strip()
if not host:
raise ValueError("rtl_tcp host cannot be empty")
# Allow alphanumeric, dots, hyphens (valid for hostnames and IPs)
if not re.match(r'^[a-zA-Z0-9][a-zA-Z0-9.\-]*$', host):
raise ValueError(f"Invalid rtl_tcp host: {host}")
if len(host) > 253:
raise ValueError("rtl_tcp host too long")
return host
def validate_rtl_tcp_port(port: Any) -> int:
"""Validate and return rtl_tcp server port."""
try:
port_int = int(port)
if not 1 <= port_int <= 65535:
raise ValueError(f"Port must be between 1 and 65535, got {port_int}")
return port_int
except (ValueError, TypeError) as e:
raise ValueError(f"Invalid rtl_tcp port: {port}") from e
def validate_gain(gain: Any) -> float:
"""Validate and return gain value."""
try: