-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsimulation.py
More file actions
86 lines (71 loc) · 3.08 KB
/
Copy pathsimulation.py
File metadata and controls
86 lines (71 loc) · 3.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import config
from transmitter import Transmitter
from receiver import Receiver
from channel import ChannelEnvironment
class Simulation:
def __init__(self, scenario="GOOD", duration_sec=600, rx_config=None):
self.duration_us = duration_sec * 1000000
self.current_time = 0
self.scenario = scenario
self.tx = Transmitter()
self.rx = Receiver(overrides=rx_config)
self.channel = ChannelEnvironment(scenario=scenario)
# Stats
self.tx_count = 0
self.ack_count = 0
self.recovery_events = 0 # transitions to scan
self.total_downtime = 0 # time spent in SCANNING
def run(self):
last_rx_state = "SCANNING"
while self.current_time < self.duration_us:
# 1. Update Environment
self.channel.update_time(self.current_time)
# 2. Update RX state (timers)
prev_rx_state = self.rx.state
self.rx.step(self.current_time)
if prev_rx_state == "SYNCED" and self.rx.state == "SCANNING":
self.recovery_events += 1
if self.rx.state == "SCANNING":
self.total_downtime += config.TIME_STEP_US
# 3. TX Step
packet = self.tx.step(self.current_time)
if packet:
self.tx_count += 1
# Try to deliver to RX
# First, physical check: Are they on same channel?
rx_channel = self.rx.get_listening_channel()
delivered_packet = None
if packet.channel == rx_channel:
if self.channel.can_deliver(packet):
delivered_packet = packet
# RX processing
if delivered_packet:
ack = self.rx.receive_packet(delivered_packet, self.current_time)
if ack:
# Reverse path: RX -> TX
# Note: TX in this sim is "independent" and doesn't process ACKs logic-wise,
# but we count them for stats.
# Check channel reverse path
if self.channel.can_deliver(ack):
self.ack_count += 1
# Advance time
self.current_time += config.TIME_STEP_US
return self.get_results()
def get_results(self):
success_rate = (self.rx.total_received / self.tx_count) * 100 if self.tx_count > 0 else 0
avg_recovery = (self.total_downtime / self.recovery_events / 1000) if self.recovery_events > 0 else 0 # ms
return {
"scenario": self.scenario,
"tx_packets": self.tx_count,
"rx_packets": self.rx.total_received,
"success_rate": success_rate,
"max_consecutive_loss": self.rx.max_consecutive_losses,
"recovery_events": self.recovery_events,
"avg_recovery_time_ms": avg_recovery
}
if __name__ == "__main__":
# Quick test run
print("Running 10s test...")
sim = Simulation(scenario="MEDIUM", duration_sec=10)
res = sim.run()
print(res)