Skip to content

GiZano/QuakeGuard

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

113 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🌋 QuakeGuard

Electro-Domestic Seismic Alarm System

Full-Stack IoT Architecture for Real-Time Earthquake Detection

Version License C++ Python React Native PostgreSQL Redis Docker

CI Backend CI Frontend CI IoT

QuakeGuard Logo


📖 Overview

QuakeGuard is a full-stack IoT architecture for real-time detection, analysis, and reporting of seismic events. The system transforms everyday household appliances — washing machines, TVs, refrigerators — into a distributed seismic sensor network, each node capable of detecting and reporting earthquake activity autonomously.

Intelligent edge sensors (ESP32-C3 + ADXL345) analyze vibrations locally using professional-grade algorithms and transmit cryptographically signed data to an asynchronous cloud backend. The backend is engineered to handle the massive traffic spikes — the Thundering Herd effect — typical during widespread seismic events, ensuring reliable alarm delivery without bottlenecking. A React Native mobile app receives real-time haptic and visual alerts via WebSocket.

🎓 Developed as a school contest project for Hackersgen by Sorint.lab and the GF Marilli competition.


🏗️ System Architecture

ESP32-C3 + ADXL345
       │
       │  MQTT (signed payload)
       ▼
MQTT Bridge ──► POST /misurations/ ──► ECDSA Verification
                                              │
                                              ▼
                                        Redis Queue
                                              │
                                              ▼
                                     Background Worker
                                      │           │
                                      ▼           ▼
                               PostgreSQL    Redis Pub/Sub
                               + PostGIS          │
                                                  ▼
                                           WebSocket Broadcast
                                                  │
                                                  ▼
                                        React Native Mobile App
                                        (Haptic + Visual Alert)

The project follows Microservices and Event-Driven Design principles across three fully independent layers.


📡 IoT Edge (firmware/)

Feature Detail
Hardware ESP32-C3 SuperMini + ADXL345 Accelerometer
Sampling Rate 100 Hz
Detection Algorithm STA/LTA (Short Term / Long Term Average)
Signal Processing Digital High-Pass Filter (HPF) to remove gravity
Data Structure Statically allocated Ring Buffers (RingBuffer<100> STA, RingBuffer<1000> LTA)
Security ECDSA NIST256p cryptographic signing on every payload
Transmission MQTT publish to quakeguard/telemetry
Provisioning Automated device handshake on first boot via POST /devices/register
Secret Injection Compile-time ENROLLMENT_TOKEN via PlatformIO pre-script + #error fail-fast

☁️ Backend (backend/)

Feature Detail
Framework FastAPI (Python 3.11), fully async
Security API Key auth, ECDSA signature verification, Anti-Replay (60s window)
Message Broker Redis — decouples ingestion from processing
Rate Limiting Fixed-window 50 req/s per IP via Redis
Alert Engine ML-like magnitude proxy (M = log10(PGA_calib) + b), threshold M ≥ 4.5
Deduplication Redis TTL cooldown lock per zone (60s), prevents alert storms
Persistence PostgreSQL + PostGIS with recorded_at timestamps
Zone Assignment Automatic via PostGIS ST_Contains spatial query, ordered by ST_Area ascending
Zone Seeding 8 pre-populated global macro-regions + "Unknown Region" fallback
Observability GET /health — concurrent PostgreSQL + Redis ping
Secrets Fail-fast RuntimeError on missing env vars at startup
MQTT Bridge mqtt_subscriber.py — forwards MQTT payloads to the secure HTTP pipeline

📱 Frontend (mobile/)

Feature Detail
Framework React Native (Expo) with TypeScript
Navigation Expo Router — 3-tab Bottom Navigator (Monitor, Sensors Map, Settings)
State Management Zustand slices (usePreferencesStore, useAlertStore)
Server State TanStack Query + Axios — caching, background refetch, retry
Real-Time WebSocket context with exponential backoff reconnection
Alert Delivery SOS haptic vibration pattern + OS push notification via expo-notifications
Alert History In-session feed of last 10 critical events
Offline Mode Toggle silences WebSocket, halts all TanStack Query polling
Notifications notificationsEnabled toggle gates haptics and push notifications
Safe Areas react-native-safe-area-context — Dynamic Island and punch-hole compatible

🔐 Security Model

Data integrity is paramount in an emergency system. Every telemetry packet is cryptographically secured end-to-end.

ESP32 signs payload with ECDSA NIST256p (SHA256)
         ↓
Backend verifies signature against registered public key
         ↓
Timestamp validated within 60-second window (Anti-Replay)
         ↓
API Key checked on every request (X-API-Key header)
         ↓
Payload accepted → Redis Queue

Threat model coverage:

  • ✅ Man-in-the-Middle (MitM) — ECDSA signature verification
  • ✅ Spoofing — public key registration + signature check
  • ✅ Replay attacks — 60-second timestamp window
  • ✅ Brute force — rate limiting 50 req/s per IP
  • ✅ Unauthorized access — API Key + enrollment token fail-fast

🚀 Quick Start

Prerequisites

  • Docker Desktop & Docker Compose
  • PlatformIO (VS Code Extension)
  • Node.js 18+ & Expo Go (mobile)
  • A mobile hotspot or shared WiFi network for ESP32 + backend connectivity

1. Configure Environment Variables

cd backend/api
cp .env.example .env

Edit .env and set the required secrets:

IOT_API_KEY=your_secret_key
MOBILE_WS_TOKEN=your_ws_token
ENROLLMENT_TOKEN=your_enrollment_token
POSTGRES_DB=quakeguard_db
POSTGRES_USER=developer
POSTGRES_PASSWORD=your_db_password
API_PORT=8000

⚠️ The backend will refuse to start if any of these are missing — this is intentional fail-fast behavior.

2. Launch the Backend Stack

cd backend/api
docker compose up --build -d
Endpoint URL
API http://localhost:8000
Swagger UI http://localhost:8000/docs
Health Check http://localhost:8000/health

3. Configure and Flash the IoT Firmware

cd firmware/esp32_code
cp esp32_config.env.example esp32_config.env
# Edit esp32_config.env with your network IP and ENROLLMENT_TOKEN

Flash via PlatformIO. On first boot the device will:

  1. Open a WiFi captive portal (QuakeGuard-Setup)
  2. Connect to your network
  3. Automatically register with the backend and receive a sensor_id

💡 If the sensor registers with latitude=0.0, longitude=0.0 it will be assigned to "Unknown Region". Hardcode your coordinates in main.cpp for correct zone assignment until GPS integration is complete.

4. Launch the Mobile App

cd mobile
npm install

Update constants/config.ts with your machine's local IP:

export const API_BASE_URL = "http://YOUR_LOCAL_IP:8000";

Create .env in the mobile root:

EXPO_PUBLIC_IOT_API_KEY=your_secret_key
EXPO_PUBLIC_MOBILE_WS_TOKEN=your_ws_token
npx expo start

Scan the QR code with Expo Go. Ensure your phone is on the same WiFi network as the backend machine.


🧪 Stress Test

Validates the full pipeline: ingestion → Redis → worker → PostGIS → WebSocket alerts.

cd backend/api
export API_URL="http://localhost:8000"
export NUM_SENSORS=150
export CONCURRENCY_LIMIT=50
python -m tests.stress_test

Three phases:

Phase What it tests
🔥 Phase 1 — Firehose 150 concurrent sensors, rate limiter validation
⚔️ Phase 2 — Security Bad signature blocked (401), Replay attack blocked (403)
🔍 Phase 3 — E2E DB persistence verified via polling GET /sensors/{id}/statistics

A successful run ends with 🏆 SYSTEM CERTIFIED.


🎮 Demo Mode

Trigger a simulated earthquake instantly from Swagger UI without running the stress test:

POST /demo/trigger-earthquake

Default payload (works with empty {}):

{
  "zone_id": 1,
  "magnitude": 7.5,
  "message": "Simulated Critical Event"
}

This publishes directly to the Redis quake_alerts channel, bypassing the IoT pipeline entirely and triggering the mobile app alert UI within milliseconds.


🗺️ Geographic Zones

The database is pre-seeded with 8 global macro-regions. Sensors are automatically assigned to the correct zone via PostGIS spatial query at registration time.

Zone Coverage
Italy - North Lombardy, Veneto, Piedmont
Italy - Center Tuscany, Lazio, Umbria
Italy - South & Islands Campania, Sicily, Sardinia
Western Europe France, Spain, Germany, UK
North America USA, Canada, Mexico
South America Brazil, Argentina, Chile
East Asia China, Japan, India
Unknown Region Fallback for unmapped coordinates

🔄 CI/CD Pipeline

Workflow Trigger Checks
backend-ci.yml backend/** Bandit, Safety, stress test
frontend-ci.yml mobile/** ESLint, npm audit
iot-ci.yml firmware/** PlatformIO compilation
pr-lint.yml All PRs Semantic PR title (type(scope): message)
devops-ci.yml .github/workflows/** Actionlint workflow validation

🗂️ Project Structure

QuakeGuard/
├── backend/
│   └── api/
│       ├── src/
│       │   ├── main.py              # FastAPI gateway + REST endpoints
│       │   ├── security.py          # ECDSA, API Key, Anti-Replay
│       │   ├── worker.py            # Redis consumer + magnitude + alert engine
│       │   ├── mqtt_subscriber.py   # MQTT to HTTP bridge
│       │   ├── seed.py              # Geographic zone seeder
│       │   ├── models.py            # SQLAlchemy ORM models
│       │   ├── schemas.py           # Pydantic request/response schemas
│       │   └── database.py          # DB engine and session factory
│       ├── tests/
│       │   └── stress_test.py       # Critical E2E stress test suite
│       ├── build.ps1                # Automatic container publish
│       ├── docker-compose.yml
│       ├── Dockerfile
│       ├── mosquitto.conf
│       ├── requirements.txt         # Python requirements for backend development
│       └── .env.example
├── mobile/
│   ├── app/                         # Expo Router screens
│   │   └── (tabs)/
│   │       ├── index.tsx            # Monitor / Dashboard
│   │       ├── map.tsx              # Sensor Network Map
│   │       └── settings.tsx         # User Preferences
│   ├── api/                     # Axios client + TanStack Query hooks
│   ├── components/              # Shared UI components
│   ├── store/                   # Zustand state slices
│   ├── context/
│   │   └── WebSocketContext.tsx     # Real-time alert context
│   └── constants/
│       └── config.ts                # Centralized configuration
└── firmware/
    └── esp32_code/
        ├── src/
        │   ├── main.cpp             # FreeRTOS tasks, STA/LTA, MQTT, provisioning
        │   └── RingBuffer.h         # Statically allocated circular buffer
        ├── test/                    # Test scripts to insert into the ESP32
        ├── key_generator/
        │   └── key_gen.py           # ECDSA key generator for backend testing
        ├── esp32_config.env.example
        ├── extra_script.py          # ENV variables injector
        └── platformio.ini

🔮 Roadmap

Version Focus
v1.0 ✅ Current — full E2E pipeline, mobile app, CI/CD
v1.1 Documentation wiki, Alembic migrations, cloud MQTT broker
v2.0 AI-powered seismic intelligence assistant (Ollama + natural language queries)

📄 License

This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). See the LICENSE file for details.


Developed by GiZano and riccardo0731
Open Source — AGPL-3.0 License

About

Development of a real-time earthquake detection system, to alert the population even in areas where there isn’t a dedicated relevation system. The solution will realize stand-alone detectors, which will be applicable to appliances in the future. The data will be sent to a server which will then send an alert in case of a seismic wave.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors