from __future__ import annotations import math from typing import Literal from app.models.schemas import LinkBudget def fspl_db(distance_m: float, freq_mhz: float) -> float: if distance_m <= 0: return 0.0 return 20.0 * math.log10(distance_m / 1000.0) + 20.0 * math.log10(freq_mhz) + 27.55 def compute_link_budget( tx_power_dbm: float, rx_sensitivity_dbm: float, distance_m: float, freq_mhz: float, ) -> LinkBudget: loss = fspl_db(distance_m, freq_mhz) margin = tx_power_dbm - rx_sensitivity_dbm - loss status: Literal["good", "marginal", "poor"] if margin >= 20: status = "good" elif margin >= 10: status = "marginal" else: status = "poor" return LinkBudget( tx_power_dbm=tx_power_dbm, rx_sensitivity_dbm=rx_sensitivity_dbm, margin_db=round(margin, 1), status=status, )