Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Traceroute Feature #211

Merged
merged 26 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
6e14542
Add button to Message page to send a traceroute to a node.
fifieldt May 26, 2024
a7237bc
Revert "Support floats in number fields"
fifieldt May 26, 2024
82c1d3e
Support floats in number fields
chrisdrackett Apr 30, 2024
97b9570
Revert "Add button to Message page to send a traceroute to a node."
fifieldt May 26, 2024
1458497
Add button to Message page to send a traceroute to a node.
fifieldt May 26, 2024
390b168
Subscribe to and store traceroutePackets
fifieldt May 26, 2024
8626399
Add Toast lib to Messages page
fifieldt May 26, 2024
be31176
Add basic traceroute display
fifieldt May 26, 2024
056a194
Add formatting logic for multi-hop traceroutes
fifieldt May 27, 2024
f16cce9
Fix case where intermediary node in traceroute is unknown.
fifieldt May 27, 2024
a728b84
Don't show traceroute button on Channels
fifieldt May 27, 2024
0f89e04
Only show traceroutes on node direct message pageso
fifieldt May 27, 2024
7b6b8da
Fix build errors
fifieldt May 27, 2024
54c9834
Fix type Number - number
fifieldt May 27, 2024
e825a73
Fix build errors
fifieldt May 27, 2024
569c2da
Fix traceroute ordering for multi-hop traceroutes
fifieldt May 27, 2024
452f258
Fix incorrect use of operator build error.
fifieldt May 27, 2024
daff97a
Fix double double arrow on unknown nodes in multi-hop traceroutes
fifieldt May 27, 2024
bcac95e
Merge remote-tracking branch 'origin/master' into traceroute
Hunter275 Jun 16, 2024
e9a681a
Add tr column and Toast when starting tr
Hunter275 Jun 16, 2024
026256a
Merge branch 'meshtastic:master' into master
fifieldt Jun 17, 2024
9e04c1f
Merge branch 'master' into traceroute
fifieldt Jun 21, 2024
bcebfd2
Merge remote-tracking branch 'meshtastic/master' into traceroute
Hunter275 Jul 4, 2024
f3fbe75
Merge branch 'meshtastic:master' into traceroute
Hunter275 Jul 4, 2024
0955bbe
Merge remote-tracking branch 'hunter275/traceroute' into traceroute
Hunter275 Jul 4, 2024
d42e8c1
minor changes and biome fixes
Hunter275 Jul 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 45 additions & 19 deletions src/components/PageComponents/Messages/ChannelChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,42 +5,68 @@ import {
} from "@app/core/stores/deviceStore.js";
import { Message } from "@components/PageComponents/Messages/Message.js";
import { MessageInput } from "@components/PageComponents/Messages/MessageInput.js";
import type { Types } from "@meshtastic/js";
import { TraceRoute } from "@components/PageComponents/Messages/TraceRoute.js";
import type { Protobuf, Types } from "@meshtastic/js";
import { InboxIcon } from "lucide-react";

export interface ChannelChatProps {
messages?: MessageWithState[];
channel: Types.ChannelNumber;
to: Types.Destination;
traceroutes?: Types.PacketMetadata<Protobuf.Mesh.RouteDiscovery>[];
}

export const ChannelChat = ({
messages,
channel,
to,
traceroutes,
}: ChannelChatProps): JSX.Element => {
const { nodes } = useDevice();

return (
<div className="flex flex-grow flex-col">
<div className="flex flex-grow flex-col">
{messages ? (
messages.map((message, index) => (
<Message
key={message.id}
message={message}
lastMsgSameUser={
index === 0 ? false : messages[index - 1].from === message.from
}
sender={nodes.get(message.from)}
/>
))
) : (
<div className="m-auto">
<InboxIcon className="m-auto" />
<Subtle>No Messages</Subtle>
</div>
)}
<div className="flex flex-grow">
<div className="flex flex-grow flex-col">
{messages ? (
messages.map((message, index) => (
<Message
key={message.id}
message={message}
lastMsgSameUser={
index === 0
? false
: messages[index - 1].from === message.from
}
sender={nodes.get(message.from)}
/>
))
) : (
<div className="m-auto">
<InboxIcon className="m-auto" />
<Subtle>No Messages</Subtle>
</div>
)}
</div>
<div
className={`flex flex-grow flex-col border-slate-400 border-l ${traceroutes === undefined ? "hidden" : ""}`}
>
{to === "broadcast" ? null : traceroutes ? (
traceroutes.map((traceroute, index) => (
<TraceRoute
key={traceroute.id}
from={nodes.get(traceroute.from)}
to={nodes.get(traceroute.to)}
route={traceroute.data.route}
/>
))
) : (
<div className="m-auto">
<InboxIcon className="m-auto" />
<Subtle>No Traceroutes</Subtle>
</div>
)}
</div>
</div>
<div className="p-3">
<MessageInput to={to} channel={channel} />
Expand Down
32 changes: 32 additions & 0 deletions src/components/PageComponents/Messages/TraceRoute.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useDevice } from "@app/core/stores/deviceStore.js";
import type { Protobuf } from "@meshtastic/js";

export interface TraceRouteProps {
from?: Protobuf.Mesh.NodeInfo;
to?: Protobuf.Mesh.NodeInfo;
route: Array<number>;
}

export const TraceRoute = ({
from,
to,
route,
}: TraceRouteProps): JSX.Element => {
const { nodes } = useDevice();

return route.length === 0 ? (
<div className="ml-5 flex">
<span className="ml-4 border-l-2 border-l-backgroundPrimary pl-2 text-textPrimary">
{to?.user?.longName}{from?.user?.longName}
</span>
</div>
) : (
<div className="ml-5 flex">
<span className="ml-4 border-l-2 border-l-backgroundPrimary pl-2 text-textPrimary">
{to?.user?.longName}
{route.map((hop) => `${nodes.get(hop)?.user?.longName ?? "Unknown"}↔`)}
{from?.user?.longName}
</span>
</div>
);
};
29 changes: 29 additions & 0 deletions src/core/stores/deviceStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ export interface Device {
direct: Map<number, MessageWithState[]>;
broadcast: Map<Types.ChannelNumber, MessageWithState[]>;
};
traceroutes: Map<
number,
Types.PacketMetadata<Protobuf.Mesh.RouteDiscovery>[]
>;
connection?: Types.ConnectionType;
activePage: Page;
activeNode: number;
Expand Down Expand Up @@ -75,6 +79,9 @@ export interface Device {
addPosition: (position: Types.PacketMetadata<Protobuf.Mesh.Position>) => void;
addConnection: (connection: Types.ConnectionType) => void;
addMessage: (message: MessageWithState) => void;
addTraceRoute: (
traceroute: Types.PacketMetadata<Protobuf.Mesh.RouteDiscovery>,
) => void;
addMetadata: (from: number, metadata: Protobuf.Mesh.DeviceMetadata) => void;
removeNode: (nodeNum: number) => void;
setMessageState: (
Expand Down Expand Up @@ -122,6 +129,7 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
direct: new Map(),
broadcast: new Map(),
},
traceroutes: new Map(),
connection: undefined,
activePage: "messages",
activeNode: 0,
Expand Down Expand Up @@ -487,6 +495,7 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
}),
);
},

addMetadata: (from, metadata) => {
set(
produce<DeviceState>((draft) => {
Expand All @@ -498,6 +507,26 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
}),
);
},
addTraceRoute: (traceroute) => {
set(
produce<DeviceState>((draft) => {
console.log("addTraceRoute called");
console.log(traceroute);
const device = draft.devices.get(id);
if (!device) {
return;
}

const nodetraceroutes = device.traceroutes.get(traceroute.from);
if (nodetraceroutes) {
nodetraceroutes.push(traceroute);
device.traceroutes.set(traceroute.from, nodetraceroutes);
} else {
device.traceroutes.set(traceroute.from, [traceroute]);
}
}),
);
},
removeNode: (nodeNum) => {
set(
produce<DeviceState>((draft) => {
Expand Down
6 changes: 6 additions & 0 deletions src/core/subscriptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ export const subscribeAll = (
});
});

connection.events.onTraceRoutePacket.subscribe((traceRoutePacket) => {
device.addTraceRoute({
...traceRoutePacket,
});
});

connection.events.onPendingSettingsChange.subscribe((state) => {
device.setPendingSettingsChanges(state);
});
Expand Down
29 changes: 27 additions & 2 deletions src/pages/Messages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ import { PageLayout } from "@components/PageLayout.js";
import { Sidebar } from "@components/Sidebar.js";
import { SidebarSection } from "@components/UI/Sidebar/SidebarSection.js";
import { SidebarButton } from "@components/UI/Sidebar/sidebarButton.js";
import { useToast } from "@core/hooks/useToast.js";
import { useDevice } from "@core/stores/deviceStore.js";
import { Hashicon } from "@emeraldpay/hashicon-react";
import { Protobuf, Types } from "@meshtastic/js";
import { getChannelName } from "@pages/Channels.js";
import { HashIcon } from "lucide-react";
import { HashIcon, WaypointsIcon } from "lucide-react";
import { useState } from "react";

export const MessagesPage = (): JSX.Element => {
const { channels, nodes, hardware, messages } = useDevice();
const { channels, nodes, hardware, messages, traceroutes, connection } =
useDevice();
const [chatType, setChatType] =
useState<Types.PacketDestination>("broadcast");
const [activeChat, setActiveChat] = useState<number>(
Expand All @@ -25,6 +27,7 @@ export const MessagesPage = (): JSX.Element => {
(ch) => ch.role !== Protobuf.Channel.Channel_Role.DISABLED,
);
const currentChannel = channels.get(activeChat);
const { toast } = useToast();

return (
<>
Expand Down Expand Up @@ -72,6 +75,27 @@ export const MessagesPage = (): JSX.Element => {
? nodes.get(activeChat)?.user?.longName ?? "Unknown"
: "Loading..."
}`}
actions={
chatType === "direct"
? [
{
icon: WaypointsIcon,
async onClick() {
const targetNode = nodes.get(activeChat)?.num;
if (targetNode === undefined) return;
toast({
title: "Sending Traceroute, please wait...",
});
await connection?.traceRoute(targetNode).then(() =>
toast({
title: "Traceroute sent.",
}),
);
},
},
]
: []
}
>
{allChannels.map(
(channel) =>
Expand All @@ -92,6 +116,7 @@ export const MessagesPage = (): JSX.Element => {
to={activeChat}
messages={messages.direct.get(node.num)}
channel={Types.ChannelNumber.Primary}
traceroutes={traceroutes.get(node.num)}
/>
),
)}
Expand Down