From 371b9fdbb867d5873b6348f02d3b10072b3b4c7a Mon Sep 17 00:00:00 2001 From: Lloyd Date: Mon, 19 Jan 2026 11:52:23 +0000 Subject: [PATCH] fix: update airtime calculations to use config values in AirtimeManager --- repeater/airtime.py | 30 +++++++++++++++++++----------- repeater/engine.py | 11 ++++------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/repeater/airtime.py b/repeater/airtime.py index 7dfef85..bd8ae26 100644 --- a/repeater/airtime.py +++ b/repeater/airtime.py @@ -9,10 +9,17 @@ logger = logging.getLogger("AirtimeManager") class AirtimeManager: def __init__(self, config: dict): self.config = config + self.radio_config = config.get("radio", {}) self.max_airtime_per_minute = config.get("duty_cycle", {}).get( "max_airtime_per_minute", 3600 ) + # Store radio settings for airtime calculations + self.spreading_factor = self.radio_config.get("spreading_factor", 7) + self.bandwidth = self.radio_config.get("bandwidth", 125000) + self.coding_rate = self.radio_config.get("coding_rate", 5) + self.preamble_length = self.radio_config.get("preamble_length", 8) + # Track airtime in rolling window self.tx_history = [] # [(timestamp, airtime_ms), ...] self.window_size = 60 # seconds @@ -21,10 +28,10 @@ class AirtimeManager: def calculate_airtime( self, payload_len: int, - spreading_factor: int = 7, - bandwidth_hz: int = 125000, - coding_rate: int = 5, - preamble_len: int = 8, + spreading_factor: int = None, + bandwidth_hz: int = None, + coding_rate: int = None, + preamble_len: int = None, crc_enabled: bool = True, explicit_header: bool = True, ) -> float: @@ -35,19 +42,20 @@ class AirtimeManager: Args: payload_len: Payload length in bytes - spreading_factor: SF7-SF12 (default: 7) - bandwidth_hz: Bandwidth in Hz (default: 125000) - coding_rate: CR denominator, 5=4/5, 6=4/6, 7=4/7, 8=4/8 (default: 5) - preamble_len: Preamble symbols (default: 8) + spreading_factor: SF7-SF12 (uses config value if None) + bandwidth_hz: Bandwidth in Hz (uses config value if None) + coding_rate: CR denominator, 5=4/5, 6=4/6, 7=4/7, 8=4/8 (uses config value if None) + preamble_len: Preamble symbols (uses config value if None) crc_enabled: Whether CRC is enabled (default: True) explicit_header: Whether explicit header mode is used (default: True) Returns: Airtime in milliseconds """ - sf = spreading_factor - bw_khz = bandwidth_hz / 1000 - cr = coding_rate + sf = spreading_factor or self.spreading_factor + bw_khz = (bandwidth_hz or self.bandwidth) / 1000 + cr = 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 diff --git a/repeater/engine.py b/repeater/engine.py index 3b3ee36..3a34e69 100644 --- a/repeater/engine.py +++ b/repeater/engine.py @@ -153,10 +153,7 @@ class RepeaterHandler(BaseHandler): forwarded_path = list(fwd_pkt.path) if fwd_pkt.path else [] # Check duty-cycle before scheduling TX - packet_bytes = ( - fwd_pkt.write_to() if hasattr(fwd_pkt, "write_to") else fwd_pkt.payload or b"" - ) - airtime_ms = PacketTimingUtils.estimate_airtime_ms(len(packet_bytes), self.radio_config) + airtime_ms = self.airtime_mgr.calculate_airtime(fwd_pkt.get_raw_length()) can_tx, wait_time = self.airtime_mgr.can_transmit(airtime_ms) @@ -584,8 +581,8 @@ class RepeaterHandler(BaseHandler): import random - packet_len = len(packet.payload) if packet.payload else 0 - airtime_ms = PacketTimingUtils.estimate_airtime_ms(packet_len, self.radio_config) + packet_len = packet.get_raw_length() + airtime_ms = self.airtime_mgr.calculate_airtime(packet_len) route_type = packet.header & PH_ROUTE_MASK @@ -660,7 +657,7 @@ class RepeaterHandler(BaseHandler): # Record airtime after successful TX if airtime_ms > 0: self.airtime_mgr.record_tx(airtime_ms) - packet_size = len(fwd_pkt.payload) + packet_size = fwd_pkt.get_raw_length() logger.info( f"Retransmitted packet ({packet_size} bytes, {airtime_ms:.1f}ms airtime)" )