diff --git a/repeater/data_acquisition/sqlite_handler.py b/repeater/data_acquisition/sqlite_handler.py index 205b43d..56eaa38 100644 --- a/repeater/data_acquisition/sqlite_handler.py +++ b/repeater/data_acquisition/sqlite_handler.py @@ -250,6 +250,27 @@ def _run_migrations(self): ) logger.info(f"Migration '{migration_name}' applied successfully") + # Migration 4: Add airtime_ms column to packets table + migration_name = "add_airtime_ms_to_packets" + existing = conn.execute( + "SELECT migration_name FROM migrations WHERE migration_name = ?", + (migration_name,) + ).fetchone() + + if not existing: + cursor = conn.execute("PRAGMA table_info(packets)") + columns = [column[1] for column in cursor.fetchall()] + + if "airtime_ms" not in columns: + conn.execute("ALTER TABLE packets ADD COLUMN airtime_ms REAL") + logger.info("Added airtime_ms column to packets table") + + conn.execute( + "INSERT INTO migrations (migration_name, applied_at) VALUES (?, ?)", + (migration_name, time.time()) + ) + logger.info(f"Migration '{migration_name}' applied successfully") + conn.commit() except Exception as e: @@ -350,8 +371,8 @@ def store_packet(self, record: dict): transmitted, is_duplicate, drop_reason, src_hash, dst_hash, path_hash, header, transport_codes, payload, payload_length, tx_delay_ms, packet_hash, original_path, forwarded_path, raw_packet, - lbt_attempts, lbt_backoff_delays_ms, lbt_channel_busy - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + lbt_attempts, lbt_backoff_delays_ms, lbt_channel_busy, airtime_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, ( record.get("timestamp", time.time()), record.get("type", 0), @@ -377,7 +398,8 @@ def store_packet(self, record: dict): record.get("raw_packet"), record.get("lbt_attempts", 0), json.dumps(record.get("lbt_backoff_delays_ms")) if record.get("lbt_backoff_delays_ms") else None, - int(bool(record.get("lbt_channel_busy", False))) + int(bool(record.get("lbt_channel_busy", False))), + record.get("airtime_ms") )) except Exception as e: @@ -543,7 +565,7 @@ def get_recent_packets(self, limit: int = 100) -> list: transmitted, is_duplicate, drop_reason, src_hash, dst_hash, path_hash, header, transport_codes, payload, payload_length, tx_delay_ms, packet_hash, original_path, forwarded_path, raw_packet, - lbt_attempts, lbt_backoff_delays_ms, lbt_channel_busy + lbt_attempts, lbt_backoff_delays_ms, lbt_channel_busy, airtime_ms FROM packets ORDER BY timestamp DESC LIMIT ? @@ -590,7 +612,7 @@ def get_filtered_packets(self, transmitted, is_duplicate, drop_reason, src_hash, dst_hash, path_hash, header, transport_codes, payload, payload_length, tx_delay_ms, packet_hash, original_path, forwarded_path, raw_packet, - lbt_attempts, lbt_backoff_delays_ms, lbt_channel_busy + lbt_attempts, lbt_backoff_delays_ms, lbt_channel_busy, airtime_ms FROM packets """ @@ -621,7 +643,7 @@ def get_packet_by_hash(self, packet_hash: str) -> Optional[dict]: transmitted, is_duplicate, drop_reason, src_hash, dst_hash, path_hash, header, transport_codes, payload, payload_length, tx_delay_ms, packet_hash, original_path, forwarded_path, raw_packet, - lbt_attempts, lbt_backoff_delays_ms, lbt_channel_busy + lbt_attempts, lbt_backoff_delays_ms, lbt_channel_busy, airtime_ms FROM packets WHERE packet_hash = ? """, (packet_hash,)).fetchone() diff --git a/repeater/engine.py b/repeater/engine.py index 3a34e69..877b925 100644 --- a/repeater/engine.py +++ b/repeater/engine.py @@ -246,6 +246,9 @@ async def __call__(self, packet: Packet, metadata: Optional[dict] = None, local_ if hasattr(packet, "payload") and packet.payload and len(packet.payload) >= 1: src_hash = f"{packet.payload[0]:02X}" + # Calculate airtime for the received packet (once, stored with packet) + packet_airtime_ms = self.airtime_mgr.calculate_airtime(packet.get_raw_length()) + # Record packet for charts packet_record = { "timestamp": time.time(), @@ -284,6 +287,7 @@ async def __call__(self, packet: Packet, metadata: Optional[dict] = None, local_ "lbt_attempts": lbt_attempts if transmitted else 0, "lbt_backoff_delays_ms": lbt_backoff_delays_ms if transmitted and lbt_backoff_delays_ms else None, "lbt_channel_busy": lbt_channel_busy if transmitted else False, + "airtime_ms": packet_airtime_ms, } # Store packet record to persistent storage