Store & Forward packet type support #97

Closed
opened 2026-06-17 00:09:28 +03:00 by skobkin · 1 comment
Owner

Store & Forward packet type support in the logs.

Currently it's displayed as "Other app packet" with these details:

{
  "portnum_name": "STORE_FORWARD_APP",
  "portnum_value": 65
}
  • add new packet type
  • implement custom details view (like in traceroute) if there's something useful to show
Store & Forward packet type support in the logs. Currently it's displayed as "Other app packet" with these details: ```json { "portnum_name": "STORE_FORWARD_APP", "portnum_value": 65 } ``` - add new packet type - implement custom details view (like in traceroute) if there's something useful to show
skobkin self-assigned this 2026-06-17 00:09:28 +03:00
Collaborator

Two questions to settle before any code: (1) how granular should the packet-type taxonomy be and (2) what does the STORE_FORWARD_APP payload actually carry that the existing traceroute-style details view needs.

On the packet-type side

The current portnum_name = "STORE_FORWARD_APP" fallback to "Other app packet" is just the default unknown-portnum branch. A clean fix is to add a single enum case — PacketType::StoreForward — in the same portnum.ts / packet_type.go file that already enumerates Position, Telemetry, Traceroute, etc. No schema change, no migration; just one more variant. The enum is the load-bearing piece — every downstream surface (log filters, map legend, statistics bins) keys off it.

Where it shows up today Change needed
web/src/types/packet.ts (or the equivalent Go enum in internal/projection/) add StoreForward = 'STORE_FORWARD_APP'
Log filter sidebar one new row in the portnum picker (group it with the routing/protocol set, not the data classes)
Map legend / statistics page if it has a packet-type breakdown, add the new bucket
Search (?packet_type=...) works automatically once the enum is exhaustive

On the custom details view — what to actually show

The S&F module has two distinct modes in Meshtastic firmware (see the StoreAndForward.proto definition in meshtastic/firmware): the server side (history pulls, History messages) and the client side (WantNodeNum, HistoryRequest, Heartbeat). Whether the user actually needs a custom view depends on which direction the captured packets came from.

Payload shape What the details view should show Effort
StoreAndForward.Server.History (binary) list of (node_num, timestamp, payload_portnum) triples — decoded from the varint-length-prefixed repeated History field High — protobuf decode in Go + a tabular renderer in the web UI; worth it only if a real share of captured packets are S&F
StoreAndForward.Client.HistoryRequest / WantNodeNum / Heartbeat request side; one row per request with wanted_dest, last_heard, from_node Low — just JSON fields the protobuf already exposes; render a small two-column details panel
Unknown / future S&F subtypes raw hex preview + a "decode pending — newer firmware" hint Trivial — same shape as the existing "Other app" details view, just under a recognisable heading

My recommendation

  • Land the enum + the log-filter integration in PR 1. Smallest scope, fixes the "other app packet" mislabel on every S&F row, and gives the project a handle for the work below. Don't touch the details view yet.
  • PR 2 = the details view, scoped to the client-side S&F messages only (Heartbeat, HistoryRequest, WantNodeNum). The data is already JSON-friendly; the work is renderer + a couple of unit tests, not protobuf plumbing. This is what the traceroute custom view is closest to in shape — look at PacketDetailsTraceroute.tsx and the corresponding Go decoder to crib the structure.
  • Defer server-side History decoding to a separate issue gated on a concrete share of S&F packets being captured. Decoding the binary repeated History block is the one piece of work that needs a careful protobuf dependency decision, and there's no point paying that cost until we know the data is actually present in the local capture.

One thing worth deciding before PR 1 lands

Should the S&F bucket group with routing packets (Heartbeat, Traceroute, StoreForward) or with data packets (Position, Telemetry, TextMessage)? I'd say routing — the payload is about moving data to/from a store, not about user-visible content — but the log filter sidebar taxonomy might disagree. Worth pinning down because renaming a packet-type group later is a UI-breaking change for anyone with saved filters.

Smallest first PR checklist

  1. Add StoreForward to the packet-type enum.
  2. Add a row to the log-filter picker under whichever group is decided above.
  3. Map STORE_FORWARD_APPStoreForward in the projection layer (single switch case, same file as the existing portnum-name mapping).
  4. Verify the existing "Other app packet" count drops to zero on a capture that contains S&F traffic, and that the search bar accepts the new filter.

Open questions

  1. Routing group vs data group for the new bucket?
  2. Do you have a representative capture with S&F packets I can target the test against, or is the existing test fixture a synthetic one? (Affects whether PR 2's regression test can ship in the same PR or a follow-up.)
  3. Is the StoreAndForward.proto already vendored in web/src/proto/, or does the project rely on the upstream meshtastic/firmware checkout at build time? Affects whether PR 2 needs a buf generate step in CI.
Two questions to settle before any code: **(1) how granular should the packet-type taxonomy be** and **(2) what does the STORE_FORWARD_APP payload actually carry that the existing traceroute-style details view needs**. **On the packet-type side** The current `portnum_name = "STORE_FORWARD_APP"` fallback to `"Other app packet"` is just the default *unknown-portnum* branch. A clean fix is to add a single enum case — `PacketType::StoreForward` — in the same `portnum.ts` / `packet_type.go` file that already enumerates `Position`, `Telemetry`, `Traceroute`, etc. No schema change, no migration; just one more variant. The enum is the load-bearing piece — every downstream surface (log filters, map legend, statistics bins) keys off it. | Where it shows up today | Change needed | |---|---| | `web/src/types/packet.ts` (or the equivalent Go enum in `internal/projection/`) | add `StoreForward = 'STORE_FORWARD_APP'` | | Log filter sidebar | one new row in the portnum picker (group it with the routing/protocol set, not the data classes) | | Map legend / statistics page | if it has a packet-type breakdown, add the new bucket | | Search (`?packet_type=...`) | works automatically once the enum is exhaustive | **On the custom details view — what to actually show** The S&F module has two distinct modes in Meshtastic firmware (see the `StoreAndForward.proto` definition in `meshtastic/firmware`): the **server** side (history pulls, `History` messages) and the **client** side (`WantNodeNum`, `HistoryRequest`, `Heartbeat`). Whether the user actually needs a custom view depends on which direction the captured packets came from. | Payload shape | What the details view should show | Effort | |---|---|---| | `StoreAndForward.Server.History` (binary) | list of `(node_num, timestamp, payload_portnum)` triples — decoded from the `varint`-length-prefixed `repeated History` field | **High** — protobuf decode in Go + a tabular renderer in the web UI; worth it only if a real share of captured packets are S&F | | `StoreAndForward.Client.HistoryRequest` / `WantNodeNum` / `Heartbeat` | request side; one row per request with `wanted_dest`, `last_heard`, `from_node` | **Low** — just JSON fields the protobuf already exposes; render a small two-column details panel | | Unknown / future S&F subtypes | raw hex preview + a "decode pending — newer firmware" hint | **Trivial** — same shape as the existing "Other app" details view, just under a recognisable heading | **My recommendation** - **Land the enum + the log-filter integration in PR 1.** Smallest scope, fixes the "other app packet" mislabel on every S&F row, and gives the project a handle for the work below. Don't touch the details view yet. - **PR 2 = the details view, scoped to the client-side S&F messages only** (Heartbeat, HistoryRequest, WantNodeNum). The data is already JSON-friendly; the work is renderer + a couple of unit tests, not protobuf plumbing. This is what the traceroute custom view is closest to in shape — look at `PacketDetailsTraceroute.tsx` and the corresponding Go decoder to crib the structure. - **Defer server-side `History` decoding** to a separate issue gated on a concrete share of S&F packets being captured. Decoding the binary `repeated History` block is the one piece of work that needs a careful protobuf dependency decision, and there's no point paying that cost until we know the data is actually present in the local capture. **One thing worth deciding before PR 1 lands** Should the S&F bucket group with **routing** packets (Heartbeat, Traceroute, StoreForward) or with **data** packets (Position, Telemetry, TextMessage)? I'd say **routing** — the payload is about *moving data to/from a store*, not about user-visible content — but the log filter sidebar taxonomy might disagree. Worth pinning down because renaming a packet-type group later is a UI-breaking change for anyone with saved filters. **Smallest first PR checklist** 1. Add `StoreForward` to the packet-type enum. 2. Add a row to the log-filter picker under whichever group is decided above. 3. Map `STORE_FORWARD_APP` → `StoreForward` in the projection layer (single switch case, same file as the existing portnum-name mapping). 4. Verify the existing "Other app packet" count drops to zero on a capture that contains S&F traffic, and that the search bar accepts the new filter. **Open questions** 1. Routing group vs data group for the new bucket? 2. Do you have a representative capture with S&F packets I can target the test against, or is the existing test fixture a synthetic one? (Affects whether PR 2's regression test can ship in the same PR or a follow-up.) 3. Is the `StoreAndForward.proto` already vendored in `web/src/proto/`, or does the project rely on the upstream `meshtastic/firmware` checkout at build time? Affects whether PR 2 needs a `buf generate` step in CI.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
skobkin/meshmap-lite#97
No description provided.