Monitoreo visualmente mi red Zigbee (Linkquality & Last_seen)

Objetivo: hacer visibles (y utilizables) dos piezas clave de información para cada dispositivo Zigbee:

  • linkquality (salud radioeléctrica) y
  • ultimo _seen (última comunicación)

Se trata de detectar inmediatamente una sirena «perdida» o una batería HS, sin esperar a descubrirla por casualidad.

🧭 ¿Por qué pongo esto en su lugar?

Con 69 Dispositivos Zigbee, No tenía visibilidad simple para responder a dos preguntas básicas: ¿El dispositivo captura correctamente? y ¿Se ha comunicado recientemente?
En una sirena, no es aceptable averiguar «al azar»: Quiero ver inmediatamente si está muda, fuera de la red, o en problemas de radio.

Por lo tanto, he decidido mostrar en todas partes:

  • linkquality : Indicador de calidad de enlace de radio (LQI). (Esta es una «foto» útil para identificar las zonas débiles).
  • ultimo _seen : fecha/hora de la última comunicación (o hora relativa: 12s, 4m, 2h …).



Atrapa de ⚠ #1 : hay dos «configuration.yaml»

Al principio, me dijeron: En Home Assistant, hay dos archivos diferentes.

  • El archivo principal de Home Assistant: /config/configuration.yaml
  • El archivo Zigbee2MQTT: /config/zigbee2mqtt/configuration.yaml

Importante: para ultimo _seen y (en la práctica) la exposición/activación por defecto, todo está configurado lateralmente Zigbee2MQTT, es decir, en /config/zigbee2mqtt/configuration.yaml.

Atrapa de 🧹 #2 : La interfaz de usuario adicional Zigbee2MQTT puede «limpiar» las opciones

Me he comportado muy dolorosamente: Añadí opciones avanzadas, guardé … y luego la interfaz complementaria pareció «simplificar» el archivo suprimiendo lo que no entendía.

El método fiable (en casa):

  • Edito directamente /config/zigbee2mqtt/configuration.yaml (Editor de archivos o SSH)
  • Ahorro
  • Estoy reiniciando Zigbee2MQTT

🕒 Activar ultimo _seen en Zigbee2MQTT (obligatorio)

Por defecto, Zigbee2MQTT no puede publicar ultimo _seen (desactivar el valor).
Para activarlo, añado esto en la sección avanzado desde /config/zigbee2mqtt/configuration.yaml :

avanzado: # Añade "last_seen" en los mensajes MQTT # posibles valores: inhabilitar, ISO_8601, ISO_8601_local, época last_seen: ISO_8601 _local

Esta configuración le dice a Zigbee2MQTT que agregue el atributo ultimo _seen Mensajes MQTT, con un formato legible por hora local.

Formatos útiles (a elegir)

  • ISO_8601 _local : husillo legible + local (el más práctico a diario).
  • ISO_8601 : legible, pero en UTC (útil para centralizar todo en UTC).
  • época : marca de tiempo Unix (práctica para scripts/procesamiento).

🧩 Activar ultimo _seen y linkquality «por defecto» en Asistente para el hogar (opcional)

Una vez ultimo _seen activado en el lado Zigbee2MQTT, queda un punto: en Home Assistant, estas entidades a menudo se clasifican como «diagnóstico», por lo que pueden crearse, pero discapacitado automáticamente.

Para que cada nuevo dispositivo Zigbee añadido llegue directamente «listo para supervisar», lo añado en /config/zigbee2mqtt/configuration.yaml :

dispositivo_opciones: homeasistente: ultimo _visen: habilitada_por_por defecto: verdadera calidad del vínculo: habilitada_por_por defecto: cierto

Luego reinicio Zigbee2MQTT.

Importante: impacto en los dispositivos ya instalados

Esta configuración ayuda especialmente a la nuevos dispositivos (o dispositivos redescubiertos).
Para los dispositivos ya presentes, a menudo es necesario activar manualmente las entidades correspondientes en Home Assistant.

🗄 Base de datos: mantener visible la información sin «contaminar» la historia

El «riesgo» no es tanto Zigbee2MQTT (solo agrega un campo de marca de tiempo en los mensajes), sino más bien Home Assistant si guarda cada actualización de ultimo _seen en la base de datos: Puede generar mucha escritura con muchos sensores.

