mirror of
https://github.com/pyMC-dev/pyMC_Repeater.git
synced 2026-07-28 04:23:22 +02:00
fix(airtime): normalize legacy coding-rate indices
AirtimeManager fed the configured coding rate straight into the Semtech symbol formula, so a config using the legacy index form (1..4) would multiply payload symbols by the raw index instead of the 4/5..4/8 denominator and undercount airtime. Normalize through openhop_core's shared coding_rate_denominator() before calculating.
This commit is contained in:
+5
-1
@@ -3,6 +3,8 @@ import math
|
||||
import time
|
||||
from typing import Tuple
|
||||
|
||||
from openhop_core.protocol.packet_utils import coding_rate_denominator
|
||||
|
||||
logger = logging.getLogger("AirtimeManager")
|
||||
|
||||
|
||||
@@ -55,7 +57,9 @@ class AirtimeManager:
|
||||
"""
|
||||
sf = spreading_factor or self.spreading_factor
|
||||
bw_hz = bandwidth_hz or self.bandwidth
|
||||
cr = coding_rate or self.coding_rate
|
||||
# Configs and radio drivers use either the denominator form (5..8) or
|
||||
# the legacy index form (1..4); normalize before the Semtech formula.
|
||||
cr = coding_rate_denominator(coding_rate or self.coding_rate)
|
||||
preamble_len = preamble_len or self.preamble_length
|
||||
crc = 1 if crc_enabled else 0
|
||||
h = 0 if explicit_header else 1 # H=0 for explicit, H=1 for implicit
|
||||
|
||||
@@ -97,6 +97,21 @@ def test_long_range_preset_has_higher_airtime_than_fast_preset_for_same_payload(
|
||||
assert long_mgr.calculate_airtime(payload_len) > fast_mgr.calculate_airtime(payload_len)
|
||||
|
||||
|
||||
def test_legacy_coding_rate_index_matches_denominator_form():
|
||||
"""A config using the legacy index form (1..4) must compute the same
|
||||
airtime as the equivalent denominator form (5..8), not undercount
|
||||
payload symbols by multiplying with the raw index."""
|
||||
for index, denom in ((1, 5), (2, 6), (3, 7), (4, 8)):
|
||||
by_index = _make_mgr(sf=10, bw_hz=250000, cr=index, preamble=8)
|
||||
by_denom = _make_mgr(sf=10, bw_hz=250000, cr=denom, preamble=8)
|
||||
for payload_len in (16, 64, 128):
|
||||
assert math.isclose(
|
||||
by_index.calculate_airtime(payload_len),
|
||||
by_denom.calculate_airtime(payload_len),
|
||||
rel_tol=1e-9,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("_title,sf,bw_hz,cr", ALL_PRESETS, ids=ALL_PRESET_IDS)
|
||||
def test_can_transmit_blocks_after_budget_exhausted_for_each_preset(_title, sf, bw_hz, cr):
|
||||
mgr = _make_mgr(sf, bw_hz, cr, preamble=8, max_airtime_per_minute=600)
|
||||
|
||||
Reference in New Issue
Block a user