marilib-pkg 0.6.0__py3-none-any.whl → 0.7.0rc1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
marilib/tui_edge.py CHANGED
@@ -1,4 +1,6 @@
1
+ from __future__ import annotations
1
2
  from datetime import datetime, timedelta
3
+ from typing import TYPE_CHECKING
2
4
 
3
5
  from rich.columns import Columns
4
6
  from rich.console import Console, Group
@@ -8,10 +10,12 @@ from rich.panel import Panel
8
10
  from rich.table import Table
9
11
  from rich.text import Text
10
12
 
11
- from marilib import MarilibEdge
12
13
  from marilib.model import MariNode, TestState
13
14
  from marilib.tui import MarilibTUI
14
15
 
16
+ if TYPE_CHECKING:
17
+ from marilib.marilib_edge import MarilibEdge
18
+
15
19
 
16
20
  class MarilibTUIEdge(MarilibTUI):
17
21
  """A Text-based User Interface for MarilibEdge."""
@@ -36,7 +40,7 @@ class MarilibTUIEdge(MarilibTUI):
36
40
  available_height = terminal_height - 10 - 2 - 2 - 1 - 2
37
41
  return max(2, available_height)
38
42
 
39
- def render(self, mari: MarilibEdge):
43
+ def render(self, mari: "MarilibEdge"):
40
44
  """Render the TUI layout."""
41
45
  with mari.lock:
42
46
  if datetime.now() - self.last_render_time < timedelta(seconds=self.re_render_max_freq):
@@ -49,64 +53,113 @@ class MarilibTUIEdge(MarilibTUI):
49
53
  )
50
54
  self.live.update(layout, refresh=True)
51
55
 
52
- def create_header_panel(self, mari: MarilibEdge) -> Panel:
56
+ def create_header_panel(self, mari: "MarilibEdge") -> Panel:
53
57
  """Create the header panel with gateway and network stats."""
54
58
  status = Text()
55
- status.append("MarilibEdge is ", style="bold")
59
+
60
+ # UART Status Line
61
+ status.append("UART: ", style="bold cyan")
56
62
  status.append(
57
63
  "connected" if mari.serial_connected else "disconnected",
58
64
  style="bold green" if mari.serial_connected else "bold red",
59
65
  )
60
- status.append(
61
- f" via {mari.serial_interface.port} at {mari.serial_interface.baudrate} baud "
62
- f"since {mari.started_ts.strftime('%Y-%m-%d %H:%M:%S')}"
63
- )
64
- status.append(" | ")
66
+ if mari.serial_connected:
67
+ status.append(
68
+ f" via {mari.serial_interface.port} at {mari.serial_interface.baudrate} baud "
69
+ )
65
70
  secs = int((datetime.now() - mari.last_received_serial_data_ts).total_seconds())
66
71
  status.append(
67
- f"last received: {secs}s ago",
72
+ f"(last: {secs}s ago)",
68
73
  style="bold green" if secs <= 1 else "bold red",
69
74
  )
70
75
 
76
+ status.append(" | ")
77
+
78
+ # MQTT Status Line
79
+ status.append("MQTT: ", style="bold cyan")
80
+ if mari.uses_mqtt:
81
+ status.append(
82
+ "connected" if mari.mqtt_connected else "disconnected",
83
+ style="bold green" if mari.mqtt_connected else "bold red",
84
+ )
85
+ if mari.mqtt_connected:
86
+ status.append(f" to {mari.mqtt_interface.host}:{mari.mqtt_interface.port} ")
87
+ mqtt_secs = int((datetime.now() - mari.last_received_mqtt_data_ts).total_seconds())
88
+ status.append(
89
+ f"(last: {mqtt_secs}s ago)",
90
+ style="bold green" if mqtt_secs <= 1 else "bold red",
91
+ )
92
+ else:
93
+ status.append("disabled", style="bold yellow")
94
+
71
95
  status.append("\n\nGateway: ", style="bold cyan")
72
96
  status.append(f"0x{mari.gateway.info.address:016X} | ")
73
97
  status.append("Network ID: ", style="bold cyan")
74
98
  status.append(f"0x{mari.gateway.info.network_id:04X} | ")
99
+ status.append("ASN: ", style="bold cyan")
100
+ status.append(f"{mari.gateway.info.asn:020d}")
75
101
 
76
102
  status.append("\n\n")
