mirror of
https://github.com/dpup/meshstream.git
synced 2026-03-28 17:42:37 +01:00
Traceroute rendering
This commit is contained in:
@@ -26,9 +26,11 @@ format: |
|
||||
{{- if $data.textMessage }}
|
||||
{{ "Text:" | dim }} {{ $data.textMessage }}
|
||||
{{- else if $data.mapReport }}
|
||||
{{ "Map Report:" | dim }} {{ $data.mapReport | table }}
|
||||
{{ "Map Report:" | dim }}
|
||||
{{ $data.mapReport | table }}
|
||||
{{- else if $data.routeDiscovery }}
|
||||
{{ "Route Discovery:" | dim }} {{ $data.routeDiscovery | table }}
|
||||
{{ "Route Discovery:" | dim }}
|
||||
{{ $data.routeDiscovery | table }}
|
||||
{{- else if $data.position }}
|
||||
{{ "Position:" | dim }} Lat: {{ $data.position.latitudeI | mult 0.0000001 }}, Long: {{ $data.position.longitudeI | mult 0.0000001 }}
|
||||
{{- else if $data.nodeInfo }}
|
||||
|
||||
@@ -7,6 +7,7 @@ import { TelemetryPacket } from "./TelemetryPacket";
|
||||
import { ErrorPacket } from "./ErrorPacket";
|
||||
import { WaypointPacket } from "./WaypointPacket";
|
||||
import { MapReportPacket } from "./MapReportPacket";
|
||||
import { TraceroutePacket } from "./TraceroutePacket";
|
||||
import { GenericPacket } from "./GenericPacket";
|
||||
|
||||
interface PacketRendererProps {
|
||||
@@ -46,6 +47,9 @@ export const PacketRenderer: React.FC<PacketRendererProps> = ({ packet }) => {
|
||||
case PortNum.MAP_REPORT_APP:
|
||||
return <MapReportPacket packet={packet} />;
|
||||
|
||||
case PortNum.TRACEROUTE_APP:
|
||||
return <TraceroutePacket packet={packet} />;
|
||||
|
||||
default:
|
||||
return <GenericPacket packet={packet} />;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ export const PositionPacket: React.FC<PositionPacketProps> = ({ packet }) => {
|
||||
icon={<MapPin />}
|
||||
iconBgColor="bg-emerald-500"
|
||||
label="Position"
|
||||
backgroundColor="bg-emerald-950/5"
|
||||
>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
|
||||
89
web/src/components/packets/TraceroutePacket.tsx
Normal file
89
web/src/components/packets/TraceroutePacket.tsx
Normal file
@@ -0,0 +1,89 @@
|
||||
import React from "react";
|
||||
import { Packet } from "../../lib/types";
|
||||
import { PacketCard } from "./PacketCard";
|
||||
import { RouteIcon } from "lucide-react";
|
||||
import { Link } from "@tanstack/react-router";
|
||||
|
||||
interface TraceroutePacketProps {
|
||||
packet: Packet;
|
||||
}
|
||||
|
||||
export const TraceroutePacket: React.FC<TraceroutePacketProps> = ({ packet }) => {
|
||||
const { data } = packet;
|
||||
const routeDiscovery = data.routeDiscovery;
|
||||
|
||||
if (!routeDiscovery) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Convert a nodenum to hex format for display and linking
|
||||
const formatNodeId = (nodeNum: number) => {
|
||||
return nodeNum.toString(16).toLowerCase();
|
||||
};
|
||||
|
||||
// Renders a node hop with SNR info if available
|
||||
const renderHop = (nodeNum: number, index: number, snrValues?: number[]) => {
|
||||
const nodeHex = formatNodeId(nodeNum);
|
||||
const snr = snrValues && snrValues[index];
|
||||
|
||||
return (
|
||||
<React.Fragment key={`hop-${index}`}>
|
||||
<Link
|
||||
to="/node/$nodeId"
|
||||
params={{ nodeId: nodeHex }}
|
||||
className="text-blue-400 hover:underline"
|
||||
>
|
||||
!{nodeHex}
|
||||
</Link>
|
||||
{snr !== undefined && (
|
||||
<span className="text-neutral-400 text-xs ml-1">
|
||||
({(snr / 4).toFixed(1)} dB)
|
||||
</span>
|
||||
)}
|
||||
{index < (routeDiscovery.route?.length || 0) - 1 && (
|
||||
<span className="mx-2 text-neutral-500">→</span>
|
||||
)}
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<PacketCard
|
||||
packet={packet}
|
||||
icon={<RouteIcon />}
|
||||
iconBgColor="bg-purple-700"
|
||||
label="Traceroute"
|
||||
>
|
||||
<div className="space-y-6">
|
||||
{routeDiscovery.route && routeDiscovery.route.length > 0 && (
|
||||
<div>
|
||||
<h3 className="text-neutral-300 font-semibold mb-2">Route to destination:</h3>
|
||||
<div className="flex flex-wrap items-center text-sm">
|
||||
{routeDiscovery.route.map((nodeNum, index) =>
|
||||
renderHop(nodeNum, index, routeDiscovery.snrTowards)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{routeDiscovery.routeBack && routeDiscovery.routeBack.length > 0 && (
|
||||
<div>
|
||||
<h3 className="text-neutral-300 font-semibold mb-2">Return route:</h3>
|
||||
<div className="flex flex-wrap items-center text-sm">
|
||||
{routeDiscovery.routeBack.map((nodeNum, index) =>
|
||||
renderHop(nodeNum, index, routeDiscovery.snrBack)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{(!routeDiscovery.route || routeDiscovery.route.length === 0) &&
|
||||
(!routeDiscovery.routeBack || routeDiscovery.routeBack.length === 0) && (
|
||||
<div className="text-neutral-400">
|
||||
No route information available.
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</PacketCard>
|
||||
);
|
||||
};
|
||||
@@ -2,6 +2,9 @@ export * from './TextMessagePacket';
|
||||
export * from './PositionPacket';
|
||||
export * from './NodeInfoPacket';
|
||||
export * from './TelemetryPacket';
|
||||
export * from './WaypointPacket';
|
||||
export * from './MapReportPacket';
|
||||
export * from './TraceroutePacket';
|
||||
export * from './GenericPacket';
|
||||
export * from './ErrorPacket';
|
||||
export * from './PacketRenderer';
|
||||
Reference in New Issue
Block a user