From a6d82121433350b9634669f04043237deb0cff97 Mon Sep 17 00:00:00 2001 From: Jason Michalski Date: Tue, 18 Jun 2024 00:34:40 -0700 Subject: [PATCH] Add sserver generated neighbor info. --- meshview/models.py | 1 + meshview/store.py | 24 +++++++++++++++++++++++- meshview/templates/packet_details.html | 2 ++ meshview/web.py | 21 ++++++++++++++++++--- 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/meshview/models.py b/meshview/models.py index cdbc9b9..63941a1 100644 --- a/meshview/models.py +++ b/meshview/models.py @@ -47,6 +47,7 @@ class PacketSeen(Base): ) rx_time: Mapped[int] = mapped_column(BigInteger, primary_key=True) hop_limit: Mapped[int] + hop_start: Mapped[int] = mapped_column(nullable=True) channel: Mapped[str] rx_snr: Mapped[float] = mapped_column(nullable=True) rx_rssi: Mapped[int] = mapped_column(nullable=True) diff --git a/meshview/store.py b/meshview/store.py index 2d2db8a..4219e96 100644 --- a/meshview/store.py +++ b/meshview/store.py @@ -1,6 +1,7 @@ import datetime from sqlalchemy import select, func +from sqlalchemy.orm import lazyload from meshtastic.config_pb2 import Config from meshtastic.portnums_pb2 import PortNum @@ -48,6 +49,7 @@ async def process_envelope(topic, env): rx_snr=env.packet.rx_snr, rx_rssi=env.packet.rx_rssi, hop_limit=env.packet.hop_limit, + hop_start=env.packet.hop_start, topic=topic, import_time=datetime.datetime.utcnow(), ) @@ -110,7 +112,9 @@ async def process_envelope(topic, env): if env.packet.decoded.want_response: packet_id = env.packet.id else: - packet_id = env.packet.decoded.request_id + result = await session.execute(select(Packet).where(Packet.id == env.packet.decoded.request_id)) + if result.scalar_one_or_none(): + packet_id = env.packet.decoded.request_id session.add(Traceroute( packet_id=packet_id, route=env.packet.decoded.payload, @@ -234,3 +238,21 @@ async def get_traceroutes(since): .order_by(Traceroute.import_time) ) return result.scalars() + + +async def get_mqtt_neighbors(since): + async with database.async_session() as session: + result = await session.execute(select(PacketSeen, Packet) + .join(Packet) + .where( + (PacketSeen.hop_limit == PacketSeen.hop_start) + & (PacketSeen.hop_start != 0) + & (PacketSeen.import_time > (datetime.datetime.utcnow() - since)) + ) + .options( + lazyload(Packet.from_node), + lazyload(Packet.to_node), + ) + ) + return result + diff --git a/meshview/templates/packet_details.html b/meshview/templates/packet_details.html index 2a76dcd..5ce85ed 100644 --- a/meshview/templates/packet_details.html +++ b/meshview/templates/packet_details.html @@ -16,6 +16,8 @@
{{seen.rx_time|format_timestamp}}
hop_limit
{{seen.hop_limit}}
+
hop_start
+
{{seen.hop_start}}
channel
{{seen.channel}}
rx_snr
diff --git a/meshview/web.py b/meshview/web.py index 9c829fb..9438966 100644 --- a/meshview/web.py +++ b/meshview/web.py @@ -536,6 +536,10 @@ async def graph_traceroute(request): traceroutes = list(await store.get_traceroute(packet_id)) packet = await store.get_packet(packet_id) + if not packet: + return web.Response( + status=404, + ) node_ids = set() for tr in traceroutes: @@ -632,12 +636,13 @@ async def graph_network(request): root = request.query.get("root") depth = int(request.query.get("depth", 5)) hours = int(request.query.get("hours", 24)) + since = datetime.timedelta(hours=hours) nodes = {} node_ids = set() traceroutes = [] - for tr in await store.get_traceroutes(datetime.timedelta(hours=hours)): + for tr in await store.get_traceroutes(since): node_ids.add(tr.gateway_node_id) node_ids.add(tr.packet.from_node_id) node_ids.add(tr.packet.to_node_id) @@ -658,9 +663,17 @@ async def graph_network(request): edge_type = {} used_nodes = set() + for ps, p in await store.get_mqtt_neighbors(since): + node_ids.add(ps.node_id) + node_ids.add(p.from_node_id) + used_nodes.add(ps.node_id) + used_nodes.add(p.from_node_id) + edges[(p.from_node_id, ps.node_id)] += 1 + edge_type[(p.from_node_id, ps.node_id)] = 'sni' + for packet in await store.get_packets( portnum=PortNum.NEIGHBORINFO_APP, - since=datetime.timedelta(hours=hours) + since=since, ): _, neighbor_info = decode_payload.decode(packet) node_ids.add(packet.from_node_id) @@ -750,8 +763,10 @@ async def graph_network(request): for (src, dest), edge_count in edges.items(): size = max(size_ratio * edge_count, .25) arrowsize = max(size_ratio * edge_count, .5) - if edge_type[(src, dest)] == 'ni': + if edge_type[(src, dest)] in ('ni'): color = '#FF0000' + elif edge_type[(src, dest)] in ('sni'): + color = '#00FF00' else: color = '#000000' edge_dir = "forward"