A production-quality IoT monitoring and actuator control system built to manage and oversee smart drainage structures. It features real-time telemetry streaming from an Arduino UNO, a thread-safe Flask python backend, and a modern Next.js 15 debugging dashboard.
- Microcontroller: Arduino UNO
- Liquid Sensors: Analog Water Level/Raindrop sensor (
A0) - Depth/Level Sensor: Ultrasonic Range Finder (
Trig: Pin 9,Echo: Pin 10) - Visual HUD: 16x2 I2C LCD Display (
0x27) - Status Signaling: LED Indicator Array (
Green: Pin 2,Yellow: Pin 3,Red: Pin 4) - Actuator Control: Active-LOW Solar Pump Relay Switch (
Pin 5)
- Runtime: Python 3.10+
- Framework: Flask & Flask-CORS
- Serial Handler: Background daemon thread utilizing
pySerialwith a 3.0s watchdog heartbeat monitor. - WebSocket Server:
Flask-SocketIOwith cooperativethreadingasync mode.
- Framework: Next.js 15 (App Router)
- Language: TypeScript
- Styling: Tailwind CSS & Vanilla CSS
- Polling Rate: 1-second REST HTTP polling with direct CORS bindings to
127.0.0.1to bypass Windows IPv6 DNS delays.
The Arduino UNO and Flask backend exchange data over USB Serial at 9600 Baud.
Sent every 500ms as a single line-terminated (\n) JSON string:
{
"waterDetected": false,
"waterSensor": 11,
"distance": 8.50,
"waterLevel": 18,
"status": "NORMAL",
"pumpRunning": false,
"relay": false
}waterDetected(boolean): True if liquid is touching the water sensor plate.waterSensor(int): Raw analog sensor value fromA0(0 - 1023).distance(float): Computed distance in cm from the ultrasonic sensor.waterLevel(int): Computed fill percentage (0% to 100%) inside the drain.status(string): System state (NORMAL,WARNING,CHECKING,BLOCKAGE).pumpRunning(boolean): Active motor status.relay(boolean): Physical relay contact state.
Commands are written directly to the serial buffer as raw, newline-terminated keywords:
PUMP_ON\n- Closes the relay (LOW) and turns the drainage pump ON.PUMP_OFF\n- Opens the relay (HIGH) and turns the drainage pump OFF.RESET\n- Resets the blockage timers and stops the pump.
Returns the current drainage monitoring states, connection parameters, history queues, and events logs.
- Response:
{ "latest_state": { "timestamp": "2026-07-05T19:53:01.139914", "waterDetected": false, "waterSensor": 11, "distance": 8.5, "waterLevel": 18, "status": "NORMAL", "pumpRunning": false, "relay": false }, "connection_health": { "connected": true, "port": "COM3", "baud_rate": 9600, "packets_received": 142, "packets_dropped": 0, "malformed_packets": 0, "reconnect_attempts": 0, "last_packet_received": "2026-07-05T19:53:01.139914", "last_successful_command": "PUMP_ON", "last_command_status": "SUCCESS" }, "history": [...], "events": [...] }
Schedules manual controls to be dispatched to the serial thread queue.
- Request Body:
{ "command": "PUMP_ON" // Options: "PUMP_ON", "PUMP_OFF", "RESET" } - Response:
{ "success": true, "command": "PUMP_ON", "message": "Command PUMP_ON scheduled for transmission." }
- Open the Arduino IDE.
- Install the LiquidCrystal_I2C library (by Frank de Brabander).
- Connect your Arduino UNO to your PC.
- Upload the sketch code to the board.
- Important: Close the Serial Monitor in the Arduino IDE before launching the Flask server. Only one program can lock the COM port at a time.
- Navigate to the
backend/directory:cd backend - Create and activate a Python virtual environment:
python -m venv venv # On Windows (PowerShell): .\venv\Scripts\Activate # On Linux/macOS: source venv/bin/activate
- Install dependencies:
pip install -r requirements.txt
- Start the Flask server:
The background thread will scan COM ports automatically, connect, and wait for your Arduino to finish booting up before initiating the heartbeat watchdog.
python app.py
- Navigate to the
frontend/directory:cd frontend - Install dependencies:
npm install
- Start the Next.js development server:
npm run dev
- Open your browser and navigate to:
http://127.0.0.1:3000
If the dashboard stays on "Loading telemetry from Flask backend..." for more than 5 seconds:
- Ensure your browser is pointing to
http://127.0.0.1:3000rather thanhttp://localhost:3000. - Stop your dev server (
Ctrl + C) and clear the webpack caching directory using PowerShell:Remove-Item -Recurse -Force .next
- Restart using
npm run devand perform a hard-refresh (Ctrl + F5orCmd + Shift + R).