77
103
  status.append("Schedule: ", style="bold cyan")
78
- status.append(f"#{mari.gateway.info.schedule_id} ({mari.gateway.info.schedule_name}) | ")
104
+ status.append(f"#{mari.gateway.info.schedule_id} {mari.gateway.info.schedule_name} | ")
105
+ status.append(f"{len(mari.gateway.nodes)} / {mari.gateway.info.max_nodes} nodes | ")
79
106
  status.append(mari.gateway.info.repr_schedule_cells_with_colors())
80
- status.append("\n\n")
81
107
 
82
- if mari.gateway.latency_stats.last_ms > 0:
83
- status.append("Latency: ", style="bold cyan")
84
- lat = mari.gateway.latency_stats
85
- status.append(
86
- f"Last: {lat.last_ms:.1f}ms | Avg: {lat.avg_ms:.1f}ms | "
87
- f"Min: {lat.min_ms:.1f}ms | Max: {lat.max_ms:.1f}ms"
88
- )
108
+ # --- Latency and PDR Display ---
109
+ avg_latency_edge = mari.gateway.stats_avg_latency_roundtrip_node_edge_ms()
110
+ has_latency_info = avg_latency_edge > 0
111
+
112
+ # Check if we have PDR info by looking at the gateway averages
113
+ avg_uart_pdr_up = mari.gateway.stats_avg_pdr_uplink_uart()
114
+ avg_uart_pdr_down = mari.gateway.stats_avg_pdr_downlink_uart()
115
+ has_uart_pdr_info = avg_uart_pdr_up > 0 or avg_uart_pdr_down > 0
116
+
117
+ avg_radio_pdr_down = mari.gateway.stats_avg_pdr_downlink_radio()
118
+ avg_radio_pdr_up = mari.gateway.stats_avg_pdr_uplink_radio()
119
+ has_radio_pdr_info = avg_radio_pdr_down > 0 or avg_radio_pdr_up > 0
120
+
121
+ pdr_info = " | PDR:" if has_uart_pdr_info or has_radio_pdr_info else ""
122
+ radio_pdr_info = (
123
+ f" Radio ↓ {avg_radio_pdr_down:.1%} ↑ {avg_radio_pdr_up:.1%}"
124
+ if has_radio_pdr_info
125
+ else ""
126
+ )
127
+ uart_pdr_info = (
128
+ f" UART ↓ {avg_uart_pdr_down:.1%} ↑ {avg_uart_pdr_up:.1%}" if has_uart_pdr_info else ""
129
+ )
130
+
131
+ if has_latency_info or has_uart_pdr_info or has_radio_pdr_info:
132
+ status.append("\n\n")
133
+
134
+ # Display Latency
135
+ if has_latency_info:
136
+ status.append("Latency: ", style="bold yellow")
137
+ status.append(f"Avg: {avg_latency_edge:.1f}ms")
138
+
139
+ # Display PDR
140
+ status.append(f"{pdr_info}{radio_pdr_info}{uart_pdr_info}")
89
141
 
90
142
  status.append("\n\nStats: ", style="bold yellow")
91
143
  if self.test_state and self.test_state.load > 0 and self.test_state.rate > 0:
92
144
  status.append(
93
145
  "Test load: ",
94
- # style="bold yellow",
95
146
  )
96
147
  status.append(f"{self.test_state.load}% of {self.test_state.rate} pps")
97
148
  status.append(" | ")
98
149
 
99
150
  stats = mari.gateway.stats
100
- status.append(f"Nodes: {len(mari.gateway.nodes)} | ")
101
- status.append(f"Frames TX: {stats.sent_count(include_test_packets=False)} | ")
102
- status.append(f"Frames RX: {stats.received_count(include_test_packets=False)} | ")
103
- status.append(f"TX/s: {stats.sent_count(1, include_test_packets=False)} | ")
104
- status.append(f"RX/s: {stats.received_count(1, include_test_packets=False)}")
151
+ status.append(f"Frames TX: {stats.sent_count(include_test_packets=True)} | ")
152
+ status.append(f"Frames RX: {stats.received_count(include_test_packets=True)} | ")
153
+ status.append(f"TX/s: {stats.sent_count(1, include_test_packets=True)} | ")
154
+ status.append(f"RX/s: {stats.received_count(1, include_test_packets=True)}")
105
155
 
