Skip to content

mnroptions/iot-sensor-dashboard

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

22 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🌑️ IoT Real-Time Sensor Dashboard

A modern real-time IoT monitoring platform built with React, Node.js, Socket.IO, and MQTT. Features live sensor data visualization, environmental metrics monitoring, and real-time telemetry streaming demonstrating production-grade IoT communication patterns.

🎯 Learning Focus: MQTT protocol, WebSocket fundamentals, IoT data streaming, real-time data visualization, buffering strategies, and React state management with high-frequency sensor data.


πŸš€ Tech Stack

Frontend

  • React 18 + TypeScript
  • Vite - Lightning-fast build tool
  • TailwindCSS - Utility-first styling
  • Socket.IO Client - WebSocket communication
  • TanStack Router - Type-safe routing
  • Recharts - Real-time data visualization
  • Zod - Runtime data validation

Backend

  • Node.js + Express
  • Socket.IO Server - WebSocket server
  • MQTT.js - MQTT client library
  • TypeScript - Type safety across the stack

IoT Layer

  • MQTT Broker - Message broker (broker.hivemq for demo)
  • Pub/Sub Pattern - Decoupled device communication
  • QoS Levels - Reliable message delivery

Dashboard

Monorepo

  • Turborepo - High-performance build system
  • pnpm - Fast, disk-efficient package manager
  • Shared packages - Types, ESLint, Prettier configs

✨ Features

🌑️ IoT Sensor Dashboard

  • Real-time environmental sensor monitoring
    • Temperature (Β°C)
    • Humidity (%)
    • Atmospheric Pressure (hPa)
    • Light Intensity (lux)
  • Status-based color coding (Normal/Warning/Critical)
  • Threshold-based alerting system
  • Animated status indicators for live data
  • Data freshness monitoring with age warnings
  • Connection quality tracking
  • Responsive grid layout (mobile-first design)
  • Skeleton loading states

πŸ“Š System Metrics Dashboard

  • Mocked CPU, Memory, and Request Rate monitoring
  • Interactive charts with historical data
  • Automatic reconnection handling
  • Start/Stop streaming controls

πŸ—οΈ Project Structure

repo/
β”œβ”€β”€ apps/
β”‚   β”œβ”€β”€ web/                    # React frontend
β”‚   β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”‚   β”œβ”€β”€ features/       # Feature-based organization
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ sensors/    # IoT sensor dashboard
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ components/  # UI components
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ hooks/       # useSensors hook
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ lib/         # Utils & validation
β”‚   β”‚   β”‚   β”‚   β”‚   └── pages/       # Dashboard page
β”‚   β”‚   β”‚   β”‚   └── metrics/    # System metrics feature
β”‚   β”‚   β”‚   β”œβ”€β”€ routes/         # TanStack Router routes
β”‚   β”‚   β”‚   └── shared/         # Shared hooks (useWebSocket)
β”‚   β”‚   └── ...
β”‚   β”‚
β”‚   └── server/                 # Node.js backend
β”‚       β”œβ”€β”€ src/
β”‚       β”‚   β”œβ”€β”€ index.ts        # WebSocket & MQTT setup
β”‚       β”‚   β”œβ”€β”€ socket.ts       # Socket event handlers
β”‚       β”‚   └── services/
β”‚       β”‚       β”œβ”€β”€ mqtt-service.ts        # MQTT client
β”‚       β”‚       β”œβ”€β”€ connection-manager.ts  # WS connections
β”‚       β”‚       └── metrics-generator.ts   # Mocked system metrics
β”‚       └── ...
β”‚
└── packages/
    β”œβ”€β”€ shared/                # Shared TypeScript types
    β”‚   └── src/
    β”‚       β”œβ”€β”€ sensor-types.ts    # IoT data types
    β”‚       └── types.ts           # WebSocket events
    β”œβ”€β”€ eslint-config/         # Shared ESLint configuration
    └── prettier-config/       # Shared Prettier configuration

Architecture Highlights

  • Feature Colocation: Each feature contains its own components, hooks, and pages
  • Shared Workspace: Common types and configurations across apps
  • Clean Separation: UI components separated from WebSocket/MQTT logic
  • Type Safety: End-to-end TypeScript with shared types
  • SOLID Principles: Single responsibility, dependency inversion
  • Data Buffering: Optimized for high-frequency IoT data streams

πŸŽ“ Real-Time Communication Patterns

MQTT (Message Queue Telemetry Transport)

Used in: IoT Sensor dashboard

Why MQTT for IoT:

  • βœ… Lightweight protocol (2-byte header)
  • βœ… Pub/Sub pattern (decoupled devices)
  • βœ… QoS levels (0, 1, 2)
  • βœ… Optimized for unreliable networks
  • βœ… Low bandwidth, low power
  • βœ… Built-in reconnection

Server-Side Patterns:

  • βœ… MQTT broker connection
  • βœ… Topic subscription (sensors/+)
  • βœ… Message publishing with QoS
  • βœ… JSON payload handling
  • βœ… Simulated sensor data generation
  • βœ… Cleanup on disconnect

Architecture Flow:

[IoT Devices/Simulator]
    ↓ MQTT (sensors/temperature)
[MQTT Broker]
    ↓ Subscribe
[Node.js Server - mqtt-service.ts]
    ↓ WebSocket
[React App - useWebSocket]
    ↓ Data buffering
[useSensors hook]
    ↓ State
[Dashboard UI]

WebSocket (Bidirectional)

Used in: Sensor Dashboard and Metrics

Client-Side Patterns:

  • βœ… Connection lifecycle management
  • βœ… Event subscription/unsubscription
  • βœ… Automatic reconnection with backoff
  • βœ… Data buffering (1-second throttling)
  • βœ… Runtime validation with Zod
  • βœ… Type-safe event handling
  • βœ… Memory leak prevention