Mi elección: Quiero ver estos valores en todas partes, pero no necesito gráficos minuto a minuto. Por lo tanto, excluyo a esas entidades de la grabadora.

Lo que puse en /config/recorders.yaml

registrador: excluir: _globs de la entidad: *_last _seen - sensor.*_linkquality

Después de eso, reinicio Home Assistant: Los valores permanecen visibles en tiempo real, pero limito fuertemente la creación de historia innecesaria.

🗺 Supervisión visual: un plan de «radio + frescura»

No quería «una entidad perdida en una lista»: Yo quería supervisión visual, inmediatamente legible.

Principio:

  • Cada dispositivo Zigbee aparece como un pequeño rectángulo en un plano.
  • El número que se muestra a granel = Linkquality.
  • El tiempo en la parte inferior derecha = Last_seen relativo (s/m/h/d).
  • El marco negro = router (variable enrutador: 1), para reconocer rápidamente los routers.

🧰 La tarjeta de decluttering (reutilizable)

Utilizo la magia de la tarjeta de _templates que describí en esta página hace tres años:

Por lo tanto, despejar _templates + custom:decluttering-card reutilizar el mismo componente en todas partes, cambiando solo 4 variables.

Simplemente defino cuatro elementos que son diferentes para cada dispositivo:

  • Superficie: es el sensor que será procesado
  • parte superior: su posición desde arriba
  • izquierda: su posición desde la izquierda
  • enrutador: 1 si se trata de un router de lo contrario 0

Ejemplo: Página de Dashboard muy simple

Tipo: Imagen de los elementos de la imagen: /local/house/1920x1000/off_0800.png elementos: - tipo: custom:decluttering-card plantilla: variables de calidad de enlace: - área: sensor.light_chambre_parents - top: 20% - izquierda: 35% - router: 1 - tipo: custom:decluttering-card plantilla: variables de calidad de enlace: - área: sensor.fenetre_de_la_chambre_des_parents - top: 15% - izquierda: 37% - router: 0

La plantilla linkquality (la «pieza grande»)

