Skip to content
JezuePublic

About

Autonomous Flood Protection System ๐ŸŒŠ

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

ย 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

FloodGate Logo

FloodGate: Autonomous Flood Protection System

Autonomous Flood Protection System
IoT-based automated flood barrier with real-time monitoring and control

Hardware โ€ข ๐Ÿ‡ต๐Ÿ‡ฑ Polski


๐ŸŽฏ Purpose

FloodGate is an IoT system designed for automated flood protection. It combines local water detection (responding without cloud dependency) with remote monitoring and control (Web Dashboard / Smartphone). The system supports both automatic operation and manual override by the user.

Applications include:

  • Garage Entrances: Protect basement garages from street flooding
  • Building Entrances: Secure ground-floor premises during heavy rainfall
  • Industrial Sites: Protect critical infrastructure and storage areas
  • Technical Gates: Automated barrier for access points vulnerable to water damage

๐ŸŒ Language / Jฤ™zyk

Default language is Polish. To switch UI to English:

cd scripts
python switch_language.py en    # Switch to English
python switch_language.py pl    # Switch back to Polish

This changes:

  • ESP32 OLED display labels (Wodaโ†’Water, Bramaโ†’Gate)
  • SMS messages sent by device
  • Frontend dashboard UI text

After switching, rebuild ESP32 firmware: pio run


โœจ Features

Feature Description
๐Ÿšจ Automatic Flood Detection Water sensor triggers immediate gate closure
๐Ÿ“ฑ Real-time Dashboard React-based mobile-friendly interface
โฑ๏ธ Fail-safe Timer Configurable countdown before auto-close
๐Ÿ”” SMS Alerts Notifications via MQTT (Wokwi simulation)
๐Ÿ“Š Telemetry Logging TimescaleDB time-series storage
๐ŸŒค๏ธ Weather Integration Current weather from Open-Meteo API
๐Ÿ”„ Two Operation Modes AUTOMATIC (instant) or MANUAL (confirmation)
๐ŸŽฎ ESP32 Simulator Full Wokwi integration in VS Code
๐Ÿ”Œ Autonomous Operation Non-blocking MQTT - works offline
๐Ÿ“… Scheduler Support Automated daily raise/drop times

๐Ÿ—๏ธ Architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  FRONTEND - React 19 + Vite + TailwindCSS            โ”‚
โ”‚  http://localhost:5173                               โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                         โ”‚ HTTP REST
                         โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  BACKEND API - FastAPI (Python 3.12)                 โ”‚
โ”‚  http://localhost:8001                               โ”‚
โ”‚  Endpoints: /status, /command, /settings, /mode     โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                         โ”‚ MQTT
          โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
          โ–ผ                             โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  MQTT Broker     โ”‚โ—„โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚  Worker (Python)         โ”‚
โ”‚  Mosquitto:1883  โ”‚         โ”‚  Telemetry โ†’ Database    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜         โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
         โ”‚
         โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  ESP32-S3 (Wokwi Simulator)                          โ”‚
โ”‚  Water Sensor, Stepper Motor, OLED, LEDs             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
         โ”‚
         โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  DATABASE - TimescaleDB (PostgreSQL 15)              โ”‚
โ”‚  Port: 5434                                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Flow 1: Telemetry (Every 30s)

                    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                    โ”‚  ESP32 sends    โ”‚
                    โ”‚  sensor data    โ”‚
                    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                             โ”‚
                             โ–ผ
                    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                    โ”‚  MQTT Broker    โ”‚
                    โ”‚  receives msg   โ”‚
                    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                             โ”‚
                             โ–ผ
                    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                    โ”‚  Worker stores  โ”‚
                    โ”‚  in Database    โ”‚
                    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                             โ”‚
                             โ–ผ
               โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
               โ”‚  Data: water_level, battery โ”‚
               โ”‚  gate_state, timestamp      โ”‚
               โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Flow 2: Manual Command (User clicks button)

                    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                    โ”‚  User clicks    โ”‚
                    โ”‚  gate button    โ”‚
                    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                             โ”‚
                             โ–ผ
                    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                    โ”‚  Frontend sends โ”‚
                    โ”‚  POST /command  โ”‚
                    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                             โ”‚
                             โ–ผ
                    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                    โ”‚  API publishes  โ”‚
                    โ”‚  to MQTT        โ”‚
                    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                             โ”‚
                             โ–ผ
                    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                    โ”‚  ESP32 receives โ”‚
                    โ”‚  and moves gate โ”‚
                    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                             โ”‚
                             โ–ผ
                    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                    โ”‚  Telemetry sent โ”‚
                    โ”‚  with new state โ”‚
                    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Flow 3: Water Detection (with Cancel/Confirm)

                    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                    โ”‚ Water Detected  โ”‚
                    โ”‚ (sensor > 2000) โ”‚
                    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                             โ”‚
              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
              โ–ผ                             โ–ผ
       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”               โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
       โ”‚ AUTOMATIC  โ”‚               โ”‚    MANUAL     โ”‚
       โ”‚   MODE     โ”‚               โ”‚     MODE      โ”‚
       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜               โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
              โ”‚                             โ”‚
              โ–ผ                             โ–ผ
       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”               โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
       โ”‚Close gate  โ”‚               โ”‚ Show Fail-Safeโ”‚
       โ”‚immediately โ”‚               โ”‚ Modal (5 min) โ”‚
       โ”‚Send SMS    โ”‚               โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                       โ”‚
                               โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                               โ–ผ            โ–ผ            โ–ผ
                       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                       โ”‚  CLOSE   โ”‚  โ”‚  CANCEL  โ”‚  โ”‚  TIMEOUT โ”‚
                       โ”‚  NOW     โ”‚  โ”‚  (ignore)โ”‚  โ”‚  (5 min) โ”‚
                       โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜
                            โ”‚             โ”‚             โ”‚
                            โ–ผ             โ–ผ             โ–ผ
                     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                     โ”‚Close gate  โ”‚ โ”‚Gate stays  โ”‚ โ”‚Close gate  โ”‚
                     โ”‚Send SMS:   โ”‚ โ”‚OPEN        โ”‚ โ”‚Send SMS:   โ”‚
                     โ”‚"Confirmed" โ”‚ โ”‚User takes  โ”‚ โ”‚"Timeout"   โ”‚
                     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚responsibilityโ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Flow 4: Scheduled Action

                    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                    โ”‚ Worker checks   โ”‚
                    โ”‚ schedules table โ”‚
                    โ”‚ (every minute)  โ”‚
                    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                             โ”‚
              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
              โ–ผ                             โ–ผ
       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”               โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
       โ”‚  No match  โ”‚               โ”‚ Time matches  โ”‚
       โ”‚  (skip)    โ”‚               โ”‚ enabled rule  โ”‚
       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜               โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                            โ”‚
                              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                              โ–ผ                           โ–ผ
                       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”             โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                       โ”‚ Water NOT  โ”‚             โ”‚ Water IS   โ”‚
                       โ”‚ detected   โ”‚             โ”‚ detected   โ”‚
                       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜             โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”˜
                              โ”‚                          โ”‚
                              โ–ผ                          โ–ผ
                       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”             โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                       โ”‚ Execute    โ”‚             โ”‚ SKIP actionโ”‚
                       โ”‚ scheduled  โ”‚             โ”‚ Safety has โ”‚
                       โ”‚ action     โ”‚             โ”‚ priority!  โ”‚
                       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜             โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿš€ Quick Start

Prerequisites

  • Docker (for containers)
  • Python 3.10+ with pip
  • Node.js 18+ with npm
  • VS Code with PlatformIO extension (for ESP32)

1. Start Infrastructure (Docker)

cd backend-infrastructure
docker-compose up -d

Starts:

  • floodgate_db - TimescaleDB on port 5434
  • floodgate_mqtt - Mosquitto on port 1883

2. Start Backend API

cd backend-core
pip install -r requirements.txt
python run_api.py

API available at http://localhost:8001

3. Start MQTT Worker

cd backend-core
python worker.py

4. Start Frontend

cd frontend
npm install
npm run dev

Dashboard at http://localhost:5173

5. Configure ESP32 Firmware Secrets

Before running the ESP32 firmware, you must set up your network credentials:

First time setup:

cd firmware
cp include/Secrets.h.example include/Secrets.h

Then edit firmware/include/Secrets.h with your actual credentials:

#define WIFI_SSID "YOUR_WIFI_SSID"        // Your WiFi network name
#define WIFI_PASS "YOUR_WIFI_PASSWORD"    // Your WiFi password
#define MQTT_SERVER "YOUR_MQTT_IP"        // MQTT broker IP address

For Wokwi simulation:

  • WIFI_SSID: "Wokwi-GUEST"
  • WIFI_PASS: "" (empty)
  • MQTT_SERVER: Your PC's IP address (run ipconfig on Windows, ip a on Linux/macOS)

Important: include/Secrets.h is gitignored and will NOT be committed to the repository for security.

6. Run ESP32 Simulator (Wokwi)

  1. Open firmware/ folder in VS Code
  2. Install Wokwi for VS Code extension
  3. Press F1 โ†’ "Wokwi: Start Simulator"
  4. Firmware will compile with credentials from include/Secrets.h

๐Ÿ› ๏ธ Technology Stack

Frontend

Technology Version Purpose
React 19.2.0 UI Framework
TypeScript 5.9.3 Type Safety
Vite 7.2.4 Build Tool
TailwindCSS 4.1 Styling
TanStack Query 5.x Server State
Zustand 4.x Client State
Framer Motion 11.x Animations
Axios 1.x HTTP Client

Backend

Technology Version Purpose
FastAPI 0.109 REST API
Python 3.12 Runtime
Paho MQTT 2.0 MQTT Client
SQLAlchemy 2.x ORM
AsyncPG 0.29 PostgreSQL Driver
Uvicorn 0.27 ASGI Server

Infrastructure

Technology Version Purpose
TimescaleDB 2.x Time-series Database
PostgreSQL 15 Database Engine
Mosquitto 2.x MQTT Broker
Docker 24.x Containerization

Firmware

Technology Version Purpose
ESP32-S3 - Microcontroller
Arduino 2.0.6 Framework
PlatformIO 6.x Build System
PubSubClient 2.8 MQTT Library
ArduinoJson 6.21 JSON Parsing
Adafruit SSD1306 2.5 OLED Display

๐Ÿ“ Project Structure

INZYNIERKA/
โ”œโ”€โ”€ backend-core/           # Python API + Worker
โ”‚   โ”œโ”€โ”€ main.py             # FastAPI application
โ”‚   โ”œโ”€โ”€ worker.py           # MQTT โ†’ Database bridge
โ”‚   โ”œโ”€โ”€ database.py         # SQLAlchemy models
โ”‚   โ””โ”€โ”€ requirements.txt
โ”œโ”€โ”€ backend-infrastructure/ # Docker services
โ”‚   โ””โ”€โ”€ docker-compose.yml
โ”œโ”€โ”€ frontend/               # React application
โ”‚   โ”œโ”€โ”€ src/
โ”‚   โ”‚   โ”œโ”€โ”€ components/     # UI components
โ”‚   โ”‚   โ”œโ”€โ”€ hooks/          # Custom React hooks
โ”‚   โ”‚   โ”œโ”€โ”€ api/            # API client
โ”‚   โ”‚   โ””โ”€โ”€ App.tsx
โ”‚   โ””โ”€โ”€ package.json
โ”œโ”€โ”€ firmware/               # ESP32 code
โ”‚   โ”œโ”€โ”€ src/main.cpp        # Main firmware
โ”‚   โ”œโ”€โ”€ platformio.ini      # PlatformIO config
โ”‚   โ”œโ”€โ”€ diagram.json        # Wokwi circuit
โ”‚   โ””โ”€โ”€ wokwi.toml          # Wokwi config
โ”œโ”€โ”€ scripts/
โ”‚   โ””โ”€โ”€ switch_language.py  # PL/EN language switcher
โ”œโ”€โ”€ simulation/             # HIL testing tools
โ””โ”€โ”€ README.md

๐ŸŽฎ Wokwi Simulation

This project uses Wokwi for ESP32 simulation, integrated into VS Code.

Setup

  1. Install VS Code extension: Wokwi for VS Code
  2. Get free license at https://wokwi.com/license
  3. Open firmware/diagram.json
  4. Press F1 โ†’ "Wokwi: Start Simulator"

Circuit Components

Component GPIO Function
Water Sensor GPIO4 Analog input (0-50cm)
Battery Sensor GPIO5 Analog input (0-100%)
Stepper STEP GPIO10 Motor control
Stepper DIR GPIO11 Motor direction
Red LED GPIO16 Gate closing indicator
Green LED GPIO17 Gate opening indicator
OLED SDA GPIO18 Display data
OLED SCL GPIO19 Display clock

SMS Simulation

The sendSMS() function publishes to MQTT topic debug/sms instead of sending real SMS. This is for Wokwi compatibility. For production with SIM800L module, replace the implementation with AT commands.


๐Ÿ“Š API Reference

GET /api/v1/status/{device_id}

Returns current device status with weather data.

{
  "device_id": "ESP32_MAIN_001",
  "telemetry": {
    "water_level_cm": 3.2,
    "gate_closed": 0,
    "battery_pct": 85,
    "state": "IDLE",
    "scheduler_locked": 0
  },
  "logic": {
    "current_mode": "AUTOMATIC",
    "current_state_code": 0,
    "fail_safe_deadline": null
  },
  "weather": {
    "temperature": 12.5,
    "precipitation": 0.0
  }
}

Telemetry Fields:

  • water_level_cm - Water level in centimeters (0-50cm range)
  • gate_closed - Gate state: 0=OPEN, 1=CLOSED
  • battery_pct - Battery percentage (0-100%)
  • state - System state: IDLE, WATER_DETECTED, CLOSED, AUTO_DROP, etc.
  • scheduler_locked - Scheduler lock: 0=unlocked, 1=locked (water detected)

Note: Firmware also sends backward-compatible fields (water_sensor_status, curtain_state, battery_soc_perc) for legacy compatibility.

POST /api/v1/command

Send manual command to device.

{
  "device_id": "ESP32_MAIN_001",
  "action": "DROP" // or "RAISE"
}

GET /api/v1/telemetry

Get historical telemetry data (time-series).

Query Parameters:

  • device_id - Device identifier (default: ESP32_MAIN_001)
  • limit - Number of records (default: 100)

Response: Array of telemetry records with timestamps.

GET /api/v1/alarms

Get alarm history (water detection events).

Query Parameters:

  • device_id - Device identifier
  • limit - Number of records (default: 50)

GET /api/v1/commands

Get command history (user actions, scheduler actions).

Query Parameters:

  • device_id - Device identifier
  • limit - Number of records (default: 50)

GET /api/v1/schedules

Get configured automation schedules.

Response:

[
  {
    "id": 1,
    "device_id": "ESP32_MAIN_001",
    "action_type": "daily_raise",
    "hour": 8,
    "minute": 0,
    "days": ["mon", "tue", "wed", "thu", "fri"],
    "active": true,
    "custom_label": "Morning open"
  }
]

Scheduler Features:

  • Automated daily raise/drop at configured times
  • Day-of-week filtering (e.g., weekdays only)
  • Safety override: scheduler locked when water detected
  • Worker monitors schedules every minute

โš ๏ธ Limitations & Design Decisions

This section documents known limitations and architectural choices that represent acceptable trade-offs for the current scope.

1. Frontend: HTTP Polling vs WebSockets

Current Implementation: The React dashboard uses HTTP Polling (5-second interval) to fetch device status from the backend API.

Why Polling?

  • Simplified Architecture: Avoids WebSocket infrastructure complexity for the scope of this thesis project
  • Backend Infrastructure: The backend (FastAPI) already provides a robust REST API; existing MQTT connection for device communication
  • Cross-platform Compatibility: HTTP polling works consistently across all network conditions (firewalls, proxies)
  • Single Source of Truth: Device state is computed server-side; frontend just reflects current state
  • Sufficient for Flood Monitoring: 5-second refresh interval is acceptable for this use case (gates don't move faster than ~30 seconds)

Trade-off: The UI refreshes every 5 seconds, so user actions may appear with up to 5-second delay. If someone closes the gate, the UI updates within the next polling cycle (max 5sec).

When WebSockets Would Be Preferred:

  • Enterprise deployment with thousands of concurrent dashboards
  • Real-time dashboards requiring sub-second response (e.g., stock trading)
  • Bandwidth-constrained environments (polling 5sec ร— 1000 clients = significant overhead)

Production Path: To upgrade to WebSockets:

# Backend: Add python-socketio and python-socketio[aiohttp]
from socketio import AsyncServer
# Push device updates to connected clients via MQTT bridges

Implementation Details: See frontend/README.md for polling configuration (staleTime: 0, refetchInterval: 5000, etc.).

2. SMS Notifications: MQTT Debug Topic (Simulation)

Current Implementation: sendSMS() function publishes to MQTT topic debug/sms for Wokwi simulation compatibility.

How It Works:

  • Dashboard can subscribe to debug/sms to receive "SMS" messages
  • Useful for testing without real GSM hardware
  • No actual SMS sent in simulation mode

Production Implementation: Requires SIM800L GSM module with AT command implementation.

Setup for Production:

  1. Connect SIM800L module to ESP32 UART (GPIO5=RX, GPIO4=TX by default)
  2. Set phone number in firmware/include/Secrets.h:
    #define GSM_PHONE_NUMBER "+48XXXXXXXXX"
  3. Uncomment SIM800L code block in firmware/src/main.cpp in sendSMS() function
  4. Requires dedicated 4.2V power supply for GSM module

Code Template Provided: See firmware/README.md for complete AT command reference and production code example.

3. Motor Control: Non-Blocking Architecture

Design Challenge: Initial blocking delayMicroseconds() loops during gate movement locked the processor, preventing MQTT client.loop() from executing. This resulted in connection timeouts and unresponsive user commands during operation.

Architectural Solution: Implemented AccelStepper library with non-blocking state machine. The updateStepperMotion() function executes every loop iteration (~2ms per step), enabling concurrent MQTT processing between motor steps.

Result: Device maintains responsive MQTT communication and processes user commands immediately during gate movement.

Implementation Details: See firmware/README.md for architecture diagram and code details.

4. Non-Blocking MQTT Reconnect

Design Challenge: Initial implementation used blocking MQTT connection loop in setup(), preventing ESP32 from booting if broker was unavailable. Device would hang indefinitely showing "Booting..." on OLED.

Architectural Solution:

  • Setup Phase: Max 3 connection attempts with 1-second timeout each
  • Loop Phase: Non-blocking reconnect every 30 seconds
  • Autonomous Mode: Device operates fully offline if MQTT unavailable

Implementation:

// setup() - Try 3 times, then continue
int mqttAttempts = 0;
while (!client.connected() && mqttAttempts < 3) {
  if (client.connect(DEVICE_ID)) break;
  mqttAttempts++;
  delay(1000);
}
// Continue regardless of connection status

// loop() - Retry every 30 seconds (non-blocking)
static unsigned long lastMqttRetry = 0;
if (!client.connected() && (millis() - lastMqttRetry > 30000)) {
  lastMqttRetry = millis();
  client.connect(DEVICE_ID);  // Single attempt, no blocking
}

Benefits:

  • โœ… ESP32 boots in 3-4 seconds even without MQTT broker
  • โœ… Sensors, OLED, and motor control work offline
  • โœ… Automatic reconnection when broker becomes available
  • โœ… Water detection and auto-close work without backend

Result: Device is fully autonomous and resilient to network failures.

5. Manual Fail-Safe Timer Trigger

The fail-safe countdown relies on client-side timer (setInterval). For critical systems, this should run server-side with the device itself enforcing the timeout via hardware interrupt (E-STOP button for production).

Current Safety Level: Device has hardware E-STOP interrupt (GPIO2 pull-to-ground). Even if software fails, gate can be stopped physically.

6. Credentials Management

Design Choice: Sensitive credentials (WiFi, MQTT, GSM phone) stored in gitignored Secrets.h file, never committed to repository.

How It Works:

  • firmware/include/Secrets.h.example provides template
  • User copies to Secrets.h and fills in credentials
  • .gitignore prevents accidental commit

Production Safety: Each device deployment has unique Secrets.h; credentials not exposed in git history or public repositories.

Implementation: See firmware/README.md for setup instructions.

7. EEPROM Wear Protection

Design Choice: Gate position saved to EEPROM only when changed (not every movement). Extends device lifetime from ~273 years to 137+ years within the 100k write cycle limit.

Calculation:

  • Estimated usage: 2 movements/day
  • Writes per year: 730
  • Lifetime: 100,000 รท 730 = 137+ years โœ“

Implementation: See firmware/README.md for code and monitoring details.


๐Ÿ“ License

This project is licensed under the PolyForm Noncommercial 1.0.0 - see the LICENSE file for details.

โš ๏ธ LICENSE: This project is shared under the PolyForm Noncommercial 1.0.0 license.

  • โœ… Free: For private, educational, and hobbyist use (Self-Hosted).
  • โŒ Paid/Requires Permission: For any commercial use, resale, or commercial deployment.

For commercial licensing inquiries (B2B), please contact: adam.gajewski.art@gmail.com

๐ŸŽ“ Created as an engineering thesis project.


Made with โค๏ธ using ESP32 and Python

About

Autonomous Flood Protection System ๐ŸŒŠ

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages