一个具备科研可验证性的 LoRa 多跳算法评估基线。

This commit is contained in:
sinlatansen
2026-02-25 20:14:45 +08:00
parent 8537331c6f
commit 5ee1a16574
18 changed files with 1704 additions and 47 deletions

View File

@@ -5,6 +5,7 @@ Implements:
- Broadcast propagation to all nodes in range
- Airtime occupation tracking
- Collision detection (time overlap + |RSSI1 - RSSI2| < 6 dB)
- Transmission statistics for efficiency analysis
"""
import simpy
@@ -25,6 +26,7 @@ class Transmission:
end_time: float
rssi: float
channel_busy_until: float
airtime: float = 0.0 # Add airtime field
@dataclass
@@ -46,6 +48,7 @@ class Channel:
- Transmissions and their time slots
- Collision detection based on time overlap and RSSI difference
- Packet delivery to nodes within range
- Transmission statistics for efficiency analysis
"""
COLLISION_RSSI_DIFF_DB = 6.0 # RSSI difference threshold for collision
@@ -61,6 +64,13 @@ class Channel:
self.transmissions: List[Transmission] = []
self.collision_count = 0
# Efficiency metrics
self.total_transmissions = 0
self.total_airtime = 0.0
self.hello_transmissions = 0
self.data_transmissions = 0
self.ack_transmissions = 0
# Callback for packet reception (set by node manager)
self.receive_callback: Optional[Callable[[int, ReceivedPacket], None]] = None
@@ -85,11 +95,18 @@ class Channel:
# Calculate packet size and airtime
if packet.is_hello:
pkt_airtime = airtime_calc.get_hello_airtime()
self.hello_transmissions += 1
elif packet.is_ack:
pkt_airtime = airtime_calc.get_ack_airtime()
self.ack_transmissions += 1
else: # DATA
payload_size = len(packet.payload) if packet.payload else 16
pkt_airtime = airtime_calc.get_data_airtime(payload_size)
self.data_transmissions += 1
# Track transmission statistics
self.total_transmissions += 1
self.total_airtime += pkt_airtime
start_time = self.env.now
end_time = start_time + pkt_airtime
@@ -115,6 +132,7 @@ class Channel:
end_time=end_time,
rssi=sender_rssi,
channel_busy_until=end_time,
airtime=pkt_airtime,
)
if colliding:
@@ -253,7 +271,22 @@ class Channel:
return self.env.now
return max(t.channel_busy_until for t in self.transmissions)
def get_efficiency_metrics(self) -> dict:
"""Get efficiency metrics for analysis."""
return {
"total_transmissions": self.total_transmissions,
"total_airtime": self.total_airtime,
"hello_transmissions": self.hello_transmissions,
"data_transmissions": self.data_transmissions,
"ack_transmissions": self.ack_transmissions,
}
def reset(self):
"""Reset channel state."""
self.transmissions.clear()
self.collision_count = 0
self.total_transmissions = 0
self.total_airtime = 0.0
self.hello_transmissions = 0
self.data_transmissions = 0
self.ack_transmissions = 0