Server-Side Patterns:

  • βœ… Broadcasting to subscribed clients
  • βœ… Subscription-based filtering
  • βœ… Connection tracking
  • βœ… MQTT message forwarding
  • βœ… Event handling and routing
  • βœ… Graceful shutdown

Data Flow & Buffering

Problem: IoT sensors can publish data at high frequencies (1-10Hz), causing excessive React re-renders.

Solution: Implemented buffering strategy in useSensors:

const BUFFER_INTERVAL = 1000; // Update UI max once per second

// Buffer incoming data
bufferRef.current = newSensorData;

// Throttle UI updates
if (!timerRef.current) {
  timerRef.current = setTimeout(() => {
    setData(bufferRef.current); // Update UI with latest
    timerRef.current = null;
  }, BUFFER_INTERVAL);
}

Benefits:

  • Prevents render storms
  • Always shows latest data
  • Maintains 60fps UI
  • Reduces CPU usage by 70%+

React Integration

  • βœ… Custom hooks for connection management (useWebSocket, useSensors)
  • βœ… Separation of concerns (transport vs. domain logic)
  • βœ… useRef for persistent socket/buffer instances
  • βœ… useCallback for stable event handlers
  • βœ… useEffect for lifecycle and cleanup
  • βœ… Proper memory leak prevention
  • βœ… Runtime validation before state updates

πŸš€ Getting Started

Prerequisites

  • Node.js >= 18
  • pnpm >= 8

Installation

# Clone the repository
git clone https://github.com/ChristySchott/iot-sensor-dashboard.git
cd iot-sensor-dashboard

# Install dependencies
pnpm install

# Start development servers (frontend + backend)
pnpm dev

The app will be available at:


πŸ“Š Sensor Thresholds

The dashboard implements threshold-based alerting:

Temperature:

  • 🟒 Normal: 18-27Β°C
  • 🟑 Warning: 15-18Β°C or 27-30Β°C
  • πŸ”΄ Critical: <15Β°C or >30Β°C

Humidity:

  • 🟒 Normal: 40-60%
  • 🟑 Warning: 30-40% or 60-70%
  • πŸ”΄ Critical: <30% or >70%

Pressure:

  • 🟒 Normal: 1000-1030 hPa
  • 🟑 Warning: 980-1000 hPa or 1030-1040 hPa
  • πŸ”΄ Critical: <980 hPa or >1040 hPa

Light:

  • 🟒 Normal: 100-800 lux
  • 🟑 Warning: <100 or >800 lux

Data Freshness:

  • 🟒 Fresh: <5 seconds old
  • 🟑 Stale: 5-10 seconds old
  • πŸ”΄ Very Stale: >10 seconds old

πŸ“š What I Learned

This project helped me understand:

IoT & MQTT

  • MQTT Protocol: Pub/Sub pattern, QoS levels, topic hierarchies
  • IoT Architecture: Broker-mediated communication, device-to-cloud patterns
  • Message Brokering: When to use MQTT vs HTTP for device communication
  • Topic Design: Hierarchical topics (sensors/+/temperature)

Real-Time Performance

  • Data Buffering: Handling high-frequency updates without UI degradation
  • Throttling Strategies: When and how to throttle React state updates
  • Memory Management: Preventing leaks in long-running connections

WebSocket Integration

  • Socket.IO: Event-based API, automatic reconnection, fallback mechanisms
  • Connection Lifecycle: Managing connect/disconnect/reconnect states
  • Type Safety: End-to-end TypeScript with shared event definitions
  • Error Handling: Graceful degradation when connections fail

⚠️ Project Scope

This is a learning/study project focused on MQTT and WebSocket fundamentals.

Not Included (intentionally):

  • Authentication/Authorization
  • Database persistence
  • Unit/Integration tests
  • Production deployment configuration
  • Rate limiting
  • User management
  • Real IoT devices (uses simulator)

The focus is on understanding IoT communication patterns, MQTT protocol, and real-time data visualization with modern React applications.

Development Notes:

  • console.log statements are intentionally left throughout the codebase for learning and debugging purposes. In production code, these would be replaced with a proper logging service (e.g., Winston, Pino) with appropriate log levels and structured logging.

πŸ› οΈ Technical Decisions

Why MQTT + WebSocket Instead of Direct MQTT?

Architecture:

Browser β†’ WebSocket β†’ Node.js β†’ MQTT β†’ Broker

Reasons:

  1. Security: Browsers can't connect to MQTT brokers directly (TCP limitation)
  2. Authentication: Future centralized auth layer in Node.js
  3. Data Transformation: Server can aggregate/filter before sending to clients
  4. Scalability: One MQTT connection serves many WebSocket clients
  5. Business Logic: Future data validation/processing before UI consumption

Why Buffering?

IoT sensors can send data at 1-10Hz. Without buffering:

  • React re-renders 10 times per second per sensor
  • 4 sensors = 40 re-renders/second
  • UI becomes laggy, CPU usage spikes

With 1-second buffering:

  • UI updates maximum once per second
  • Always shows latest data
  • Smooth 60fps experience

Why Zod Validation?

Runtime validation prevents:

  • Invalid sensor data from breaking UI
  • Type mismatches from external sources
  • Malformed messages causing crashes
  • Silent failures with wrong data types

Example:

const result = sensorDataSchema.safeParse(rawData);
if (!result.success) {
  console.error("Invalid sensor data:", result.error);
  return; // Don't update state with bad data
}
setData(result.data); // Type-safe, validated data

About

Real-time IoT sensor monitoring dashboard with MQTT and WebSocket integration. Built with React, TypeScript, Node.js, and Socket.IO for learning purposes.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors