Integración externa - Daikin Cloud

Hola @prohand, excelente trabajo, he revisado el código de la rama y el resultado es coherente con lo que hace el núcleo. Puedes empujar, la mecánica es buena. Tres puntos, sin embargo, dos de los cuales merecen una corrección antes o justo después de la puesta en producción.

1. El padre es un contador que se reinicia, no un índice

Publicas « Energía hoy » en energy-sensor / energy, que Gladys documenta como « el consumo de energía acumulado » y trata como un índice. El trabajo calculateConsumptionFromIndex hace index(t) − index(t−1) y descarta los deltas negativos (« reinicio de contador detectado »). Por lo tanto, nada se cuenta dos veces — es por eso que tu total diario es exacto — pero todo lo que se consume entre la última encuesta antes de medianoche y la primera encuesta después se pierde, cada noche. Con 900 s de encuesta, eso es el último cuarto de hora del día; y si Daikin no llena su cubo 22h–24h hasta después de medianoche, son dos horas las que desaparecen.

La corrección adecuada: que la integración mantenga su propio acumulado (en su almacén, total += max(0, today − today_anterior)) y publique un verdadero energy-sensor / index monotónico. El núcleo deriva entonces exactamente, y el caso de medianoche desaparece.

2. Los cubos de 2 h distorsionan el costo en HP/HC y Tempo

Daikin solo expone 12 intervalos de 2 h. Tu serie de 30 minutos se parecerá entonces a 0, 0, 0, 1.8 kWh, 0, 0, 0, …. El total del día es correcto (de ahí la correspondencia con la aplicación Onecta), pero la distribución durante el día no lo es. Ahora bien, calculateCostFrom tarifica cada ventana de 30 min al precio de esa ventana: en un contrato Base no tiene consecuencias, en horas punta/valle o Tempo el costo puede ser francamente falso, según la hora en que cayó la encuesta.

Dos opciones: documentarlo claramente (« costo fiable en Base, indicativo en HP/HC »), o mejor — saveStates acepta un created_at, por lo que puedes publicar los estados del índice con fecha en los límites de los cubos Daikin en lugar de la hora de la encuesta. El consumo cae entonces en las medias horas correctas.

3. Derivar tú mismo los UUID es mi problema, no el tuyo

Elegir los id de las características para poder apuntar energy_parent_id antes de que existan las líneas, funciona (el device.create inserta las características y luego resuelve los enlaces en una segunda pasada), y tu salvaguardia — nombrar solo las características que Gladys no conoce aún — es la correcta. Pero publicar un id en el payload de descubrimiento no está en la especificación de las integraciones externas: pasa hoy porque nada lo valida, y no quiero que se convierta en un contrato implícito.

Por lo tanto, voy a cablear addEnergyFeatures() (el de Zigbee2mqtt/Tasmota) en las integraciones externas, en getDiscoveredDevices: toda integración que publique un índice tendrá el par de 30 min automáticamente, ids y enlaces gestionados por el núcleo. Mantén tu código bien aislado (featureUuid.js + el bloque en buildDevice) para poder retirarlo de un bloque cuando esté disponible.

La solicitud:

Y dos detalles:

  • El nivel energy de tu escala de capacidades no sirve de nada: energy_parent_id llegó a Gladys en agosto de 2025, mucho antes de las integraciones externas. Toda instancia capaz de ejecutar tu contenedor ya tiene el seguimiento de energía.
  • « Energía este mes » y « Energía este año » deben permanecer en el nivel 0, es normal y no hay que conectarlas en absoluto: también están tipificadas como energy, por lo que aparecen como padres posibles en Configuración → Seguimiento de energía, y un usuario que las cablee contaría los mismos kWh varias veces. Una línea en la documentación para decir « solo conecten el consumo del día » evitará la pregunta.

En resumen: adelante para la producción, y yo me encargo del punto 3 en el núcleo.