Captura de pantalla 2025-09-13 123440

La calidad del aire en casa influye directamente en nuestra salud, concentración y bienestar diario. Gracias a Home Assistant, es posible no solo medir diferentes parámetros ambientales, sino también representarlos de una forma clara, intuitiva y visual. Hoy te traigo un ejemplo de panel de calidad del aire que integra múltiples sensores y presenta los datos en un tablero muy fácil de entender.


📊 Un panel claro y directo

El panel está diseñado con tarjetas personalizadas (custom:button-card) que muestran el estado de cada variable ambiental con colores y animaciones. De un vistazo puedes saber si el aire es seguro o si hay algún peligro.

En la parte superior se muestra un indicador general:

  • SEGURO → Todos los valores están dentro de los umbrales saludables.
  • ⚠️ PELIGRO → Algún parámetro está fuera de lo recomendado.

🌡️ Parámetros monitorizados

Cada tarjeta representa un sensor, con colores que cambian según los valores:

  • 🌡️ Temperatura
  • 💧 Humedad relativa
  • 🌫️ CO₂ (ppm)
  • 🔬 Partículas (PM1.0, PM2.5 y PM10)
  • ☣️ Formaldehído (HCHO)
  • 🧪 Compuestos Orgánicos Volátiles (COVs)
  • Estado de batería y pantalla del detector

🧭 Código completo del panel

Para que el código funcione tenéis que instalar https://github.com/custom-cards/button-card mediante HACS

Código de la parte izquierda donde aparecen los iconos:

