Files
roro9stack/site/content/guide/lora-scanner.md
T
twislaandClaude Opus 5.5 305818466f
CI / build (pull_request) Successful in 2m19s
Site / build (pull_request) Successful in 9s
LoRa Scanner: MeshCore by default, and its public channel read
The MeshCore preset is the default for a new device, in the Settings and
in the radio before the Scanner is opened. The setting now accepts it:
it only took the 7 Meshtastic presets, so MeshCore picked in the App was
not saved.

Messages on MeshCore's public channel are decrypted with the channel's
published key (AES-128, checked with 2 bytes of HMAC-SHA256): the row
shows who says they sent it and the start of the text, the details the
sender, the time and the whole text. Other channels and private messages
stay encrypted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0162FokPdvY2KsS4NBfwyWPk
2026-10-09 22:19:14 +02:00

5.0 KiB

+++ title = "LoRa Scanner" description = "Listen to the radio: every packet it hears, a survey of signal strength from 863 to 870 MHz, and captures for Wireshark. It only listens." weight = 2 [extra] tag = "LoRa Scanner" screens = ["sniffer.png", "sweep.png"] +++

The Scanner uses the Cap LoRa-1262. It never transmits: it listens and shows.

Sniffer

The first view lists what the radio hears, newest first: the time, the RSSI (signal strength, in dBm) and the SNR (signal over noise, in dB). For a Meshtastic packet it also shows the sender and the receiver (the last four hex digits of their numbers) and the number of hops.

For a MeshCore packet it shows what the packet is, who it concerns and how many repeaters are in its path:

Row Is
adv Brussels-R1 2h A node saying who it is, by its name, heard through 2 repeaters
txt a3>7f A private message from the node whose key starts with a3 to the one starting with 7f (req, rsp and path look the same)
Alice: hello 1h A message on the public channel, read: who says they sent it, and the start of what it says
chan #5c 1h A message on another channel, still encrypted; #5c is the channel's byte
who's there? Someone nearby searching for nodes (repeaters, usually)
here 18a6 A node answering that search; 18a6 starts its key
ack, anon, trace, ctl An acknowledgement, a login, a trace, other control packets
Key Does
Enter The details of a packet: what is never encrypted (below), and a hex dump
p Picks what to listen to: MeshCore (the default), or one of the 7 Meshtastic presets allowed in EU868
c Starts or stops a capture
Tab Switches to the Sweep

The Scanner shows the header and the bytes. Meshtastic and MeshCore both encrypt the message itself, and the Scanner reads only one kind: what is said on MeshCore's public channel, whose key is published.

One network at a time. The radio listens on one frequency with one setting, and the two networks share neither: on a Meshtastic preset no MeshCore packet is heard, and the other way round.

MeshCore

The MeshCore preset is the setting its networks use in Europe, "EU/UK (Narrow)": 869.618 MHz, 62.5 kHz wide, SF8, coding rate 4/8. A network set up differently needs lora custom in the Shell.

Enter on a MeshCore packet shows:

  • what it is and how it travels: flood (every repeater passes it on, and adds itself to the path) or direct (it carries the route to follow);
  • the path, one repeater a hop, each named by the first byte of its key;
  • for an advert, which is signed and never encrypted: the node's name, its kind (chat node, repeater, room server, sensor), the start of its key, and its position if it gives one;
  • for a search and its answers, also in clear: what kind of node is wanted; and in an answer the node's kind, the start of its key, and how well it heard the search;
  • for a message on the public channel: the name the sender gives, when the sender's clock says it was sent (UTC), and the text;
  • for any other message: the first byte of the sender's and the receiver's keys, or the channel's byte, and how many bytes are encrypted.

The public channel is the one every MeshCore node starts with, and its key is the same everywhere, so anyone listening can read it. Private messages and other channels stay encrypted. The sender's name is part of the message and is not signed: anyone can write any name. Letters outside plain ASCII (accents, emoji) show as ?.

A byte is all a packet says about who it is from: two nodes can share it. The name comes only with a node's advert, which a node sends now and then, so a quiet network can take a while to show its names.

Capture

A capture records packets into a pcap file with LoRaTap headers in /captures/lora/ on the SD card, to open in Wireshark. It keeps recording with the App closed (the Status Bar shows CAP); the radio sleeps when the App is not open and no capture is running. Captures are never deleted unless you ask, in the Storage App, which can also show a pcap's packets on the device.

Sweep

Tab switches to the Sweep: the signal strength across 863 to 870 MHz in 100 kHz steps, drawn as bars with a mark at each peak, and a waterfall under them. The frequency the Sniffer listens on is marked. The Sniffer is paused during a Sweep and picks up where it was. The Status Bar shows SW.

The GNSS receiver raises the noise

The GNSS receiver on the same Cap makes the radio's noise floor about 8 dB worse while it runs. Settings → Pause GNSS for LoRa (off by default) puts the receiver on standby while the radio listens, except while a Track is being recorded.

The keys, as the device lists them

What Fn + h shows on these screens. These tables are generated from the firmware's own lists, so they are always the current ones.

{{ keys(scopes=["lora", "lora-packet", "lora-presets", "lora-sweep"]) }}