From 21760552e4b3c529eab90fb4fff753a2029efa21 Mon Sep 17 00:00:00 2001 From: Pablo Revilla Date: Wed, 27 Aug 2025 07:30:28 -0700 Subject: [PATCH] Added the traceroute and neighbours to the map --- meshview/templates/map.html | 140 ++++++++++++++++++++++-------------- meshview/web.py | 37 ++++++++++ 2 files changed, 122 insertions(+), 55 deletions(-) diff --git a/meshview/templates/map.html b/meshview/templates/map.html index 02af414..9132f7d 100644 --- a/meshview/templates/map.html +++ b/meshview/templates/map.html @@ -34,17 +34,13 @@
- + Show Routers Only
-
- Show Routers Only -
- + // --- Lazy load edges on node click --- + var edgeLayer = L.layerGroup().addTo(map); // initially empty + var edgesData = null; -{% endblock %} \ No newline at end of file + function loadEdges(callback) { + if (edgesData) { + callback(edgesData); + } else { + fetch('/api/edges') + .then(res => res.json()) + .then(data => { + edgesData = data.edges; + callback(edgesData); + }) + .catch(err => console.error("Error loading edges:", err)); + } + } + + function onNodeClick(node) { + loadEdges(function(edges) { + edgeLayer.clearLayers(); // remove previous edges + + edges.forEach(edge => { + if (edge.from === node.id || edge.to === node.id) { + let from = nodeIndex[edge.from]; + let to = nodeIndex[edge.to]; + if (from && to) { + let poly = L.polyline([from, to], { + color: edge.type === "neighbor" ? "red" : "blue", + weight: 2, + opacity: 1, + dashArray: edge.type === "traceroute" ? "5,5" : null + }).addTo(edgeLayer); + + poly.bringToBack(); + poly.setStyle({opacity: 1}); // highlight edge immediately + } + } + }); + }); + } + + // Attach click events to nodes + nodes.forEach(node => { + if (node.lat !== null && node.long !== null) { + let marker = markers[node.channel].find(obj => + obj.marker.getLatLng().lat === node.lat && + obj.marker.getLatLng().lng === node.long + ).marker; + + marker.on('click', () => onNodeClick(node)); + } + }); + +{% endblock %} diff --git a/meshview/web.py b/meshview/web.py index 278b314..ad1a264 100644 --- a/meshview/web.py +++ b/meshview/web.py @@ -1705,6 +1705,43 @@ async def api_config(request): except Exception as e: return web.json_response({"error": str(e)}, status=500) +@routes.get("/api/edges") +async def api_edges(request): + edges_set = set() + edge_type = {} + since = datetime.timedelta(hours=48) + + # Fetch traceroutes + for tr in await store.get_traceroutes(since): + route = decode_payload.decode_payload(PortNum.TRACEROUTE_APP, tr.route) + path = [tr.packet.from_node_id] + list(route.route) # Convert to list + if tr.done: + path.append(tr.packet.to_node_id) + else: + if path[-1] != tr.gateway_node_id: + path.append(tr.gateway_node_id) + + for i in range(len(path) - 1): + edge_pair = (path[i], path[i + 1]) + edges_set.add(edge_pair) + edge_type[edge_pair] = "traceroute" + + # Fetch NeighborInfo packets + for packet in await store.get_packets(portnum=PortNum.NEIGHBORINFO_APP, after=since): + try: + _, neighbor_info = decode_payload.decode(packet) + for node in neighbor_info.neighbors: + edge_pair = (node.node_id, packet.from_node_id) + if edge_pair not in edges_set: + edges_set.add(edge_pair) + edge_type[edge_pair] = "neighbor" + except Exception as e: + print(f"Error decoding NeighborInfo packet: {e}") + + # Prepare edges with type only + edges = [{"from": frm, "to": to, "type": edge_type[(frm, to)]} for frm, to in edges_set] + + return web.json_response({"edges": edges}) # Generic static HTML route