Building a Mesh Network Dashboard
A community mesh network dashboard gives operators a real-time view of network health — which nodes are online, battery levels, channel utilization, and connectivity maps. This page covers building a monitoring stack for a Meshtastic network.
Architecture Overview
The standard monitoring stack for Meshtastic:
Meshtastic nodes
↓ (MQTT uplink)
MQTT Broker (Mosquitto)
↓
Telegraf (or Python consumer)
↓
InfluxDB (time-series database)
↓
Grafana (dashboard and alerting)
This stack can run on a Raspberry Pi 4 or any small Linux server. Total resource requirement: approximately 500 MB RAM, 10 GB storage for 30 days of data from a 50-node network.
Step 1: MQTT Broker Setup
Install Mosquitto on your monitoring server:
sudo apt install mosquitto mosquitto-clients
sudo systemctl enable mosquitto
Minimal config at /etc/mosquitto/mosquitto.conf:
listener 1883
allow_anonymous true
persistence true
persistence_location /var/lib/mosquitto/
For production, add TLS and password authentication.
Step 2: Configure Nodes to Uplink
On each node you want to monitor:
meshtastic --set mqtt.enabled true
meshtastic --set mqtt.address "YOUR_SERVER_IP"
meshtastic --set mqtt.uplink_enabled true
meshtastic --set mqtt.json_enabled true
JSON mode outputs human-readable JSON instead of protobuf binary — easier for custom consumers but includes less data. For full data including all telemetry, use protobuf mode and decode with the meshtastic Python library.
Step 3: InfluxDB
Install InfluxDB 2.x:
wget -q https://repos.influxdata.com/influxdata-archive_compat.key
sudo apt install influxdb2
sudo systemctl enable --now influxdb
Create a bucket named "meshtastic" with 90-day retention via the InfluxDB UI at http://localhost:8086.
Step 4: Python MQTT-to-InfluxDB Bridge
pip install paho-mqtt influxdb-client meshtastic
# bridge.py — subscribe to Meshtastic MQTT, write metrics to InfluxDB
import paho.mqtt.client as mqtt
from influxdb_client import InfluxDBClient, Point
from influxdb_client.client.write_api import SYNCHRONOUS
import json, time
INFLUX_URL = "http://localhost:8086"
INFLUX_TOKEN = "YOUR_TOKEN"
INFLUX_ORG = "meshamerica"
INFLUX_BUCKET = "meshtastic"
client = InfluxDBClient(url=INFLUX_URL, token=INFLUX_TOKEN, org=INFLUX_ORG)
write_api = client.write_api(write_options=SYNCHRONOUS)
def on_message(mqttc, userdata, msg):
try:
data = json.loads(msg.payload)
node_id = data.get("from", "unknown")
if "payload" in data:
p = data["payload"]
pt = Point("node_telemetry").tag("node_id", node_id)
if "battery_level" in p:
pt = pt.field("battery_pct", p["battery_level"])
if "voltage" in p:
pt = pt.field("voltage", p["voltage"])
if "channel_utilization" in p:
pt = pt.field("channel_util", p["channel_utilization"])
write_api.write(INFLUX_BUCKET, record=pt)
except Exception as e:
print(f"Error: {e}")
mqttc = mqtt.Client()
mqttc.on_message = on_message
mqttc.connect("localhost", 1883)
mqttc.subscribe("msh/#")
mqttc.loop_forever()
Step 5: Grafana Dashboard
Install Grafana and add InfluxDB as a data source. Useful panels:
- Battery Voltage by Node — Time series, grouped by node_id tag
- Online Node Count — Count distinct nodes seen in last 30 minutes
- Channel Utilization Heatmap — Spot congestion patterns over time
- Last Seen Table — Node name and minutes since last packet
Alerting
Configure Grafana alerts to notify via email, Slack, or Telegram:
- Battery below 20% — node needs attention
- Node offline (no data in 2 hours) — repeater may be down
- Channel utilization above 30% — network congestion warning