diff --git a/src/ria_toolkit_oss/orchestration/tx_executor.py b/src/ria_toolkit_oss/orchestration/tx_executor.py index 6ae32b1..84e200b 100644 --- a/src/ria_toolkit_oss/orchestration/tx_executor.py +++ b/src/ria_toolkit_oss/orchestration/tx_executor.py @@ -37,6 +37,26 @@ from typing import Any logger = logging.getLogger(__name__) + +def _parse_hz(val: object) -> float: + """Parse a frequency value that may be a float (Hz) or a string like '2.45GHz'.""" + if isinstance(val, (int, float)): + return float(val) + s = str(val).strip() + for suffix, mult in (("GHz", 1e9), ("MHz", 1e6), ("kHz", 1e3), ("Hz", 1.0)): + if s.endswith(suffix): + return float(s[: -len(suffix)]) * mult + return float(s) + + +def _parse_seconds(val: object) -> float: + """Parse a duration value that may be a float (seconds) or a string like '5s'.""" + if isinstance(val, (int, float)): + return float(val) + s = str(val).strip() + return float(s[:-1]) if s.endswith("s") else float(s) + + # Mapping from modulation name → (PSK/QAM order, generator_type) # 'psk' uses PSKGenerator, 'qam' uses QAMGenerator _MOD_TABLE: dict[str, tuple[int, str]] = { @@ -83,7 +103,7 @@ class TxExecutor: modulation: str = agent_cfg.get("modulation", "QPSK").upper() symbol_rate: float = float(agent_cfg.get("symbol_rate", 1e6)) - center_freq: float = float(agent_cfg.get("center_frequency", 0.0)) + center_freq: float = _parse_hz(agent_cfg.get("center_frequency", 0.0)) filter_type: str = agent_cfg.get("filter", "rrc").lower() rolloff: float = float(agent_cfg.get("rolloff", 0.35)) @@ -109,7 +129,7 @@ class TxExecutor: filter_type: str, rolloff: float, ) -> None: - duration: float = float(step.get("duration", 10.0)) + duration: float = _parse_seconds(step.get("duration", 10.0)) label: str = step.get("label", "step") gain: float = float(step.get("power_dbm") or 0.0) sample_rate = symbol_rate * sps