Automatic range tests for your Meshtastic network
A small bot that sends a few messages on a channel at random moments, listens for everyone else's, and writes a report of who was heard, over how many hops, with what signal β so you don't have to babysit a laptop to test coverage.
Not affiliated with or endorsed by the Meshtastic project. "Meshtastic" is a trademark of Meshtastic LLC, used here only to say what this bot is compatible with.
What it does
π€ Sends, on a schedule
A few short messages on your test channel, at random moments, so a whole community doesn't transmit at once.
π Listens the whole time
One long-lived connection to the radio hears everyone else running the same format, recording hops, SNR, RSSI, and whether a copy came via MQTT.
π Writes a report
A readable text file and a JSON line per session β delivery rate, duplicates, relay hints, and any connection outages during the test.
π€ Runs unattended
Docker image for amd64, arm64 and arm/v7 (Raspberry Pi included). Repeats itself every week, recovers from radio reboots and WiFi drops on its own.
ποΈ Several tests, one radio
Run more than one scheduled test: one bot per test, each on its own schedule, all through the same MeshMonitor. How to set it up.
βοΈ Sends it to Telegram
Optional: each session's text report is also sent to a Telegram chat, via your own bot. Set a bot token and a chat id, and the report reaches your phone when the test ends.
What a report looks like
=== 2026-09-26 21:41 === Reporter: AB12 (!deadbeef) - Place: City - Sent: 3/3 ACK | CD34 | 0 | Villatown | RF ACK | EF56 | 1-2 | Valley | RF
One short, paste-friendly line per station heard. Each line carries the prefix,
the station's name, hop range, the place it reported, and RF or MQTT. The matching
report.jsonl line for the same session has the fuller numbers too:
- π Delivery rate β how many of its messages arrived, and duplicate readings of the same one.
- πΆ SNR and RSSI β best and worst seen during the session.
- π RF or MQTT β a copy that only arrived via MQTT is flagged and never counted as RF reach.
- π A relay hint β which node likely repeated it, when the packet made more than one hop.
report.jsonl is meant for a server to pick up later β reports stay
local for now, but a future version may let you opt in to submitting them
somewhere, for network-wide coverage stats across everyone running the bot.
Get started
New to this, or don't know what Docker is? Follow Start here.
Otherwise, on Linux, macOS or a Raspberry Pi, one command, if you already have Docker:
curl -fsSL https://raw.githubusercontent.com/cunhaax/mesh-test-bot/master/install/install.sh | sh
It asks a few questions β how the bot should reach the radio (directly, through an existing MeshMonitor, or by setting one up right here), the test channel, your city, the message prefixes, and whether to run once now or on a recurring schedule, and the session length, number of messages and report window β press Enter for any default. Then it prints the commands that start the bot(s): it never starts anything by itself. No WiFi on your radio (USB or Bluetooth only, like the RAK4631)? See radios without WiFi. See the README for installing from source or without Docker, and the MeshMonitor guide for the details of that path.
π Size your test
LoRa has no real collision avoidance, so many stations sharing a short window can flood the channel β the very congestion a range test is meant to measure. Check how much of your window a coordinated test would actually use:
Rough model: the standard LoRa time-on-air formula (Semtech
AN1200.13) times an estimated number of on-air retransmissions. Not a guarantee, and
not enforced by the bot itself β message_count is capped at 10 and
listen_minutes has a 30-minute floor, and the report window is at least 10
minutes, regardless of this calculator.