mirror of
https://github.com/rightup/pyMC_Repeater.git
synced 2026-03-28 17:43:06 +01:00
Update packet type labels in rrdtool_handler and sqlite_handler for consistency
- Enhanced readability by adding descriptive suffixes to packet type labels in both rrdtool_handler.py and sqlite_handler.py. - Aligned packet type definitions with the new naming conventions from pyMC_core, ensuring consistency across the codebase.
This commit is contained in:
@@ -220,8 +220,8 @@ class RRDToolHandler:
|
||||
"type_7": "Anonymous Request (ANON_REQ)",
|
||||
"type_8": "Returned Path (PATH)",
|
||||
"type_9": "Trace (TRACE)",
|
||||
"type_10": "Multi-part Packet",
|
||||
"type_11": "Control Packet Data",
|
||||
"type_10": "Multi-part Packet (MULTIPART)",
|
||||
"type_11": "Control (CONTROL)",
|
||||
"type_12": "Reserved Type 12",
|
||||
"type_13": "Reserved Type 13",
|
||||
"type_14": "Reserved Type 14",
|
||||
|
||||
@@ -817,10 +817,33 @@ class SQLiteHandler:
|
||||
try:
|
||||
cutoff = time.time() - (hours * 3600)
|
||||
|
||||
with sqlite3.connect(self.sqlite_path) as conn:
|
||||
conn.row_factory = sqlite3.Row
|
||||
|
||||
type_counts = {}
|
||||
# Align with pyMC_core feat/newRadios PAYLOAD_TYPES (0x0B = CONTROL)
|
||||
try:
|
||||
from pymc_core.protocol.utils import PAYLOAD_TYPES as _PT
|
||||
_human = {
|
||||
"REQ": "Request",
|
||||
"RESPONSE": "Response",
|
||||
"TXT_MSG": "Plain Text Message",
|
||||
"ACK": "Acknowledgment",
|
||||
"ADVERT": "Node Advertisement",
|
||||
"GRP_TXT": "Group Text Message",
|
||||
"GRP_DATA": "Group Datagram",
|
||||
"ANON_REQ": "Anonymous Request",
|
||||
"PATH": "Returned Path",
|
||||
"TRACE": "Trace",
|
||||
"MULTIPART": "Multi-part Packet",
|
||||
"CONTROL": "Control",
|
||||
"RAW_CUSTOM": "Custom Packet",
|
||||
}
|
||||
packet_type_names = {}
|
||||
for i in range(16):
|
||||
code = _PT.get(i)
|
||||
if code:
|
||||
label = _human.get(code, code.replace("_", " ").title())
|
||||
packet_type_names[i] = f"{label} ({code})"
|
||||
else:
|
||||
packet_type_names[i] = f"Reserved Type {i}"
|
||||
except ImportError:
|
||||
packet_type_names = {
|
||||
0: "Request (REQ)",
|
||||
1: "Response (RESPONSE)",
|
||||
@@ -832,14 +855,18 @@ class SQLiteHandler:
|
||||
7: "Anonymous Request (ANON_REQ)",
|
||||
8: "Returned Path (PATH)",
|
||||
9: "Trace (TRACE)",
|
||||
10: "Multi-part Packet",
|
||||
11: "Reserved Type 11",
|
||||
10: "Multi-part Packet (MULTIPART)",
|
||||
11: "Control (CONTROL)",
|
||||
12: "Reserved Type 12",
|
||||
13: "Reserved Type 13",
|
||||
14: "Reserved Type 14",
|
||||
15: "Custom Packet (RAW_CUSTOM)",
|
||||
}
|
||||
|
||||
with sqlite3.connect(self.sqlite_path) as conn:
|
||||
conn.row_factory = sqlite3.Row
|
||||
|
||||
type_counts = {}
|
||||
for packet_type in range(16):
|
||||
count = conn.execute(
|
||||
"SELECT COUNT(*) FROM packets WHERE type = ? AND timestamp > ?",
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
"""
|
||||
Advertisement packet handling helper for pyMC Repeater.
|
||||
|
||||
This module processes advertisement packets for neighbor tracking and discovery.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import time
|
||||
|
||||
from pymc_core.node.handlers.advert import AdvertHandler
|
||||
|
||||
logger = logging.getLogger("AdvertHelper")
|
||||
|
||||
|
||||
class AdvertHelper:
|
||||
"""Helper class for processing advertisement packets in the repeater."""
|
||||
|
||||
def __init__(self, local_identity, storage, log_fn=None):
|
||||
"""
|
||||
Initialize the advert helper.
|
||||
|
||||
Args:
|
||||
local_identity: The LocalIdentity instance for this repeater
|
||||
storage: StorageCollector instance for persisting advert data
|
||||
log_fn: Optional logging function for AdvertHandler
|
||||
"""
|
||||
self.local_identity = local_identity
|
||||
self.storage = storage
|
||||
|
||||
# Create AdvertHandler internally as a parsing utility
|
||||
self.advert_handler = AdvertHandler(log_fn=log_fn or logger.info)
|
||||
|
||||
# Cache for tracking known neighbors (avoid repeated database queries)
|
||||
self._known_neighbors = set()
|
||||
|
||||
async def process_advert_packet(self, packet, rssi: int, snr: float) -> None:
|
||||
"""
|
||||
Process an incoming advertisement packet.
|
||||
|
||||
This method uses AdvertHandler to parse the packet, then stores
|
||||
the neighbor information for tracking and discovery.
|
||||
|
||||
Args:
|
||||
packet: The advertisement packet to process
|
||||
rssi: Received signal strength indicator
|
||||
snr: Signal-to-noise ratio
|
||||
"""
|
||||
try:
|
||||
# Set signal metrics on packet for handler to use
|
||||
packet._snr = snr
|
||||
packet._rssi = rssi
|
||||
|
||||
# Use AdvertHandler to parse the packet - it now returns parsed data
|
||||
advert_data = await self.advert_handler(packet)
|
||||
|
||||
if not advert_data or not advert_data.get("valid"):
|
||||
logger.warning("Invalid advert packet received, dropping.")
|
||||
packet.mark_do_not_retransmit()
|
||||
packet.drop_reason = "Invalid advert packet"
|
||||
return
|
||||
|
||||
# Extract data from parsed advert
|
||||
pubkey = advert_data["public_key"]
|
||||
node_name = advert_data["name"]
|
||||
contact_type = advert_data["contact_type"]
|
||||
|
||||
# Skip our own adverts
|
||||
if self.local_identity:
|
||||
local_pubkey = self.local_identity.get_public_key().hex()
|
||||
if pubkey == local_pubkey:
|
||||
logger.debug("Ignoring own advert in neighbor tracking")
|
||||
return
|
||||
|
||||
# Get route type from packet header
|
||||
from pymc_core.protocol.constants import PH_ROUTE_MASK
|
||||
|
||||
route_type = packet.header & PH_ROUTE_MASK
|
||||
|
||||
# Check if this is a new neighbor (run DB read in thread to avoid blocking event loop)
|
||||
current_time = time.time()
|
||||
if pubkey not in self._known_neighbors:
|
||||
# Only check database if not in cache
|
||||
if self.storage:
|
||||
current_neighbors = await asyncio.to_thread(
|
||||
self.storage.get_neighbors
|
||||
)
|
||||
else:
|
||||
current_neighbors = {}
|
||||
is_new_neighbor = pubkey not in current_neighbors
|
||||
|
||||
if is_new_neighbor:
|
||||
self._known_neighbors.add(pubkey)
|
||||
logger.info(f"Discovered new neighbor: {node_name} ({pubkey[:16]}...)")
|
||||
else:
|
||||
is_new_neighbor = False
|
||||
|
||||
# Determine zero-hop: direct routes are always zero-hop,
|
||||
# flood routes are zero-hop if path_len <= 1 (received directly)
|
||||
path_len = len(packet.path) if packet.path else 0
|
||||
zero_hop = path_len == 0
|
||||
|
||||
# Build advert record
|
||||
advert_record = {
|
||||
"timestamp": current_time,
|
||||
"pubkey": pubkey,
|
||||
"node_name": node_name,
|
||||
"is_repeater": "REPEATER" in contact_type.upper(),
|
||||
"route_type": route_type,
|
||||
"contact_type": contact_type,
|
||||
"latitude": advert_data["latitude"],
|
||||
"longitude": advert_data["longitude"],
|
||||
"rssi": rssi,
|
||||
"snr": snr,
|
||||
"is_new_neighbor": is_new_neighbor,
|
||||
"zero_hop": zero_hop,
|
||||
}
|
||||
|
||||
# Store to database (run in thread so event loop stays responsive;
|
||||
# blocking here can cause companion TCP clients to disconnect)
|
||||
if self.storage:
|
||||
try:
|
||||
await asyncio.to_thread(
|
||||
self.storage.record_advert,
|
||||
advert_record,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to store advert record: {e}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error processing advert packet: {e}", exc_info=True)
|
||||
|
||||
Reference in New Issue
Block a user