type: grid
cards:
  - type: custom:button-card
    name: " "
    show_state: false
    show_icon: false
    state:
      - value: "off"
        operator: "=="
        name: Habitacion Grande <br> ⚠️ PELIGRO
        styles:
          card:
            - background-color: red
            - color: white
      - value: "on"
        operator: "=="
        name: Habitacion Grande <br> ✅ SEGURO
        styles:
          card:
            - background-color: green
            - color: white
    tap_action:
      action: none
    hold_action:
      action: none
    entity: binary_sensor.calidad_del_aire_habitacion_grande
    show_entity_picture: false
    styles:
      card:
        - height: 80px
        - font-size: 24px
        - font-weight: bold
        - text-transform: none
      name:
        - font-weight: bold
        - font-size: 20px
        - text-align: center
        - width: 100%
  - type: grid
    columns: 2
    square: false
    cards:
      - type: custom:button-card
        entity: sensor.air_detector_temperatura
        icon: mdi:thermometer
        name: 🌡️ Temperatura
        show_state: true
        show_units: true
        state:
          - operator: <
            value: 21
            color: blue
            styles:
              icon:
                - animation: blink 2s infinite
              card:
                - background-color: rgba(0, 0, 255, 0.1)
          - operator: <=
            value: 26
            color: green
            styles:
              card:
                - background-color: rgba(0, 128, 0, 0.1)
          - operator: ">"
            value: 26
            color: red
            styles:
              icon:
                - animation: blink 2s infinite
              card:
                - background-color: rgba(255, 0, 0, 0.1)
        styles:
          state:
            - font-size: 24px
            - font-weight: bold
          card:
            - "--blink-animation": |
                @keyframes blink {
                  0%, 100% { opacity: 1; }
                  50% { opacity: 0.3; }
                }
      - type: custom:button-card
        entity: sensor.air_detector_humedad
        icon: mdi:water-percent
        name: 💧 Humedad
        show_state: true
        show_units: true
        state:
          - operator: <
            value: 40
            color: blue
            styles:
              icon:
                - animation: blink 2s infinite
              card:
                - background-color: rgba(0, 0, 255, 0.1)
          - operator: <=
            value: 60
            color: green
            styles:
              card:
                - background-color: rgba(0, 128, 0, 0.1)
          - operator: ">"
            value: 60
            color: red
            styles:
              icon:
                - animation: blink 2s infinite
              card:
                - background-color: rgba(255, 0, 0, 0.1)
        styles:
          state:
            - font-size: 24px
            - font-weight: bold
          card:
            - "--blink-animation": |
                @keyframes blink {
                  0%, 100% { opacity: 1; }
                  50% { opacity: 0.3; }
                }
      - type: custom:button-card
        entity: sensor.air_detector_dioxido_de_carbono
        icon: mdi:molecule-co2
        name: 🌫️ CO₂
        show_state: true
        show_units: true
        state:
          - operator: <
            value: 800
            color: green
            styles:
              card:
                - background-color: rgba(0, 128, 0, 0.1)
          - operator: <=
            value: 1200
            color: orange
            styles:
              icon:
                - animation: blink 2s infinite
              card:
                - background-color: rgba(255, 165, 0, 0.1)
          - operator: ">"
            value: 1200
            color: red
            styles:
              icon:
                - animation: blink 2s infinite
              card:
                - background-color: rgba(255, 0, 0, 0.1)
        styles:
          state:
            - font-size: 24px
            - font-weight: bold
          card:
            - "--blink-animation": |
                @keyframes blink {
                  0%, 100% { opacity: 1; }
                  50% { opacity: 0.3; }
                }
      - type: custom:button-card
        entity: sensor.air_detector_pm25
        icon: mdi:blur
        name: 🔬 PM1.0
        show_state: true
        show_units: true
        state:
          - operator: <
            value: 10
            color: green
            styles:
              card:
                - background-color: rgba(0, 128, 0, 0.1)
          - operator: <=
            value: 30
            color: orange
            styles:
              icon:
                - animation: blink 2s infinite
              card:
                - background-color: rgba(255, 165, 0, 0.1)
          - operator: ">"
            value: 30
            color: red
            styles:
              icon:
                - animation: blink 2s infinite
              card:
                - background-color: rgba(255, 0, 0, 0.1)
        styles:
          state:
            - font-size: 24px
            - font-weight: bold
          card:
            - "--blink-animation": |
                @keyframes blink {
                  0%, 100% { opacity: 1; }
                  50% { opacity: 0.3; }
                }
      - type: custom:button-card
        entity: sensor.air_detector_pm2_5
        icon: mdi:blur
        name: 🔬 PM2.5
        show_state: true
        show_units: true
        state:
          - operator: <
            value: 10
            color: green
            styles:
              card:
                - background-color: rgba(0, 128, 0, 0.1)
          - operator: <=
            value: 30
            color: orange
            styles:
              icon:
                - animation: blink 2s infinite
              card:
                - background-color: rgba(255, 165, 0, 0.1)
          - operator: ">"
            value: 30
            color: red
            styles:
              icon:
                - animation: blink 2s infinite
              card:
                - background-color: rgba(255, 0, 0, 0.1)
        styles:
          state:
            - font-size: 24px
            - font-weight: bold
          card:
            - "--blink-animation": |
                @keyframes blink {
                  0%, 100% { opacity: 1; }
                  50% { opacity: 0.3; }
                }
      - type: custom:button-card
        entity: sensor.air_detector_pm10
        icon: mdi:blur
        name: 🔬 PM10
        show_state: true
        show_units: true
        state:
          - operator: <
            value: 10
            color: green
            styles:
              card:
                - background-color: rgba(0, 128, 0, 0.1)
          - operator: <=
            value: 30
            color: orange
            styles:
              icon:
                - animation: blink 2s infinite
              card:
                - background-color: rgba(255, 165, 0, 0.1)
          - operator: ">"
            value: 30
            color: red
            styles:
              icon:
                - animation: blink 2s infinite
              card:
                - background-color: rgba(255, 0, 0, 0.1)
        styles:
          state:
            - font-size: 24px
            - font-weight: bold
          card:
            - "--blink-animation": |
                @keyframes blink {
                  0%, 100% { opacity: 1; }
                  50% { opacity: 0.3; }
                }
      - type: custom:button-card
        entity: sensor.air_detector_formaldehido
        icon: mdi:chemical-weapon
        name: ☣️ Formaldehído
        show_state: true
        show_units: true
        state:
          - operator: <
            value: 0.05
            color: green
            styles:
              card:
                - background-color: rgba(0, 128, 0, 0.1)
          - operator: <=
            value: 0.1
            color: orange
            styles:
              icon:
                - animation: blink 2s infinite
              card:
                - background-color: rgba(255, 165, 0, 0.1)
          - operator: ">"
            value: 0.1
            color: red
            styles:
              icon:
                - animation: blink 2s infinite
              card:
                - background-color: rgba(255, 0, 0, 0.1)
        styles:
          state:
            - font-size: 24px
            - font-weight: bold
          card:
            - "--blink-animation": |
                @keyframes blink {
                  0%, 100% { opacity: 1; }
                  50% { opacity: 0.3; }
                }
      - type: custom:button-card
        entity: sensor.air_detector_compuestos_organicos_volatiles
        icon: mdi:beaker
        name: 🧪 COVs
        show_state: true
        show_units: true
        state:
          - operator: <
            value: 200
            color: green
            styles:
              card:
                - background-color: rgba(0, 128, 0, 0.1)
          - operator: <=
            value: 500
            color: orange
            styles:
              icon:
                - animation: blink 2s infinite
              card:
                - background-color: rgba(255, 165, 0, 0.1)
          - operator: ">"
            value: 500
            color: red
            styles:
              icon:
                - animation: blink 2s infinite
              card:
                - background-color: rgba(255, 0, 0, 0.1)
        styles:
          state:
            - font-size: 24px
            - font-weight: bold
          card:
            - "--blink-animation": |
                @keyframes blink {
                  0%, 100% { opacity: 1; }
                  50% { opacity: 0.3; }
                }
      - type: custom:button-card
        entity: switch.air_detector_screen_sleep
        icon: mdi:monitor
        name: 🖥️ Screen Sleep
        show_name: true
        show_state: true
        styles:
          card:
            - height: 73px
            - background-color: rgba(128, 128, 128, 0.1)
          name:
            - font-size: 12px
            - font-weight: bold
          state:
            - font-size: 14px
            - font-weight: bold
      - type: custom:button-card
        entity: sensor.air_detector_bateria
        icon: mdi:battery
        name: 🔋 Batería
        show_name: true
        show_state: true
        show_units: true
        styles:
          card:
            - height: 73px
            - background-color: rgba(128, 128, 128, 0.1)
          name:
            - font-size: 12px
            - font-weight: bold
          state:
            - font-size: 14px
            - font-weight: bold

Código de la parte izquierda donde aparece la leyenda:

type: grid
cards:
  - type: markdown
    content: |-
      - **✅ SEGURO**: TODOS los valores están en verde
      - **⚠️ PELIGRO**: ALGUNO de los valores no está en verde

      ### 🌡️ Temperatura
      - **AZUL**: < 21°C
      - **VERDE**: 21°C - 26°C
      - **ROJO**: > 26°C

      ### 💧 Humedad
      - **AZUL**: < 40%
      - **VERDE**: 40% - 60%
      - **ROJO**: > 60%

      ### 🌫️ CO₂
      - **VERDE**: < 800 ppm
      - **NARANJA**: 800 - 1200 ppm
      - **ROJO**: > 1200 ppm

      ### 🔬 Partículas (PM1.0, PM2.5, PM10)
      - **VERDE**: < 10 µg/m³
      - **NARANJA**: 10 - 30 µg/m³
      - **ROJO**: > 30 µg/m³

      ### ☣️ Formaldehído
      - **VERDE**: < 0.05 mg/m³
      - **NARANJA**: 0.05 - 0.1 mg/m³
      - **ROJO**: > 0.1 mg/m³

      ### 🧪 COVs
      - **VERDE**: < 200 ppb
      - **NARANJA**: 200 - 500 ppb
      - **ROJO**: > 500 ppb
    title: Leyenda de Colores - Umbrales
Comparte esta web mediante:

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Facebook
X (Twitter)
YouTube
LinkedIn
Instagram