# Vertical reusable: Climate Drainage NGS ## Qué es `climate-drainage-ngs` es la vertical reusable de MESAVAULT para medición y control de drenaje en invernadero hidropónico NGS. No representa un nodo concreto ni un cliente concreto. Representa la solución reusable de ingeniería que permite: 1. recibir uplinks del nodo en ChirpStack 2. decodificar correctamente el estado digital de `PA12` 3. persistir histórico y último valor en PostgreSQL 4. exponerlo en Grafana 5. cambiar remotamente perfiles del nodo: - `TDC` - `5VT` 6. gobernar esa lógica desde una UI web propia 7. dejar el diseño preparado para varios sensores, no para uno solo ## Qué sí pertenece a esta vertical - arquitectura técnica reusable - semántica de drenaje visible al usuario - modelo de datos `mv_control.*` - microservicio `drain-control` - scheduler - API - UI de control - queries base de Grafana - criterios de operación - archivos y rutas clave del sistema ## Qué no pertenece a esta vertical No deben vivir aquí como elemento principal: - el hardware base del `LSN50 v2` - el pinout genérico del nodo - el datasheet del `XKC-Y25-V` - el circuito físico de adaptación `LSN50 + XKC` Eso pertenece a: - `20-assets/models/dragino/lsn50-v2/` - `25-kits/lsn50-v2-xkc-y25-v-drainage/` Tampoco vive aquí el despliegue singular de un cliente concreto. Eso irá en `40-clients/` cuando exista singularidad real. ## Arquitectura consolidada La arquitectura correcta consolidada es: - OVH aloja el frontal público: - Traefik - Authentik - Grafana del cliente - routing `/control/*` - salida por Tailscale hacia `platform-40` - `platform-40` aloja la lógica real: - `drain_control_api` - `drain_control_scheduler` - `drain01_norm` - `drain01_pg` - `mv_postgres_hot` - `mv_mosquitto` - `cs_chirpstack` - el nodo `LSN50 + XKC` sigue siendo el extremo físico - el dashboard del cliente vive en OVH, no en `platform-40` - `platform-40` es backend, no frontal cliente ## Principios de diseño que definen esta vertical ### 1. Grafana no controla el nodo directamente Grafana no debe enviar downlinks directamente a ChirpStack. La lógica de control vive en un microservicio específico con API, scheduler y auditoría. ### 2. No exponer servicios internos por IP pública La UI no debe darse al cliente por `192.168.40.100:8088/ui`. Debe publicarse por OVH, detrás de Traefik y Authentik, integrada en Grafana por iframe. ### 3. No publicar alegremente en `0.0.0.0` Con Tailscale presente, el criterio correcto es bindear explícitamente a `192.168.40.100`. ### 4. La señal bruta no es semántica de negocio `raw_drain_state` no debe mostrarse tal cual al usuario. La vertical debe distinguir entre: - señal bruta - muestra válida - drenaje interpretado - estado de control - semántica final visible al usuario ## Componentes lógicos principales ### Modelo de control - `mv_control.drain_schedule` - `mv_control.drain_downlink_audit` - `mv_control.asset_device_map` ### Backend - `drain_control_api` - `drain_control_scheduler` ### UI - `/ui` - `/api/drain-window/current` - `/api/drain-window/list` - `/api/drain-window` - `/api/drain-window/force-active` - `/api/drain-window/force-auto` - `/api/drain-window/audit` ### Datos de proceso - `mv_hot.drain_readings` - `mv_hot.drain_latest` ## Estado actual Esta vertical puede considerarse técnicamente válida porque ya quedó demostrado que: - la arquitectura de la vertical es válida - el `LSN50 + XKC` funciona con el circuito definido - el decoder correcto es `byte6 & 0x02` - el downlink LoRaWAN funciona - `set_tdc` y `set_5vt` funcionan por radio - la micro-API y el scheduler funcionan - la UI funciona - PostgreSQL persiste correctamente - ya no se confunden muestras de reposo con drenaje real ## Referencias cruzadas - kit físico validado: `25-kits/lsn50-v2-xkc-y25-v-drainage/` - activo base del nodo: `20-assets/models/dragino/lsn50-v2/` - plataforma backend: `10-platforms/homelab/platform-40/` - frontal/tenant: `10-platforms/ovh-cloud/` - BookStack: `pendiente_de_crear` - Vaultwarden: `pendiente_de_crear`