desmontaje de _templates: calidad de los enlaces: por defecto: - superior: 5% - izquierda: 95% - router: 0 elementos: Tipo: custom:entidad de tarjeta de botón: | [[retorno “[[zona]]_linkquality“; ]]] mostrar _icon: nombre falso: | [[ return '[[zone]]]' .replace(/^sensor \./i, '') .replace(/_/g, ' '') .trim(); ]]] mostrar _state: true show_unidades: false custom_fields (en inglés): Visto por última vez: | [[const obj = states[“[[zone]]_last _seen“]; si (!obj ||!obj.state || obj.state === 'no disponible') devuelve '!!'; const last = nueva fecha (obj.state); si (isNaN(last.getTime()) devuelve '!!'; const now = nueva fecha(); const segundos = Math.floor((ahora - último) / 1000); if (seconds < 60) return ` (en inglés)${segundos}s“; const minutos = Math.floor (segundos / 60); si (minutos < 60) devuelve `${minutos}m“; const hours = Math.floor (minutos / 60); « if (hours < 24) return `» (en inglés).${horas}h“; const days = Math.floor (horas/24); ¡ Regreso `${días}d“; ]]] estilos: tarjeta: - frontera: ¿| [[volver ([router]]] == 1)? «2px sólido negro»: «ninguno»; ]]] - sombra de caja: Ninguno - posición: relativo - radio fronterizo: 8px - anchura mínima: 100px - altura: 45px - pantalla: flex – dirección flexible: columna - Justificar contenido: centro - alinear-elementos: centro - color: nombre blanco: - tamaño de fuente: 10px - altura de línea: «1» - relleno: 0 - margen: 0 - Alineación de texto: centro - color: blanco - flex: 1 - anchura máxima: 95px - envoltura de palabras: break-word - desbordamiento: oculto - espacio en blanco: estado normal: - tamaño de fuente: 15px - font-weight: negrita - altura de línea: «1» - relleno: 0 - margen: 0 - Alineación de texto: centro - color: blanco - flex: 1 custom_fields: Visto por última vez: - posición: absoluto - inferior: 0px - derecha: 0px - tamaño de fuente: 10px - color: negro - relleno: 2px 4px - radio-frontera: 4px - caja-sombra: 0 1px 3px rgba(0,0,0,0.3) - fondo: | [[const obj = states[“[[zone]]_last _seen“]; si (!obj ||!obj.state) devuelve «rgba(128,128,128,0.5)»; const last = nueva fecha (obj.state); const now = nueva fecha(); const segundos = Math.floor((ahora - último) / 1000); si (seconds < 1200) devuelve «rgba(0.255,0,0.9)»; // Green <20min si (segundos < 1800) devuelve 'rgba(255,255,0,0.9)'; // Amarillo 20-30min si (segundos < 7200) devuelve 'rgba(255,165,0,0.9)'; // Orange <2h retorno 'rgba(255,0,0,0.9)'; // Rojo >2h ]]] Estado: -valor: estilos no disponibles: tarjeta: - antecedentes: rgba(255,0,0,0.3) - operador: Valor «>»: 200 estilos: tarjeta: - antecedentes: rgba(0,180,0,0.3) - operador: Valor «>»: 150 estilos: tarjeta: - antecedentes: rgba(34,255,34,0.3) - operador: Valor «>»: 130 estilos: tarjeta: - antecedentes: rgba(255,255,0,0.3) - operador: Valor «>=»: 80 estilos: tarjeta: - antecedentes: rgba(255,165,0,0.3) - operador: Valor «<»: 80 estilos: tarjeta: - antecedentes: estilo rgba(255,107,53,0.3): parte superior: «[[arriba]]» a la izquierda: «[[izquierda]]»

Simplemente, ¿qué hace este código?

Esta plantilla define una plantilla de mapa única que se reutiliza para todos los dispositivos Zigbee, cambiando solo la variable [[zona]].

La propiedad de entidad se construye dinámicamente en JavaScript ([[[ … ]]) para apuntar a la entidad [[zona]] _linkquality, que muestra automáticamente la calidad del enlace del dispositivo (valor LQI devuelto por Zigbee2MQTT o ZHA).

El nombre también se genera en el lado del cliente: Se elimina el prefijo del sensor, se sustituye el _ por espacios y se realiza un recorte(), que produce una etiqueta legible a partir del identificador de entidad.

El último campo personalizado lee la entidad [[zona]] _last _seen en estados[], convierte su valor en objeto Date, y luego calcula la diferencia con la hora actual para mostrar un tiempo relativo (s, m, h, d). Si el valor está vacío, no está disponible o es una fecha no válida, se muestra !! en lugar de mostrar un valor inconsistente.

El último estilo de insignia visto en la parte inferior derecha utiliza una función JavaScript que devuelve un color RGBA diferente dependiendo de la edad de la última comunicación (gris si no hay valor, luego verde → amarillo → naranja → rojo dependiendo del número de segundos transcurridos), que codifica visualmente la frescura de los datos.

La sección dice: la tarjeta de botones define varios umbrales para el valor de LinkQuality: no disponible, luego corta >200, >150, >130, >=80, <80, cada uno aplicando un fondo de color específico de la tarjeta, que convierte un valor numérico en un indicador de calidad de radio inmediatamente legible.

Las propiedades de formato (flex, min-width, height, border-radius, absolute badge position, etc.) aseguran una representación compacta y uniforme, con un borde negro opcional cuando [[router]] == 1 para identificar visualmente los routers Zigbee en comparación con los terminales simples.

🧠 Adiciones útiles: Zigbee2MQTT Información de Salud Global

Aquí está el código de esta tarjeta

Tipo: Imagen de los elementos de la imagen: /local/house/1920x1000/off_0800.png elementos: - tipo: custom:mod-tarjeta: Tipo: Título de las entidades: Aparece en Zigbee2MQTT _header _toggle: entidades falsas: - entidad: _bridge _permit _join nombre: Permitir la inclusión - entidad: button.zigbee2mqtt _bridge _restart nombre: Reiniciar - entidad: select.zigbee2mqtt _bridge _log _level nombre: Nivel de registro - entidad: _sensor.zigbee2mqtt _bridge _connection _nombre del estado: Estado de conexión - tipo: custom:template-entity-row name (nombre de la fila de la entidad de la plantilla): Lanzado desde el estado: > {% set e = states.binary_sensor.zigbee2mqtt _bridge _connection _state %} {% si e no es ninguno y e.state no está en ['no disponible', 'desconocido'] %} {{ ((now() - e.last _changed).total _seconds() / 3600) | round(1) }} h {% de lo contrario %} No disponible {% endif %} - entidad: sensor.zigbee2mqtt _bridge _coordinator _version nombre: Versión de coordinación - entidad: Sensor.zigbee2mqtt _bridge _version nombre: Versión Zigbee2MQTT - entidad: sensor.number_de _sensors_linkq_en _error nombre: Icono inalcanzable: mdi:círculo de alerta - entidad: sensor.number_de _sensors_linkq nombre: Icono total: mdi:dispositivos - entidad: sensor.zigbee _linkquality _nombre medio: Icono de LinkQuality promedio: mdi:estilo de señal: parte superior: 35% izquierda: 75% anchura: 450px

He añadido un sensor para calcular el promedio de Linkquality

Este sensor se agrega al archivo templates.yaml, aquí está su código:

- nombre: «zigbee_linkquality_average» (en inglés): zigbee _linkquality _unidad media _of _measurement: "LQI" state_class: estado de medición: >- {% | selectattr('entity_id', 'search', '_linkquality') | selectattr('state', 'is_number') | map(attribute='state') | map('float') | list %} {% si linkqualities | longitud > 0 %} {{ (cualidades | suma/longitud |) | round(1) }} {% de lo contrario %} 0 {% endif %}

He añadido un sensor para calcular el número de sensores

- nombre: "Número de sensores Linkq" _id único: sensor.number _sensors Estado de _linkq: >- {% set lq _sensors = states.sensor | selectattr('entidad _id', 'búsqueda', '_linkquality'$') Lista | %} {{ lq _sensors | count }} icono: mdi:unidad señal-variante_of_measurement: "sensores"

He añadido un sensor para calcular el número de dispositivos por error

- nombre: "Número de sensores Linkq en error" _id único: sensor.number _sensors _linkq Estado de error de _: >- {% set lq _sensors = states.sensor | selectattr('entidad _id', 'búsqueda', '_linkquality'$') | selectattr('state', 'in', ['unavailable', 'unknown', 'None']) Lista de | %} {{ lq _sensors | count }} icono: mdi:unidad de círculo de alerta_of_measurement: "sensores"

He añadido un indicador en el tablero principal para informar el número de error

En primer lugar esta plantilla para mostrar xx en error / yy en total

- nombre: "zigbee _unreachable _synthese" _id único: Sensor.zigbee _estado de _synthese alcanzable: >- {{ states('sensor.number_de _sensors _linkq _en _error') }}/{ states('sensor.number_de _sensors _linkq') }} icono: mdi:alert-circle

Y en mis elementos pictóricos, añado:

- tipo: condiciones condicionales: - condición: entidad estatal: sensor.number _de _sensors _linkq _en _en Estado de error _not: Elementos "0": - tipo: custom:entidad de tarjeta de botón: Sensor.zigbee _Icono de _synthese accesible: mdi:zigbee show_nombre: falso show_state: verdadero estilo: parte superior: 5% izquierda: 5% transforma: traducir(-50%, -50%) estilos: indíquese: - color: rojo - font-weight: 700 - tamaño de fuente: Icono de 16px: - color: rojo - anchura: 20px - altura: Tarjeta de 20px: - radio fronterizo: 999px - relleno: 4px 6px - fondo: transparente - caja-sombra: ninguno

Este bloque se utiliza para mostrar un pequeño indicador rojo "Zigbee in error" en el plan del tablero solo cuando hay al menos un sensor problemático.

Este es un elemento condicional en una tarjeta de elementos de imagen: sólo muestra su contenido si sensor.number _sensors _linkq _en _en error es diferente de "0" (por lo que si al menos un sensor es inalcanzable o en error de LinkQuality).

Cuando la condición es verdadera, muestra una custom:button-card basada en sensor.zigbee _unreachable _synthese, que probablemente contiene "3 in error" o texto similar.

El botón se coloca en la parte superior izquierda del avión (5 % / 5 %), centrada a través de la transformada: traducir(-50%, -50%), con un fondo transparente y sin sombras para mantener solo el icono de Zigbee y el texto.

El icono y el estado de Zigbee están estilizados en rojo, negrita y tamaño 16 px, con un radio de borde: 999px para dar una apariencia de rotulador / etiqueta, por lo que es una advertencia visual discreta pero claramente visible, siempre y cuando haya sensores por error.

Para averiguar quién está equivocado

Para echar un vistazo a la lista de equipos por error, aquí están los códigos necesarios.

Declaración de plantillas

- nombre: "Número de sensores Linkq en error" _id único: sensor.number _sensors _linkq Estado de error de _: >- {% set lq _sensors = states.sensor | selectattr('entidad _id', 'búsqueda', '_linkquality'$') | selectattr('state', 'in', ['unavailable', 'unknown', 'None']) Lista de | %} {{ lq _sensors | count }} icono: mdi:unidad de círculo de alerta_of_measurement: "sensores" - nombre: «Linkquality Sensor List in Error» (en inglés): Sensor.liste _sensors _linkquality Estado del _error: >- {% set lq _sensors = states.sensor | selectattr('entidad _id', 'búsqueda', '_linkquality'$') | selectattr('state', 'in', ['unavailable', 'unknown', 'None']) | map(attribute='entity _id') | map('regex _replace', 'sensor \\\\\\\\.(.*) _linkquality$', '\\\\\\\\1') | list %} {% Número de conjuntos = lq _sensors | length %} {% si cuenta == 0 %} Ninguna {% elif count <= 5 %} {{ lq _sensors | join(', ') }} {% de lo contrario %} {{ lq _sensors[:5] | join(', ') ~ ' + ' ~ count }} {% endif %} atributos: cómputo: >- {% set lq _sensors = states.sensor | selectattr('entidad _id', 'búsqueda', '_linkquality'$') | selectattr('state', 'in', ['unavailable', 'unknown', 'None']) | map(attribute='entity _id') | map('regex _replace', 'sensor \\\\\\\\.(.*) _linkquality$', '\\\\\\\\1') | list %} {{ lq _sensors | length }} _list completo: >- {% set lq _sensors = states.sensor | selectattr('entidad _id', 'búsqueda', '_linkquality'$') | selectattr('state', 'in', ['unavailable', 'unknown', 'None']) | map(attribute='entity _id') | map('regex _replace', 'sensor \\\\\\\\.(.*) _linkquality$', '\\\\\\\\1') | list %} {{ lq _sensors | join(', ') | default('None') }} icono: mdi:alert-circle

Y en el Dasboard, siempre en los elementos de la imagen

Tipo: Imagen de los elementos de la imagen: /local/house/1920x1000/off_0800.png elementos: - tipo: custom:mod-tarjeta: Tipo: Título de las entidades: Sensores Zigbee en entidades de error: - tipo: custom:template-entity-row entity: sensor.liste _sensors _linkquality _en _error nombre: Estado de la lista: > {% set s = states('sensor.liste _sensors _linkquality _en _error') %} {% si no está en ['desconocido', 'no disponible', ''] %} {{ s.replace(',', '\\\\n') } {% de lo contrario %} Ninguna {% endif %} estilo: parte superior: 80% izquierda: 75% anchura: 450px

✅ Resumen simple (los 3 bloques esenciales)

1. Zigbee2MQTT: Activar last_seen

avanzado: ultimo _visen: ISO_8601 _local

2. Zigbee2MQTT: Habilitar por defecto en HA (opcional pero conveniente)

dispositivo_opciones: homeasistente: ultimo _visen: habilitada_por_por defecto: verdadera calidad del vínculo: habilitada_por_por defecto: cierto

3. Asistente del hogar: no registrar estas entidades en el PP

registrador: excluir: _globs de la entidad: *_last _seen - sensor.*_linkquality

🎯 Lo que cambia a diario

  • Veo inmediatamente zonas débiles (baja calidad de enlace) y sé qué reforzar (enrutador, colocación, canal, etc.).
  • Lo sé exactamente Cuando una sirena dejó de hablar (la última _seen), ya no «supongo».
  • Mantengo una base de datos saludable (sin historial innecesario en sensores que se mueven todo el tiempo).



Aclaración ? preguntas ?

Este debate (si sigue abierto) está disponible:

https://forum.hacf.fr/t/retex-je-surveille-visuellement-mon-reseau-zigbee-linkquality-last-seen/76732