#65 — Calculateur Budget Liaison RF
PLANIFIÉ
Priorité: 🔴 CRITIQUE · Type: TYPE G · Conteneur: rgz-tools · Code: tools/rf_link_budget/Dépendances: aucune
Description
Calculateur standalone de budget liaison radio 5.8 GHz. Implémente la formule Friis (Free Space Path Loss), calcule le rapport signal-sur-bruit (SNR), margin de lien, et auto-classe le revendeur en V1 (short distance, haute performance), V2 (medium, équilibré), ou V3 (long distance, dégradé).
Interface CLI (Python script) + API REST optionnel. Zéro dépendance externe (sauf numpy/scipy pour calculs). Utilisé en phase planification (#56 onboarding) pour valider faisabilité technique avant déploiement.
Formules Radio
FREE SPACE PATH LOSS (FSPL):
FSPL(dB) = 20 × log₁₀(d) + 20 × log₁₀(f) + 92.45
où:
d = distance en km
f = fréquence en GHz
92.45 = constant Friis conversion
Exemple: d=2.5 km, f=5.8 GHz
= 20×log₁₀(2.5) + 20×log₁₀(5.8) + 92.45
= 20×0.398 + 20×0.763 + 92.45
= 7.96 + 15.26 + 92.45
= 115.67 dB
SIGNAL-TO-NOISE RATIO (SNR):
SNR(dB) = EIRP - FSPL - Losses + Gain_rx - Noise_floor
où:
EIRP = TX Power + TX Antenna Gain (dBm + dBi = dBm)
FSPL = Free Space Path Loss (dB, positif = loss)
Losses = Cable loss RX (dB, typo 2dB)
Gain_rx = RX Antenna Gain (dBi, 18 dBi standard LiteBeam)
Noise_floor = -95 dBm (5.8 GHz ambient + margin)
Exemple:
EIRP = 20 dBm (TX) + 18 dBi (TX antenna) = 38 dBm
FSPL = 115.67 dB (voir calcul ci-dessus)
Cable_loss = 2 dB
Gain_RX = 18 dBi
Noise_floor = -95 dBm
SNR = 38 - 115.67 - 2 + 18 - (-95)
= 38 - 115.67 - 2 + 18 + 95
= 33.33 dB
MARGIN:
Margin(dB) = SNR - SNR_min_required
où SNR_min_required dépend du modulation/coding:
V1 (short): 25 dB (QPSK, -70 dBm RX)
V2 (medium): 15 dB (16-QAM, -80 dBm RX)
V3 (long): 10 dB (BPSK, -85 dBm RX)
CLASSIFICATION:
if Margin_V1 >= 0 dB:
Class = V1 (excellent SNR, short distance optimal)
elif Margin_V2 >= 0 dB:
Class = V2 (good SNR, medium distance, balanced)
elif Margin_V3 >= 0 dB:
Class = V3 (acceptable SNR, long distance, degraded)
else:
Class = INFEASIBLE (link not viable)Modèles de Données
python
class LinkBudgetRequest(BaseModel):
distance_km: float (0.1 to 50)
frequency_ghz: float (5.0 to 6.0) = 5.8
tx_power_dbm: float (-20 to 30) = 20
tx_antenna_gain_dbi: float (0 to 24) = 18
rx_antenna_gain_dbi: float (0 to 24) = 18
cable_loss_db: float (0 to 5) = 2
noise_floor_dbm: float (-100 to -80) = -95
fading_margin_db: float (0 to 10) = 3
class LinkBudgetResult(BaseModel):
distance_km: float
fspl_db: float
eirp_dbm: float
rx_power_dbm: float
snr_db: float
margin_v1_db: float
margin_v2_db: float
margin_v3_db: float
classification: str (V1|V2|V3|INFEASIBLE)
feasible: bool
recommendation: str
link_quality_percent: int (0-100)Configuration
env
# .env.example
RF_LINK_BUDGET_FREQUENCY_DEFAULT_GHZ=5.8
RF_LINK_BUDGET_TX_POWER_DEFAULT_DBM=20
RF_LINK_BUDGET_ANTENNA_GAIN_DEFAULT_DBI=18
RF_LINK_BUDGET_CABLE_LOSS_DB=2
RF_LINK_BUDGET_NOISE_FLOOR_DBM=-95
RF_LINK_BUDGET_FADING_MARGIN_DB=3
RF_LINK_BUDGET_SNR_V1_MIN_DB=25
RF_LINK_BUDGET_SNR_V2_MIN_DB=15
RF_LINK_BUDGET_SNR_V3_MIN_DB=10
RF_LINK_BUDGET_DISTANCE_MIN_KM=0.1
RF_LINK_BUDGET_DISTANCE_MAX_KM=50Endpoints API
| Méthode | Route | Requête | Réponse | Notes |
|---|---|---|---|---|
| POST | /api/v1/tools/rf-budget | 200 OK | ||
| POST | /api/v1/tools/rf-budget/batch | [, ] | 200 OK | |
| GET | /api/v1/tools/rf-budget/defaults | — | 200 OK |
Commandes Utiles
bash
# CLI: Calculer SNR pour liaison 2.5 km
python3 tools/rf_link_budget/calculator.py \
--distance 2.5 \
--frequency 5.8 \
--tx-power 20 \
--antenna-gain 18
# Sortie:
# FSPL: 115.67 dB
# EIRP: 38 dBm
# RX Power: -77.67 dBm
# SNR: 17.33 dB
# Margin V1: -7.67 dB (NOT OK)
# Margin V2: 2.33 dB (OK - V2 feasible)
# Margin V3: 7.33 dB (OK - V3 feasible)
# Classification: V2
# Recommendation: "Medium distance link. Suitable for V2 deployment."
# API: Tester SNR pour distances multiples
curl -X POST http://localhost:8000/api/v1/tools/rf-budget/batch \
-H "Content-Type: application/json" \
-d '[
{"distance_km": 1.0, "frequency_ghz": 5.8, "tx_power_dbm": 20, "antenna_gain_dbi": 18},
{"distance_km": 2.5, "frequency_ghz": 5.8, "tx_power_dbm": 20, "antenna_gain_dbi": 18},
{"distance_km": 5.0, "frequency_ghz": 5.8, "tx_power_dbm": 20, "antenna_gain_dbi": 18}
]' | jq '.items[] | {distance_km, classification, margin_v2_db}'
# API: Simple POST
curl -X POST http://localhost:8000/api/v1/tools/rf-budget \
-d '{
"distance_km": 3.2,
"frequency_ghz": 5.8,
"tx_power_dbm": 23,
"tx_antenna_gain_dbi": 20,
"rx_antenna_gain_dbi": 20,
"cable_loss_db": 1.5,
"noise_floor_dbm": -95
}' | jq '.classification, .feasible, .margin_v2_db'
# Obtenir defaults
curl http://localhost:8000/api/v1/tools/rf-budget/defaults | jq '.'Exemple d'Utilisation (Onboarding #56)
Technicien reçoit paramètres terrain:
- Distance AP → Hub = 3.2 km
- Fréquence = 5.8 GHz (bande Ubiquiti LiteBeam)
- TX Power = 20 dBm (standard Ubiquiti)
- Antenna Gain = 18 dBi (LiteBeam spec)
Appelle #65:
POST /api/v1/tools/rf-budget {distance_km: 3.2, ...}
Reçoit:
{
"classification": "V2",
"feasible": true,
"margin_v2_db": 8.5,
"margin_v3_db": 18.5,
"recommendation": "Good signal margin. V2 link recommended. SNR = 23 dB."
}
Décision: ✓ Déploiement OK, V2 classification
→ Crée entrée #68 Site Survey DB avec class=V2
→ Passe à étape 3 onboarding (#56)Intégration Avec Autres Outils
- #56 onboarding-reseller: Valide faisabilité technique avant déploiement
- #68 site-survey-db: Enregistre classification V1/V2/V3 pour chaque site
- #26 dba-daemon: Utilise classification pour tuner MIR/CIR par classe
- #27 htb-fq-codel: QoS ajusté selon V1/V2/V3 profil
Implémentation TODO
- [ ] Formule FSPL (Friis path loss)
- [ ] Calcul SNR (EIRP - FSPL - losses + gain - noise_floor)
- [ ] Classification V1/V2/V3 logic
- [ ] Margin calculation (per class)
- [ ] CLI interface (argparse)
- [ ] API endpoint POST /api/v1/tools/rf-budget
- [ ] Batch endpoint (multiple distances)
- [ ] Input validation (distance, frequency ranges)
- [ ] Tests: exact FSPL calculation vs known values
- [ ] Tests: classification logic (boundary cases)
- [ ] Documentation: formula références (IEEE 802.11 specs)
Dernière mise à jour: 2026-02-21