diff --git a/meshview/models.py b/meshview/models.py index be6992a..ab62e2e 100644 --- a/meshview/models.py +++ b/meshview/models.py @@ -17,6 +17,8 @@ class Node(Base): long_name: Mapped[str] short_name: Mapped[str] hw_model: Mapped[str] + last_lat: Mapped[int] = mapped_column(BigInteger, nullable=True) + last_long: Mapped[int] = mapped_column(BigInteger, nullable=True) class Packet(Base): diff --git a/meshview/store.py b/meshview/store.py index fe5d389..fc1dca0 100644 --- a/meshview/store.py +++ b/meshview/store.py @@ -87,6 +87,18 @@ async def process_envelope(topic, env): ) session.add(node) + if env.packet.decoded.portnum == PortNum.POSITION_APP: + position = decode_payload.decode_payload( + PortNum.POSITION_APP, env.packet.decoded.payload + ) + if position.latitude_i and position.longitude_i: + from_node_id = getattr(env.packet, 'from') + node = (await session.execute(select(Node).where(Node.node_id == from_node_id))).scalar_one_or_none() + if node: + node.last_lat = position.latitude_i + node.last_long = position.longitude_i + session.add(node) + await session.commit() if new_packet: await packet.awaitable_attrs.to_node @@ -129,7 +141,7 @@ async def get_packets(node_id=None, portnum=None): return result.scalars() -async def get_packets_from(node_id=None, portnum=None): +async def get_packets_from(node_id=None, portnum=None, limit=500): async with database.async_session() as session: q = select(Packet) @@ -139,7 +151,7 @@ async def get_packets_from(node_id=None, portnum=None): ) if portnum: q = q.where(Packet.portnum == portnum) - result = await session.execute(q.limit(500).order_by(Packet.import_time.desc())) + result = await session.execute(q.limit(limit).order_by(Packet.import_time.desc())) return result.scalars() diff --git a/meshview/templates/node.html b/meshview/templates/node.html index d73edc3..d44040d 100644 --- a/meshview/templates/node.html +++ b/meshview/templates/node.html @@ -77,6 +77,10 @@ }).addTo(map); L.polyline(trace).addTo(map); L.marker(trace[0]).addTo(map); + {% for n in neighbors %} + L.circleMarker({{n | tojson}}).addTo(map); + L.polyline([trace[0], {{n | tojson}}], {color: 'red'}).addTo(map); + {% endfor %} {% endif %} diff --git a/meshview/templates/packet.html b/meshview/templates/packet.html index e20c0df..ede0b53 100644 --- a/meshview/templates/packet.html +++ b/meshview/templates/packet.html @@ -44,7 +44,6 @@
{{packet.payload}}
-
diff --git a/meshview/web.py b/meshview/web.py
index d2c3103..04b513b 100644
--- a/meshview/web.py
+++ b/meshview/web.py
@@ -35,6 +35,23 @@ async def build_trace(node_id):
return trace
+async def build_neighbors(node_id):
+ packet = (await store.get_packets_from(node_id, PortNum.NEIGHBORINFO_APP, 1)).first()
+ if not packet:
+ return []
+ _, payload = decode_payload.decode(packet)
+ neighbors = []
+ async with asyncio.TaskGroup() as tg:
+ for n in payload.neighbors:
+ neighbors.append(tg.create_task(store.get_node(n.node_id)))
+
+ result = []
+ for node in [n.result() for n in neighbors]:
+ if node.last_lat and node.last_long:
+ result.append((node.last_lat * 1e-7, node.last_long * 1e-7))
+ return result
+
+
def node_id_to_hex(node_id):
if node_id == 4294967295:
return "^all"
@@ -176,6 +193,7 @@ async def node_search(request):
node_task = tg.create_task(store.get_node(node_id))
packets_task = tg.create_task(store.get_packets(node_id, portnum=portnum))
trace_task = tg.create_task(build_trace(node_id))
+ neighbors_task = tg.create_task(build_neighbors(node_id))
else:
loop = asyncio.get_running_loop()
node_task = loop.create_future()
@@ -184,6 +202,8 @@ async def node_search(request):
packets_task.set_result(())
trace_task = loop.create_future()
trace_task.set_result([])
+ neighbors_task = loop.create_future()
+ neighbors_task.set_result([])
node_options_task = tg.create_task(store.get_fuzzy_nodes(raw_node_id))
@@ -201,6 +221,7 @@ async def node_search(request):
node_options=options,
portnum=portnum,
trace=trace_task.result(),
+ neighbors=neighbors_task.result(),
),
content_type="text/html",
)