Las dos piezas que faltaban: la visualización de series temporales sobre Grafana embebido, y el control de desviaciones con notificaciones por rol. Cambia el rol arriba a la derecha y verás cómo cambia todo lo demás.
En producción esta zona es un <iframe> a un panel de Grafana en modo kiosk. La selección de zona, métrica y rango no se hace dentro de Grafana: se hace aquí y viaja al panel por variables en la URL, que es lo que ata el modelo 3D a los datos. Lo que ves dibujado es una simulación con datos generados.
| Severidad | 🔧 Instalador / mantenedor | 📋 Administrador / gestor | 🏢 Propiedad |
|---|
De 22:00 a 7:00 solo salen las críticas. El resto se acumula en el resumen de la mañana.
Histéresis del 5 %, dos lecturas consecutivas fuera de banda, máximo 6 avisos por hora y edificio, y agrupación por zona.
Sin reconocer a los 15 min → segundo canal y jefe de mantenimiento. A los 60 min → administrador.
Silencia una zona durante una intervención programada, y lo deja registrado para que no parezca un hueco de datos.
Con la pila decidida, la pregunta ya no es «Grafana sí o no», sino dónde termina Grafana y dónde empieza Fusión 3D. Si esa frontera queda difusa, acabáis manteniendo dos productos que se pisan. La línea que propongo es nítida: Grafana dibuja las series, y todo lo espacial —el color de una zona en el modelo, la chincheta que parpadea, el estado que ve el técnico en el móvil— lo resuelve vuestro backend consultando InfluxDB directamente.
| Necesidad | Quién la resuelve | Por qué |
|---|---|---|
| Colorear las zonas del modelo 3D por temperatura o consumo | API propia → InfluxDB | Es un valor por espacio, cacheado en Redis. Meter un iframe aquí sería absurdo |
| Estado actual y minigráfico en la ficha de una estancia | API propia → InfluxDB | Debe funcionar en el móvil del técnico, offline y en dos toques |
| Gráfica de detalle, comparación entre zonas, rangos largos | Grafana embebido | Es exactamente para lo que existe. No tiene sentido reescribirlo |
| Exploración libre del instalador cuando algo huele raro | Grafana, abierto aparte | Enlace «abrir en Grafana» con el rango y la zona ya puestos |
| Informe de cumplimiento auditable | API propia → InfluxDB | La evidencia tiene que ser vuestra, exportable y con sello de tiempo, no una captura de pantalla |
| Evaluación de reglas y umbrales | Grafana Alerting → webhook | Ver el apartado 4: se aprovecha el evaluador, pero la incidencia vive en vuestro dominio |
El usuario nunca navega dentro de Grafana. Los controles —zona, métrica, rango— están en vuestra interfaz y viajan al panel como variables en la URL del iframe, como se ve en la barra gris de arriba: si cambias de zona, cambia el src. Así el modelo 3D sigue siendo el mando y Grafana es la pantalla, no un producto paralelo con su propio menú.
Aquí se decide si el sistema aguanta o se ahoga a los dos años. En una base de series temporales el enemigo no es el volumen de puntos, es la cardinalidad: el número de combinaciones distintas de etiquetas. Cada etiqueta que se añade multiplica, no suma.
medida: lectura etiquetas (indexadas, cardinalidad acotada) tenant tnt_brain4 // redundante con el bucket, útil en consultas building bld_olias storey sty_p02 space spc_open_space // la clave: permite agrupar por zona point pnt_knx_1_2_14 metric energia_activa // temperatura | potencia | co2 | estado protocol knx campos (no indexados) value 12.4 quality 1 // 0 = dato dudoso o interpolado NUNCA como etiqueta: marcas de tiempo, identificadores de mensaje, valores continuos, nombres de estancia editables por el usuario. El nombre legible vive en PostgreSQL y se une por space; si se etiqueta con el nombre, cada vez que el gestor lo corrija nace una serie nueva y el histórico se parte en dos.
| Decisión | Recomendación | Motivo |
|---|---|---|
| Aislamiento entre clientes | Un bucket por inquilino, y por edificio en carteras grandes | Aislamiento duro, tokens de lectura por inquilino y borrado limpio al darse de baja. Filtrar por etiqueta depende de que nadie se equivoque en una consulta |
| Retención | Crudo 13 meses · agregados 10 minutos y 1 hora, sin caducidad | Trece meses permiten comparar contra el mismo mes del año anterior, que es como se mide el ahorro. Los agregados son los que sostienen el informe de cumplimiento |
| Agregados | Tarea programada que rellena los buckets de 10 min y 1 h | Una gráfica de 30 días no debe leer datos crudos: ni Grafana ni el móvil lo aguantan bien |
| Escritura | Por lotes desde el normalizador, con reintento y cola en el gateway | Un corte de red no puede perder lecturas: la continuidad del histórico es un requisito normativo, no una comodidad |
| Huecos | Marcar la ausencia como evento, no interpolar en silencio | Un hueco no detectado es un fallo de eficiencia que nadie ve. De hecho, «sin datos» debe ser una regla de aviso |
En el análisis inicial propuse TimescaleDB para las series. Con InfluxDB decidido, ese punto queda sustituido y conviene actualizar el documento. La consecuencia real es que ya no hay una sola base de datos: la semántica del edificio, los anclajes y los inquilinos siguen en PostgreSQL, y las lecturas viven aparte. Todo lo que antes se resolvía con un join ahora son dos consultas y una unión en el servicio. No es grave, pero hay que asumirlo en el diseño de la API desde el principio en lugar de descubrirlo en el tercer informe.
Es la parte que más proyectos rompe. Hay tres caminos y solo uno sirve para un SaaS multi-inquilino:
Con eso resuelto: una organización de Grafana por inquilino, una carpeta por edificio, y un usuario de servicio con permiso de solo lectura sobre el bucket que le corresponde.
Nadie construye a mano el panel de cada cliente. Los cuadros de mando se definen en ficheros versionados y se despliegan con el resto del sistema, con variables por edificio y por zona. Un cliente nuevo no es trabajo de configuración: es una fila más.
// URL que compone el frontend para el iframe
const src = `${GRAFANA}/d-solo/fusion-zona/zona`
+ `?orgId=${tenant.grafanaOrgId}`
+ `&panelId=2`
+ `&var-building=${buildingId}`
+ `&var-space=${spaceId}` // ← lo pone el clic en el modelo 3D
+ `&var-metric=${metric}`
+ `&from=now-24h&to=now`
+ `&theme=${isDark ? 'dark' : 'light'}` // el panel sigue el tema de la app
+ `&kiosk` // sin menús de Grafana
+ `&auth_token=${shortLivedJwt}`;
# grafana.ini — lo mínimo para que el iframe cargue
[security]
allow_embedding = true
cookie_samesite = none // exige HTTPS en ambos extremos
[auth.jwt]
enabled = true
header_name = X-JWT-Assertion
jwk_set_url = https://api.fusion3d.es/.well-known/jwks.json
| Límite | Qué significa | Qué hacer |
|---|---|---|
| Licencia AGPL | Grafana OSS es AGPLv3. Ejecutarlo como servicio aparte y embeberlo por iframe no convierte vuestro código en derivado, pero modificar Grafana sí obliga a publicar esos cambios | No tocar el código de Grafana. Si hace falta, consultarlo con un abogado antes, no después |
| Marca | Quitar el logotipo y personalizar la apariencia es función de la edición Enterprise | Asumir la marca de Grafana en el panel, o presupuestar Enterprise cuando el cliente lo exija |
| Cookies de terceros | Los navegadores restringen cookies entre dominios y eso rompe iframes mal montados | Servir Grafana bajo vuestro propio dominio, por ejemplo metricas.fusion3d.es, detrás del mismo proxy |
| Vuelta desde Grafana | Un panel puede enlazar hacia vuestra aplicación, pero no puede pedirle que navegue estando dentro del iframe | La dirección 3D → Grafana es fluida por variables; la contraria, un enlace que abre pestaña. No prometer más |
| Móvil | Un panel embebido en una pantalla de teléfono se lee mal | En móvil, minigráfico propio y botón «ver detalle», que abre Grafana a pantalla completa |
Grafana trae un motor de alertas capaz de evaluar consultas y disparar avisos. La tentación es usarlo tal cual y ahorrarse el trabajo. La tentación contraria es escribir un motor propio desde cero. Las dos son malas por separado; la buena es partirlo:
La razón de fondo es que una alerta de Grafana vive en Grafana: no sabe qué es un anclaje, no puede reconocerse desde el móvil del técnico, no entra en el parte de mantenimiento y no aparece en el informe de cumplimiento. La evaluación es commodity; la incidencia es vuestro producto.
POST /v1/hooks/grafana (punto de contacto tipo webhook)
{
"status": "firing",
"labels": {
"rule": "consumo_sobre_base",
"space": "spc_open_space", // las etiquetas de Influx viajan intactas
"building": "bld_olias",
"severity": "serious"
},
"values": { "actual": 41.2, "baseline": 29.8 },
"startsAt": "2026-09-06T18:42:11Z",
"fingerprint": "a3f1c9…" // idempotencia: no duplicar la incidencia
}
→ Fusión 3D: crea o actualiza la incidencia, resuelve el anclaje del
espacio, aplica la política de notificación por rol y horario, y devuelve 200.
El cierre llega con el mismo fingerprint y status "resolved".
Cinco tipos cubren el noventa por ciento de lo que un edificio necesita vigilar. Conviene resistirse a añadir más hasta que un cliente lo pida:
El RITE exige que el sistema detecte las pérdidas de eficiencia e informe al responsable. Ese «e informe» es literal: hay que poder demostrar a quién se avisó, cuándo y qué se hizo. El rastro que se ve en la ficha de la desviación —detectada, notificada, reconocida, resuelta, con nombres y horas— no es un adorno de la interfaz: es el documento que se le enseña al inspector y el que sostiene la medición y verificación de un certificado de ahorro. Conviene que sea inmutable y exportable desde el primer día.
El error clásico de este módulo es tratar «avisar» como una función técnica. No lo es: el instalador y el administrador quieren cosas opuestas, y si se les manda lo mismo, uno se satura y el otro se entera tarde.
| 🔧 Instalador o mantenedor | 📋 Administrador o gestor | |
|---|---|---|
| Qué quiere | Saber qué está roto, dónde está y poder actuar | Saber si el edificio va bien y qué le va a costar |
| Cuándo | Ahora, incluida la madrugada si es crítico | Por la mañana, en un resumen. Solo lo crítico interrumpe |
| Canal | Notificación en el móvil y WhatsApp; SMS al escalar | Correo con el resumen; WhatsApp solo para lo crítico |
| Qué puede hacer | Reconocer, actuar sobre el equipo, cerrar con causa | Reconocer, pedir intervención, aprobar gasto |
| Qué le sobra | Los resúmenes y los gráficos bonitos | El detalle técnico y los avisos de comunicación |
Un sistema de avisos mal calibrado se desactiva solo: la gente lo silencia y a partir de ahí no protege nada. Cinco defensas, todas visibles en el panel de arriba:
Y un detalle que vosotros tenéis regalado: la API de WhatsApp Business ya la habéis integrado en GrinPass. Para un administrador de fincas español, WhatsApp es el canal que sí lee. Reutilizarlo aquí es de las pocas ventajas de partida que no hay que construir.
Del histórico de la comercializadora a la ficha firmada, en cinco pasos. Lo que sostiene el expediente no es la ficha: es poder enseñar la línea base medida, la medición actual con sus hitos y una comparativa que un verificador pueda recorrer sin creerse nada.
La validación corre en el navegador en cuanto se suelta el fichero: resolución, huecos, duplicados, saltos de horario y valores imposibles. Un lote con incidencias se puede cargar igual, pero queda marcado en el expediente — un hueco que nadie declara es lo primero que encuentra el verificador.
La ficha TER050 compara servicio a servicio, no el total del edificio. Mientras un servicio no tenga origen de dato asignado, su energía final hay que reconstruirla con coeficientes y declararlo como tal. Esto es exactamente lo que decide si el expediente se sostiene.
La diferencia entre laborable y festivo a igual temperatura exterior es lo que aísla la carga dependiente del horario. Es la primera separación que se puede hacer sin instalar nada.
Las líneas grises al fondo son la línea base del mismo tramo de calendario, para que la lectura sea inmediata. Las marcas verticales son actuaciones: cada una lleva su registro de quién o qué la ordenó.
El orden no es decorativo: primero se lleva el consumo de referencia a las condiciones del periodo actual —clima y ocupación—, y sólo después se descuenta cada medida. Así el verificador ve que el ahorro reclamado no es un invierno suave.
La ficha TER050 compara el consumo del año anterior con el posterior, servicio a servicio. Quien no midiera antes tiene que reconstruir esa línea base con facturas y estimaciones, y eso es exactamente lo que un verificador mira con lupa. De ahí que la sección de carga de históricos no sea un formulario administrativo: es la pieza que decide si el resto del expediente vale algo.
Por eso la carga hace cuatro cosas que un importador corriente no hace:
servicio no hay agregación por servicio, y sin agregación por servicio no hay TER050. Preguntarlo después es preguntarlo tarde.El agregado mensual se recalcula cuando haga falta; el fichero original de la comercializadora, no. El expediente guarda las tres capas —fichero tal como llegó, serie normalizada y agregados— y la serie meteorológica que se usó para normalizar. Si el verificador pregunta de dónde sale un número, la respuesta tiene que poder recorrerse hacia atrás hasta la línea del CSV.
Esta es la confusión que más expedientes rompe, y conviene tenerla clara antes de enseñar la consola a un cliente. Hay dos cifras de ahorro y ninguna sustituye a la otra:
| Ahorro normativo · el que se certifica | Ahorro medido · el que se demuestra | |
|---|---|---|
| De dónde sale | De los factores del Anexo II: (1 − f_post / f_ini) × EF del servicio | De comparar la medición actual con la línea base normalizada |
| Qué necesita | La energía final por servicio y las dos clases BAC, inicial y alcanzada | Histórico continuo, hitos registrados y corrección por clima y ocupación |
| Quién lo usa | La ficha: es el número que se convierte en certificados | El verificador, para creerse la energía final declarada y el salto de clase |
| Si no coinciden | No es un error: la ficha es un método tabulado y la medición es la realidad de un edificio concreto. Lo que no puede pasar es que el medido sea mucho menor que el normativo y nadie lo explique | |
El criterio de verificación 25-11.02 prohíbe asignar la clase D al estado inicial: hay que justificar A, B o C. Poner D infla el ahorro —el factor de calefacción salta de 1,00 a 1,44— y tumba el expediente entero. El formulario del paso 5 no deja seleccionar D, y pide el inventario de funciones de control que justifica la clase de partida.
Nada de esto sirve si la instalación era obligatoria. Por encima de 290 kW el control ya es exigible desde el 1 de enero de 2025, así que no genera certificados. La ventana real es el tramo de 70 a 290 kW, y se cierra el 31 de diciembre de 2029. El expediente recoge la potencia térmica nominal precisamente para poder decir esto antes de que nadie gaste dinero.
Esto es la primera fase: las cinco secciones existen, se navegan y calculan sobre datos generados. Lo que queda antes de que un expediente real pase por aquí:
| Pieza | Estado | Qué falta |
|---|---|---|
| Carga y validación de ficheros | Funciona en el navegador | Subida al servidor, huella real del fichero, deduplicación entre lotes y conector directo a Datadis |
| Línea base | Estadística y perfil de día tipo | Regresión real contra grados-día oficiales de AEMET y congelación firmada con sello de tiempo |
| Medición actual | Espejo con hitos | Hitos alimentados del registro de actuaciones del motor domótico, no de una lista escrita a mano |
| Comparativa | Normalización y atribución | Intervalo de confianza por medida, NMBE y CV(RMSE) calculados sobre el modelo real, y grupo testigo como objeto del modelo de datos |
| Ficha TER050 | Cálculo vivo con los factores de Oficinas | Los 56 factores del Anexo II en base de datos, generación del PDF y de los anexos I y III, y paquete de evidencia exportable |