J
2026-04-13 11:48:15 -04:00
|
|
|
"""Hardware detection and heartbeat payload construction for the streamer."""
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
from ria_toolkit_oss.sdr import detect_available
|
|
|
|
|
|
J
2026-04-16 11:13:43 -04:00
|
|
|
from .config import AgentConfig
|
|
|
|
|
|
J
2026-04-13 11:48:15 -04:00
|
|
|
|
|
|
|
|
def available_devices() -> list[str]:
|
|
|
|
|
"""Return a sorted list of device names whose driver modules import cleanly."""
|
|
|
|
|
return sorted(detect_available().keys())
|
|
|
|
|
|
|
|
|
|
|
J
2026-04-16 11:13:43 -04:00
|
|
|
def heartbeat_payload(
|
|
|
|
|
status: str = "idle",
|
|
|
|
|
app_id: str | None = None,
|
|
|
|
|
*,
|
|
|
|
|
cfg: AgentConfig | None = None,
|
|
|
|
|
sessions: dict | None = None,
|
|
|
|
|
) -> dict:
|
|
|
|
|
"""Build the JSON body of a periodic heartbeat frame.
|
|
|
|
|
|
|
|
|
|
*cfg* drives the ``capabilities`` list and the ``tx_enabled`` flag. If not
|
|
|
|
|
supplied, the heartbeat advertises RX-only with ``tx_enabled=False`` —
|
|
|
|
|
matching the pre-TX shape.
|
|
|
|
|
"""
|
|
|
|
|
c = cfg or AgentConfig()
|
|
|
|
|
capabilities = ["rx"]
|
|
|
|
|
if c.tx_enabled:
|
|
|
|
|
capabilities.append("tx")
|
|
|
|
|
|
J
2026-04-13 11:48:15 -04:00
|
|
|
payload: dict = {
|
|
|
|
|
"type": "heartbeat",
|
|
|
|
|
"hardware": available_devices(),
|
|
|
|
|
"status": status,
|
J
2026-04-16 11:13:43 -04:00
|
|
|
"capabilities": capabilities,
|
|
|
|
|
"tx_enabled": bool(c.tx_enabled),
|
J
2026-04-13 11:48:15 -04:00
|
|
|
}
|
J
2026-04-16 15:12:56 -04:00
|
|
|
# Surface configured interlock values so the hub can pre-filter UI controls
|
|
|
|
|
# before sending a tx_start that would be rejected. Only included when TX
|
|
|
|
|
# is opted in AND the operator set a cap.
|
|
|
|
|
if c.tx_enabled:
|
|
|
|
|
if c.tx_max_gain_db is not None:
|
|
|
|
|
payload["tx_max_gain_db"] = float(c.tx_max_gain_db)
|
|
|
|
|
if c.tx_max_duration_s is not None:
|
|
|
|
|
payload["tx_max_duration_s"] = float(c.tx_max_duration_s)
|
|
|
|
|
if c.tx_allowed_freq_ranges:
|
|
|
|
|
payload["tx_allowed_freq_ranges"] = [
|
|
|
|
|
[float(lo), float(hi)] for lo, hi in c.tx_allowed_freq_ranges
|
|
|
|
|
]
|
J
2026-04-13 11:48:15 -04:00
|
|
|
if app_id:
|
|
|
|
|
payload["app_id"] = app_id
|
J
2026-04-16 11:13:43 -04:00
|
|
|
if sessions:
|
|
|
|
|
payload["sessions"] = sessions
|
J
2026-04-13 11:48:15 -04:00
|
|
|
return payload
|