106
- return Panel(status, title="[bold]MarilibEdge Status", border_style="blue")
156
+ return Panel(
157
+ status,
158
+ title=f"[bold]MariEdge running since {mari.started_ts.strftime('%Y-%m-%d %H:%M:%S')}",
159
+ border_style="blue",
160
+ )
107
161
 
108
162
  def create_nodes_table(self, nodes: list[MariNode], title="") -> Table:
109
- """Create a table displaying information about connected nodes."""
110
163
  table = Table(
111
164
  show_header=True,
112
165
  header_style="bold cyan",
@@ -116,33 +169,88 @@ class MarilibTUIEdge(MarilibTUI):
116
169
  )
117
170
  table.add_column("Node Address", style="cyan")
118
171
  table.add_column("TX", justify="right")
119
- table.add_column("TX/s", justify="right")
172
+ table.add_column("/s", justify="right")
120
173
  table.add_column("RX", justify="right")
121
- table.add_column("RX/s", justify="right")
122
- table.add_column("SR(total)", justify="right")
123
- table.add_column("PDR Down", justify="right")
124
- table.add_column("PDR Up", justify="right")
125
- table.add_column("RSSI", justify="right")
126
- table.add_column("Latency (ms)", justify="right")
174
+ table.add_column("/s", justify="right")
175
+ table.add_column("Radio ↓ PDR | RSSI", justify="center")
176
+ table.add_column("Radio ↑ PDR | RSSI", justify="center")
177
+ table.add_column("UART PDR ↓ | ↑", justify="center")
178
+ table.add_column("Latency", justify="center")
179
+
127
180
  for node in nodes:
128
181
  lat_str = (
129
- f"{node.latency_stats.avg_ms:.1f}" if node.latency_stats.last_ms > 0 else "..."
182
+ f"{node.stats_avg_latency_roundtrip_node_edge_ms():.1f} ms"
183
+ if node.stats_avg_latency_roundtrip_node_edge_ms() > 0
184
+ else "..."
130
185
  )
186
+ # PDR Downlink with color coding
187
+ if node.stats_pdr_downlink_radio() > 0:
188
+ if node.stats_pdr_downlink_radio() > 0.9:
189
+ pdr_down_str = f"[white]{node.stats_pdr_downlink_radio():>4.0%}[/white]"
190
+ elif node.stats_pdr_downlink_radio() > 0.8:
191
+ pdr_down_str = f"[yellow]{node.stats_pdr_downlink_radio():>4.0%}[/yellow]"
192
+ else:
193
+ pdr_down_str = f"[red]{node.stats_pdr_downlink_radio():>4.0%}[/red]"
194
+ else:
195
+ pdr_down_str = "..."
196
+
197
+ # PDR Uplink with color coding
198
+ if node.stats_pdr_uplink_radio() > 0:
199
+ if node.stats_pdr_uplink_radio() > 0.9:
200
+ pdr_up_str = f"[white]{node.stats_pdr_uplink_radio():>4.0%}[/white]"
201
+ elif node.stats_pdr_uplink_radio() > 0.8:
202
+ pdr_up_str = f"[yellow]{node.stats_pdr_uplink_radio():>4.0%}[/yellow]"
203
+ else:
204
+ pdr_up_str = f"[red]{node.stats_pdr_uplink_radio():>4.0%}[/red]"
205
+ else:
206
+ pdr_up_str = "..."
207
+
208
+ # PDR UART Up / Down with color coding
209
+ if node.stats_pdr_downlink_uart() > 0:
210
+ if node.stats_pdr_downlink_uart() > 0.9:
211
+ pdr_down_gw_edge_str = f"[white]{node.stats_pdr_downlink_uart():>4.0%}[/white]"
212
+ elif node.stats_pdr_downlink_uart() > 0.8:
213
+ pdr_down_gw_edge_str = (
214
+ f"[yellow]{node.stats_pdr_downlink_uart():>4.0%}[/yellow]"
215
+ )
216
+ else:
217
+ pdr_down_gw_edge_str = f"[red]{node.stats_pdr_downlink_uart():>4.0%}[/red]"
218
+ else:
219
+ pdr_down_gw_edge_str = "..."
220
+
221
+ if node.stats_pdr_uplink_uart() > 0:
222
+ if node.stats_pdr_uplink_uart() > 0.9:
223
+ pdr_up_gw_edge_str = f"[white]{node.stats_pdr_uplink_uart():>4.0%}[/white]"
224
+ elif node.stats_pdr_uplink_uart() > 0.8:
225
+ pdr_up_gw_edge_str = f"[yellow]{node.stats_pdr_uplink_uart():>4.0%}[/yellow]"
226
+ else:
227
+ pdr_up_gw_edge_str = f"[red]{node.stats_pdr_uplink_uart():>4.0%}[/red]"
228
+ else:
229
+ pdr_up_gw_edge_str = "..."
230
+
231
+ rssi_node_str = (
232
+ f"{node.stats_rssi_node_dbm():.0f}"
233
+ if node.stats_rssi_node_dbm() is not None
234
+ else "..."
235
+ )
236
+ rssi_gw_str = (
237
+ f"{node.stats_rssi_gw_dbm():.0f}" if node.stats_rssi_gw_dbm() is not None else "..."
238
+ )
239
+
131
240
  table.add_row(
132
241
  f"0x{node.address:016X}",
133
- str(node.stats.sent_count(include_test_packets=False)),
134
- str(node.stats.sent_count(1, include_test_packets=False)),
135
- str(node.stats.received_count(include_test_packets=False)),
136
- str(node.stats.received_count(1, include_test_packets=False)),
137
- f"{node.stats.success_rate():>4.0%}",
138
- f"{node.pdr_downlink:>4.0%}",
139
- f"{node.pdr_uplink:>4.0%}",
140
- f"{node.stats.received_rssi_dbm(5)}",
242
+ str(node.stats.sent_count(include_test_packets=True)),
243
+ str(node.stats.sent_count(1, include_test_packets=True)),
244
+ str(node.stats.received_count(include_test_packets=True)),
245
+ str(node.stats.received_count(1, include_test_packets=True)),
246
+ f"{pdr_down_str} | {rssi_node_str} dBm",
247
+ f"{pdr_up_str} | {rssi_gw_str} dBm",
248
+ f"{pdr_down_gw_edge_str} | {pdr_up_gw_edge_str}",
141
249
  lat_str,
142
250
  )
