You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

330 lines
6.6 KiB
Markdown

# 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.