# Arquitectura Del Sistema ## Objetivo El sistema mide variables fisicoquimicas de un fotobiorreactor usando una Raspberry Pi y circuitos Atlas Scientific EZO por I2C. La Raspberry ejecuta una API, un recolector de datos, Nginx y un dashboard web. La arquitectura evita un driver personalizado de kernel. El acceso al hardware se realiza desde espacio de usuario mediante `/dev/i2c-1`. ## Vista General ```text Sondas fisicas | Circuitos Atlas Scientific EZO | Bus I2C de Raspberry Pi (/dev/i2c-1) | +------------------------------+ | Helpers C | | - EZO_ACQUIRE | | - EZO_COMMAND | +------------------------------+ | +------------------------------+ | Backend Node.js | | - API Express | | - Recolector continuo | | - Alarmas | | - Notificaciones | +------------------------------+ | +------------------------------+ | Archivos locales | | - data/*.json | | - logs/*.csv | | - config/*.json | +------------------------------+ | +------------------------------+ | Nginx + Dashboard web | +------------------------------+ ``` ## Capas ### 1. Hardware Sensores principales: | Variable | Circuito | Direccion | |---|---|---:| | Temperatura | EZO-RTD | `0x66` | | pH | EZO-pH | `0x63` | | Oxigeno disuelto | EZO-DO | `0x61` | | Conductividad | EZO-EC | `0x64` | Los sensores deben estar en modo I2C. Si un sensor esta en UART no aparecera en `i2cdetect`. ### 2. Helpers C Ubicacion: ```text sensors/EZOCommand/ ``` Binarios: ```text EZO_ACQUIRE EZO_COMMAND ``` `EZO_ACQUIRE` toma lecturas agrupadas. En lugar de esperar un segundo por cada sensor, envia `R` a los sensores habilitados, espera una sola ventana de conversion y luego recoge respuestas. Esto reduce tiempo de ciclo y carga del bus. `EZO_COMMAND` envia un comando a un circuito especifico. Se usa para: - `i` - `Status` - `R` - `Cal,?` - Calibraciones - Compensaciones - Cambios de configuracion EZO Ambos usan: ```text /tmp/photobioreactor-i2c.lock ``` Ese lock evita acceso simultaneo al bus I2C. ### 3. Recolector Archivo: ```text api/acquisition.js ``` Responsabilidades: - Leer configuracion de runtime. - Ejecutar adquisicion en modo demo o hardware. - Publicar JSON actual por sensor. - Agregar filas CSV. - Evaluar alarmas. - Despachar notificaciones. - Aplicar retencion historica. Servicio: ```text photobioreactor-acquisition.service ``` ### 4. API Archivo: ```text api/server.js ``` Responsabilidades: - Servir endpoints de configuracion. - Exponer historicos para exportacion. - Ejecutar comandos EZO. - Guardar umbrales. - Guardar notificaciones. - Limpiar historicos. - Servir bibliotecas locales `Chart.js` y `SheetJS`. Servicio: ```text photobioreactor-api.service ``` ### 5. Frontend Ubicacion: ```text frontend/ ``` Archivos principales: | Archivo | Uso | |---|---| | `index.html` | Estructura del dashboard | | `dashboard.css` | Diseno responsive | | `dashboard.js` | Lecturas, graficas, alarmas y configuracion | | `ezo-service.js` | Consola y calibracion EZO | | `export-service.js` | Exportacion CSV | | `export-excel.js` | Exportacion Excel | El dashboard lee JSON cada segundo y actualiza tarjetas, estados y resumen de alarmas. Las graficas se actualizan cada 10 segundos por defecto y muestran solo el dia actual. Los CSV conservan el historico segun la retencion configurada. ### 6. Nginx Nginx sirve el frontend y redirige `/api/` hacia Express. En produccion la API escucha en `127.0.0.1`; Nginx es la entrada HTTP para navegadores de la red local. ## Flujo De Lectura ```text 1. systemd inicia photobioreactor-acquisition. 2. El recolector lee config/runtime.json. 3. El recolector ejecuta EZO_ACQUIRE con los sensores habilitados. 4. EZO_ACQUIRE toma el lock I2C. 5. EZO_ACQUIRE consulta los EZO por /dev/i2c-1. 6. El recolector escribe data/*.json. 7. El recolector agrega filas a logs/*.csv. 8. El dashboard lee data/*.json cada segundo. 9. El dashboard actualiza tarjetas, alarmas y graficas. ``` ## Flujo De Comandos Y Calibracion ```text 1. El operador usa la consola o el panel de calibracion. 2. El frontend envia POST /api/sensors/:type/command. 3. La API valida token y comando. 4. La API ejecuta EZO_COMMAND. 5. EZO_COMMAND toma el lock I2C. 6. EZO_COMMAND envia el comando al circuito. 7. La API devuelve la respuesta real o demo. 8. La interfaz muestra TX/RX y, si aplica, consulta Cal,?. ``` Para comandos manuales desde terminal, detenga primero el recolector: ```bash sudo systemctl stop photobioreactor-acquisition sudo rm -f /tmp/photobioreactor-i2c.lock ``` ## Archivos De Datos Lectura actual: ```text data/EZORTD.json data/EZOPH.json data/EZODO.json data/EZOEC.json ``` Historicos: ```text logs/temperature.csv logs/ph.csv logs/do.csv logs/ec.csv ``` Alarmas: ```text logs/alarms.csv ``` Configuracion: ```text config/runtime.json config/alarms.json config/sensors.json config/notifications.json ``` En Raspberry instalada, la aplicacion vive en: ```text /opt/photobioreactor ``` Las notificaciones de produccion viven en: ```text /etc/photobioreactor/notifications.json ``` ## Estados De Sensor | Estado | Significado | |---|---| | `NORMAL` | Valor valido dentro del rango | | `WARNING` | Valor cerca de un limite | | `CRITICAL` | Valor fuera de rango | | `OFFLINE` | Sensor habilitado sin lectura valida | | `DISABLED` | Sensor deshabilitado por configuracion | ## Seguridad La API protege acciones criticas con `API_AUTH_TOKEN` si esta configurado. Acciones protegidas: - Comandos EZO. - Calibraciones. - Cambios de umbrales. - Cambios de runtime. - Cambios de notificaciones. - Borrado de historicos. El dashboard envia el token como: ```text X-API-Token ``` ## Almacenamiento El crecimiento principal viene de los CSV historicos. Los JSON se sobrescriben. Peor caso operativo: ```text 4 sensores 1 lectura por segundo 30 dias ``` Resultado aproximado: ```text 350 a 375 MB por mes ``` Ver detalles en: ```text docs/STORAGE_ESTIMATE.md ``` ## Razon Para No Usar Driver De Kernel El protocolo Atlas EZO es ASCII sobre I2C. No requiere temporizacion de kernel ni procesamiento en tiempo real estricto. Mantenerlo en espacio de usuario permite: - Diagnostico con comandos simples. - Cambios rapidos de calibracion. - Menor riesgo de bloquear el sistema. - Despliegue mas sencillo. - Compatibilidad directa con Raspberry Pi OS. Un driver de kernel solo tendria sentido si existiera una necesidad medible que no pueda resolverse con `/dev/i2c-1`, por ejemplo latencias estrictas, integracion profunda con subsistemas Linux o requerimientos industriales especificos.