diff --git a/README.md b/README.md index fa42219..02145f4 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # AtmoSync - Sistema de Monitoreo de Temperatura y Humedad +![Dashboard](/img/Imagen3.png) + AtmoSync es una aplicación fullstack para monitorear temperatura y humedad en tiempo real desde dispositivos IoT (ESP32 + DHT11/DHT22). Incluye un backend con Node.js/Express, una base de datos MongoDB Atlas y una interfaz moderna con React/Vite. --- @@ -7,40 +9,76 @@ AtmoSync es una aplicación fullstack para monitorear temperatura y humedad en t ## Tabla de Contenidos - [Características](#características) +- [Objetivos del Proyecto](#objetivos-del-proyecto) +- [Integrantes](#integrantes) +- [Contexto Académico](#contexto-académico) - [API REST](#api-rest) -- [Endpoints](#endpoints) -- [Codigo ESP32](#arduino--esp32) +- [Arduino / ESP32](#arduino--esp32) +- [Autenticación](#autenticación) +- [Dashboard Web](#dashboard-web) +- [Visualización de Datos con Chart.js](#visualización-de-datos-con-chartjs) +- [Base de Datos Utilizada](#base-de-datos-utilizada) +- [Control del LED desde el Dashboard](#control-del-led-desde-el-dashboard) +- [Sobre Nosotros](#sobre-nosotros) +- [Comunicación entre el ESP32 y la API REST](#comunicación-entre-el-esp32-y-la-api-rest) +- [Creación de la API REST con Express](#creación-de-la-api-rest-con-express) +- [Envío y Recepción de Datos JSON](#envío-y-recepción-de-datos-json) +--- -## Características +# Características - Autenticación de usuarios con registro e inicio de sesión - API REST para recepción de datos de sensores IoT -- Control de actuadores (LED) a través de la API -- Dashboard con gráficas en tiempo real de temperatura y humedad -- Indicadores de estado (temperatura alta, humedad baja) -- Actualización automática de datos cada 3 segundos -- Base de datos en la nube con MongoDB Atlas -- CORS habilitado para integración con cualquier cliente +- Control de actuadores (LED) +- Dashboard con gráficas en tiempo real +- Base de datos MongoDB Atlas +- Comunicación entre ESP32 y API REST --- +# Objetivos del Proyecto + +- Implementar comunicación entre dispositivos IoT y una API REST +- Monitorear temperatura y humedad en tiempo real +- Almacenar datos en una base de datos NoSQL +- Visualizar datos mediante dashboards interactivos + +--- -## API REST +# Integrantes -Base URL: `http://localhost:5000` +- Richard Montes +- Diego Barrios +- Ronald Pradilla --- -### Prueba de conexión +# Contexto Académico + +Proyecto desarrollado aplicando conceptos de: + +- APIs REST +- Comunicación HTTP +- Bases de datos NoSQL +- Desarrollo frontend y backend +- Internet de las Cosas (IoT) + --- -### Sensores +# API REST + +Base URL: +```txt +http://localhost:5000 +``` + +--- -#### Guardar lectura del sensor +## Sensores -Endpoint utilizado por el ESP32 para enviar datos de temperatura y humedad. +### Guardar lectura del sensor ```http POST /sensor @@ -52,227 +90,131 @@ Content-Type: application/json } ``` -**Respuesta exitosa (200):** +**Respuesta exitosa:** + ```json { "ok": true } ``` --- -#### Obtener todas las lecturas +### Obtener lecturas ```http GET /lecturas ``` -**Respuesta exitosa (200):** +**Respuesta:** + ```json [ { "_id": "507f1f77bcf86cd799439012", "temperatura": 25.5, "humedad": 65.2 - }, - { - "_id": "507f1f77bcf86cd799439013", - "temperatura": 26.1, - "humedad": 63.8 } ] ``` -> Las lecturas se devuelven en el orden de inserción. El dashboard muestra las últimas 10. -> ``` +--- -### Endpoints +## Endpoints -| Método | Endpoint | Autenticación | Descripción | -|--------|----------|:---:|-------------| -| GET | `/prueba` | No | Verificar conexión al servidor | -| POST | `/register` | No | Registrar nuevo usuario | -| POST | `/login` | No | Iniciar sesión | -| POST | `/sensor` | No | Guardar lectura de sensor | -| GET | `/lecturas` | No | Obtener todas las lecturas | -| POST | `/led` | No | Cambiar estado del LED | -| GET | `/led` | No | Obtener estado del LED | +| Método | Endpoint | Descripción | +|--------|----------|-------------| +| GET | `/prueba` | Verificar conexión | +| POST | `/register` | Registrar usuario | +| POST | `/login` | Iniciar sesión | +| POST | `/sensor` | Guardar lectura | +| GET | `/lecturas` | Obtener lecturas | +| POST | `/led` | Cambiar estado LED | +| GET | `/led` | Obtener estado LED | --- +# Arduino / ESP32 + +![imagen](/img/Imagen11.png) + +En este apartado observamos el sensor DHT11 conectado a la placa ESP32 utilizada en el proyecto. + +El sensor lee los valores de temperatura y humedad para enviarlos hacia la API REST desarrollada con Node.js y Express. -### Arduino / ESP32 +--- +## Código ESP32 ```cpp #include #include #include + #define LEDPIN 2 #define DHTPIN 4 #define DHTTYPE DHT11 - -DHT dht(DHTPIN, DHTTYPE); - -const char* ssid = "FAMILIA-MONTES-2.4"; -const char* password = "NUEVO2024"; - -void setup() { - Serial.begin(115200); - dht.begin(); - pinMode(LEDPIN, OUTPUT); - WiFi.begin(ssid, password); - Serial.print("Conectando a WiFi"); - - while (WiFi.status() != WL_CONNECTED) { - delay(500); - Serial.print("."); - } - - Serial.println("\nConectado!"); - Serial.print("IP del ESP32: "); - Serial.println(WiFi.localIP()); -} - -void loop() { - if (WiFi.status() == WL_CONNECTED) { - HTTPClient httpLED; - httpLED.begin("http://192.168.1.77:5000/led"); - - int code = httpLED.GET(); - - if (code == 200) { - String payload = httpLED.getString(); - - Serial.print("Payload recibido: "); - Serial.println(payload); - - if (payload.indexOf("true") != -1) { - digitalWrite(LEDPIN, HIGH); - } else { - digitalWrite(LEDPIN, LOW); - } - } - - Serial.print("Código HTTP LED: "); - Serial.println(code); - -httpLED.end(); - float hum = dht.readHumidity(); - float temp = dht.readTemperature(); - - if (isnan(hum) || isnan(temp)) { - Serial.println("Error leyendo el sensor, revisa los cables"); - delay(5000); - return; - } - - String json = "{\"temperatura\":" + String(temp) + ",\"humedad\":" + String(hum) + "}"; - - Serial.print("Enviando: "); - Serial.println(json); - - HTTPClient http; - http.begin("http://192.168.1.77:5000/sensor"); - http.addHeader("Content-Type", "application/json"); - - int response = http.POST(json); - - Serial.print("Respuesta del servidor: "); - Serial.println(response); - - http.end(); - } else { - Serial.println("WiFi desconectado, reconectando..."); - WiFi.begin(ssid, password); - } - - delay(1000); -} -#### Verificar que el servidor responde - -```http -GET /prueba -``` - -**Respuesta (200):** -``` -FUNCIONA ESTA RUTA ``` --- -### Autenticación +# Autenticación -#### Registrar nuevo usuario -![Registro](/img/Imagen1.png) +## Registrar nuevo usuario -```http -POST /register -Content-Type: application/json +![Registro](/img/Imagen1.png) -{ - "email": "usuario@ejemplo.com", - "password": "miContraseña123" -} -``` +La interfaz de registro permite crear nuevas cuentas dentro de la plataforma AtmoSync. -**Respuesta exitosa (200):** -``` -Usuario guardado -``` +Cuando el usuario completa el formulario, React realiza una petición `POST` hacia `/register`. -**Errores posibles:** -```json -{ "error": "El email ya está registrado" } +```js +fetch("http://127.0.0.1:5000/register", { + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({ + email, + username, + password + }) +}); ``` --- -#### Iniciar sesión +## Iniciar sesión + ![Inicio de sesion](/img/Imagen2.png) -```http -POST /login -Content-Type: application/json +La interfaz de inicio de sesión permite autenticar usuarios utilizando correo y contraseña. -{ - "email": "usuario@ejemplo.com", - "password": "miContraseña123" -} -``` +Mensajes posibles: -**Respuesta exitosa (200):** -``` -Usuario encontrado -``` +- `Usuario no existe` +- `Contraseña incorrecta` +- `Completa todos los campos` -**Respuesta fallida:** -``` -Usuario no existe -``` +--- -**Respuesta fallida (contraseña incorrecta):** -``` -Contraseña incorrecta +# Dashboard Web -``` -## Dashboard Web ![Dashboard](/img/Imagen3.png) La interfaz web fue desarrollada con React + Vite y permite visualizar en tiempo real los datos enviados desde el ESP32. -El dashboard consume la API REST del backend mediante peticiones `fetch` y muestra: +El dashboard muestra: - Temperatura actual - Humedad actual -- Gráficas dinámicas de temperatura y humedad +- Gráficas dinámicas - Historial de lecturas - Indicadores de estado - Control remoto del LED conectado al ESP32 - --- -### Tecnologías utilizadas +## Tecnologías utilizadas + - React - Vite - Chart.js @@ -281,11 +223,13 @@ El dashboard consume la API REST del backend mediante peticiones `fetch` y muest --- -### Actualización en tiempo real -![Dasboard](/img/Imagen4.png) +## Actualización en tiempo real + +![Dashboard](/img/Imagen4.png) + El dashboard obtiene nuevas lecturas automáticamente cada 3 segundos utilizando `setInterval`. -``` +```js useEffect(() => { const obtenerDatos = () => { @@ -302,33 +246,99 @@ useEffect(() => { }, []); ``` + +--- + +# Visualización de Datos con Chart.js + +![Librería Chart.js](/img/Imagen5.png) + +Para representar gráficamente los datos de temperatura y humedad en tiempo real, se implementó la librería Chart.js junto con `react-chartjs-2`. + --- -### Libreria para visualizar graficas -Utilizamos chartJS, es este: -![libreria](/img/Imagen5.png) +## Configuración de Chart.js + +```js +import { + Chart as ChartJS, + CategoryScale, + LinearScale, + PointElement, + LineElement, + Title, + Tooltip, + Legend +} from 'chart.js'; +``` -Aquí agregamos Chart.JS para visualizar los datos +--- -![libreria](/img/Imagen6.png) +## Obtención de Datos desde la API -Luego vamos agregando las tarjetas +```js +fetch("http://192.168.1.77:5000/lecturas") +``` +Los datos son obtenidos desde el backend y actualizados automáticamente. --- -## Base de datos Utilizada -Tenemos esta base de datos NOSQL hecha en mongodbAtlas: + +## Creación de las Gráficas + +```js +const temperaturaData = { + labels: datos.map((_, index) => `Lectura ${index + 1}`), + datasets: [ + { + label: 'Temperatura °C', + data: datos.map(item => item.temperatura), + }, + ], +}; +``` + +--- + +## Renderizado de las Gráficas + +```js + +``` + +![Dashboard con gráficas](/img/Imagen6.png) + +--- + +# Base de Datos Utilizada + ![Base de datos](/img/Imagen7.png) -Aquí nos muestra los datos del sensor con el respectivo ID del registro que mandaría desde el código. +El proyecto utiliza MongoDB Atlas para almacenar las lecturas del sensor. + +Cada documento contiene: + +- `_id` +- `temperatura` +- `humedad` + +--- ![Base de datos](/img/Imagen8.png) -También tenemos el otro apartado de los usuarios donde se evidencian los usuarios registrados desde el apartado de register que vimos anteriormente. + +También existe una colección para almacenar los usuarios registrados. + +--- + +# Control del LED desde el Dashboard + +![Dashboard](/img/Imagen3.png) + +Dentro del dashboard se encuentra el apartado para controlar el LED conectado al ESP32. --- -### Control de LED -#### Cambiar estado del LED +## Cambiar estado del LED ```http POST /led @@ -339,40 +349,42 @@ Content-Type: application/json } ``` -`true` = encendido, `false` = apagado. - -**Respuesta exitosa (200):** -```json -{ "ok": true } -``` +- `true` → enciende LED +- `false` → apaga LED --- -#### Obtener estado actual del LED +## Obtener estado del LED ```http GET /led ``` -**Respuesta (200):** +Respuesta: + ```json -{ "estado": true } +{ + "estado": true +} ``` -> El estado del LED se almacena en memoria. Se reinicia a `false` al reiniciar el servidor. - --- + +![Led](/img/Imagen20.png) + +El LED puede controlarse remotamente desde la aplicación web. + --- -## Sobre Nosotros +# Sobre Nosotros ![About](/img/Imagen9.png) + ![About](/img/Imagen10.png) -En el apartado **“Sobre Nosotros”** se presenta información general sobre los creadores y desarrolladores del proyecto AtmoSync. -Además, se describe el propósito del sistema, enfocado en el monitoreo ambiental mediante tecnologías IoT, así como las herramientas y tecnologías utilizadas durante el desarrollo de la plataforma. +En esta sección se presenta información sobre los desarrolladores y tecnologías utilizadas. -En la parte inferior de esta sección se muestran las principales tecnologías implementadas en el proyecto, incluyendo: +Tecnologías principales: - React - Node.js @@ -381,96 +393,77 @@ En la parte inferior de esta sección se muestran las principales tecnologías i - ESP32 - Chart.js -Esta sección permite conocer el contexto del proyecto y las tecnologías utilizadas para el desarrollo del sistema fullstack. - --- -### Objetivos del Proyecto - -- Implementar comunicación entre dispositivos IoT y una API REST -- Monitorear temperatura y humedad en tiempo real -- Almacenar datos en una base de datos NoSQL -- Visualizar información mediante dashboards interactivos -- Controlar actuadores remotamente desde una aplicación web ---- +# Comunicación entre el ESP32 y la API REST -### Integrantes +![imagen](/img/Imagen11.png) -- Richard Montes -- Diego Barrios -- Ronald Pradilla +El ESP32 obtiene los datos del sensor DHT11 y los prepara para ser enviados mediante HTTP. --- -### Contexto Académico +![imagen](/img/Imagen12.png) -Este proyecto fue desarrollado como práctica de integración entre hardware y software, aplicando conceptos de: +Los datos son convertidos a formato JSON. -- APIs REST -- Comunicación HTTP -- Bases de datos NoSQL -- Desarrollo frontend y backend -- Internet de las Cosas (IoT) -- Visualización de datos en tiempo real +```cpp +String json = "{\"temperatura\":" + String(temp) + ",\"humedad\":" + String(hum) + "}"; +``` ---- +Luego son enviados mediante un `POST` hacia `/sensor`. +--- -### Modelos de base de datos +![imagen](/img/Imagen13.png) -#### Usuario (`models/user.js`) +El ESP32 también realiza una petición `GET` al endpoint `/led`. -| Campo | Tipo | Descripción | -|-------|------|-------------| -| `_id` | ObjectId | Identificador único generado por MongoDB | -| `email` | String | Correo electrónico del usuario | -| `password` | String | Contraseña del usuario | +```cpp +httpLED.begin("http://192.168.1.77:5000/led"); +``` -#### Lectura de sensor (`models/HumedadR.js`) +--- -| Campo | Tipo | Descripción | -|-------|------|-------------| -| `_id` | ObjectId | Identificador único generado por MongoDB | -| `temperatura` | Number | Temperatura en grados Celsius | -| `humedad` | Number | Humedad relativa en porcentaje | +![imagen](/img/Imagen14.png) -### Stack tecnológico +--- -| Capa | Tecnología | Versión | -|------|-----------|---------| -| Frontend | React | 19.2.4 | -| Build tool | Vite | 8.0.4 | -| Gráficas | Chart.js + react-chartjs-2 | 4.5.1 / 5.3.1 | -| Backend | Express | 5.2.1 | -| Base de datos | MongoDB Atlas | — | +# Creación de la API REST con Express -**Versión:** 1.0.0 +```js +const express = require('express'); +const app = express(); +``` -![imagen](/img/Imagen11.png) -En este apartado del sensor y la placa ESP32 utilizada en nuestro proyecto, leemos los respectivos datos (Read between sensor and led) +La variable `app` representa la aplicación principal creada con Express. --- -![imagen](/img/Imagen12.png) -Luego, en esta línea de código, hacemos un Pushing data para enviarlo a la API en formato JSON. ---- -![imagen](/img/Imagen13.png) -En esta parte hacemos un GET para la API /led que está en nuestro código que veremos acontinuación. -![imagen](/img/Imagen14.png) ---- +![imagen](/img/Imagen15.png) -A continuación, aquí representamos la creación de la respectiva api tipo express que denominamos como “app”: +Luego se crea el endpoint `/sensor` utilizando el método `POST`. + +```js +app.post('/sensor', async (req, res) => { +``` -![imagen](/img/Imagen15.png) -Luego que creamos la api llamado “app”, hacemos un post llamado /sensor en el que tendrá las variables constantes que requiere el sensor para poder recibir sus datos. --- -Api: + +# Envío y Recepción de Datos JSON + ![imagen](/img/Imagen16.png) + ![imagen](/img/Imagen17.png) -Como lo vemos en esta parte, convertimos las variables de temperatura y humedad en tipo JSON donde la api los reconozca para entregar su respectiva respuesta. -Luego de eso enviamos un POST para esa misma api y así, las constantes que creamos en /sensor, las reconoce como tipo json. + +En esta parte del proyecto se convierten los datos del sensor a formato JSON para que la API pueda reconocerlos correctamente. + +Luego el ESP32 envía la información al backend mediante una petición HTTP `POST`. --- + ![imagen](/img/Imagen18.png) -En este apartado hacermos un Get llamado /lecturas, es decir… Cuando alguien entre a la ruta de /lecturas, estará usando un Get donde leemos y buscamos los datos que se encuentran en “HumedadR” ---- \ No newline at end of file + +Finalmente el dashboard consulta los datos desde `/lecturas` para visualizarlos en tiempo real mediante gráficas y tablas. + +--- diff --git a/img/Imagen20.png b/img/Imagen20.png new file mode 100644 index 0000000..949ea04 Binary files /dev/null and b/img/Imagen20.png differ