143
251
  return table
144
252
 
145
- def create_nodes_panel(self, mari: MarilibEdge) -> Panel:
253
+ def create_nodes_panel(self, mari: "MarilibEdge") -> Panel:
146
254
  """Create the panel that contains the nodes table."""
147
255
  nodes = mari.gateway.nodes
148
256
  max_rows = self.get_max_rows()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: marilib-pkg
3
- Version: 0.6.0
3
+ Version: 0.7.0rc1
4
4
  Summary: MariLib is a Python library for interacting with the Mari network.
5
5
  Project-URL: Homepage, https://github.com/DotBots/marilib
6
6
  Project-URL: Bug Tracker, https://github.com/DotBots/marilib/issues
@@ -25,14 +25,36 @@ Description-Content-Type: text/markdown
25
25
  # MariLib 💫 👀 🐍
26
26
 
27
27
  MariLib is a Python library to interact with a local [Mari](https://github.com/DotBots/mari) network.
28
- It connects to a Mari gateway via UART.
28
+ It connects to a Mari gateway via:
29
+ - UART, using MarilibEdge
30
+ - MQTT, using MarilibCloud
29
31
 
30
32
  ## Example with TUI
31
33
  MariLib provides a stateful class with gateway and node information, network statistics, and a rich real-time TUI:
32
34
 
33
35
  [mari-edge-2.webm](https://github.com/user-attachments/assets/fe50f2ba-8e67-4522-8700-69730f8e3aee)
34
36
 
35
- See the how it works in `examples/basic.py`.
37
+ To run with a gateway connected via UART:
38
+ ```bash
39
+ # for example, using the Inria Argus MQTT broker
40
+ (.venv) $ python examples/mari_edge.py -m mqtts://argus.paris.inria.fr:8883
41
+ ```
42
+ You can see how it works using `examples/mari_edge.py --help`.
43
+
44
+ To run with a gateway connected via MQTT:
45
+ ```bash
46
+ # for example, using the Inria Argus MQTT broker
47
+ (.venv) $ python examples/mari_cloud.py -n 0x0100 -m mqtts://argus.paris.inria.fr:8883
48
+ ```
49
+
50
+ ## Setup and dependencies
51
+ To setup the environment, do:
52
+
53
+ ```bash
54
+ $ python -m venv .venv
55
+ $ source .venv/bin/activate
56
+ (.venv) $ pip install -e .
57
+ ```
36
58
 
37
59
  ## Minimal example
38
60
  Here is a minimal example showcasing how to use MariLib:
@@ -0,0 +1,33 @@
1
+ examples/frames.py,sha256=LQ-eWWtv3plFmNzXVVMESidkLpU54vuUir0DjGCZLPI,964
2
+ examples/mari_cloud.py,sha256=GsxnX0V1a3wcx503xTbCoQKwS6niaedG4Ne73zW_V4E,2408
3
+ examples/mari_cloud_minimal.py,sha256=zaLnd61gkqht5AclJC6Hfc1CPS_8BzTmGE-tItbWlao,1125
4
+ examples/mari_edge.py,sha256=3B6_kM3jCyO7bZhVRTlHIn4lSAOFdJhJ9Gh3qJNie-U,1875
5
+ examples/mari_edge_minimal.py,sha256=9vOsIdW9WnS_GQg9fBw_G1wkvGFokwsiM83Q8etoUpA,1090
6
+ examples/mari_edge_stats.py,sha256=0wfgZ5hJjcpX35VrtzxSRD5YYOcZtQnpXqMIteDaxbE,4719
7
+ examples/uart.py,sha256=pUvkpVf64T94XFLzgyHSzMOZISMrm0wqyurjNyS3JhY,823
8
+ examples/raspberry-pi/sense_hat_ui.py,sha256=y1Rseqs0fCK-2HuQ0yCVU9SlHBCeN4ylifjvzlqhJn0,7170
9
+ marilib/__init__.py,sha256=8Fr_Z__t3Wovz4aHwLeqVQqqK0FLAXktcIWJKKKnviw,134
10
+ marilib/communication_adapter.py,sha256=SNYDrIQqDRk5rbZJB02KTyVrFY_xJVvRu0KNEwA_qbU,7084
11
+ marilib/logger.py,sha256=UHM4v6fXl5uvporz6-No8Pe3rw60rACv2BN11h7h5vA,8867
12
+ marilib/mari_protocol.py,sha256=4gzl3v0w4i54KPBkzZ-0pF3RREjQ2thL535ocFfXxBI,10571
13
+ marilib/marilib.py,sha256=m7drdxhAMnjTrqYjUvwqunreYpffz7-AKgaOkuXHukg,939
14
+ marilib/marilib_cloud.py,sha256=s9S8YCP2_adIkdnvyh9TzJ0EvDCSQ4j1G22XXElevPA,7820
15
+ marilib/marilib_edge.py,sha256=WyQ0ItBzM5XDfnReFV4x-EQHJiplm4SiVj_AsOA5x9M,9605
16
+ marilib/metrics.py,sha256=eH3toxToZF-a-NAx5q5iRD4Qw-fi8zKC-mGFwZqd-qg,5936
17
+ marilib/model.py,sha256=oh54K7MrXXdwOfYJ7prRkkSoxhkuaroO475ZLJb4vKU,19476
18
+ marilib/pdr.py,sha256=V0J3zgneVyvikZhA-6_4Bc6Q_JxJevpb9QXs9k9Sq2I,3359
19
+ marilib/protocol.py,sha256=wOsG_oIk2Ls6gnbDYa5_g1sbHGuYgsj6liiax_yTn34,3786
20
+ marilib/serial_hdlc.py,sha256=6EDbjkJ5RU_1Gv3OhHaIhLAXscce_2-yCv-602sw2-8,8119
21
+ marilib/serial_uart.py,sha256=vc8FhUXDEV5XZ9H-cHHZR1Hk_T9z_rM_U7sj7TiOwvg,2801
22
+ marilib/tui.py,sha256=doTpHnZqyHEglSck_a1cl9DU1uTCZavVOlcZjA8aTV4,231
23
+ marilib/tui_cloud.py,sha256=Cl5V63_7RZWePd8FdmGiZd1vqdeYUxtlH5dIgIUCHiM,6866
24
+ marilib/tui_edge.py,sha256=y3jnxOZiPJ-NZW7Aar0K5d7v7lvg0RUDnksTF7rR7tc,12273
25
+ tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
+ tests/test_hdlc.py,sha256=SSgDpdTa2ga-P5tlXZtGvjliame4Ug9FwyreSw_nT9k,2450
27
+ tests/test_protocol.py,sha256=JJRtzCV2BygogSFFmss4FwYLb7x3Zy8sIEWxzopfxNE,1167
28
+ marilib_pkg-0.7.0rc1.dist-info/METADATA,sha256=nL7jVhrdHLD3pHh3MqnuiUEweYDly1CF2iyUU1NW7Zw,2579
29
+ marilib_pkg-0.7.0rc1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
30
+ marilib_pkg-0.7.0rc1.dist-info/entry_points.txt,sha256=hDmlCur_i2xCiPm4GiD98fAfZBp1duLRinNwv8YO1yg,50
31
+ marilib_pkg-0.7.0rc1.dist-info/licenses/AUTHORS,sha256=gGgRHmEH6klwG7KQd4rYVy0AT8MkA9mMimfiN1NvOHU,96
32
+ marilib_pkg-0.7.0rc1.dist-info/licenses/LICENSE,sha256=j97C1uBc5chpQWi4bv_2SrqExuvKaJK2Ch6L2LFkoc4,1492
33
+ marilib_pkg-0.7.0rc1.dist-info/RECORD,,
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ marilib = marilib.cli.main:main
marilib/latency.py DELETED
@@ -1,78 +0,0 @@
1
- import struct
2
- import threading
3
- import time
4
- from typing import TYPE_CHECKING
5
- import math
6
-
7
- from marilib.mari_protocol import Frame
8
-
9
- if TYPE_CHECKING:
10
- from marilib.marilib import MariLib
11
-
12
- LATENCY_PACKET_MAGIC = b"\x4c\x54" # "LT" for Latency Test
13
-
14
-
15
- class LatencyTester:
16
- """A thread-based class to periodically test latency to all nodes."""
17
-
18
- def __init__(self, marilib: "MariLib", interval: float = 10.0):
19
- self.marilib = marilib
20
- self.interval = interval
21
- self._stop_event = threading.Event()
22
- self._thread = threading.Thread(target=self._run, daemon=True)
23
-
24
- def start(self):
25
- """Starts the latency testing thread."""
26
- print("[yellow]Latency tester started.[/]")
27
- self._thread.start()
28
-
29
- def stop(self):
30
- """Stops the latency testing thread."""
31
- self._stop_event.set()
32
- self._thread.join()
33
- print("[yellow]Latency tester stopped.[/]")
34
-
35
- def _run(self):
36
- """The main loop for the testing thread."""
37
- while not self._stop_event.is_set():
38
- if not self.marilib.gateway.nodes:
39
- time.sleep(self.interval)
40
- continue
41
-
42
- for node in list(self.marilib.gateway.nodes):
43
- if self._stop_event.is_set():
44
- break
45
- self.send_latency_request(node.address)
46
- time.sleep(self.interval / len(self.marilib.gateway.nodes))
47
-
48
- def send_latency_request(self, address: int):
49
- """Sends a latency request packet to a specific address."""
50
-
51
- payload = LATENCY_PACKET_MAGIC + struct.pack("<d", time.time())
52
- self.marilib.send_frame(address, payload)
53
-
54
- def handle_response(self, frame: Frame):
55
- """
56
- Processes a latency response frame.
57
- This should be called when a LATENCY_DATA event is received.
58
- """
59
- if not frame.payload.startswith(LATENCY_PACKET_MAGIC):
60
- return
61
- try:
62
- # Unpack the original timestamp from the payload
63
- original_ts = struct.unpack("<d", frame.payload[2:10])[0]
64
- rtt = time.time() - original_ts
65
- if math.isnan(rtt) or math.isinf(rtt):
66
- return # Ignore corrupted/invalid packets
67
- if rtt < 0 or rtt > 5.0:
68
- return # Ignore this outlier
69
-
70
- node = self.marilib.gateway.get_node(frame.header.source)
71
- if node:
72
- # Update statistics for both the specific node and the whole gateway
73
- node.latency_stats.add_latency(rtt)
74
- self.marilib.gateway.latency_stats.add_latency(rtt)
75
-
76
- except (struct.error, IndexError):
77
- # Ignore packets that are too short or malformed
78
- pass
@@ -1,30 +0,0 @@
1
- examples/frames.py,sha256=SSC36A66kFwL-U5HtFgAuK6_BI1ik_84EFJ7DoG0oBo,780
2
- examples/mari_cloud.py,sha256=EQmQb6AiZt49j6bI4h9kAe8nfy6Zg5PfY0WTYKc8Kes,1860
3
- examples/mari_cloud_minimal.py,sha256=zaLnd61gkqht5AclJC6Hfc1CPS_8BzTmGE-tItbWlao,1125
4
- examples/mari_edge.py,sha256=VI5iv46f5ejbNn7H6A7pQjSDrdWsj3pDM6DrLos5SuI,1936
5
- examples/mari_edge_minimal.py,sha256=9vOsIdW9WnS_GQg9fBw_G1wkvGFokwsiM83Q8etoUpA,1090
6
- examples/mari_edge_stats.py,sha256=LQx4gtfFCp1rP0uBo1UCLg5e5eusDKsH_beoKj5_CAI,4340
7
- examples/uart.py,sha256=pUvkpVf64T94XFLzgyHSzMOZISMrm0wqyurjNyS3JhY,823
8
- marilib/__init__.py,sha256=PCxfi_8iZpMbc5DscErorPXqdO7qghp6t1MFU0NnYfk,130
9
- marilib/communication_adapter.py,sha256=IEcSLm5lbtFMtFCZ784QdvZZ5zcqL1IZQ90CSSp-XvM,6998
10
- marilib/latency.py,sha256=jz-7Yvgmk-BO40FHW_pltHbRV2OL1QD-dCkV9iSJiiY,2729
11
- marilib/logger.py,sha256=IgkC1JM9sf3JxiSBYUcHeuYpiRrwcODVR2Y54GA2LPA,7867
12
- marilib/mari_protocol.py,sha256=b1hQdSJX8CjPtKgosO7F-vt8ZHsnZ9QqMI2oKNL4r0E,2516
13
- marilib/marilib.py,sha256=m7drdxhAMnjTrqYjUvwqunreYpffz7-AKgaOkuXHukg,939
14
- marilib/marilib_cloud.py,sha256=0yPTea0J2h4EkWwTcU4QAr001srd9_P6LOPtmJmhH24,7346
15
- marilib/marilib_edge.py,sha256=tzjeNtI_SpvghYxgV_y8j27d6xXX-1HIQc2TGKuNOg0,9743
16
- marilib/model.py,sha256=0WAEtMxqnqziSG0epZfLXlXVAzVRNfou4n6suhtdB1k,12831
17
- marilib/protocol.py,sha256=wOsG_oIk2Ls6gnbDYa5_g1sbHGuYgsj6liiax_yTn34,3786
18
- marilib/serial_hdlc.py,sha256=6EDbjkJ5RU_1Gv3OhHaIhLAXscce_2-yCv-602sw2-8,8119
19
- marilib/serial_uart.py,sha256=7sv8Ouj-y7k2Yry6cINil9WgVYvy1cRPPpIbW4JLVQo,2764
20
- marilib/tui.py,sha256=doTpHnZqyHEglSck_a1cl9DU1uTCZavVOlcZjA8aTV4,231
21
- marilib/tui_cloud.py,sha256=LZQVYLSwdLBubUcbUy7Eoahma_98b690ndCVgXSm_EA,5672
22
- marilib/tui_edge.py,sha256=N2i0aUZ2zeaC0oPcCamNd5FY0wTDtmp2KWFF1yL6ABA,7573
23
- tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
- tests/test_hdlc.py,sha256=SSgDpdTa2ga-P5tlXZtGvjliame4Ug9FwyreSw_nT9k,2450
25
- tests/test_protocol.py,sha256=JJRtzCV2BygogSFFmss4FwYLb7x3Zy8sIEWxzopfxNE,1167
26
- marilib_pkg-0.6.0.dist-info/METADATA,sha256=FuhL1nVncSyrIJ1mpqqReAajGZSCQcCJW-gEsQbE0h4,1992
27
- marilib_pkg-0.6.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
28
- marilib_pkg-0.6.0.dist-info/licenses/AUTHORS,sha256=gGgRHmEH6klwG7KQd4rYVy0AT8MkA9mMimfiN1NvOHU,96
29
- marilib_pkg-0.6.0.dist-info/licenses/LICENSE,sha256=j97C1uBc5chpQWi4bv_2SrqExuvKaJK2Ch6L2LFkoc4,1492
30
- marilib_pkg-0.6.0.dist-info/RECORD,,