diff --git a/meshview/models.py b/meshview/models.py index 4c2215b..baa0391 100644 --- a/meshview/models.py +++ b/meshview/models.py @@ -60,4 +60,5 @@ class Traceroute(Base): gateway_node_id: Mapped[int] = mapped_column(BigInteger) done: Mapped[bool] route: Mapped[bytes] + import_time: Mapped[datetime] diff --git a/meshview/store.py b/meshview/store.py index c1d51d0..9093153 100644 --- a/meshview/store.py +++ b/meshview/store.py @@ -109,6 +109,7 @@ async def process_envelope(topic, env): route=env.packet.decoded.payload, done=not env.packet.decoded.want_response, gateway_node_id=int(env.gateway_id[1:], 16), + import_time=datetime.datetime.utcnow(), )) await session.commit() @@ -207,5 +208,6 @@ async def get_traceroute(packet_id): result = await session.execute( select(Traceroute) .where(Traceroute.packet_id == packet_id) + .order_by(Traceroute.import_time) ) return result.scalars() diff --git a/meshview/web.py b/meshview/web.py index 3aa1058..c2674f3 100644 --- a/meshview/web.py +++ b/meshview/web.py @@ -557,6 +557,7 @@ async def graph_traceroute(request): mqtt_nodes = set() saw_reply = set() dest = None + node_seen_time = {} for tr in traceroutes: if tr.done: saw_reply.add(tr.gateway_node_id) @@ -571,6 +572,12 @@ async def graph_traceroute(request): elif path[-1] != tr.gateway_node_id: # It seems some nodes add them self to the list before uplinking path.append(tr.gateway_node_id) + + for node_id in path[-2:]: + if node_id not in node_seen_time: + if tr.import_time: + node_seen_time[node_id] = tr.import_time + mqtt_nodes.add(tr.gateway_node_id) node_color[path[-1]] = '#' + hex(hash(tuple(path)))[3:9] paths.add(tuple(path)) @@ -579,12 +586,21 @@ async def graph_traceroute(request): for path in paths: used_nodes.update(path) + import_times = [tr.import_time for tr in traceroutes if tr.import_time] + if import_times: + first_time = min(import_times) + else: + first_time = 0 + for node_id in used_nodes: node = await nodes[node_id] if not node: node_name = node_id_to_hex(node_id) else: node_name = f'[{node.short_name}] {node.long_name} - {node_id_to_hex(node_id)}' + if node_id in node_seen_time: + ms = (node_seen_time[node_id] - first_time).total_seconds() / 1000 + node_name += f'\n {ms:.2f}ms' style = 'dashed' if node_id == dest: style = 'filled'