Sunday, 11 October 2026

AI Sleep Detection & Driver Alert System

 

AI Sleep Detection & Driver Alert System

ESP32 + AI + IoT Web Dashboard + n8n Automation + Telegram Voice Alerts + Google Sheets + ThingSpeak

This project is designed to detect signs of driver drowsiness, immediately alert the driver, and send monitoring data to an IoT dashboard. It combines an ESP32-based embedded system with AI-assisted event analysis, n8n automation, Telegram notifications, Google Sheets data logging, and ThingSpeak cloud visualization.

AI-Assisted Driver Drowsiness Detection System Using RPI4 - Hackster.io
 
 
 
Driver Safety Monitoring System | AI Alerts to Prevent Accidents – LogisFleet
 
 
 
ESP32 IOT Dashboard. | ESP32
 
9
 

Proposed project title

AI-Powered IoT-Based Driver Sleep Detection and Alert System Using ESP32, AI Agent, n8n Automation, Telegram Voice Notifications, Google Sheets and ThingSpeak Cloud Dashboard.

The key safety principle is that drowsiness detection and the immediate local warning must work even if Wi-Fi, the cloud, or n8n is unavailable. Cloud AI and automation are supplementary features, not the only way to alert a sleepy driver.

1. Project abstract

Driver fatigue and drowsiness can reduce attention, slow reaction time, and increase road-safety risks. This project proposes an embedded driver-monitoring prototype that identifies possible drowsiness from eye-closure signals, activates a local alarm, and transmits event information to a cloud-connected monitoring platform.

The ESP32 collects sensor data and evaluates a configurable drowsiness rule. When a possible drowsiness event occurs, a buzzer and warning LED activate. The ESP32 then sends an event through Wi-Fi to an n8n webhook. The n8n workflow can log the event in Google Sheets, send Telegram notifications, and update the IoT monitoring dashboard. An AI agent can summarize repeated events and produce human-readable reports.

For a camera-based version, an ESP32-S3 camera board can be used to develop an eye-state detection model. Espressif provides the ESP32-S3-EYE platform and ESP-WHO computer-vision framework as a starting point for embedded vision development. Eye-closure detection for driving requires a suitable model and validation beyond basic face detection.

documentation.espressif.com
+1

 

Project objectives

  • Detect prolonged eye closure or other signs of possible drowsiness.

  • Trigger an immediate local buzzer and LED warning.

  • Display system status on an IoT webpage.

  • Automate alerts through n8n and Telegram.

  • Record event time, duration, and alert level in Google Sheets.

  • Visualize numerical monitoring data using ThingSpeak.

  • Use an AI agent to analyze event history and summarize risk patterns.

  • Continue local warning operation if cloud connectivity fails.

2. System architecture

Driver monitoring sensors

IR eye-blink sensor for the starter prototype, or camera-based eye-state AI

 

ESP32 / ESP32-S3 controller

Evaluate eye state, track closure duration, trigger buzzer and LED

Wi-Fi event transmission

n8n automation and AI agent

Webhook → event validation → logging → alerting → optional AI summary

Telegram

Text and optional voice alerts

Google Sheets

Event history and reports

ThingSpeak

Time-series charts

IoT webpage

Live status and event history

Important design distinction: the local alarm is controlled by the ESP32. The cloud system handles remote notifications, recordkeeping, visualization, and optional AI analysis. The AI agent must not be the sole mechanism responsible for an urgent driver warning.

3. Hardware components required

For the first working prototype, use a digital eye-blink sensor. It is simpler to test than a camera-based AI model and helps you build the complete IoT automation pipeline first.

GitHub - TronixLab/DOIT_ESP32_DevKit-v1_30P · GitHub
 
 
 

1. ESP32 DevKit V1

Main microcontroller

Handles sensor readings, drowsiness timing, the local alarm, and Wi-Fi communication.

 
Eye Blink Sensor (High Quality) With Goggle
 – Harish Projects
 
 
 

2. IR eye-blink sensor module

Driver eye-state input

Supplies a digital signal representing detected eye/blink states. Verify its output polarity and whether it can reliably distinguish open eyes from closed eyes before setting thresholds.

 
Active Buzzer Module - 3.3-5V | Fastbit Embedded
 
 
 

3. Active buzzer

Generates the immediate audible warning. Use a suitable transistor driver if the buzzer current exceeds the GPIO's safe output capability.

 
Chanzon Breadboard Kit - Solderless Prototype with Morocco | Ubuy
 
 
 

4. Red LED, 220–330 Ω resistor, breadboard and jumper wires

Visual warning and circuit prototyping.

 
Espressif ESP32-S3-EYE - ESP32-S3 Camera Board - The Pi Hut
 
 
 

5. Optional camera AI upgrade

Use an ESP32-S3-EYE or another supported camera platform for face/eye tracking. The camera version requires camera-specific firmware and a validated eye-state model; the starter code below does not perform image-based AI.

You will also need a USB data cable, a computer, Wi-Fi, an n8n instance, a Telegram bot, a Google account, and a ThingSpeak account.

4. Circuit / schematic diagram

This is the proposed wiring for the digital IR-sensor starter version.

IR eye-blink sensor

VCC → suitable supply voltage for the module

GND → GND

OUT → GPIO 27

 

ESP32 DevKit V1

GPIO 27: sensor input

GPIO 26: buzzer driver output

GPIO 25: LED output

GND: common ground

GPIO 26

Buzzer driver

Then buzzer and suitable supply

GPIO 25

220–330 Ω resistor

Then LED → GND

Connect all grounds together. Confirm sensor voltage compatibility and output polarity before connecting it to the ESP32. Never feed 5 V directly into an ESP32 GPIO.

Pin connection table

Component

ESP32 connection

IR sensor OUT

GPIO 27

Active buzzer driver input

GPIO 26

LED anode through resistor

GPIO 25

Sensor GND

GND

Buzzer-driver GND

GND

Sensor VCC

Per module specification

For a camera-based version, follow the camera board's own pin mapping. Do not reuse these GPIO assignments blindly on an ESP32-S3 camera board, because camera and peripheral pins may already be allocated.

5. Flowchart of the complete system

#chatgpt-mermaid-_r_c9_{font-family:-apple-system-body,ui-sans-serif,-apple-system,system-ui,"Segoe UI",Helvetica,"Apple Color Emoji",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";font-size:16px;fill:rgb(13, 13, 13);}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#chatgpt-mermaid-_r_c9_ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#chatgpt-mermaid-_r_c9_ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#chatgpt-mermaid-_r_c9_ .error-icon{fill:rgb(243, 243, 243);}#chatgpt-mermaid-_r_c9_ .error-text{fill:rgb(13, 13, 13);stroke:rgb(13, 13, 13);}#chatgpt-mermaid-_r_c9_ .edge-thickness-normal{stroke-width:1px;}#chatgpt-mermaid-_r_c9_ .edge-thickness-thick{stroke-width:3.5px;}#chatgpt-mermaid-_r_c9_ .edge-pattern-solid{stroke-dasharray:0;}#chatgpt-mermaid-_r_c9_ .edge-thickness-invisible{stroke-width:0;fill:none;}#chatgpt-mermaid-_r_c9_ .edge-pattern-dashed{stroke-dasharray:3;}#chatgpt-mermaid-_r_c9_ .edge-pattern-dotted{stroke-dasharray:2;}#chatgpt-mermaid-_r_c9_ .marker{fill:rgb(143, 143, 143);stroke:rgb(143, 143, 143);}#chatgpt-mermaid-_r_c9_ .marker.cross{stroke:rgb(143, 143, 143);}#chatgpt-mermaid-_r_c9_ svg{font-family:-apple-system-body,ui-sans-serif,-apple-system,system-ui,"Segoe UI",Helvetica,"Apple Color Emoji",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";font-size:16px;}#chatgpt-mermaid-_r_c9_ p{margin:0;}#chatgpt-mermaid-_r_c9_ .label{font-family:-apple-system-body,ui-sans-serif,-apple-system,system-ui,"Segoe UI",Helvetica,"Apple Color Emoji",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_c9_ .cluster-label text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_c9_ .cluster-label span{color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_c9_ .cluster-label span p{background-color:transparent;}#chatgpt-mermaid-_r_c9_ .label text,#chatgpt-mermaid-_r_c9_ span{fill:rgb(13, 13, 13);color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_c9_ .node rect,#chatgpt-mermaid-_r_c9_ .node circle,#chatgpt-mermaid-_r_c9_ .node ellipse,#chatgpt-mermaid-_r_c9_ .node polygon,#chatgpt-mermaid-_r_c9_ .node path{fill:rgb(222, 234, 251);stroke:rgb(83, 154, 248);stroke-width:1px;}#chatgpt-mermaid-_r_c9_ .rough-node .label text,#chatgpt-mermaid-_r_c9_ .node .label text,#chatgpt-mermaid-_r_c9_ .image-shape .label,#chatgpt-mermaid-_r_c9_ .icon-shape .label{text-anchor:middle;}#chatgpt-mermaid-_r_c9_ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#chatgpt-mermaid-_r_c9_ .rough-node .label,#chatgpt-mermaid-_r_c9_ .node .label,#chatgpt-mermaid-_r_c9_ .image-shape .label,#chatgpt-mermaid-_r_c9_ .icon-shape .label{text-align:center;}#chatgpt-mermaid-_r_c9_ .node.clickable{cursor:pointer;}#chatgpt-mermaid-_r_c9_ .root .anchor path{fill:rgb(143, 143, 143)!important;stroke-width:0;stroke:rgb(143, 143, 143);}#chatgpt-mermaid-_r_c9_ .arrowheadPath{fill:rgb(143, 143, 143);}#chatgpt-mermaid-_r_c9_ .edgePath .path{stroke:rgb(143, 143, 143);stroke-width:1px;}#chatgpt-mermaid-_r_c9_ .flowchart-link{stroke:rgb(143, 143, 143);fill:none;}#chatgpt-mermaid-_r_c9_ .edgeLabel{background-color:rgb(252, 252, 252);text-align:center;}#chatgpt-mermaid-_r_c9_ .edgeLabel p{background-color:rgb(252, 252, 252);}#chatgpt-mermaid-_r_c9_ .edgeLabel rect{opacity:0.5;background-color:rgb(252, 252, 252);fill:rgb(252, 252, 252);}#chatgpt-mermaid-_r_c9_ .labelBkg{background-color:rgba(252, 252, 252, 0.5);}#chatgpt-mermaid-_r_c9_ .cluster rect{fill:rgb(243, 243, 243);stroke:rgba(0, 0, 0, 0.1);stroke-width:1px;}#chatgpt-mermaid-_r_c9_ .cluster text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_c9_ .cluster span{color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_c9_ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:-apple-system-body,ui-sans-serif,-apple-system,system-ui,"Segoe UI",Helvetica,"Apple Color Emoji",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";font-size:12px;background:rgb(243, 243, 243);border:1px solid rgba(0, 0, 0, 0.1);border-radius:2px;pointer-events:none;z-index:100;}#chatgpt-mermaid-_r_c9_ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_c9_ rect.text{fill:none;stroke-width:0;}#chatgpt-mermaid-_r_c9_ .icon-shape,#chatgpt-mermaid-_r_c9_ .image-shape{background-color:rgb(252, 252, 252);text-align:center;}#chatgpt-mermaid-_r_c9_ .icon-shape p,#chatgpt-mermaid-_r_c9_ .image-shape p{background-color:rgb(252, 252, 252);padding:2px;}#chatgpt-mermaid-_r_c9_ .icon-shape .label rect,#chatgpt-mermaid-_r_c9_ .image-shape .label rect{opacity:0.5;background-color:rgb(252, 252, 252);fill:rgb(252, 252, 252);}#chatgpt-mermaid-_r_c9_ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#chatgpt-mermaid-_r_c9_ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#chatgpt-mermaid-_r_c9_ .node .neo-node{stroke:rgb(83, 154, 248);}#chatgpt-mermaid-_r_c9_ [data-look="neo"].node rect,#chatgpt-mermaid-_r_c9_ [data-look="neo"].cluster rect,#chatgpt-mermaid-_r_c9_ [data-look="neo"].node polygon{stroke:url(#chatgpt-mermaid-_r_c9_-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#chatgpt-mermaid-_r_c9_ [data-look="neo"].swimlane.cluster rect{filter:none;}#chatgpt-mermaid-_r_c9_ [data-look="neo"].node path{stroke:url(#chatgpt-mermaid-_r_c9_-gradient);stroke-width:1px;}#chatgpt-mermaid-_r_c9_ [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#chatgpt-mermaid-_r_c9_ [data-look="neo"].node .neo-line path{stroke:rgb(83, 154, 248);filter:none;}#chatgpt-mermaid-_r_c9_ [data-look="neo"].node circle{stroke:url(#chatgpt-mermaid-_r_c9_-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#chatgpt-mermaid-_r_c9_ [data-look="neo"].node circle .state-start{fill:#000000;}#chatgpt-mermaid-_r_c9_ [data-look="neo"].icon-shape .icon{fill:url(#chatgpt-mermaid-_r_c9_-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#chatgpt-mermaid-_r_c9_ [data-look="neo"].icon-shape .icon-neo path{stroke:url(#chatgpt-mermaid-_r_c9_-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#chatgpt-mermaid-_r_c9_ .node text{font-size:14px;font-weight:600;letter-spacing:normal;fill:rgb(0, 79, 153);}#chatgpt-mermaid-_r_c9_ .edgeLabels text{font-size:13px;font-weight:600;letter-spacing:-0.08px;fill:rgb(0, 79, 153);}#chatgpt-mermaid-_r_c9_ .node tspan[font-weight="normal"],#chatgpt-mermaid-_r_c9_ .edgeLabels tspan[font-weight="normal"]{font-weight:600;}#chatgpt-mermaid-_r_c9_ .edgeLabel .label rect{opacity:1;rx:13px;ry:13px;fill:rgb(245, 250, 255);stroke:rgb(206, 219, 229);stroke-width:1px;}#chatgpt-mermaid-_r_c9_ .node rect,#chatgpt-mermaid-_r_c9_ .node circle,#chatgpt-mermaid-_r_c9_ .node ellipse,#chatgpt-mermaid-_r_c9_ .node polygon,#chatgpt-mermaid-_r_c9_ .node path{fill:rgb(229, 243, 255);stroke:rgba(0, 0, 0, 0.1);stroke-width:1px;}#chatgpt-mermaid-_r_c9_ .node rect{rx:16px;ry:16px;}#chatgpt-mermaid-_r_c9_ .node.mermaid-decision .label-container{fill:rgb(245, 250, 255);stroke:rgb(206, 219, 229);stroke-dasharray:2,2;}#chatgpt-mermaid-_r_c9_ .edgePaths .flowchart-link{stroke:rgb(143, 143, 143);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;}#chatgpt-mermaid-_r_c9_ .marker{fill:rgb(143, 143, 143);stroke:rgb(143, 143, 143);}#chatgpt-mermaid-_r_c9_ :root{--mermaid-font-family:-apple-system-body,ui-sans-serif,-apple-system,system-ui,"Segoe UI",Helvetica,"Apple Color Emoji",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";}Power ONInitialize ESP32, sensor andalarmSensor signal valid?Show sensor fault and warnlocallyRead eye stateEyes closed?Reset closure timerMeasure continuous closuredurationClosure exceeds threshold?Activate buzzer and warningLEDSend event through Wi-FiCloud reachable?Keep local alarm activeRetry event transmissionn8n webhook receives eventLog event in Google SheetsSend Telegram alertUpdate ThingSpeak anddashboardOptional AI event summaryRe-evaluate eye stateNoYesNoYesNoYesNoYes

This flowchart represents the intended design. The cloud retries, persistent event queue, and sensor-fault detection must be implemented and tested in the final firmware before treating those features as operational.

6. How the system works — step by step

  1. System startup

    The ESP32 initializes the sensor input, warning LED, buzzer output, serial monitor, and Wi-Fi connection.

  2. Eye-state monitoring

    The sensor reports a signal that the firmware interprets as open or closed. Sensor placement and signal polarity must be verified experimentally.

  3. Drowsiness timing

    The ESP32 measures how long the signal continuously indicates closed eyes. A short closure is ignored; a prolonged closure triggers the configured warning.

  4. Local warning

    The buzzer and LED activate without waiting for an internet request. A real driver-monitoring system should also detect sensor obstruction, poor lighting, and invalid readings where applicable.

  5. IoT event upload

    The ESP32 sends an event containing a device identifier, event type, duration, and alert level to an n8n webhook.

  6. n8n automation

    n8n validates the payload, records it, and routes the event to the required services. The n8n Telegram integration supports sending messages through a configured bot.

    n8n Docs

     

  7. Cloud monitoring

    Google Sheets stores a history of events. ThingSpeak records numeric fields for time-series charts, and the webpage displays the latest status and event information.

  8. AI-agent analysis

    An AI agent can summarize repeated events, identify patterns in recorded data, and generate a daily report. Its output is advisory; it does not decide whether the local safety alarm activates.

7. ESP32 Arduino software code

The following is a starter firmware for the IR-sensor version. It implements the local warning and sends an event to an n8n webhook and ThingSpeak.

It assumes the sensor output is LOW when the eyes are detected as closed. If your module works in the opposite direction, change the configuration constant after testing.

Before uploading, install the ESP32 board package in Arduino IDE and configure the board for your exact ESP32 model.


#include <WiFi.h>
#include <HTTPClient.h>
#include <WiFiClientSecure.h>
#include <ArduinoJson.h>

// ---------- Wi-Fi ----------
const char* WIFI_SSID = "YOUR_WIFI_NAME";
const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD";

// ---------- n8n webhook ----------
// Example: https://your-n8n-domain/webhook/driver-event
const char* N8N_WEBHOOK =
  "https://YOUR_N8N_DOMAIN/webhook/driver-event";

// ---------- ThingSpeak ----------
const char* THINGSPEAK_WRITE_KEY = "YOUR_WRITE_API_KEY";

// ---------- GPIO (ESP32 DevKit V1 example) ----------
const int EYE_SENSOR_PIN = 27;
const int BUZZER_PIN = 26;
const int LED_PIN = 25;

// Verify sensor output polarity before using.
const int CLOSED_LEVEL = LOW;

// Demo threshold only. Must be calibrated and validated.
const unsigned long CLOSED_THRESHOLD_MS = 1500;
const unsigned long EVENT_COOLDOWN_MS = 10000;

unsigned long closedSince = 0;
unsigned long lastEvent = 0;
bool wasClosed = false;
bool alarmActive = false;
bool eventSentForClosure = false;

void connectWiFi() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

  Serial.print("Connecting to Wi-Fi...");
  unsigned long start = millis();

  while (WiFi.status() != WL_CONNECTED &&
         millis() - start < 15000) {
    delay(300);
    Serial.print(".");
  }

  Serial.println();

  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("Wi-Fi connected");
    Serial.println(WiFi.localIP());
  } else {
    Serial.println("Wi-Fi unavailable; local alarm remains active");
  }
}

void setAlarm(bool active) {
  alarmActive = active;
  digitalWrite(BUZZER_PIN, active ? HIGH : LOW);
  digitalWrite(LED_PIN, active ? HIGH : LOW);
}

bool postToN8n(unsigned long durationMs) {
  if (WiFi.status() != WL_CONNECTED) return false;

  WiFiClientSecure client;

  // DEMO ONLY: disables TLS certificate verification.
  // For production, configure the correct CA certificate.
  client.setInsecure();

  HTTPClient https;
  if (!https.begin(client, N8N_WEBHOOK)) return false;

  https.addHeader("Content-Type", "application/json");

  JsonDocument doc;
  doc["device_id"] = "driver-unit-01";
  doc["event"] = "DROWSINESS_WARNING";
  doc["eye_closed_ms"] = durationMs;
  doc["alert_level"] = "HIGH";
  doc["uptime_ms"] = millis();

  String payload;
  serializeJson(doc, payload);

  int status = https.POST(payload);
  https.end();

  Serial.printf("n8n HTTP status: %d\n", status);
  return status >= 200 && status < 300;
}

bool updateThingSpeak(unsigned long durationMs) {
  if (WiFi.status() != WL_CONNECTED) return false;

  WiFiClientSecure client;

  // DEMO ONLY: use certificate validation in production.
  client.setInsecure();

  HTTPClient https;
  String url =
    "https://api.thingspeak.com/update?api_key=" +
    String(THINGSPEAK_WRITE_KEY) +
    "&field1=" + String(alarmActive ? 1 : 0) +
    "&field2=" + String(durationMs / 1000.0, 1) +
    "&field3=1";

  if (!https.begin(client, url)) return false;

  int status = https.GET();
  String response = https.getString();
  https.end();

  Serial.printf("ThingSpeak HTTP status: %d\n", status);
  Serial.println("ThingSpeak response: " + response);

  // ThingSpeak returns a non-zero entry ID for a successful update.
  return status >= 200 && status < 300 &&
         response.toInt() > 0;
}

void setup() {
  Serial.begin(115200);

  pinMode(EYE_SENSOR_PIN, INPUT);
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(LED_PIN, OUTPUT);

  setAlarm(false);
  connectWiFi();

  Serial.println("Driver monitoring prototype ready");
}

void loop() {
  unsigned long now = millis();
  bool eyesClosed =
    digitalRead(EYE_SENSOR_PIN) == CLOSED_LEVEL;

  if (eyesClosed) {
    if (!wasClosed) {
      closedSince = now;
      wasClosed = true;
      eventSentForClosure = false;
    }

    unsigned long duration = now - closedSince;

    if (duration >= CLOSED_THRESHOLD_MS) {
      setAlarm(true);

      if (!eventSentForClosure &&
          (lastEvent == 0 ||
           now - lastEvent >= EVENT_COOLDOWN_MS)) {

        // Try cloud delivery once per qualifying closure.
        bool n8nOk = postToN8n(duration);
        bool tsOk = updateThingSpeak(duration);

        Serial.printf("n8n=%s, ThingSpeak=%s\n",
          n8nOk ? "OK" : "FAILED",
          tsOk ? "OK" : "FAILED");

        lastEvent = now;
        eventSentForClosure = true;
      }
    }
  } else {
    wasClosed = false;
    closedSince = 0;
    eventSentForClosure = false;
    setAlarm(false);
  }

  delay(20);
}

Important notes about the starter code

  • The 1.5-second threshold is a demonstration setting, not a medically or scientifically validated drowsiness threshold.

  • This code does not run an AI vision model. It uses a digital sensor signal and a timing rule.

  • A sensor that cannot reliably identify eye closure cannot reliably detect drowsiness. Validate the actual sensor before relying on its output.

  • setInsecure() disables HTTPS certificate verification. It is included only to simplify a controlled classroom demonstration; replace it with certificate validation before real deployment.

  • The code makes one upload attempt per qualifying closure. A production version needs a persistent retry queue, duplicate-event protection, and verified sensor-fault handling.

  • The example's buzzer turns off when the sensor indicates open eyes. For a validated safety-oriented design, define explicit alarm acknowledgement and recovery logic and test it thoroughly.

  • Do not test the prototype while driving on public roads. Bench-test it first, then conduct any further testing under appropriate controlled conditions.

8. n8n automation workflow

The n8n workflow is the central automation layer. It receives the event from the ESP32 and forwards it to your chosen cloud services.

#chatgpt-mermaid-_r_d0_{font-family:-apple-system-body,ui-sans-serif,-apple-system,system-ui,"Segoe UI",Helvetica,"Apple Color Emoji",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";font-size:16px;fill:rgb(13, 13, 13);}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#chatgpt-mermaid-_r_d0_ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#chatgpt-mermaid-_r_d0_ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#chatgpt-mermaid-_r_d0_ .error-icon{fill:rgb(243, 243, 243);}#chatgpt-mermaid-_r_d0_ .error-text{fill:rgb(13, 13, 13);stroke:rgb(13, 13, 13);}#chatgpt-mermaid-_r_d0_ .edge-thickness-normal{stroke-width:1px;}#chatgpt-mermaid-_r_d0_ .edge-thickness-thick{stroke-width:3.5px;}#chatgpt-mermaid-_r_d0_ .edge-pattern-solid{stroke-dasharray:0;}#chatgpt-mermaid-_r_d0_ .edge-thickness-invisible{stroke-width:0;fill:none;}#chatgpt-mermaid-_r_d0_ .edge-pattern-dashed{stroke-dasharray:3;}#chatgpt-mermaid-_r_d0_ .edge-pattern-dotted{stroke-dasharray:2;}#chatgpt-mermaid-_r_d0_ .marker{fill:rgb(143, 143, 143);stroke:rgb(143, 143, 143);}#chatgpt-mermaid-_r_d0_ .marker.cross{stroke:rgb(143, 143, 143);}#chatgpt-mermaid-_r_d0_ svg{font-family:-apple-system-body,ui-sans-serif,-apple-system,system-ui,"Segoe UI",Helvetica,"Apple Color Emoji",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";font-size:16px;}#chatgpt-mermaid-_r_d0_ p{margin:0;}#chatgpt-mermaid-_r_d0_ .label{font-family:-apple-system-body,ui-sans-serif,-apple-system,system-ui,"Segoe UI",Helvetica,"Apple Color Emoji",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_d0_ .cluster-label text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_d0_ .cluster-label span{color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_d0_ .cluster-label span p{background-color:transparent;}#chatgpt-mermaid-_r_d0_ .label text,#chatgpt-mermaid-_r_d0_ span{fill:rgb(13, 13, 13);color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_d0_ .node rect,#chatgpt-mermaid-_r_d0_ .node circle,#chatgpt-mermaid-_r_d0_ .node ellipse,#chatgpt-mermaid-_r_d0_ .node polygon,#chatgpt-mermaid-_r_d0_ .node path{fill:rgb(222, 234, 251);stroke:rgb(83, 154, 248);stroke-width:1px;}#chatgpt-mermaid-_r_d0_ .rough-node .label text,#chatgpt-mermaid-_r_d0_ .node .label text,#chatgpt-mermaid-_r_d0_ .image-shape .label,#chatgpt-mermaid-_r_d0_ .icon-shape .label{text-anchor:middle;}#chatgpt-mermaid-_r_d0_ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#chatgpt-mermaid-_r_d0_ .rough-node .label,#chatgpt-mermaid-_r_d0_ .node .label,#chatgpt-mermaid-_r_d0_ .image-shape .label,#chatgpt-mermaid-_r_d0_ .icon-shape .label{text-align:center;}#chatgpt-mermaid-_r_d0_ .node.clickable{cursor:pointer;}#chatgpt-mermaid-_r_d0_ .root .anchor path{fill:rgb(143, 143, 143)!important;stroke-width:0;stroke:rgb(143, 143, 143);}#chatgpt-mermaid-_r_d0_ .arrowheadPath{fill:rgb(143, 143, 143);}#chatgpt-mermaid-_r_d0_ .edgePath .path{stroke:rgb(143, 143, 143);stroke-width:1px;}#chatgpt-mermaid-_r_d0_ .flowchart-link{stroke:rgb(143, 143, 143);fill:none;}#chatgpt-mermaid-_r_d0_ .edgeLabel{background-color:rgb(252, 252, 252);text-align:center;}#chatgpt-mermaid-_r_d0_ .edgeLabel p{background-color:rgb(252, 252, 252);}#chatgpt-mermaid-_r_d0_ .edgeLabel rect{opacity:0.5;background-color:rgb(252, 252, 252);fill:rgb(252, 252, 252);}#chatgpt-mermaid-_r_d0_ .labelBkg{background-color:rgba(252, 252, 252, 0.5);}#chatgpt-mermaid-_r_d0_ .cluster rect{fill:rgb(243, 243, 243);stroke:rgba(0, 0, 0, 0.1);stroke-width:1px;}#chatgpt-mermaid-_r_d0_ .cluster text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_d0_ .cluster span{color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_d0_ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:-apple-system-body,ui-sans-serif,-apple-system,system-ui,"Segoe UI",Helvetica,"Apple Color Emoji",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";font-size:12px;background:rgb(243, 243, 243);border:1px solid rgba(0, 0, 0, 0.1);border-radius:2px;pointer-events:none;z-index:100;}#chatgpt-mermaid-_r_d0_ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_d0_ rect.text{fill:none;stroke-width:0;}#chatgpt-mermaid-_r_d0_ .icon-shape,#chatgpt-mermaid-_r_d0_ .image-shape{background-color:rgb(252, 252, 252);text-align:center;}#chatgpt-mermaid-_r_d0_ .icon-shape p,#chatgpt-mermaid-_r_d0_ .image-shape p{background-color:rgb(252, 252, 252);padding:2px;}#chatgpt-mermaid-_r_d0_ .icon-shape .label rect,#chatgpt-mermaid-_r_d0_ .image-shape .label rect{opacity:0.5;background-color:rgb(252, 252, 252);fill:rgb(252, 252, 252);}#chatgpt-mermaid-_r_d0_ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#chatgpt-mermaid-_r_d0_ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#chatgpt-mermaid-_r_d0_ .node .neo-node{stroke:rgb(83, 154, 248);}#chatgpt-mermaid-_r_d0_ [data-look="neo"].node rect,#chatgpt-mermaid-_r_d0_ [data-look="neo"].cluster rect,#chatgpt-mermaid-_r_d0_ [data-look="neo"].node polygon{stroke:url(#chatgpt-mermaid-_r_d0_-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#chatgpt-mermaid-_r_d0_ [data-look="neo"].swimlane.cluster rect{filter:none;}#chatgpt-mermaid-_r_d0_ [data-look="neo"].node path{stroke:url(#chatgpt-mermaid-_r_d0_-gradient);stroke-width:1px;}#chatgpt-mermaid-_r_d0_ [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#chatgpt-mermaid-_r_d0_ [data-look="neo"].node .neo-line path{stroke:rgb(83, 154, 248);filter:none;}#chatgpt-mermaid-_r_d0_ [data-look="neo"].node circle{stroke:url(#chatgpt-mermaid-_r_d0_-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#chatgpt-mermaid-_r_d0_ [data-look="neo"].node circle .state-start{fill:#000000;}#chatgpt-mermaid-_r_d0_ [data-look="neo"].icon-shape .icon{fill:url(#chatgpt-mermaid-_r_d0_-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#chatgpt-mermaid-_r_d0_ [data-look="neo"].icon-shape .icon-neo path{stroke:url(#chatgpt-mermaid-_r_d0_-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#chatgpt-mermaid-_r_d0_ .node text{font-size:14px;font-weight:600;letter-spacing:normal;fill:rgb(0, 79, 153);}#chatgpt-mermaid-_r_d0_ .edgeLabels text{font-size:13px;font-weight:600;letter-spacing:-0.08px;fill:rgb(0, 79, 153);}#chatgpt-mermaid-_r_d0_ .node tspan[font-weight="normal"],#chatgpt-mermaid-_r_d0_ .edgeLabels tspan[font-weight="normal"]{font-weight:600;}#chatgpt-mermaid-_r_d0_ .edgeLabel .label rect{opacity:1;rx:13px;ry:13px;fill:rgb(245, 250, 255);stroke:rgb(206, 219, 229);stroke-width:1px;}#chatgpt-mermaid-_r_d0_ .node rect,#chatgpt-mermaid-_r_d0_ .node circle,#chatgpt-mermaid-_r_d0_ .node ellipse,#chatgpt-mermaid-_r_d0_ .node polygon,#chatgpt-mermaid-_r_d0_ .node path{fill:rgb(229, 243, 255);stroke:rgba(0, 0, 0, 0.1);stroke-width:1px;}#chatgpt-mermaid-_r_d0_ .node rect{rx:16px;ry:16px;}#chatgpt-mermaid-_r_d0_ .node.mermaid-decision .label-container{fill:rgb(245, 250, 255);stroke:rgb(206, 219, 229);stroke-dasharray:2,2;}#chatgpt-mermaid-_r_d0_ .edgePaths .flowchart-link{stroke:rgb(143, 143, 143);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;}#chatgpt-mermaid-_r_d0_ .marker{fill:rgb(143, 143, 143);stroke:rgb(143, 143, 143);}#chatgpt-mermaid-_r_d0_ :root{--mermaid-font-family:-apple-system-body,ui-sans-serif,-apple-system,system-ui,"Segoe UI",Helvetica,"Apple Color Emoji",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";}ESP32 sends JSON eventWebhook TriggerValidate device and payloadValid event?Reject and log invalid eventNormalize event dataGoogle Sheets: Append RowTelegram: Send MessageAI Agent: Optional eventsummaryText-to-Speech serviceTelegram: Send AudioUpdate event statusIoT Dashboard / APINoYes

Build the workflow in n8n

  1. Create a Webhook node

    Set the HTTP method to POST and use a path such as driver-event. Use the production webhook URL after activating the workflow.

  2. Add an IF node

    Check that device_id, event, and eye_closed_ms exist. Only accept the expected event type, and apply authentication or a secret token to protect the webhook.

  3. Add a Google Sheets node

    Select your Google account, spreadsheet, worksheet, and the append-row operation. Map the incoming JSON properties to spreadsheet columns.

  4. Add a Telegram node

    Configure Telegram credentials and select the operation for sending a text message. n8n has a built-in Telegram integration for bot-based messaging.

    n8n Docs

     

  5. Add optional AI analysis

    Pass a limited event summary and recent aggregate counts to an AI Agent node. Ask it to summarize the history, not to diagnose a medical condition or decide whether the local alarm should sound.

  6. Add voice notifications

    Connect a text-to-speech service or an available TTS endpoint, then pass its generated audio file to Telegram's audio or voice-message operation. Text-to-speech is a separate integration; the Telegram node alone does not create spoken audio from arbitrary text.

  7. Add error handling

    Add error branches and workflow-failure notifications. Do not let a failed Google Sheets request prevent an urgent notification from being sent.

Example Telegram text alert

🚨 DRIVER DROWSINESS WARNING

Device: driver-unit-01
Event: Prolonged eye closure detected
Closure duration: 1.8 seconds
Alert level: HIGH

Please stop driving at a safe location as soon as possible and rest. Do not continue driving while sleepy.

This is an automated sensor alert, not a confirmed medical diagnosis.

Example spoken alert

Your text-to-speech service can turn the following into an audio clip:

Warning. Possible driver drowsiness detected. Please pay attention to your condition, pull over at a safe location, and rest before continuing your journey.

Voice-alert delivery options: a Telegram audio file, a Telegram voice message, or a spoken announcement on a separate in-vehicle speaker. Sending a remote Telegram message does not automatically make the driver's phone speak aloud; that depends on the phone's notification settings and the delivery method.

9. Google Sheets data logging

Create a Google spreadsheet named Driver_Sleep_Monitoring.

Use this first row as your header:

Column

Field

Example

A

Timestamp

Automatically generated by n8n

B

Device ID

driver-unit-01

C

Event

DROWSINESS_WARNING

D

Eye-closed duration (ms)

1800

E

Alert level

HIGH

F

Wi-Fi / device status

Connected

G

Notification status

Sent

H

AI summary

Repeated warning events observed

Configure the Google Sheets node to append one row per accepted event. Generate the timestamp on the server or in n8n rather than relying on a potentially incorrect device clock.

Example data for a demonstration:

Time

Device

Duration

Alert

10:05:01

driver-unit-01

300 ms

Normal

10:15:22

driver-unit-01

1800 ms

Warning

10:23:14

driver-unit-01

2200 ms

Warning

These are sample records, not actual measurements.

10. ThingSpeak cloud dashboard

Create a channel named Driver Sleep Detection.

ThingSpeak supports channels with up to eight numeric fields, making it suitable for storing the numerical values from this prototype.

GitHub
+1

 

Recommended channel fields:

Field

Meaning

Data

Field 1

Alarm status

0 = off, 1 = on

Field 2

Eye-closure duration

Seconds

Field 3

Drowsiness event

0 = no event, 1 = event

Field 4

Event counter

Number of events

For the current starter code, Field 1 represents the alarm state at upload time, Field 2 is closure duration in seconds, and Field 3 is set to 1 on each upload attempt. Field 4 is not yet implemented.

Setup steps:

  1. Create a ThingSpeak account and channel.

  2. Enable the fields listed above.

  3. Copy the channel's Write API Key into the firmware.

  4. Upload the firmware and check whether new channel entries appear.

  5. Use the channel's charts to display alarm status, closure duration, and event counts.

  6. Keep the channel private unless you have a reason to publish the data.

ThingSpeak update requests are subject to service limits and channel update timing. The code does not yet implement a queue or a schedule for failed uploads, so use a suitable sampling interval for your account and application.

11. IoT webpage dashboard

The webpage can be a responsive interface for desktop and mobile devices.

Driver Safety Monitor

Example dashboard layout

Prototype UI

System status

Monitoring

Last alert

Example

Closure duration

1.8 s

Cloud connection

Demo

 

Recommended dashboard sections

  • Current sensor state and alarm status
  • Latest events with timestamps
  • Closure duration and event-count charts
  • Wi-Fi, webhook, and cloud-service health
  • Telegram and voice-notification delivery history
  • Daily event summary generated by the AI agent

The values shown here are illustrative placeholders, not a live connection to your ESP32.

For the first version, embed the ThingSpeak charts in a webpage. For a more advanced version, build a separate webpage that retrieves current status and event history from an authenticated backend. Avoid exposing API keys, Telegram bot tokens, or n8n credentials in browser JavaScript.

12. AI agent design

The AI agent is an optional analysis layer that runs after event collection. It can use the recent event history to explain trends and prepare reports.

Suggested agent inputs

  • Device ID and event timestamp.

  • Eye-closure duration from each event.

  • Number of events in the last hour or day.

  • Sensor, Wi-Fi, and cloud connection status.

  • Notification delivery status.

Suggested AI-agent prompt

You are an assistant for an experimental driver-monitoring IoT system.

Analyze the supplied event records and produce:

  1. A concise summary of recent drowsiness-warning events.

  2. The number of warnings in the supplied period.

  3. Any repeated event patterns or sensor faults evident in the data.

  4. A clear note when data is missing or unreliable.

  5. A safety reminder when repeated warnings are present.

Do not diagnose a medical condition. Do not claim that the driver is safe based on missing events. Do not change the ESP32 alarm thresholds or disable any local warning. If the data is insufficient, state that clearly.

Output a short summary suitable for a monitoring dashboard and a Google Sheets report.

For an advanced version, the AI agent could request a daily aggregate from Google Sheets and write a summary to a separate report sheet. Keep the alert path independent of AI availability.

13. Project mind map

#chatgpt-mermaid-_r_el_{font-family:-apple-system-body,ui-sans-serif,-apple-system,system-ui,"Segoe UI",Helvetica,"Apple Color Emoji",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";font-size:16px;fill:rgb(13, 13, 13);}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#chatgpt-mermaid-_r_el_ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#chatgpt-mermaid-_r_el_ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#chatgpt-mermaid-_r_el_ .error-icon{fill:rgb(243, 243, 243);}#chatgpt-mermaid-_r_el_ .error-text{fill:rgb(13, 13, 13);stroke:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .edge-thickness-normal{stroke-width:1px;}#chatgpt-mermaid-_r_el_ .edge-thickness-thick{stroke-width:3.5px;}#chatgpt-mermaid-_r_el_ .edge-pattern-solid{stroke-dasharray:0;}#chatgpt-mermaid-_r_el_ .edge-thickness-invisible{stroke-width:0;fill:none;}#chatgpt-mermaid-_r_el_ .edge-pattern-dashed{stroke-dasharray:3;}#chatgpt-mermaid-_r_el_ .edge-pattern-dotted{stroke-dasharray:2;}#chatgpt-mermaid-_r_el_ .marker{fill:rgb(143, 143, 143);stroke:rgb(143, 143, 143);}#chatgpt-mermaid-_r_el_ .marker.cross{stroke:rgb(143, 143, 143);}#chatgpt-mermaid-_r_el_ svg{font-family:-apple-system-body,ui-sans-serif,-apple-system,system-ui,"Segoe UI",Helvetica,"Apple Color Emoji",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";font-size:16px;}#chatgpt-mermaid-_r_el_ p{margin:0;}#chatgpt-mermaid-_r_el_ .edge{stroke-width:3;}#chatgpt-mermaid-_r_el_ .section--1 rect,#chatgpt-mermaid-_r_el_ .section--1 path,#chatgpt-mermaid-_r_el_ .section--1 circle,#chatgpt-mermaid-_r_el_ .section--1 polygon,#chatgpt-mermaid-_r_el_ .section--1 path{fill:rgb(83, 154, 248);}#chatgpt-mermaid-_r_el_ .section--1 text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section--1 span{color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .node-icon--1{font-size:40px;color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-edge--1{stroke:rgb(83, 154, 248);}#chatgpt-mermaid-_r_el_ .edge-depth--1{stroke-width:17;}#chatgpt-mermaid-_r_el_ .section--1 line{stroke:rgb(247.0418994413, 166.3240223463, 59.4581005587);stroke-width:3;}#chatgpt-mermaid-_r_el_ .disabled,#chatgpt-mermaid-_r_el_ .disabled circle,#chatgpt-mermaid-_r_el_ .disabled text{fill:lightgray;}#chatgpt-mermaid-_r_el_ .disabled text{fill:#efefef;}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section--1 rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section--1 path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section--1 circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section--1 polygon{fill:rgb(83, 154, 248);stroke:rgb(83, 154, 248);stroke-width:1px;}#chatgpt-mermaid-_r_el_ [data-look="neo"].section-edge--1{stroke:rgb(83, 154, 248);}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section--1 text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-0 rect,#chatgpt-mermaid-_r_el_ .section-0 path,#chatgpt-mermaid-_r_el_ .section-0 circle,#chatgpt-mermaid-_r_el_ .section-0 polygon,#chatgpt-mermaid-_r_el_ .section-0 path{fill:rgb(107, 198, 127);}#chatgpt-mermaid-_r_el_ .section-0 text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-0 span{color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .node-icon-0{font-size:40px;color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-edge-0{stroke:rgb(107, 198, 127);}#chatgpt-mermaid-_r_el_ .edge-depth-0{stroke-width:14;}#chatgpt-mermaid-_r_el_ .section-0 line{stroke:rgb(205.6463414634, 126.8536585367, 188.3292682927);stroke-width:3;}#chatgpt-mermaid-_r_el_ .disabled,#chatgpt-mermaid-_r_el_ .disabled circle,#chatgpt-mermaid-_r_el_ .disabled text{fill:lightgray;}#chatgpt-mermaid-_r_el_ .disabled text{fill:#efefef;}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-0 rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-0 path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-0 circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-0 polygon{fill:rgb(107, 198, 127);stroke:rgb(107, 198, 127);stroke-width:1px;}#chatgpt-mermaid-_r_el_ [data-look="neo"].section-edge-0{stroke:rgb(107, 198, 127);}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-0 text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-1 rect,#chatgpt-mermaid-_r_el_ .section-1 path,#chatgpt-mermaid-_r_el_ .section-1 circle,#chatgpt-mermaid-_r_el_ .section-1 polygon,#chatgpt-mermaid-_r_el_ .section-1 path{fill:rgb(239, 139, 87);}#chatgpt-mermaid-_r_el_ .section-1 text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-1 span{color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .node-icon-1{font-size:40px;color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-edge-1{stroke:rgb(239, 139, 87);}#chatgpt-mermaid-_r_el_ .edge-depth-1{stroke-width:11;}#chatgpt-mermaid-_r_el_ .section-1 line{stroke:rgb(73.760869565, 181.6413043477, 237.7391304348);stroke-width:3;}#chatgpt-mermaid-_r_el_ .disabled,#chatgpt-mermaid-_r_el_ .disabled circle,#chatgpt-mermaid-_r_el_ .disabled text{fill:lightgray;}#chatgpt-mermaid-_r_el_ .disabled text{fill:#efefef;}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-1 rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-1 path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-1 circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-1 polygon{fill:rgb(239, 139, 87);stroke:rgb(239, 139, 87);stroke-width:1px;}#chatgpt-mermaid-_r_el_ [data-look="neo"].section-edge-1{stroke:rgb(239, 139, 87);}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-1 text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-2 rect,#chatgpt-mermaid-_r_el_ .section-2 path,#chatgpt-mermaid-_r_el_ .section-2 circle,#chatgpt-mermaid-_r_el_ .section-2 polygon,#chatgpt-mermaid-_r_el_ .section-2 path{fill:rgb(248, 212, 93);}#chatgpt-mermaid-_r_el_ .section-2 text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-2 span{color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .node-icon-2{font-size:40px;color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-edge-2{stroke:rgb(248, 212, 93);}#chatgpt-mermaid-_r_el_ .edge-depth-2{stroke-width:8;}#chatgpt-mermaid-_r_el_ .section-2 line{stroke:rgb(50.3431952664, 95.8224852073, 246.1568047338);stroke-width:3;}#chatgpt-mermaid-_r_el_ .disabled,#chatgpt-mermaid-_r_el_ .disabled circle,#chatgpt-mermaid-_r_el_ .disabled text{fill:lightgray;}#chatgpt-mermaid-_r_el_ .disabled text{fill:#efefef;}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-2 rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-2 path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-2 circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-2 polygon{fill:rgb(248, 212, 93);stroke:rgb(248, 212, 93);stroke-width:1px;}#chatgpt-mermaid-_r_el_ [data-look="neo"].section-edge-2{stroke:rgb(248, 212, 93);}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-2 text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-3 rect,#chatgpt-mermaid-_r_el_ .section-3 path,#chatgpt-mermaid-_r_el_ .section-3 circle,#chatgpt-mermaid-_r_el_ .section-3 polygon,#chatgpt-mermaid-_r_el_ .section-3 path{fill:rgb(184, 151, 244);}#chatgpt-mermaid-_r_el_ .section-3 text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-3 span{color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .node-icon-3{font-size:40px;color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-edge-3{stroke:rgb(184, 151, 244);}#chatgpt-mermaid-_r_el_ .edge-depth-3{stroke-width:5;}#chatgpt-mermaid-_r_el_ .section-3 line{stroke:rgb(149.7173913044, 219.3043478259, 23.1956521739);stroke-width:3;}#chatgpt-mermaid-_r_el_ .disabled,#chatgpt-mermaid-_r_el_ .disabled circle,#chatgpt-mermaid-_r_el_ .disabled text{fill:lightgray;}#chatgpt-mermaid-_r_el_ .disabled text{fill:#efefef;}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-3 rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-3 path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-3 circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-3 polygon{fill:rgb(184, 151, 244);stroke:rgb(184, 151, 244);stroke-width:1px;}#chatgpt-mermaid-_r_el_ [data-look="neo"].section-edge-3{stroke:rgb(184, 151, 244);}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-3 text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-4 rect,#chatgpt-mermaid-_r_el_ .section-4 path,#chatgpt-mermaid-_r_el_ .section-4 circle,#chatgpt-mermaid-_r_el_ .section-4 polygon,#chatgpt-mermaid-_r_el_ .section-4 path{fill:rgb(246, 142, 188);}#chatgpt-mermaid-_r_el_ .section-4 text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-4 span{color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .node-icon-4{font-size:40px;color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-edge-4{stroke:rgb(246, 142, 188);}#chatgpt-mermaid-_r_el_ .edge-depth-4{stroke-width:2;}#chatgpt-mermaid-_r_el_ .section-4 line{stroke:rgb(18.405737705, 231.0942622953, 137.0204918033);stroke-width:3;}#chatgpt-mermaid-_r_el_ .disabled,#chatgpt-mermaid-_r_el_ .disabled circle,#chatgpt-mermaid-_r_el_ .disabled text{fill:lightgray;}#chatgpt-mermaid-_r_el_ .disabled text{fill:#efefef;}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-4 rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-4 path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-4 circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-4 polygon{fill:rgb(246, 142, 188);stroke:rgb(246, 142, 188);stroke-width:1px;}#chatgpt-mermaid-_r_el_ [data-look="neo"].section-edge-4{stroke:rgb(246, 142, 188);}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-4 text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-5 rect,#chatgpt-mermaid-_r_el_ .section-5 path,#chatgpt-mermaid-_r_el_ .section-5 circle,#chatgpt-mermaid-_r_el_ .section-5 polygon,#chatgpt-mermaid-_r_el_ .section-5 path{fill:rgb(83, 154, 248);}#chatgpt-mermaid-_r_el_ .section-5 text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-5 span{color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .node-icon-5{font-size:40px;color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-edge-5{stroke:rgb(83, 154, 248);}#chatgpt-mermaid-_r_el_ .edge-depth-5{stroke-width:-1;}#chatgpt-mermaid-_r_el_ .section-5 line{stroke:rgb(247.0418994413, 166.3240223463, 59.4581005587);stroke-width:3;}#chatgpt-mermaid-_r_el_ .disabled,#chatgpt-mermaid-_r_el_ .disabled circle,#chatgpt-mermaid-_r_el_ .disabled text{fill:lightgray;}#chatgpt-mermaid-_r_el_ .disabled text{fill:#efefef;}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-5 rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-5 path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-5 circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-5 polygon{fill:rgb(83, 154, 248);stroke:rgb(83, 154, 248);stroke-width:1px;}#chatgpt-mermaid-_r_el_ [data-look="neo"].section-edge-5{stroke:rgb(83, 154, 248);}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-5 text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-6 rect,#chatgpt-mermaid-_r_el_ .section-6 path,#chatgpt-mermaid-_r_el_ .section-6 circle,#chatgpt-mermaid-_r_el_ .section-6 polygon,#chatgpt-mermaid-_r_el_ .section-6 path{fill:rgb(107, 198, 127);}#chatgpt-mermaid-_r_el_ .section-6 text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-6 span{color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .node-icon-6{font-size:40px;color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-edge-6{stroke:rgb(107, 198, 127);}#chatgpt-mermaid-_r_el_ .edge-depth-6{stroke-width:-4;}#chatgpt-mermaid-_r_el_ .section-6 line{stroke:rgb(205.6463414634, 126.8536585367, 188.3292682927);stroke-width:3;}#chatgpt-mermaid-_r_el_ .disabled,#chatgpt-mermaid-_r_el_ .disabled circle,#chatgpt-mermaid-_r_el_ .disabled text{fill:lightgray;}#chatgpt-mermaid-_r_el_ .disabled text{fill:#efefef;}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-6 rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-6 path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-6 circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-6 polygon{fill:rgb(107, 198, 127);stroke:rgb(107, 198, 127);stroke-width:1px;}#chatgpt-mermaid-_r_el_ [data-look="neo"].section-edge-6{stroke:rgb(107, 198, 127);}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-6 text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-7 rect,#chatgpt-mermaid-_r_el_ .section-7 path,#chatgpt-mermaid-_r_el_ .section-7 circle,#chatgpt-mermaid-_r_el_ .section-7 polygon,#chatgpt-mermaid-_r_el_ .section-7 path{fill:rgb(239, 139, 87);}#chatgpt-mermaid-_r_el_ .section-7 text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-7 span{color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .node-icon-7{font-size:40px;color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-edge-7{stroke:rgb(239, 139, 87);}#chatgpt-mermaid-_r_el_ .edge-depth-7{stroke-width:-7;}#chatgpt-mermaid-_r_el_ .section-7 line{stroke:rgb(73.760869565, 181.6413043477, 237.7391304348);stroke-width:3;}#chatgpt-mermaid-_r_el_ .disabled,#chatgpt-mermaid-_r_el_ .disabled circle,#chatgpt-mermaid-_r_el_ .disabled text{fill:lightgray;}#chatgpt-mermaid-_r_el_ .disabled text{fill:#efefef;}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-7 rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-7 path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-7 circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-7 polygon{fill:rgb(239, 139, 87);stroke:rgb(239, 139, 87);stroke-width:1px;}#chatgpt-mermaid-_r_el_ [data-look="neo"].section-edge-7{stroke:rgb(239, 139, 87);}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-7 text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-8 rect,#chatgpt-mermaid-_r_el_ .section-8 path,#chatgpt-mermaid-_r_el_ .section-8 circle,#chatgpt-mermaid-_r_el_ .section-8 polygon,#chatgpt-mermaid-_r_el_ .section-8 path{fill:rgb(248, 212, 93);}#chatgpt-mermaid-_r_el_ .section-8 text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-8 span{color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .node-icon-8{font-size:40px;color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-edge-8{stroke:rgb(248, 212, 93);}#chatgpt-mermaid-_r_el_ .edge-depth-8{stroke-width:-10;}#chatgpt-mermaid-_r_el_ .section-8 line{stroke:rgb(50.3431952664, 95.8224852073, 246.1568047338);stroke-width:3;}#chatgpt-mermaid-_r_el_ .disabled,#chatgpt-mermaid-_r_el_ .disabled circle,#chatgpt-mermaid-_r_el_ .disabled text{fill:lightgray;}#chatgpt-mermaid-_r_el_ .disabled text{fill:#efefef;}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-8 rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-8 path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-8 circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-8 polygon{fill:rgb(248, 212, 93);stroke:rgb(248, 212, 93);stroke-width:1px;}#chatgpt-mermaid-_r_el_ [data-look="neo"].section-edge-8{stroke:rgb(248, 212, 93);}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-8 text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-9 rect,#chatgpt-mermaid-_r_el_ .section-9 path,#chatgpt-mermaid-_r_el_ .section-9 circle,#chatgpt-mermaid-_r_el_ .section-9 polygon,#chatgpt-mermaid-_r_el_ .section-9 path{fill:rgb(184, 151, 244);}#chatgpt-mermaid-_r_el_ .section-9 text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-9 span{color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .node-icon-9{font-size:40px;color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-edge-9{stroke:rgb(184, 151, 244);}#chatgpt-mermaid-_r_el_ .edge-depth-9{stroke-width:-13;}#chatgpt-mermaid-_r_el_ .section-9 line{stroke:rgb(149.7173913044, 219.3043478259, 23.1956521739);stroke-width:3;}#chatgpt-mermaid-_r_el_ .disabled,#chatgpt-mermaid-_r_el_ .disabled circle,#chatgpt-mermaid-_r_el_ .disabled text{fill:lightgray;}#chatgpt-mermaid-_r_el_ .disabled text{fill:#efefef;}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-9 rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-9 path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-9 circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-9 polygon{fill:rgb(184, 151, 244);stroke:rgb(184, 151, 244);stroke-width:1px;}#chatgpt-mermaid-_r_el_ [data-look="neo"].section-edge-9{stroke:rgb(184, 151, 244);}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-9 text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-10 rect,#chatgpt-mermaid-_r_el_ .section-10 path,#chatgpt-mermaid-_r_el_ .section-10 circle,#chatgpt-mermaid-_r_el_ .section-10 polygon,#chatgpt-mermaid-_r_el_ .section-10 path{fill:rgb(246, 142, 188);}#chatgpt-mermaid-_r_el_ .section-10 text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-10 span{color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .node-icon-10{font-size:40px;color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-edge-10{stroke:rgb(246, 142, 188);}#chatgpt-mermaid-_r_el_ .edge-depth-10{stroke-width:-16;}#chatgpt-mermaid-_r_el_ .section-10 line{stroke:rgb(18.405737705, 231.0942622953, 137.0204918033);stroke-width:3;}#chatgpt-mermaid-_r_el_ .disabled,#chatgpt-mermaid-_r_el_ .disabled circle,#chatgpt-mermaid-_r_el_ .disabled text{fill:lightgray;}#chatgpt-mermaid-_r_el_ .disabled text{fill:#efefef;}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-10 rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-10 path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-10 circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-10 polygon{fill:rgb(246, 142, 188);stroke:rgb(246, 142, 188);stroke-width:1px;}#chatgpt-mermaid-_r_el_ [data-look="neo"].section-edge-10{stroke:rgb(246, 142, 188);}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-10 text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-root rect,#chatgpt-mermaid-_r_el_ .section-root path,#chatgpt-mermaid-_r_el_ .section-root circle,#chatgpt-mermaid-_r_el_ .section-root polygon{fill:rgb(83, 154, 248);}#chatgpt-mermaid-_r_el_ .section-root text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .section-root span{color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#chatgpt-mermaid-_r_el_ .edge{fill:none;}#chatgpt-mermaid-_r_el_ .mindmap-node-label{dy:1em;alignment-baseline:middle;text-anchor:middle;dominant-baseline:middle;text-align:center;}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-root rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-root path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-root circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-root polygon{fill:rgb(83, 154, 248);}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-root .text-inner-tspan{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section--1 rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section--1 path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section--1 circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section--1 polygon{stroke:url(#chatgpt-mermaid-_r_el_-gradient);fill:rgb(222, 234, 251);}#chatgpt-mermaid-_r_el_ .section--1 line{stroke-width:0;}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-0 rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-0 path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-0 circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-0 polygon{stroke:url(#chatgpt-mermaid-_r_el_-gradient);fill:rgb(222, 234, 251);}#chatgpt-mermaid-_r_el_ .section-0 line{stroke-width:0;}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-1 rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-1 path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-1 circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-1 polygon{stroke:url(#chatgpt-mermaid-_r_el_-gradient);fill:rgb(222, 234, 251);}#chatgpt-mermaid-_r_el_ .section-1 line{stroke-width:0;}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-2 rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-2 path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-2 circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-2 polygon{stroke:url(#chatgpt-mermaid-_r_el_-gradient);fill:rgb(222, 234, 251);}#chatgpt-mermaid-_r_el_ .section-2 line{stroke-width:0;}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-3 rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-3 path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-3 circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-3 polygon{stroke:url(#chatgpt-mermaid-_r_el_-gradient);fill:rgb(222, 234, 251);}#chatgpt-mermaid-_r_el_ .section-3 line{stroke-width:0;}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-4 rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-4 path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-4 circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-4 polygon{stroke:url(#chatgpt-mermaid-_r_el_-gradient);fill:rgb(222, 234, 251);}#chatgpt-mermaid-_r_el_ .section-4 line{stroke-width:0;}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-5 rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-5 path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-5 circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-5 polygon{stroke:url(#chatgpt-mermaid-_r_el_-gradient);fill:rgb(222, 234, 251);}#chatgpt-mermaid-_r_el_ .section-5 line{stroke-width:0;}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-6 rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-6 path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-6 circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-6 polygon{stroke:url(#chatgpt-mermaid-_r_el_-gradient);fill:rgb(222, 234, 251);}#chatgpt-mermaid-_r_el_ .section-6 line{stroke-width:0;}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-7 rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-7 path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-7 circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-7 polygon{stroke:url(#chatgpt-mermaid-_r_el_-gradient);fill:rgb(222, 234, 251);}#chatgpt-mermaid-_r_el_ .section-7 line{stroke-width:0;}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-8 rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-8 path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-8 circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-8 polygon{stroke:url(#chatgpt-mermaid-_r_el_-gradient);fill:rgb(222, 234, 251);}#chatgpt-mermaid-_r_el_ .section-8 line{stroke-width:0;}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-9 rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-9 path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-9 circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-9 polygon{stroke:url(#chatgpt-mermaid-_r_el_-gradient);fill:rgb(222, 234, 251);}#chatgpt-mermaid-_r_el_ .section-9 line{stroke-width:0;}#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-10 rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-10 path,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-10 circle,#chatgpt-mermaid-_r_el_ [data-look="neo"].mindmap-node.section-10 polygon{stroke:url(#chatgpt-mermaid-_r_el_-gradient);fill:rgb(222, 234, 251);}#chatgpt-mermaid-_r_el_ .section-10 line{stroke-width:0;}#chatgpt-mermaid-_r_el_ .node .neo-node{stroke:rgb(83, 154, 248);}#chatgpt-mermaid-_r_el_ [data-look="neo"].node rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].cluster rect,#chatgpt-mermaid-_r_el_ [data-look="neo"].node polygon{stroke:url(#chatgpt-mermaid-_r_el_-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#chatgpt-mermaid-_r_el_ [data-look="neo"].swimlane.cluster rect{filter:none;}#chatgpt-mermaid-_r_el_ [data-look="neo"].node path{stroke:url(#chatgpt-mermaid-_r_el_-gradient);stroke-width:1px;}#chatgpt-mermaid-_r_el_ [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#chatgpt-mermaid-_r_el_ [data-look="neo"].node .neo-line path{stroke:rgb(83, 154, 248);filter:none;}#chatgpt-mermaid-_r_el_ [data-look="neo"].node circle{stroke:url(#chatgpt-mermaid-_r_el_-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#chatgpt-mermaid-_r_el_ [data-look="neo"].node circle .state-start{fill:#000000;}#chatgpt-mermaid-_r_el_ [data-look="neo"].icon-shape .icon{fill:url(#chatgpt-mermaid-_r_el_-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#chatgpt-mermaid-_r_el_ [data-look="neo"].icon-shape .icon-neo path{stroke:url(#chatgpt-mermaid-_r_el_-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#chatgpt-mermaid-_r_el_ :root{--mermaid-font-family:-apple-system-body,ui-sans-serif,-apple-system,system-ui,"Segoe UI",Helvetica,"Apple Color Emoji",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";}AI Driver Sleep DetectionHardwareESP32 or ESP32-S3IR eye sensorOptional cameraBuzzer and LEDFirmwareSensor readingEye-closure timerLocal alarmWi-Fi event uploadAI and Automationn8n webhookEvent validationAI summaryWorkflow error handlingNotificationsTelegram textText-to-speechTelegram audioCloudGoogle SheetsThingSpeakIoT webpageTestingSensor calibrationFalse alarmsNetwork outageSafety validation

14. Testing and validation plan

Complete these tests on a workbench before considering any vehicle installation.

Test

Expected result

Normal sensor signal

No drowsiness alarm

Short simulated closure

No alarm if below the configured threshold

Prolonged simulated closure

Local buzzer and LED activate

Wi-Fi disconnected

Local alarm continues

n8n unavailable

Local alarm continues; event is retried only if retry logic has been implemented

Google Sheets error

Other alert paths should remain operational in the final workflow

Telegram failure

Failure is recorded and retried according to workflow policy

Sensor unplugged or blocked

A fault is detected in the final validated implementation

Power cycle

System starts safely and reconnects to available services

Measure false alarms and missed detections across different users, lighting conditions, eyewear, head positions, and sensor placements. An IR blink sensor is a basic demonstration input; it cannot establish that a driver is alert or reliably distinguish every cause of prolonged eye closure.

Safety limitation: this is an educational prototype, not a certified driver-safety device. Do not rely on it to decide whether it is safe to drive, and do not test it while operating a vehicle.

15. Final project documentation structure

Use the following chapter structure for your college project report.

  1. Chapter 1 — Introduction: Driver fatigue, problem statement, motivation, and objectives.

  2. Chapter 2 — Literature Review: Existing drowsiness-detection techniques, IR sensors, computer vision, and IoT-based alert systems.

  3. Chapter 3 — System Requirements: Hardware, software, communication protocols, and cloud services.

  4. Chapter 4 — System Design: Block diagram, circuit schematic, flowchart, and system architecture.

  5. Chapter 5 — Hardware Implementation: ESP32 connections, sensor installation, alarm circuit, and power supply.

  6. Chapter 6 — Software Implementation: Arduino firmware, sensor timing logic, Wi-Fi, HTTP requests, and event handling.

  7. Chapter 7 — n8n Automation: Webhook, validation, Google Sheets, Telegram, TTS, and AI agent.

  8. Chapter 8 — Cloud Dashboard: ThingSpeak fields, webpage design, and event history.

  9. Chapter 9 — Testing and Results: Sensor calibration, response times, false alarms, network failures, and test records.

  10. Chapter 10 — Conclusion and Future Scope: Camera-based AI, improved eye-state estimation, event buffering, and more reliable driver monitoring.

16. Future improvements

  • Replace the basic IR input with camera-based eye-state detection and a validated model.

  • Add head-pose estimation and additional indicators to reduce false alarms.

  • Store events locally during Wi-Fi outages and upload them when connectivity returns.

  • Add authenticated device-to-server communication and encrypted credential storage.

  • Create a live dashboard with separate device-health and drowsiness-event indicators.

  • Add daily and weekly AI-generated reports from aggregated data.

  • Measure system performance using a documented test dataset.

Useful technical references:

17. Recommended implementation order

To make the project easier to complete and troubleshoot, build it in this order:

  1. Connect the ESP32, IR sensor, LED, and buzzer.
  2. Test the sensor's actual output and verify the local alarm.
  3. Configure the n8n webhook and verify that it receives a test event.
  4. Connect Google Sheets and confirm event records are stored.
  5. Configure Telegram text alerts, then add text-to-speech and audio delivery.
  6. Connect ThingSpeak and display the numerical monitoring data.
  7. Build the IoT webpage and add AI summaries last.
  8. Test network failures, sensor faults, duplicate alerts, and false positives.

The most important next step is to establish a reliable local sensor-and-alarm circuit before adding the cloud services. Once that works, the remaining features can be integrated and tested individually.

 

Project Summary

AI Sleep Detection & Driver Alert System Using ESP32, AI Agent, IoT, n8n and Telegram Voice Alerts

Project title: AI-Powered IoT-Based Driver Sleep Detection and Alert System Using ESP32, n8n Automation, Telegram Voice Notifications, Google Sheets and ThingSpeak Cloud Dashboard.

Abstract

The AI Sleep Detection and Driver Alert System is an IoT-based safety prototype designed to detect possible driver drowsiness and generate immediate warnings. The system uses an ESP32 microcontroller with an eye-blink sensor to monitor eye-closure duration. When prolonged eye closure is detected, the ESP32 activates a buzzer and warning LED to alert the driver locally.

Using built-in Wi-Fi, the ESP32 can transmit event data to an n8n automation workflow. The workflow records events in Google Sheets, sends Telegram notifications, and supports voice alerts through a text-to-speech service. ThingSpeak provides cloud-based data visualization, while an IoT webpage displays system status, event history, and monitoring information. An optional AI agent analyzes recorded events, identifies repeated warning patterns, and generates summaries.

The system is designed to keep local warnings independent of internet connectivity. Future enhancements include camera-based eye-state recognition, improved drowsiness estimation, sensor-fault detection, and reliable offline event storage.

Main objectives

  • Detect possible driver drowsiness using eye-closure monitoring.

  • Activate a local buzzer and LED when a configurable threshold is exceeded.

  • Send remote alerts through Telegram and optional voice notifications.

  • Store event history in Google Sheets.

  • Visualize monitoring data through ThingSpeak and an IoT webpage.

  • Use n8n to automate communication between the ESP32 and cloud services.

  • Apply AI to summarize event history and identify patterns.

Hardware and software requirements

Category

Components

Controller

ESP32 DevKit V1

Sensor

Digital IR eye-blink sensor

Alert devices

Active buzzer, LED and resistor

Optional AI hardware

ESP32-S3 camera board

Programming

Arduino IDE, ESP32 board package

Automation

n8n

Notifications

Telegram Bot API

Data storage

Google Sheets

Cloud visualization

ThingSpeak

AI and voice

AI Agent and text-to-speech service

Dashboard

IoT webpage

Working principle

#chatgpt-mermaid-_r_h1_{font-family:-apple-system-body,ui-sans-serif,-apple-system,system-ui,"Segoe UI",Helvetica,"Apple Color Emoji",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";font-size:16px;fill:rgb(13, 13, 13);}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#chatgpt-mermaid-_r_h1_ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#chatgpt-mermaid-_r_h1_ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#chatgpt-mermaid-_r_h1_ .error-icon{fill:rgb(243, 243, 243);}#chatgpt-mermaid-_r_h1_ .error-text{fill:rgb(13, 13, 13);stroke:rgb(13, 13, 13);}#chatgpt-mermaid-_r_h1_ .edge-thickness-normal{stroke-width:1px;}#chatgpt-mermaid-_r_h1_ .edge-thickness-thick{stroke-width:3.5px;}#chatgpt-mermaid-_r_h1_ .edge-pattern-solid{stroke-dasharray:0;}#chatgpt-mermaid-_r_h1_ .edge-thickness-invisible{stroke-width:0;fill:none;}#chatgpt-mermaid-_r_h1_ .edge-pattern-dashed{stroke-dasharray:3;}#chatgpt-mermaid-_r_h1_ .edge-pattern-dotted{stroke-dasharray:2;}#chatgpt-mermaid-_r_h1_ .marker{fill:rgb(143, 143, 143);stroke:rgb(143, 143, 143);}#chatgpt-mermaid-_r_h1_ .marker.cross{stroke:rgb(143, 143, 143);}#chatgpt-mermaid-_r_h1_ svg{font-family:-apple-system-body,ui-sans-serif,-apple-system,system-ui,"Segoe UI",Helvetica,"Apple Color Emoji",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";font-size:16px;}#chatgpt-mermaid-_r_h1_ p{margin:0;}#chatgpt-mermaid-_r_h1_ .label{font-family:-apple-system-body,ui-sans-serif,-apple-system,system-ui,"Segoe UI",Helvetica,"Apple Color Emoji",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_h1_ .cluster-label text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_h1_ .cluster-label span{color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_h1_ .cluster-label span p{background-color:transparent;}#chatgpt-mermaid-_r_h1_ .label text,#chatgpt-mermaid-_r_h1_ span{fill:rgb(13, 13, 13);color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_h1_ .node rect,#chatgpt-mermaid-_r_h1_ .node circle,#chatgpt-mermaid-_r_h1_ .node ellipse,#chatgpt-mermaid-_r_h1_ .node polygon,#chatgpt-mermaid-_r_h1_ .node path{fill:rgb(222, 234, 251);stroke:rgb(83, 154, 248);stroke-width:1px;}#chatgpt-mermaid-_r_h1_ .rough-node .label text,#chatgpt-mermaid-_r_h1_ .node .label text,#chatgpt-mermaid-_r_h1_ .image-shape .label,#chatgpt-mermaid-_r_h1_ .icon-shape .label{text-anchor:middle;}#chatgpt-mermaid-_r_h1_ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#chatgpt-mermaid-_r_h1_ .rough-node .label,#chatgpt-mermaid-_r_h1_ .node .label,#chatgpt-mermaid-_r_h1_ .image-shape .label,#chatgpt-mermaid-_r_h1_ .icon-shape .label{text-align:center;}#chatgpt-mermaid-_r_h1_ .node.clickable{cursor:pointer;}#chatgpt-mermaid-_r_h1_ .root .anchor path{fill:rgb(143, 143, 143)!important;stroke-width:0;stroke:rgb(143, 143, 143);}#chatgpt-mermaid-_r_h1_ .arrowheadPath{fill:rgb(143, 143, 143);}#chatgpt-mermaid-_r_h1_ .edgePath .path{stroke:rgb(143, 143, 143);stroke-width:1px;}#chatgpt-mermaid-_r_h1_ .flowchart-link{stroke:rgb(143, 143, 143);fill:none;}#chatgpt-mermaid-_r_h1_ .edgeLabel{background-color:rgb(252, 252, 252);text-align:center;}#chatgpt-mermaid-_r_h1_ .edgeLabel p{background-color:rgb(252, 252, 252);}#chatgpt-mermaid-_r_h1_ .edgeLabel rect{opacity:0.5;background-color:rgb(252, 252, 252);fill:rgb(252, 252, 252);}#chatgpt-mermaid-_r_h1_ .labelBkg{background-color:rgba(252, 252, 252, 0.5);}#chatgpt-mermaid-_r_h1_ .cluster rect{fill:rgb(243, 243, 243);stroke:rgba(0, 0, 0, 0.1);stroke-width:1px;}#chatgpt-mermaid-_r_h1_ .cluster text{fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_h1_ .cluster span{color:rgb(13, 13, 13);}#chatgpt-mermaid-_r_h1_ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:-apple-system-body,ui-sans-serif,-apple-system,system-ui,"Segoe UI",Helvetica,"Apple Color Emoji",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";font-size:12px;background:rgb(243, 243, 243);border:1px solid rgba(0, 0, 0, 0.1);border-radius:2px;pointer-events:none;z-index:100;}#chatgpt-mermaid-_r_h1_ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:rgb(13, 13, 13);}#chatgpt-mermaid-_r_h1_ rect.text{fill:none;stroke-width:0;}#chatgpt-mermaid-_r_h1_ .icon-shape,#chatgpt-mermaid-_r_h1_ .image-shape{background-color:rgb(252, 252, 252);text-align:center;}#chatgpt-mermaid-_r_h1_ .icon-shape p,#chatgpt-mermaid-_r_h1_ .image-shape p{background-color:rgb(252, 252, 252);padding:2px;}#chatgpt-mermaid-_r_h1_ .icon-shape .label rect,#chatgpt-mermaid-_r_h1_ .image-shape .label rect{opacity:0.5;background-color:rgb(252, 252, 252);fill:rgb(252, 252, 252);}#chatgpt-mermaid-_r_h1_ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#chatgpt-mermaid-_r_h1_ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#chatgpt-mermaid-_r_h1_ .node .neo-node{stroke:rgb(83, 154, 248);}#chatgpt-mermaid-_r_h1_ [data-look="neo"].node rect,#chatgpt-mermaid-_r_h1_ [data-look="neo"].cluster rect,#chatgpt-mermaid-_r_h1_ [data-look="neo"].node polygon{stroke:url(#chatgpt-mermaid-_r_h1_-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#chatgpt-mermaid-_r_h1_ [data-look="neo"].swimlane.cluster rect{filter:none;}#chatgpt-mermaid-_r_h1_ [data-look="neo"].node path{stroke:url(#chatgpt-mermaid-_r_h1_-gradient);stroke-width:1px;}#chatgpt-mermaid-_r_h1_ [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#chatgpt-mermaid-_r_h1_ [data-look="neo"].node .neo-line path{stroke:rgb(83, 154, 248);filter:none;}#chatgpt-mermaid-_r_h1_ [data-look="neo"].node circle{stroke:url(#chatgpt-mermaid-_r_h1_-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#chatgpt-mermaid-_r_h1_ [data-look="neo"].node circle .state-start{fill:#000000;}#chatgpt-mermaid-_r_h1_ [data-look="neo"].icon-shape .icon{fill:url(#chatgpt-mermaid-_r_h1_-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#chatgpt-mermaid-_r_h1_ [data-look="neo"].icon-shape .icon-neo path{stroke:url(#chatgpt-mermaid-_r_h1_-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#chatgpt-mermaid-_r_h1_ .node text{font-size:14px;font-weight:600;letter-spacing:normal;fill:rgb(0, 79, 153);}#chatgpt-mermaid-_r_h1_ .edgeLabels text{font-size:13px;font-weight:600;letter-spacing:-0.08px;fill:rgb(0, 79, 153);}#chatgpt-mermaid-_r_h1_ .node tspan[font-weight="normal"],#chatgpt-mermaid-_r_h1_ .edgeLabels tspan[font-weight="normal"]{font-weight:600;}#chatgpt-mermaid-_r_h1_ .edgeLabel .label rect{opacity:1;rx:13px;ry:13px;fill:rgb(245, 250, 255);stroke:rgb(206, 219, 229);stroke-width:1px;}#chatgpt-mermaid-_r_h1_ .node rect,#chatgpt-mermaid-_r_h1_ .node circle,#chatgpt-mermaid-_r_h1_ .node ellipse,#chatgpt-mermaid-_r_h1_ .node polygon,#chatgpt-mermaid-_r_h1_ .node path{fill:rgb(229, 243, 255);stroke:rgba(0, 0, 0, 0.1);stroke-width:1px;}#chatgpt-mermaid-_r_h1_ .node rect{rx:16px;ry:16px;}#chatgpt-mermaid-_r_h1_ .node.mermaid-decision .label-container{fill:rgb(245, 250, 255);stroke:rgb(206, 219, 229);stroke-dasharray:2,2;}#chatgpt-mermaid-_r_h1_ .edgePaths .flowchart-link{stroke:rgb(143, 143, 143);stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;}#chatgpt-mermaid-_r_h1_ .marker{fill:rgb(143, 143, 143);stroke:rgb(143, 143, 143);}#chatgpt-mermaid-_r_h1_ :root{--mermaid-font-family:-apple-system-body,ui-sans-serif,-apple-system,system-ui,"Segoe UI",Helvetica,"Apple Color Emoji",Arial,sans-serif,"Segoe UI Emoji","Segoe UI Symbol";}Eye-Blink SensorESP32 ControllerProlonged Eye Closure?Activate Buzzer and LEDSend Event via Wi-Fin8n AutomationGoogle SheetsTelegram Voice and Text AlertsThingSpeak DashboardAI Event SummaryIoT WebpageNoYes

Expected outcome

The prototype demonstrates how embedded electronics, IoT cloud services, automation, and AI-assisted analysis can work together to monitor possible driver drowsiness. It provides immediate local warnings and supports remote event tracking and reporting.

Safety note: This is an educational prototype, not a certified driver-safety device. An IR sensor and a simple eye-closure threshold cannot reliably determine whether a person is fit to drive. The local warning should work without cloud connectivity, and the system must be thoroughly tested before any real-world use.

No comments:

Post a Comment