feat(ui): add SNR, RSSI, hops info for messages (#963)

* feat(ui): add SNR, RSSI, hops, MQTT info for messages

* review fixes

* zeros for new fields

* Move label under the message

---------

Co-authored-by: Pmmlabs <meshtastic@pmmlabs.ru>
This commit is contained in:
Alexey Stepanov
2025-11-27 15:42:11 -05:00
committed by GitHub
co-authored by Pmmlabs
parent 6a7be99a6a
commit 020e9d6b63
8 changed files with 89 additions and 1 deletions
@@ -216,6 +216,21 @@ export const MessageItem = ({ message }: MessageItemProps) => {
<span className="font-medium text-sm text-slate-900 dark:text-slate-100 truncate mr-1">
{displayName}
</span>
{message.viaMqtt && (
<TooltipProvider delayDuration={300}>
<Tooltip>
<TooltipTrigger asChild>
<span className="text-lg text-slate-800 dark:text-slate-200 -mt-6 h-1">
☁️
</span>
</TooltipTrigger>
<TooltipContent className="bg-slate-800 dark:bg-slate-600 text-white px-4 py-1 rounded text-xs">
MQTT
<TooltipArrow className="fill-slate-800 dark:fill-slate-600" />
</TooltipContent>
</Tooltip>
</TooltipProvider>
)}
{messageDate && (
<time
dateTime={messageDate.toISOString()}
@@ -245,6 +260,16 @@ export const MessageItem = ({ message }: MessageItemProps) => {
{message.message}
</div>
)}
{(message.hops && (
<div className="text-xs text-slate-500 dark:text-slate-200 whitespace-pre-wrap break-words">
{t("hops.text", { value: message.hops })}
</div>
)) ||
(message.rxSnr && message.rxRssi && (
<div className="text-xs text-slate-500 dark:text-slate-200 whitespace-pre-wrap break-words">
SNR: {message.rxSnr}, RSSI: {message.rxRssi}
</div>
))}
</div>
</div>
{/* Actions Menu Placeholder */}
@@ -11,6 +11,10 @@ class PacketToMessageDTO {
state: MessageState;
message: string;
type: MessageType;
hops: number;
rxRssi: number;
rxSnr: number;
viaMqtt: boolean;
constructor(data: Types.PacketMetadata<string>, nodeNum: number) {
this.channel = data.channel;
@@ -36,6 +40,10 @@ class PacketToMessageDTO {
);
}
this.date = dateTimestamp;
this.hops = data.hops;
this.rxRssi = data.rxRssi;
this.rxSnr = data.rxSnr;
this.viaMqtt = data.viaMqtt;
}
toMessage(): Message {
@@ -48,6 +56,10 @@ class PacketToMessageDTO {
state: this.state,
message: this.message,
type: this.type,
hops: this.hops,
rxRssi: this.rxRssi,
rxSnr: this.rxSnr,
viaMqtt: this.viaMqtt,
};
}
}
@@ -53,6 +53,10 @@ const directMessageToOther1: Message = {
messageId: 101,
state: MessageState.Waiting,
message: "Hello other 1 from me",
rxSnr: 1,
rxRssi: 2,
viaMqtt: false,
hops: 3,
};
const directMessageFromOther1: Message = {
@@ -64,6 +68,10 @@ const directMessageFromOther1: Message = {
messageId: 102,
state: MessageState.Waiting,
message: "Hello me from other 1",
rxSnr: 1,
rxRssi: 2,
viaMqtt: false,
hops: 3,
};
const directMessageToOther2: Message = {
@@ -75,6 +83,10 @@ const directMessageToOther2: Message = {
messageId: 103,
state: MessageState.Waiting,
message: "Hello other 2 from me",
rxSnr: 1,
rxRssi: 2,
viaMqtt: false,
hops: 3,
};
const broadcastMessage1: Message = {
@@ -86,6 +98,10 @@ const broadcastMessage1: Message = {
messageId: 201,
state: MessageState.Waiting,
message: "Broadcast message 1",
rxSnr: 1,
rxRssi: 2,
viaMqtt: false,
hops: 3,
};
const broadcastMessage2: Message = {
@@ -97,6 +113,10 @@ const broadcastMessage2: Message = {
messageId: 202,
state: MessageState.Waiting,
message: "Broadcast message 2",
rxSnr: 1,
rxRssi: 2,
viaMqtt: false,
hops: 3,
};
describe("MessageStore persistence & rehydrate", () => {
@@ -764,6 +784,10 @@ describe("MessageStore persistence & rehydrate", () => {
messageId: i,
state: MessageState.Waiting,
message: `m${i}`,
rxSnr: 1,
rxRssi: 2,
viaMqtt: false,
hops: 3,
});
}
@@ -15,6 +15,10 @@ interface MessageBase {
messageId: number;
state: MessageState;
message: string;
rxSnr: number;
rxRssi: number;
viaMqtt: boolean;
hops: number;
}
interface GenericMessage<T extends MessageType> extends MessageBase {