Skip to content
shuvaaashishPublic

About

AtmoNode: A high-scalability IoT ecosystem for real-time atmospheric monitoring. Built with Django, React, and ESP32 to transform physical rooms into data-driven connected spaces.

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Latest commit

 

History

19 Commits

Folders and files

Repository files navigation

AtmoNode

AtmoNode is a full-stack IoT air-quality monitoring platform built with Django REST Framework and React. It manages sensor nodes, ingests environmental readings, supports role-based node access, and provides a live dashboard for temperature, humidity, and pollution trends.

Tech Stack

  • Backend: Django 6, Django REST Framework, Djoser (token auth), PostgreSQL, Gunicorn
  • Frontend: React 19, Vite, Axios, Lucide icons
  • Hardware/Firmware: ESP32 C++ (Arduino framework), DHT11, MQ135, I2C LCD, ArduinoJson
  • Infra: Docker, Docker Compose, Nginx reverse proxy, optional TLS via Certbot

Architecture

  • backend/
    • Django API (/auth/*, /api/*)
    • PostgreSQL-backed models for users, nodes, access roles, and readings
    • Gunicorn app server behind Nginx
  • frontend/
    • React dashboard and auth UI
    • Polling-based live updates for node readings
  • Hardware node (ESP32) samples sensors and sends JSON readings to backend ingestion API
  • Nginx proxies requests to Django and serves static files

Core Features

  • Email-based user registration and login (token authentication)
  • Node registration with owner/editor/viewer role model
  • Owner-only access sharing per node
  • Device ingestion endpoint secured by device token
  • Reading filters by location
  • Frontend dashboard with:
    • Latest sensor values and threshold alerts
    • Historical trend charts
    • Sync status indicator

Repository Structure

atmonode/
├── backend/
│   ├── atmonode/        # sensor domain app (nodes/readings/access)
│   ├── users/           # custom email-based user model
│   ├── core/            # Django settings and URL routing
│   ├── docker-compose.yml
│   ├── docker-compose.prod.yml
│   └── Dockerfile
├── frontend/
│   ├── src/
│   └── package.json
└── firmware/
    └── hardware.ino   # ESP32 firmware sketch (sensor read + API post)

Hardware (C++)

The project includes device-side firmware in C++ at firmware/hardware.ino.

Current Hardware Implementation

  • Platform: ESP32 (Arduino framework)
  • Sensors/Peripherals:
    • DHT11 on GPIO 4 (temperature and humidity)
    • MQ135 on ADC pin 34 (pollution approximation)
    • 16x2 I2C LCD (LiquidCrystal_I2C)
  • Connectivity:
    • Wi-Fi client with HTTPS POST to /api/readings/
    • Payload fields: device_uid, temperature, humidity, pollution
  • Sampling/Push interval: every 10 seconds

Device → Backend Data Flow

  1. Firmware derives a unique device_uid from ESP32 eFuse MAC.
  2. Firmware reads DHT11 and MQ135 values and prints status to LCD + serial.
  3. Firmware sends JSON to backend ingestion endpoint.
  4. Backend validates device authentication and maps device_uid to a registered node.
  5. Reading is persisted and shown on dashboard.

Firmware Configuration Notes

The current sketch contains hardcoded values for:

  • Wi-Fi SSID/password
  • API URL
  • auth token

For production, move these to secure provisioning/secrets storage and avoid committing real credentials in source control.

Build/Upload (Arduino IDE)

  1. Install board support for ESP32.
  2. Install required libraries:
    • DHT sensor library
    • ArduinoJson
    • LiquidCrystal_I2C
  3. Open firmware/hardware.ino in Arduino IDE.
  4. Select ESP32 board and COM port.
  5. Build and upload.
  6. Monitor serial output at 115200 baud.

Quick Start (Docker)

1) Configure environment

Create backend/.env.prod:

# Django
DJANGO_SECRET_KEY=replace-with-a-secure-secret
DEBUG=False
DJANGO_ALLOWED_HOSTS=127.0.0.1,localhost
DJANGO_CSRF_TRUSTED_ORIGINS=http://127.0.0.1:8001,http://localhost:8001
DEVICE_INGEST_TOKEN=replace-with-strong-device-token

# Django DB connection
DATABASE_NAME=dockerdjango
DATABASE_USER=dbuser
DATABASE_PASSWORD=dbpassword
DATABASE_HOST=db
DATABASE_PORT=5432

# Postgres container vars
POSTGRES_DB=dockerdjango
POSTGRES_USER=dbuser
POSTGRES_PASSWORD=dbpassword

2) Start services

cd backend
docker compose -f docker-compose.yml up --build -d

App will be available at:

  • API + auth via Nginx: http://localhost:8001

Local Development (Without Docker)

Backend

cd backend
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Create backend/.env.local:

DJANGO_SECRET_KEY=dev-secret
DEBUG=True
DATABASE_NAME=your_db_name
DATABASE_USER=your_db_user
DATABASE_PASSWORD=your_db_password
DATABASE_HOST=127.0.0.1
DATABASE_PORT=5432
DJANGO_ALLOWED_HOSTS=127.0.0.1,localhost
DJANGO_CSRF_TRUSTED_ORIGINS=http://127.0.0.1:8000,http://localhost:8000
DEVICE_INGEST_TOKEN=dev-device-token

Run migrations and server:

python manage.py migrate
python manage.py runserver

Backend URL: http://127.0.0.1:8000

Frontend

cd frontend
npm install

Create frontend/.env:

VITE_API_BASE_URL=http://127.0.0.1:8000

Run frontend:

npm run dev

Frontend URL: usually http://127.0.0.1:5173

API Overview

Base URL (Docker): http://localhost:8001

Auth (Djoser)

  • POST /auth/users/ — register
  • POST /auth/token/login/ — login and receive auth token
  • POST /auth/token/logout/ — logout
  • GET /auth/users/me/ — current user profile

Domain API

  • GET /api/users/ — list users (excluding current user)
  • GET /api/nodes/ — list nodes user can access
  • POST /api/nodes/ — create node
  • POST /api/nodes/{node_id}/grant-access/ — grant/update node access role
  • GET /api/readings/?location=<location> — list accessible readings
  • POST /api/readings/ — create reading

Authentication Notes

  • User-authenticated requests use header:
    • Authorization: Token <auth_token>
  • Device ingestion (unauthenticated user) requires either:
    • X-Device-Token: <DEVICE_INGEST_TOKEN>
    • or Authorization: Device <DEVICE_INGEST_TOKEN>
  • Device ingestion payload must include device_uid that matches a registered node.

Example device ingestion request:

curl -X POST http://localhost:8001/api/readings/ \
  -H "Content-Type: application/json" \
  -H "X-Device-Token: <DEVICE_INGEST_TOKEN>" \
  -d '{
    "device_uid": "NODE-ABC-123",
    "temperature": 24.6,
    "humidity": 61.2,
    "pollution": 142.0
  }'

Operations

Stop services

cd backend
docker compose down

Rebuild services

cd backend
docker compose up --build -d

Django management in container

cd backend
docker compose exec django-web python manage.py createsuperuser

About

AtmoNode: A high-scalability IoT ecosystem for real-time atmospheric monitoring. Built with Django, React, and ESP32 to transform physical rooms into data-driven connected spaces.

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages