AI Child Safety Monitoring System with Emotion/Expression Detection, ESP32, n8n, AI Agent, Telegram Voice Alerts, Google Sheets & ThingSpeak
Below is a complete reference design you can use as a final-year project, IoT/AI project, prototype, or dissertation implementation.
One important design point: a camera cannot reliably determine a child's actual internal emotional state. In this project, the AI should therefore report “observed facial expression” or “apparent expression”—for example, happy-looking, sad-looking, fearful-looking, neutral—rather than claiming that the child definitely feels a particular emotion. This is especially important for a child-safety application.
The ESP32 can operate as a Wi-Fi station and connect to an Internet network; Espressif's current Arduino-ESP32 documentation supports this architecture.
1. Project Title
AI-Powered Child Safety Monitoring and Expression Detection System Using ESP32, IoT, n8n Agentic Automation, Telegram Voice Alerts, Google Sheets and ThingSpeak
Short title
AI Child Safety Monitoring System Using ESP32 + n8n + AI Agent
2. Abstract
This project presents an IoT-based child safety monitoring system that combines an ESP32-based sensing device, camera/image analysis, artificial intelligence, cloud automation and real-time notification services.
The ESP32 continuously monitors environmental and safety parameters such as temperature, humidity, motion, light level and optionally sound/noise. A camera module captures an image when a monitoring condition occurs or at configured intervals. The collected information is transmitted through Wi-Fi to an n8n automation server.
n8n acts as the central orchestration layer. It receives sensor data through a Webhook, evaluates safety rules, optionally sends an image to a vision-capable AI model for analysis, stores selected events in Google Sheets, publishes telemetry to ThingSpeak and generates an alert when a configurable threshold or combination of conditions is detected.
When an important event occurs, an AI Agent converts the structured event information into a concise human-readable safety message. The system can then send a Telegram text notification and a voice alert to an authorized guardian.
The proposed architecture separates sensing, AI interpretation, decision/automation, data logging, and notification. This makes the system modular and easier to extend.
Telegram provides an HTTP-based Bot API, and its current sendVoice operation supports voice-message delivery to a chat. ThingSpeak provides REST APIs for writing channel data through HTTP GET or POST requests.
3. Main Objectives
The project has the following objectives:
-
Monitor a child's surrounding environment using IoT sensors.
-
Capture images using an ESP32 camera.
-
Analyze selected images using an AI vision model.
-
Identify potentially concerning observable conditions, rather than claiming certainty about a child's internal emotional state.
-
Automatically process events using n8n.
-
Use an AI Agent to generate an understandable alert message.
-
Send Telegram notifications to an authorized guardian.
-
Send Telegram voice alerts for high-priority events.
-
Store event records in Google Sheets.
-
Publish sensor telemetry to ThingSpeak.
-
Provide an IoT webpage for local monitoring.
-
Provide configurable safety thresholds.
-
Maintain an event history.
-
Reduce unnecessary alerts through event filtering and cooldown logic.
4. Overall System Architecture
┌──────────────────────────────┐
│ CHILD AREA │
│ │
│ Child / Room / Play Area │
└──────────────┬───────────────┘
│
┌─────────────────────┼─────────────────────┐
│ │ │
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌────────────┐
│ Temperature│ │ PIR Motion │ │ Light │
│ / Humidity │ │ Sensor │ │ Sensor │
└─────┬─────┘ └─────┬─────┘ └─────┬──────┘
│ │ │
└─────────────────────┼─────────────────────┘
▼
┌───────────────────┐
│ ESP32 │
│ │
│ Sensor Controller │
│ Wi-Fi │
│ Web Server │
│ Camera Interface │
└─────────┬─────────┘
│
Wi-Fi / HTTPS
│
┌──────────────────▼─────────────────┐
│ n8n │
│ Automation Server │
│ │
│ Webhook → Validation → Rules │
│ ↓ │
│ AI Vision / AI Agent │
│ ↓ │
│ Decision Engine │
└───────┬──────────┬───────────┬────┘
│ │ │
┌───────▼───┐ ┌───▼──────┐ ┌──▼──────────┐
│ Telegram │ │ Google │ │ ThingSpeak │
│ Alert │ │ Sheets │ │ Dashboard │
└───────┬───┘ └──────────┘ └─────────────┘
│
┌───────▼────────┐
│ Guardian Phone │
│ Text + Voice │
└────────────────┘
5. Recommended Hardware
Core hardware
| Component | Purpose |
|---|---|
| ESP32-CAM or ESP32 camera-capable board | Controller + camera |
| ESP32 development board | Alternative controller |
| DHT22/DHT11 | Temperature/humidity |
| PIR HC-SR501 | Motion detection |
| LDR/BH1750 | Light measurement |
| MQ-series sensor | Optional environmental/gas experiment |
| Microphone module | Optional sound-level monitoring |
| Buzzer | Local warning |
| LED | Status indication |
| 5 V power supply | Power |
| Breadboard | Prototyping |
| Jumper wires | Connections |
Recommended camera configuration
For a simple prototype:
ESP32-CAM + OV2640 camera
For a more capable design:
ESP32-S3 camera board
The exact GPIO assignment depends on the particular ESP32-CAM board, so the GPIO table must be taken from the board's schematic rather than copied blindly from another ESP32-CAM variant.
6. Software Stack
Firmware:
Arduino IDE
ESP32 Arduino Core
C/C++
IoT:
Wi-Fi
HTTP/HTTPS
ESP32 Web Server
Automation:
n8n
AI:
Vision-capable AI model
AI Agent / LLM
Cloud:
Google Sheets
ThingSpeak
Notification:
Telegram Bot API
Telegram Voice Message
Dashboard:
ESP32 Web Page
ThingSpeak charts
Optional:
MQTT
Firebase
Node-RED
PostgreSQL
The current Arduino-ESP32 documentation supports Wi-Fi station mode for connecting an ESP32 to an access point and obtaining an IP address.
7. Functional Blocks
The project can be divided into eight major blocks.
Block 1 — Sensing
Sensors measure:
-
temperature
-
humidity
-
motion
-
light
-
optional sound
-
optional distance
Block 2 — Camera
The camera captures a JPEG image when required.
Block 3 — ESP32
The ESP32:
-
reads sensors
-
controls the camera
-
hosts a local webpage
-
connects to Wi-Fi
-
sends data to n8n
-
receives configuration commands
Block 4 — n8n
n8n becomes the central automation controller.
Block 5 — AI
AI analyses:
-
image
-
sensor information
-
event context
Block 6 — Decision Engine
The system determines whether the event is:
NORMAL
LOW PRIORITY
WARNING
CRITICAL
Block 7 — Cloud
Data goes to:
-
Google Sheets
-
ThingSpeak
Block 8 — Notification
The guardian receives:
-
Telegram text
-
Telegram voice alert
-
optionally image
8. Example Safety Logic
Do not use a single emotion classification as the trigger for an emergency.
Instead, combine multiple signals.
For example:
Motion detected
+
High noise level
+
Observed distressed-looking facial expression
↓
Potential concern
↓
AI reviews context
↓
Guardian notification
Another example:
Room temperature > configured limit
+
Child detected in room
↓
Temperature warning
↓
Telegram notification
Another:
Motion detected
+
No expected adult/guardian confirmation
+
Configured monitoring schedule
↓
Potential safety event
↓
Guardian alert
This is much more defensible than:
AI says "sad"
↓
EMERGENCY
9. System Flow Diagram
START
│
▼
ESP32 Power ON
│
▼
Initialize Sensors
│
▼
Initialize Camera
│
▼
Wi-Fi?
┌─────┴─────┐
│ │
NO YES
│ │
└── Retry ▼
Read Sensors
│
▼
Safety Condition?
┌─────┴─────┐
NO YES
│ │
│ ▼
│ Capture Image
│ │
│ ▼
│ Send to n8n
│ │
└──────┬─────┘
▼
n8n Webhook
│
▼
Validate JSON
│
▼
AI Vision
│
▼
AI Agent
│
▼
Safety Decision
┌───────┼────────┐
│ │ │
NORMAL WARNING CRITICAL
│ │ │
▼ ▼ ▼
Logging Alert Voice Alert
│ │ │
└───────┼────────┘
▼
Google Sheets
│
▼
ThingSpeak
│
▼
END
10. Hardware Schematic
A generic prototype wiring diagram can be represented as follows.
+----------------------+
| ESP32 |
| |
3.3V -----| 3V3 GND |----- GND
| |
DHT DATA -------| GPIO 4 |
PIR OUT --------| GPIO 13 |
LDR OUT --------| GPIO 34 |
BUZZER ---------| GPIO 25 |
STATUS LED -----| GPIO 2 |
| |
| Camera Connector |
+----------┬-----------+
│
▼
OV2640 Camera
Example sensor connections
DHT22
DHT22 ESP32
VCC ------------ 3.3V
GND ------------ GND
DATA ------------ GPIO4
PIR
PIR ESP32
VCC ------------ 5V/appropriate supply
GND ------------ GND
OUT ------------ GPIO13
Check your PIR module's output voltage before connecting it to an ESP32 GPIO.
LDR voltage divider
3.3V
│
[LDR]
│
├──────────── GPIO34
│
[10kΩ]
│
GND
11. ESP32 Webpage
The ESP32 can host a local webpage.
Example:
+------------------------------------------------+
| AI CHILD SAFETY MONITOR |
+------------------------------------------------+
| Device: ESP32-CAM |
| Status: ONLINE |
| |
| Temperature 27.4 °C |
| Humidity 61 % |
| Motion DETECTED |
| Light 345 lux |
| |
| Camera |
| +--------------------------------------------+ |
| | | |
| | CAMERA IMAGE | |
| | | |
| +--------------------------------------------+ |
| |
| AI Observation: Neutral-looking expression |
| Safety Status: NORMAL |
| |
| [Capture Image] [Send Test Alert] |
+------------------------------------------------+
The webpage should be treated primarily as a device/local dashboard. The cloud dashboard can be provided separately through ThingSpeak.
12. ESP32 Firmware
Below is a starting firmware architecture. Because ESP32-CAM boards have different pin mappings, replace the camera pin configuration with the values for your exact board.
#include <WiFi.h>
#include <WebServer.h>
#include <HTTPClient.h>
#include <DHT.h>
#define DHT_PIN 4
#define DHT_TYPE DHT22
#define PIR_PIN 13
#define LDR_PIN 34
#define BUZZER_PIN 25
#define LED_PIN 2
const char* WIFI_SSID = "YOUR_WIFI";
const char* WIFI_PASSWORD = "YOUR_PASSWORD";
const char* N8N_WEBHOOK =
"https://YOUR-N8N-DOMAIN/webhook/child-monitor";
const char* THINGSPEAK_API_KEY =
"YOUR_THINGSPEAK_WRITE_KEY";
DHT dht(DHT_PIN, DHT_TYPE);
WebServer server(80);
float temperature = 0;
float humidity = 0;
int lightLevel = 0;
bool motionDetected = false;
unsigned long lastUpload = 0;
const unsigned long uploadInterval = 15000;
void connectWiFi()
{
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi connected");
Serial.print("IP: ");
Serial.println(WiFi.localIP());
}
void readSensors()
{
temperature = dht.readTemperature();
humidity = dht.readHumidity();
lightLevel = analogRead(LDR_PIN);
motionDetected = digitalRead(PIR_PIN);
}
String getJSON()
{
String json = "{";
json += "\"device_id\":\"ESP32_CHILD_01\",";
json += "\"temperature\":" + String(temperature, 2) + ",";
json += "\"humidity\":" + String(humidity, 2) + ",";
json += "\"light\":" + String(lightLevel) + ",";
json += "\"motion\":";
json += motionDetected ? "true" : "false";
json += "}";
return json;
}
void sendToN8N()
{
if (WiFi.status() != WL_CONNECTED)
return;
HTTPClient http;
http.begin(N8N_WEBHOOK);
http.addHeader("Content-Type", "application/json");
String payload = getJSON();
int responseCode = http.POST(payload);
Serial.print("n8n response: ");
Serial.println(responseCode);
http.end();
}
void sendToThingSpeak()
{
if (WiFi.status() != WL_CONNECTED)
return;
HTTPClient http;
String url =
"https://api.thingspeak.com/update?"
"api_key=" + String(THINGSPEAK_API_KEY) +
"&field1=" + String(temperature) +
"&field2=" + String(humidity) +
"&field3=" + String(lightLevel) +
"&field4=" + String(motionDetected ? 1 : 0);
http.begin(url);
int responseCode = http.GET();
Serial.print("ThingSpeak response: ");
Serial.println(responseCode);
http.end();
}
void handleRoot()
{
readSensors();
String page = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
<meta name="viewport"
content="width=device-width, initial-scale=1">
<title>AI Child Safety Monitor</title>
<style>
body {
font-family: Arial;
background: #101827;
color: white;
padding: 20px;
}
.card {
background: #1e293b;
padding: 20px;
margin: 10px;
border-radius: 12px;
}
.value {
font-size: 28px;
color: #38bdf8;
}
</style>
</head>
<body>
<h1>AI Child Safety Monitor</h1>
<div class="card">
Temperature
<div class="value">)rawliteral";
page += String(temperature, 1);
page += R"rawliteral( °C</div>
</div>
<div class="card">
Humidity
<div class="value">)rawliteral";
page += String(humidity, 1);
page += R"rawliteral( %</div>
</div>
<div class="card">
Motion
<div class="value">)rawliteral";
page += motionDetected ? "DETECTED" : "NONE";
page += R"rawliteral(</div>
</div>
<div class="card">
Light Level
<div class="value">)rawliteral";
page += String(lightLevel);
page += R"rawliteral(</div>
</div>
</body>
</html>
)rawliteral";
server.send(200, "text/html", page);
}
void setup()
{
Serial.begin(115200);
pinMode(PIR_PIN, INPUT);
pinMode(LDR_PIN, INPUT);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(LED_PIN, OUTPUT);
dht.begin();
connectWiFi();
server.on("/", handleRoot);
server.begin();
Serial.println("Web server started");
}
void loop()
{
server.handleClient();
readSensors();
unsigned long now = millis();
if (now - lastUpload > uploadInterval)
{
lastUpload = now;
sendToThingSpeak();
// Send to n8n only when appropriate,
// or use a longer interval in production.
if (motionDetected ||
temperature > 30.0)
{
sendToN8N();
}
}
delay(100);
}
ThingSpeak's current API accepts channel updates using https://api.thingspeak.com/update with a channel write API key and fieldX values.
13. JSON Sent by ESP32
The ESP32 should send structured data rather than a long text string.
Example:
{
"device_id": "ESP32_CHILD_01",
"timestamp": "2026-09-22T18:00:00Z",
"temperature": 29.4,
"humidity": 62.5,
"light": 280,
"motion": true,
"noise_level": 71,
"event": "motion_detected"
}
If an image is being sent separately:
{
"device_id": "ESP32_CHILD_01",
"event": "visual_check",
"temperature": 29.4,
"humidity": 62.5,
"motion": true,
"image_required": true
}
14. n8n Architecture
The main n8n workflow should look like:
┌─────────────┐
│ Webhook │
│ ESP32 data │
└──────┬──────┘
│
▼
┌─────────────┐
│ Validate │
│ Input JSON │
└──────┬──────┘
│
▼
┌─────────────┐
│ Normalize │
│ Data │
└──────┬──────┘
│
▼
┌──────────────────┐
│ Safety Rules │
│ Temperature │
│ Motion │
│ Noise │
└─────────┬────────┘
│
▼
Need AI Vision?
/ \
NO YES
│ │
│ ┌────▼─────┐
│ │ AI Vision│
│ └────┬─────┘
│ │
└─────┬─────┘
▼
┌───────────────┐
│ AI Agent │
│ Context + AI │
└───────┬───────┘
│
▼
┌─────────────────┐
│ Decision Engine │
└───────┬─────────┘
│
┌────┴────┐
│ │
NORMAL ALERT
│ │
▼ ▼
Logging Telegram
│
┌────┴─────┐
│ │
Text Voice
n8n has a built-in Telegram integration for automating Telegram operations.
15. n8n Workflow 1 — Sensor Webhook
Create:
Webhook
↓
Set / Edit Fields
↓
Code
↓
IF
↓
Google Sheets
↓
ThingSpeak
Webhook configuration
HTTP Method:
POST
Path:
child-monitor
Your ESP32 then posts to:
https://YOUR-N8N-SERVER/webhook/child-monitor
16. n8n Data Normalization Code
Use an n8n Code node:
const data = $json;
const temperature = Number(data.temperature || 0);
const humidity = Number(data.humidity || 0);
const light = Number(data.light || 0);
const motion =
data.motion === true ||
data.motion === "true" ||
data.motion === 1;
let priority = "NORMAL";
if (temperature >= 35) {
priority = "WARNING";
}
if (motion && temperature >= 35) {
priority = "HIGH";
}
return [{
json: {
device_id: data.device_id || "UNKNOWN",
timestamp: data.timestamp || new Date().toISOString(),
temperature,
humidity,
light,
motion,
priority
}
}];
17. AI Vision Analysis
The AI should receive an instruction similar to:
You are a child-safety observation assistant.
Analyze only visible information in the supplied image.
Describe observable:
- facial expression
- posture
- visible activity
- environmental hazards
- whether assistance may be appropriate
Do not claim to know the child's internal emotional state.
Do not diagnose medical or psychological conditions.
Return structured JSON.
Use:
{
"observed_expression": "",
"activity": "",
"visible_hazard": "",
"concern_level": "normal|warning|high",
"reason": ""
}
Example output:
{
"observed_expression": "distressed-looking",
"activity": "sitting on floor",
"visible_hazard": "none obvious",
"concern_level": "warning",
"reason": "The image shows a distressed-looking facial expression, but the cause cannot be determined from the image alone."
}
18. AI Agent Design
The AI Agent should not have unlimited authority.
Use it as a reasoning and message-generation component, while deterministic safety rules remain responsible for actual alert thresholds.
Recommended architecture
Sensor Rules
│
▼
Deterministic
Safety Engine
│
├───────────────┐
│ │
▼ ▼
Normal Potential Event
│
▼
AI Analysis
│
▼
AI Agent
│
▼
Alert Decision
This prevents the LLM from being the only safety mechanism.
19. AI Agent System Prompt
Use something similar to:
You are an AI IoT safety assistant.
Your job is to interpret structured sensor information and
computer-vision observations and create concise safety messages.
Important rules:
1. Do not claim certainty about a child's emotions.
2. Use "appears", "observed", or "looks" for visual expressions.
3. Do not diagnose illness or psychological conditions.
4. Do not identify a child by face.
5. Do not infer sensitive characteristics.
6. Treat sensor threshold violations according to configured rules.
7. Never invent sensor values.
8. Never invent events.
9. If information is insufficient, say so.
10. For a critical configured event, generate a concise alert.
11. Include the device ID and timestamp.
12. Do not include unnecessary personal information.
Return JSON:
{
"severity": "normal|warning|high",
"title": "",
"message": "",
"voice_message": "",
"reason": ""
}
20. Example AI Agent Input
{
"device_id": "ESP32_CHILD_01",
"temperature": 36.1,
"humidity": 70,
"motion": true,
"noise_level": 78,
"observed_expression": "distressed-looking",
"visible_hazard": "none obvious"
}
Possible output:
