IoT Monitoring System
Build an IoT monitoring system with a Raspberry Pi. Collect sensor data, visualize it on a dashboard, and set up alerts.
Introduction
An MQTT-based IoT monitoring system is the scalable way to aggregate sensor data from multiple Raspberry Pis or devices. MQTT brokers are lightweight, support pub/sub messaging, and integrate seamlessly with InfluxDB and Grafana. This architecture handles single sensors to hundreds of devices.
Architecture Overview
Sensors publish to a Mosquitto MQTT broker. The broker distributes messages. Telegraf subscribes to topics and writes to InfluxDB. Grafana queries InfluxDB and displays dashboards. You can add alerts, webhooks, and automation at any layer.
Temp Sensor (Pi 1) \
Humidity Sensor (Pi 2) --[Mosquitto MQTT]--[Telegraf]--[InfluxDB]--[Grafana]
Light Sensor (Pi 3) /
Prerequisites
- Raspberry Pi 4/5 with 2GB+ RAM
- Docker and Docker Compose
- Python 3.9+
pip install paho-mqtt- Optional: additional Pis with sensors (DHT22, BMP280, light sensors)
Step 1 — Deploy MQTT Broker (Mosquitto) with Docker Compose
Create docker-compose.yml:
version: "3.8"
services:
mosquitto:
image: eclipse-mosquitto:latest
container_name: mosquitto
ports:
- "1883:1883"
- "9001:9001"
volumes:
- ./mosquitto.conf:/mosquitto/config/mosquitto.conf
- mosquitto_data:/mosquitto/data
- mosquitto_logs:/mosquitto/log
restart: unless-stopped
influxdb:
image: influxdb:2.7-alpine
container_name: influxdb
ports:
- "8086:8086"
environment:
INFLUXDB_DB: iot
INFLUXDB_ADMIN_USER: admin
INFLUXDB_ADMIN_PASSWORD: homelab123
volumes:
- influxdb_data:/var/lib/influxdb2
restart: unless-stopped
telegraf:
image: telegraf:latest
container_name: telegraf
volumes:
- ./telegraf.conf:/etc/telegraf/telegraf.conf
depends_on:
- mosquitto
- influxdb
restart: unless-stopped
grafana:
image: grafana/grafana:latest
container_name: grafana
ports:
- "3000:3000"
environment:
GF_SECURITY_ADMIN_PASSWORD: admin
volumes:
- grafana_data:/var/lib/grafana
depends_on:
- influxdb
restart: unless-stopped
volumes:
mosquitto_data:
mosquitto_logs:
influxdb_data:
grafana_data:
Create mosquitto.conf:
listener 1883
protocol mqtt
allow_anonymous true
listener 9001
protocol websockets
allow_anonymous true
Start the stack:
docker-compose up -d
Verify MQTT is running:
docker exec mosquitto mosquitto_sub -t '$SYS/#' | head -5
Step 2 — Create Telegraf MQTT Subscriber Config
Create telegraf.conf:
[global_tags]
environment = "homelab"
[agent]
interval = "10s"
round_interval = true
flush_interval = "10s"
[[inputs.mqtt_consumer]]
servers = ["tcp://mosquitto:1883"]
topics = [
"sensors/temperature/#",
"sensors/humidity/#",
"sensors/light/#"
]
data_format = "json"
name_override = "sensor_reading"
[[outputs.influxdb_v2]]
urls = ["http://influxdb:8086"]
token = "admin"
organization = "homelab"
bucket = "iot"
Step 3 — Python MQTT Publisher for Sensors
Create mqtt_publisher.py to send sensor data:
import paho.mqtt.client as mqtt
import json
import time
import random
from datetime import datetime
# MQTT broker
broker = "localhost"
port = 1883
client = mqtt.Client()
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to MQTT broker")
else:
print(f"Failed to connect, return code {rc}")
client.on_connect = on_connect
client.connect(broker, port, keepalive=60)
client.loop_start()
def publish_sensor(location, sensor_type, value):
topic = f"sensors/{sensor_type}/{location}"
payload = json.dumps({
"timestamp": datetime.now().isoformat(),
"value": value,
"unit": "celsius" if sensor_type == "temperature" else "percent" if sensor_type == "humidity" else "lux"
})
client.publish(topic, payload)
print(f"Published to {topic}: {value}")
try:
while True:
# Simulate multiple sensors from different locations
locations = ["living_room", "bedroom", "kitchen", "garage"]
for location in locations:
# Temperature: 15-28°C with noise
temp = 20 + random.gauss(0, 2)
publish_sensor(location, "temperature", round(temp, 1))
# Humidity: 30-70% with noise
humidity = 50 + random.gauss(0, 5)
publish_sensor(location, "humidity", max(0, min(100, round(humidity, 1))))
# Light: 0-1000 lux
light = random.uniform(0, 1000)
publish_sensor(location, "light", round(light, 0))
time.sleep(60) # Publish every minute
except KeyboardInterrupt:
print("\nShutdown")
client.loop_stop()
client.disconnect()
Install the MQTT client:
pip3 install paho-mqtt
Run it:
python3 mqtt_publisher.py
You should see messages published every 60 seconds.
Step 4 — Verify Data Flow
Check that data is flowing to InfluxDB:
curl -G http://localhost:8086/api/v2/query \
-H "Authorization: Token admin" \
-d "db=iot" | jq .
Or use the InfluxDB UI at http://localhost:8086.
Step 5 — Create Grafana Dashboards
Open http://localhost:3000 (login: admin/admin).
Add InfluxDB data source:
- URL:
http://influxdb:8086 - Organization:
homelab - Token:
admin - Bucket:
iot
Create panels:
- Temperature by Location — Line graph, group by location
- Humidity Gauge — Gauge panel showing current humidity
- Light Levels — Bar chart of lux by location
- All Metrics Table — Table showing latest values
Example Flux query for temperature:
from(bucket: "iot")
|> range(start: -1h)
|> filter(fn: (r) => r._measurement == "sensor_reading" and r._field == "value")
|> filter(fn: (r) => contains(value: r.topic, str: "temperature"))
|> group(columns: ["location"])
Step 6 — Add Alerting Rules
In Grafana:
- Create an alert rule on the temperature panel
- Set threshold: temp > 28°C
- For: 5 minutes (avoid false triggers)
- Notify via email or webhook
Configure webhook to call a Lambda, call Home Assistant, or send a Slack message.
Troubleshooting
Data not appearing in InfluxDB — Check Telegraf logs: docker logs telegraf. Verify MQTT broker connectivity with mosquitto_sub -h localhost -t 'sensors/#'.
Connection refused on port 1883 — Ensure Mosquitto container is running: docker ps | grep mosquitto. Check firewall: sudo ufw allow 1883 if using UFW.
Telegraf crashing with auth error — The InfluxDB token and org must match. In telegraf.conf, use token = "admin" for v2 API. If using InfluxDB v1, switch the output plugin to [[outputs.influxdb]] instead.
Duplicate data — Each sensor should publish to unique topic like sensors/temperature/location1, sensors/temperature/location2. Avoid publishing to the same topic from multiple sources without unique identifiers.
Summary
An MQTT-based system scales easily. Start with one Pi publishing temperature and humidity. Add light sensors, motion detectors, or door sensors as separate publishers. The broker and Telegraf handle the aggregation. Grafana provides real-time visibility and alerting. From here, integrate with Home Assistant, automate based on sensor thresholds, or archive data to long-term storage.