A real distributed systems project โ€” not a toy script.

Built with the actual MQTT protocol used by AWS IoT, Tesla, and billions of embedded devices worldwide.


๐ŸŽฌ What's happening under the hood

  Every 3โ€“5 seconds, each node wakes up, generates a reading, and shouts it
  into the network. The hub is always listening. The dashboard is always watching.

  โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
  โ•‘                     LIVE SENSOR NETWORK (simulated)                     โ•‘
  โ• โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฃ
  โ•‘                                                                          โ•‘
  โ•‘   ๐ŸŒก  node_1  temp=22.4ยฐC  โ”€โ”€โ”                                          โ•‘
  โ•‘   ๐ŸŒก  node_2  temp=19.8ยฐC  โ”€โ”€โ”ค                                          โ•‘
  โ•‘   ๐Ÿ’ง  node_3  humi=58.3%   โ”€โ”€โ”ผโ”€โ”€โ–บ  [ Mosquitto Broker :1883 ]           โ•‘
  โ•‘   ๐Ÿ’ง  node_4  humi=61.1%   โ”€โ”€โ”ค          โ”‚                               โ•‘
  โ•‘   ๐Ÿ‘  node_5  motion=0     โ”€โ”€โ”˜          โ”‚ subscribe sensors/+/+         โ•‘
  โ•‘                                         โ–ผ                               โ•‘
  โ•‘                                  [ hub.py ]                             โ•‘
  โ•‘                                  โ”œโ”€ logs readings to SQLite             โ•‘
  โ•‘                                  โ”œโ”€ tracks heartbeats per node          โ•‘
  โ•‘                                  โ””โ”€ 15s silence = โŒ OFFLINE            โ•‘
  โ•‘                                         โ”‚                               โ•‘
  โ•‘                                         โ–ผ                               โ•‘
  โ•‘                              [ Streamlit Dashboard ]                    โ•‘
  โ•‘                              โ”œโ”€ ๐ŸŸข node_1  22.4ยฐC   2s ago             โ•‘
  โ•‘                              โ”œโ”€ ๐ŸŸข node_2  19.8ยฐC   4s ago             โ•‘
  โ•‘                              โ”œโ”€ ๐Ÿ”ด node_3  OFFLINE  23s ago  โ† ALERT   โ•‘
  โ•‘                              โ”œโ”€ ๐ŸŸข node_4  61.1%    1s ago             โ•‘
  โ•‘                              โ””โ”€ ๐ŸŸข node_5  motion=0  3s ago            โ•‘
  โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

Kill any node with one command. The hub detects the silence. The dashboard goes red. Revive it. It comes back online. The whole thing is live.


๐ŸŽฅ Demo

IoT Sensor Network Demo

Click to watch โ€” live fault detection, node recovery, and real-time dashboard


โœจ Why this project exists

Most IoT tutorials fake it โ€” one script, fake pub/sub, no real network, no real protocol.

This project uses real MQTT over a real broker with real distributed processes. The same architecture pattern behind:

Real System What it shares with this project
๐Ÿ  Smart home hubs (Google Home, Amazon Echo) MQTT pub/sub between devices and hub
๐Ÿญ Industrial SCADA systems Sensor nodes โ†’ central aggregator โ†’ dashboard
๐Ÿš— Tesla vehicle telemetry Heartbeat-based liveness detection
โ˜๏ธ AWS IoT Core Topic-based routing, wildcard subscriptions
โš“ Kubernetes Heartbeat timeouts โ†’ node marked NotReady

๐Ÿงฉ Core concepts demonstrated

๐Ÿ“จ MQTT Publish / Subscribe โ€” click to expand

MQTT is a messaging protocol designed in 1999 for oil pipeline monitoring over satellite โ€” low bandwidth, unreliable connections, constrained devices. Those same properties make it the dominant IoT protocol today.

How it works here:

node_1 publishes โ”€โ”€โ–บ sensors/node_1/temperature  โ”€โ”€โ–บ broker โ”€โ”€โ–บ hub receives
node_1 publishes โ”€โ”€โ–บ sensors/node_1/heartbeat    โ”€โ”€โ–บ broker โ”€โ”€โ–บ hub receives
hub subscribes   โ”€โ”€โ–บ sensors/+/+                 (+ matches any single level)

Publishers and subscribers never connect to each other โ€” the broker decouples them entirely. A node doesn't know or care that the hub exists.

๐Ÿ–ฅ๏ธ Distributed Process Architecture โ€” click to expand

Each sensor node is a completely independent OS process with:

  • Its own MQTT client connection
  • Its own data generation loop
  • No shared memory with any other node
  • No knowledge that other nodes exist
PID 21564  sensor_node.py  node_1  temperature
PID 11088  sensor_node.py  node_2  temperature
PID  7896  sensor_node.py  node_3  humidity
PID  4208  sensor_node.py  node_4  humidity
PID  3892  sensor_node.py  node_5  motion
PID  9100  hub.py          โ† subscribes to all of them

Kill PID 7896 โ€” the others keep running. The hub notices the silence. This is how real embedded hardware behaves.

๐Ÿ’“ Heartbeat-based Fault Detection โ€” click to expand

A classic distributed systems pattern used in Kubernetes, ZooKeeper, Consul, and every serious distributed database.

The algorithm:

Every 5 seconds:
  node โ†’ publishes heartbeat to sensors/{node_id}/heartbeat

Every 5 seconds (hub fault-detection thread):
  for each known node:
    if (now - last_heartbeat) > 15 seconds:
      mark node OFFLINE
      log alert

When heartbeat resumes:
  if node was OFFLINE:
    mark node ONLINE
    log recovery alert

Sleep-mode awareness: Nodes can publish their expected sleep schedule before going dormant. The hub uses this to avoid false-alarming โ€” it knows the difference between "dead" and "intentionally sleeping."

๐Ÿ“Š Real-time Monitoring Dashboard โ€” click to expand

The Streamlit dashboard polls SQLite every 3 seconds and shows:

  • Node status grid โ€” per-node cards with color-coded online/offline status, current reading, last-seen timestamp
  • Time-series charts โ€” rolling Plotly charts for temperature, humidity, and motion
  • Alert log โ€” timestamped log of every offline event, recovery, and anomalous reading

SQLite is used as a lightweight shared state store โ€” the hub writes, the dashboard reads. No additional infrastructure needed.


๐Ÿ—‚ Project structure

iot-sensor-network/
โ”‚
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ sensor_node.py      # ๐ŸŒก  Independent sensor device โ€” MQTT publisher
โ”‚   โ”‚                       #     Generates realistic temperature / humidity / motion
โ”‚   โ”‚                       #     Publishes readings + heartbeats
โ”‚   โ”‚
โ”‚   โ”œโ”€โ”€ hub.py              # ๐Ÿ–ฅ  Central hub โ€” MQTT subscriber
โ”‚   โ”‚                       #     Logs all readings to SQLite
โ”‚   โ”‚                       #     Fault-detection thread watches heartbeats
โ”‚   โ”‚
โ”‚   โ”œโ”€โ”€ launch_nodes.py     # ๐Ÿš€  Spawns all 5 nodes as separate OS processes
โ”‚   โ”‚                       #     Writes PID records so fault_injector can find them
โ”‚   โ”‚
โ”‚   โ””โ”€โ”€ fault_injector.py   # ๐Ÿ’€  Kill / revive individual nodes on demand
โ”‚                           #     Demonstrates fault detection live
โ”‚
โ”œโ”€โ”€ app.py                  # ๐Ÿ“Š  Streamlit dashboard โ€” live monitoring UI
โ”œโ”€โ”€ mqtt_test.py            # โœ…  Connectivity verification script
โ”œโ”€โ”€ requirements.txt        # ๐Ÿ“ฆ  Pinned dependencies
โ”œโ”€โ”€ .gitignore
โ””โ”€โ”€ README.md

โš™๏ธ Tech stack

Layer Technology Version Role
Message broker Mosquitto 2.x Routes all MQTT messages
MQTT client paho-mqtt 2.1.0 Python MQTT pub/sub
Database SQLite stdlib Time-series + state store
Dashboard Streamlit 1.36.0 Live web UI
Charts Plotly 5.22.0 Interactive time-series
Data wrangling pandas 2.2.2 DB โ†’ DataFrame queries

๐Ÿš€ Getting started

Prerequisites

  • Python 3.9 โ€“ 3.12
  • Mosquitto MQTT broker โ€” this is a system service, not a pip package

Step 1 โ€” Install Mosquitto

โš ๏ธ This step is required. The hub and nodes will fail with ConnectionRefusedError if Mosquitto isn't running.

Windows:

  1. Download the installer from https://mosquitto.org/download/ (64-bit .exe)
  2. Run it โ€” installs as a Windows service automatically
  3. Start the service (PowerShell as Administrator):
net start mosquitto
  1. Verify it's listening:
netstat -an | findstr 1883
# Should show: 0.0.0.0:1883   LISTENING

macOS:

brew install mosquitto
brew services start mosquitto

Linux:

sudo apt install mosquitto mosquitto-clients
sudo systemctl start mosquitto

Step 2 โ€” Python environment

# Windows
py -3.11 -m venv venv
venv\Scripts\python.exe -m pip install -r requirements.txt

# macOS / Linux
python3.11 -m venv venv
source venv/bin/activate
pip install -r requirements.txt

Step 3 โ€” Verify connectivity

Run this before anything else. It connects to Mosquitto, publishes a test message, and confirms it arrives back.

# Windows
venv\Scripts\python.exe mqtt_test.py

# macOS / Linux
python mqtt_test.py

Expected output:

โœ… All Python imports OK
โœ… Connected to Mosquitto at localhost:1883
โœ… Received message: {"test": true, ...}
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
๏ฟฝ๏ฟฝ๏ฟฝ MQTT CONNECTIVITY TEST PASSED
   You can now start the full simulation.
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

Step 4 โ€” Run the simulation

Open three terminal windows in the project root.

Terminal 1 โ€” Start the hub first:

venv\Scripts\python.exe src/hub.py
[hub] Connected to broker at localhost:1883
[hub] Subscribed to sensors/+/+
[hub] ๐Ÿ“ก node_1/temperature: 22.4ยฐC       โ† data starts flowing
[hub] ๐Ÿ“ก node_3/humidity: 58.1%

Terminal 2 โ€” Launch all sensor nodes:

venv\Scripts\python.exe src/launch_nodes.py
โœ… node_1   (temperature) โ€” PID 21564
โœ… node_2   (temperature) โ€” PID 11088
โœ… node_3   (humidity   ) โ€” PID 7896
โœ… node_4   (humidity   ) โ€” PID 4208
โœ… node_5   (motion     ) โ€” PID 3892

Terminal 3 โ€” Open the dashboard:

venv\Scripts\streamlit.exe run app.py

Opens at http://localhost:8501 โ€” auto-refreshes every 3 seconds.


Step 5 โ€” Demo fault detection ๐Ÿ”ฅ

This is the interesting part. Open a fourth terminal:

# Kill node_3 โ€” simulates a dead battery or lost connection
venv\Scripts\python.exe src/fault_injector.py --kill node_3

Watch what happens:

# After ~15 seconds silence, the hub fires:
[hub] โŒ Node node_3 OFFLINE (no heartbeat for 15s)
[hub] ๐Ÿ”” ALERT [offline] node_3: Node node_3 went offline

The dashboard card for node_3 turns ๐Ÿ”ด RED.

# Bring it back
venv\Scripts\python.exe src/fault_injector.py --revive node_3
# Hub immediately detects the returning heartbeat:
[hub] โœ… Node node_3 came back ONLINE
[hub] ๐Ÿ”” ALERT [online] node_3: Node node_3 reconnected

Card goes ๐ŸŸข GREEN. The full cycle is logged in the alerts panel.


๐ŸŒก Sensor simulation details

Sensor Behaviour Range
Temperature Slow random walk ยฑ 0.3ยฐC per step, 3% chance of a sudden spike (+3โ€“8ยฐC) 15ยฐC โ€“ 35ยฐC
Humidity Slow random walk ยฑ 0.5% per step 20% โ€“ 90%
Motion Binary trigger, ~5% probability per reading 0 or 1

The hub flags anomalies automatically:

  • Temperature > 30ยฐC or < 15ยฐC โ†’ alert logged
  • Humidity > 80% โ†’ alert logged
  • Motion triggered โ†’ alert logged

๐Ÿ”ง Troubleshooting

Problem Fix
ConnectionRefusedError on port 1883 Run net start mosquitto as Administrator
Dashboard shows "waiting for data" Start hub.py before opening the dashboard
Nodes exit immediately Run mqtt_test.py first to verify broker is reachable
ModuleNotFoundError Run pip install -r requirements.txt inside your venv
Port 1883 already in use Another Mosquitto instance is running โ€” check Services

๐Ÿ—บ Future work

This is a v1 local simulation. The path to production:

  • ๐Ÿ”’ TLS + Auth โ€” production MQTT uses port 8883 with client certificates or username/password. Noted in code comments throughout.
  • โ˜๏ธ Cloud broker โ€” swap localhost:1883 for AWS IoT Core, HiveMQ Cloud, or EMQX. The node/hub code is broker-agnostic.
  • ๐Ÿ“ Real hardware โ€” sensor_node.py runs unmodified on a Raspberry Pi. Point BROKER_HOST at a real broker and connect actual sensors.
  • ๐Ÿ“ˆ Time-series DB โ€” replace SQLite with InfluxDB or TimescaleDB for production-scale workloads and Grafana dashboards.
  • ๐Ÿ˜ด Sleep mode โ€” already partially implemented. Nodes publish their sleep schedule; the hub suppresses false-alarm timeouts during intentional dormant periods.

๐Ÿ“– Why MQTT?

MQTT was designed in 1999 for monitoring oil pipelines over satellite links โ€” high latency, low bandwidth, unreliable connections, constrained devices. Those exact constraints describe IoT hardware.

Compared to HTTP:

MQTT HTTP
Header overhead 2 bytes fixed ~800 bytes minimum
Connection model Persistent Request/response
Broker decoupling โœ… Yes โŒ No
QoS guarantees 3 levels None built-in
Idle detection Last Will & Testament Polling

Today MQTT is the default protocol for AWS IoT Core, Azure IoT Hub, Google Cloud IoT, and most commercial smart home platforms.


Built by Eddie ยท Python ยท MQTT ยท Distributed Systems

If this was useful, leave a โญ