Skip to main content

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