""" Packet model for LoRa route simulation. Defines packet types and structure for HELLO, DATA, and ACK packets. """ from dataclasses import dataclass from enum import IntEnum from typing import Optional class PacketType(IntEnum): """Packet type enumeration.""" HELLO = 1 DATA = 2 ACK = 3 @dataclass class Packet: """ LoRa packet structure. Attributes: type: Packet type (HELLO, DATA, or ACK) src: Source node ID dst: Destination node ID (-1 for broadcast) seq: Sequence number hop: Current hop count payload: Optional payload data rssi: Received signal strength indicator (set on receive) """ type: PacketType src: int dst: int seq: int hop: int = 0 payload: Optional[str] = None rssi: Optional[float] = None # Set by receiver def __repr__(self) -> str: return ( f"Packet({self.type.name}, src={self.src}, dst={self.dst}, " f"seq={self.seq}, hop={self.hop})" ) @property def is_broadcast(self) -> bool: """Check if packet is broadcast (dst = -1).""" return self.dst == -1 @property def is_hello(self) -> bool: """Check if packet is a HELLO packet.""" return self.type == PacketType.HELLO @property def is_data(self) -> bool: """Check if packet is a DATA packet.""" return self.type == PacketType.DATA @property def is_ack(self) -> bool: """Check if packet is an ACK packet.""" return self.type == PacketType.ACK def to_dict(self) -> dict: """Convert packet to dictionary for serialization.""" return { "type": self.type.name, "src": self.src, "dst": self.dst, "seq": self.seq, "hop": self.hop, "payload": self.payload, "rssi": self.rssi, }