HectorziN - Domótica y Home Assistant
Blog de HectorziN
Volver a todas las entradas

🛒 Cómo crear una Lista de la Compra Visual e Impactante en Home Assistant (Parte 1)

¿Sigues usando una lista de la compra aburrida en texto? Es hora de subir de nivel. En este tutorial te enseño a transformar tu gestión de víveres en un panel gráfico, intuitivo y profesional. Gracias a la potencia de las tarjetas personalizadas de HACS, lograremos que añadir productos a tu despensa sea tan visual como comprar en una tienda online.

En YouTube comparto más tutoriales, pruebas y domótica real. Suscribirme

Lista de la compra gráfica en Home Assistant

Vídeo relacionado en YouTube

Video
Créditos y Agradecimientos: Este proyecto nace de la increíble idea y el trabajo de Aguacatec. Si quieres profundizar en el concepto original, te recomiendo visitar su guía detallada: Domotizar tu lista de la compra 4.0.
De hecho, ya va por la versión 4, mi video y ese blog se hizo usando la versión 1.0 de base. Recomiendo mirar su artículo y tal vez usar mi video como referencia

El Objetivo: Un Dashboard de Compra Profesional

La idea es sustituir la lista nativa de Home Assistant por una interfaz llena de iconos y colores. Queremos que al pulsar sobre la imagen de una manzana o un brick de leche, este se añada automáticamente a nuestra lista de pendientes.

Paso 1: Instalación de Componentes en HACS

Para que la interfaz luzca tan profesional y funcional como en el vídeo, necesitaremos tener instaladas las siguientes tarjetas desde HACS (Home Assistant Community Store):

  • Mushroom Cards: Para una estética limpia y botones reactivos.
  • Swipe Card: Ideal para navegar entre recetas de forma táctil.
  • Bubble Card: Para ventanas emergentes (pop-ups) estilizadas.
  • Auto Entities: Para que la lista se actualice sola según lo que tengamos en el carrito.
  • Card Mod: Para personalizar el CSS y que todo encaje a la perfección.

Paso 2: Preparando las Imágenes y Entidades

Como explico en el vídeo, el secreto está en la preparación:

  • Iconos personalizados: Debemos guardar las imágenes de nuestros productos en la carpeta /config/www/. Esto nos permitirá llamarlas desde nuestras tarjetas.
    Puedes descargar iconos aquí: https://flaticon.es
  • Entidades de entrada: Utilizaremos input_boolean o interruptores virtuales para cada producto. Cuando el interruptor está "encendido", significa que el producto falta en la despensa

Paso 3: Creando el Catálogo de Productos (shopping_list_products)

Para que nuestra lista de la compra no sea solo un montón de nombres, sino que esté organizada por categorías (Verduras, Lácteos, Limpieza, etc.) y con iconos bonitos, vamos a utilizar entidades input_text.

1. Estructura en configuration.yaml

Como explico en el vídeo, lo más limpio es tener estos productos en un archivo separado. En tu configuration.yaml, asegúrate de tener esta línea para que Home Assistant lea tu carpeta de configuraciones:

input_text: !include_dir_merge_named input_text/

Las Entidades Maestras: lista_compra y lista_compra_completado

Además de crear el catálogo de productos por categorías, necesitamos dos "contenedores" principales. Estas entidades actuarán como la memoria de nuestra lista: una guardará lo que nos falta por comprar y la otra lo que ya hemos echado al carrito.

Debes añadirlas en tu archivo de configuración de input_text (por ejemplo, en input_text.yaml o dentro de tu carpeta dedicada):

yaml
# Esta entidad almacena los productos que seleccionas en el catálogo
lista_compra:
  name: "Lista de la compra"
  min: 0
  max: 5000
  initial: ""

# Esta entidad almacena los productos que ya has marcado como 'comprados'
lista_compra_completado:
  name: "Lista de la compra completado"
  min: 0
  max: 5000
  initial: ""

¿Por qué son necesarias?

  1. Sincronización: Cuando pulsas sobre un tomate en tu catálogo visual, el sistema añade la palabra "tomate" al input_text.lista_compra.
  2. Estado visual: La tarjeta que instalamos en el Dashboard lee estas entidades para saber qué iconos deben aparecer iluminados (los que están en la lista) y cuáles apagados.
  3. Capacidad: Ponemos el max: 5000 para asegurarnos de que, por muy grande que sea tu compra del mes, el texto nunca se corte y quepan todos los ingredientes.
"Recuerda que estas entidades son puramente textuales. Sirven de puente para que la interfaz gráfica sea así de fluida. Si en algún momento ves que la lista no se actualiza, comprueba que los nombres de estas entidades coinciden exactamente con los que has configurado en el código de tu tarjeta de Home Assistant."

2. Configuración del archivo shopping_list_products.yaml

Dentro de esa carpeta, crea el archivo shopping_list_products.yaml. Aquí definiremos cada categoría. Es vital que todos los IDs empiecen por shopping_list_, ya que el código de la tarjeta busca ese prefijo para mostrar los productos.

Aquí tienes el ejemplo de cómo configurarlo:

yaml
shopping_list_cat_verduras:
  name: "Shopping List - cat - Verduras"
  initial: "Cebollas,Tomates,Pepino,Pimiento,Calabacín"
  icon: "mdi:sprout"
  min: 0
  max: 2000
shopping_list_cat_frutas:
  name: "Shopping List - cat - Frutas"
  initial: "Plátanos,Aguacate,Uvas,Limón,Naranja"
  icon: "mdi:fruit-grapes"
  min: 0
  max: 2000
shopping_list_cat_pan_y_pasteles:
  name: "Shopping List - cat - Pan y pasteles"
  icon: "mdi:baguette"
  min: 0
  max: 2000
shopping_list_cat_lacteos:
  name: "Shopping List - cat - Lácteos"
  icon: "mdi:cheese"
  min: 0
  max: 2000
shopping_list_cat_carne:
  name: "Shopping List - cat - Carne"
  initial: "Albóndigas,Bistec,Bacón,Butifarra,Bratwurst,Carne,Pollo,Salchicha,Ternera,Cordero"
  icon: "mdi:food-steak"
  min: 0
  max: 2000
shopping_list_cat_pescado:
  name: "Shopping List - cat - Pescado"
  initial: "Anchoas,Atún,Calamares,Boquerones,Bogavante,Dorada,Gambas,Sepia,Merluza"
  icon: "mdi:fish"
  min: 0
  max: 2000
shopping_list_cat_ingredientes_y_especias:
  name: "Shopping List - cat - Ingredientes y especias"
  initial: "Aceite,Vinagre,Sal,Azúcar,Sacarina,Azafrán,Pimienta,Curry,Eneldo,Tomillo,Romero,Pimentón,Salsa de soja,Vainilla,Canela"
  icon: "mdi:spoon-sugar"
  min: 0
  max: 2000
shopping_list_cat_congelados_y_preparados:
  name: "Shopping List - cat - Congelados y preparados"
  initial: "Canelones,Alitas de pollo,Pizza,Doritos,Ensaladilla rusa,Patatas fritas"
  icon: "mdi:french-fries"
  min: 0
  max: 2000
shopping_list_cat_cereales_y_pasta:
  name: "Shopping List - cat - Cereales y pasta"
  initial: "Arroz,Macarrones,Garbanzos,Fideos,Espaguetis,Harina"
  icon: "mdi:barley"
  min: 0
  max: 2000
shopping_list_cat_aperitivos_y_dulces:
  name: "Shopping List - cat - Aperitivos y dulces"
  initial: "Patatas chips,Nachos,Chuches,Chocolate,Mermelada,Miel,Pipas,Palomitas"
  icon: "mdi:popcorn"
  min: 0
  max: 2000
shopping_list_cat_bebidas:
  name: "Shopping List - cat - Bebidas"
  initial: "Cerveza,Clara,Cola,Vino,Agua,Zumo de naranja,Horchata"
  icon: "mdi:beer"
  min: 0
  max: 2000
shopping_list_cat_drogueria:
  name: "Shopping List - cat - Droguería"
  initial: "Alcohol,Amoníaco,Bolsas de basura,Detergente de lavadora,Estropajo,Papel de aluminio,Papel de cocina,Suavizante,Papel hijiénico"
  icon: "mdi:broom"
  min: 0
  max: 2000
shopping_list_cat_aseo_y_salud:
  name: "Shopping List - cat - Aseo y salud"
  initial: "Acondicionador,Champú,Gel,Pasta de dientes,Compresas,Tampón,Desodorante"
  icon: "mdi:toothbrush"
  min: 0
  max: 2000
shopping_list_cat_mascotas:
  name: "Shopping List - cat - Mascotas"
  initial: "Alpiste,Arena,Comida para perros,Comida de gato,Golosinas para perros,Golosinas para gato,Pienso"
  icon: "mdi:dog"
  min: 0
  max: 2000
shopping_list_cat_jardin_y_hogar:
  name: "Shopping List - cat - Jardín y hogar"
  initial: "Carbón,Pastillas barbacoa"
  icon: "mdi:grill"
  min: 0
  max: 2000

💡 Puntos clave a recordar:

  • Initial: Aquí es donde escribes los productos de esa categoría, siempre separados por punto y coma (;).
  • Icon: El icono de MDI que verás en la cabecera de la categoría.
  • Max: Lo ponemos en 2000 para que nunca nos quedemos cortos al añadir más productos en el futuro.
  • Nomenclatura: Si usas una integración como Bring, intenta que los nombres coincidan exactamente para que Home Assistant encuentre los iconos automáticamente.

¿Por qué hacerlo así?

Al definir los productos en el initial de un input_text, permitimos que la tarjeta de la lista de la compra lea ese texto, lo "rompa" por los puntos y coma, y nos cree esos botones tan visuales que ves en el catálogo. ¡Es la base para que todo sea rápido y táctil!

Recuerda que para que estos cambios se apliquen, debes guardar el archivo y reiniciar Home Assistant (o recargar las entidades de texto si tienes habilitada la opción).

Paso 3: Configuración de la Tarjeta Visual

El corazón de este tutorial es el código YAML de la tarjeta. Usamos Custom Button Card para definir:

  • Estado visual: Si el producto no está en la lista, el icono se ve en blanco y negro o con opacidad. Al pulsarlo, cobra color.
  • Acción de pulsación: Al tocar la imagen, se activa el servicio que añade el elemento a nuestra lista real de la compra.

Paso 4. El Widget de Resumen: Una tarjeta que "late" cuando hay mucha compra

Antes de entrar en el menú detallado, vamos a crear una tarjeta de resumen para tu panel principal. Esta tarjeta es inteligente: nos mostrará el número total de productos y, si la lista supera los 15 artículos, cambiará a color rojo y empezará a latir para avisarnos de que toca ir al supermercado.

Copia este código en una tarjeta Mushroom Template de tu dashboard:

yaml
type: custom:mushroom-template-card
primary: '{{ states("todo.la_compra") }} productos'
secondary: Lista de la compra
icon: mdi:shopping
entity: todo.la_compra
icon_color: |-
  {% if states("todo.la_compra") | int >= 15 %} white
  {% endif %}
layout: vertical
fill_container: false
tap_action:
  action: navigate
  navigation_path: /dashboard-casa/lista-de-la-compra
card_mod:
  style: |
    {% if states("todo.la_compra") | int >= 15 %}
    ha-state-icon {
      animation: beat 2s ease-out infinite both;
      transform-origin: 50% 50%;
    }  
    @keyframes beat {
      0% { transform: scale(1); }
      10% { transform: scale(1.2); }
      17% { transform: scale(1.05); }
      33% { transform: scale(1.30); }
      60% { transform: scale(1); }
    }    
    ha-card {
      --primary-text-color: #ffffff;
      --secondary-text-color: #ffff00;
      background: linear-gradient( rgba(238, 82, 79, 1), rgba(181, 42, 39, 1) );
    }
    {% endif %}

💡 ¿Qué hace especial a esta tarjeta?

  • Contador automático: La línea {{ states("todo.la_compra") }} extrae en tiempo real el número de tareas pendientes en tu lista de Bring o Home Assistant.
  • Animación CSS (Keyframes): Gracias a card_mod, inyectamos un pequeño código CSS que hace que el icono crezca y encoja. Es un efecto visual muy potente que le da vida a tu Home Assistant.
  • Condicionales: El bloque {% if ... %} permite que el diseño sea sobrio cuando la lista está vacía, pero llamativo cuando hay muchas cosas pendientes.
Asegúrate de que el entity_id (en este caso todo.la_compra) coincida con el nombre que le hayas dado a tu integración de lista de tareas.

Paso 5: Creando el Menú de Navegación Visual

Para que nuestra lista de la compra sea realmente funcional y parezca una aplicación nativa, necesitamos un menú superior que nos permita navegar rápidamente entre las distintas secciones. Utilizaremos Mushroom Template Cards combinadas con Card Mod para aplicar esos degradados de color tan característicos del canal.

Aquí tienes el código YAML que debes pegar en una tarjeta de tipo Grid (Cuadrícula) en tu Dashboard:

yaml
square: false
type: grid
columns: 3
cards:
  # Botón para ir al Catálogo de productos
  - type: custom:mushroom-template-card
    primary: Catálogo
    secondary: ''
    icon: mdi:view-grid
    tap_action:
      action: navigate
      navigation_path: '#catalogue'
    layout: vertical
    icon_color: white
    card_mod:
      style: |
        ha-card {
          background: linear-gradient( rgba(83, 125, 182, 1), rgba(62, 94, 140, 1) );
          --primary-text-color: #ffffff;
        }

  # Botón para ver los productos comprados recientemente
  - type: custom:mushroom-template-card
    primary: Recientes
    secondary: ''
    icon: mdi:history
    tap_action:
      action: navigate
      navigation_path: '#bought_items'
    layout: vertical
    icon_color: white
    card_mod:
      style: |
        ha-card {
          background: linear-gradient( rgba(79, 171, 162, 1), rgba(38, 133, 124, 1) );
          --primary-text-color: #ffffff;
        }

  # Botón para acceder a la sección de Recetas automáticas
  - type: custom:mushroom-template-card
    primary: Recetas
    secondary: ''
    icon: mdi:creation
    tap_action:
      action: navigate
      navigation_path: '#recipes'
    layout: vertical
    icon_color: white
    card_mod:
      style: |
        ha-card {
          background: linear-gradient( rgba(143, 184, 84, 1), rgba(107, 139, 62, 1) );
          --primary-text-color: #ffffff;
        }

🔍 Detalles importantes del código:

  • Navigation Path: Fíjate que el navigation_path usa almohadillas (como #catalogue). Esto funciona junto con las Bubble Cards (pop-ups) que configuramos en el vídeo, permitiendo que al pulsar el botón se abra la ventana correspondiente de forma instantánea.
  • Personalización de colores: Los degradados (gradients) están definidos en la sección de card_mod. Puedes cambiar los valores RGBA para que los botones coincidan con los colores de tu tema de Home Assistant.
  • Layout Vertical: Al usar el diseño vertical, conseguimos que los iconos queden centrados y grandes, ideal para su uso en dispositivos móviles en plena compra.

Paso 6: El Corazón de la Lista: Visualización Dinámica de Productos

Llegamos a la parte más espectacular del tutorial: la cuadrícula que muestra los productos que ya hemos añadido. Gracias a Auto Entities y un poco de código en Jinja2, la lista se generará sola y mostrará la imagen de cada producto que tengamos guardada en nuestra carpeta www.

Copia este código dentro de tu Dashboard (preferiblemente dentro de un pop-up de Bubble Card):

yaml
type: conditional
conditions:
  - entity: todo.la_compra
    state_not: '0'
card:
  type: vertical-stack
  cards:
    - type: custom:bubble-card
      card_type: separator
      name: Productos en la lista de la compra
      icon: mdi:shopping
    - type: custom:auto-entities
      show_empty: false
      card:
        square: true
        type: grid
        columns: 3
      card_param: cards
      filter:
        template: |-
          {%- set LISTA = states('input_text.lista_compra') -%}
          {%- set ITEMS = states('todo.la_compra') | int -%}
          {%- for INDEX in range(ITEMS) -%}
            {%- set product_total = LISTA.split(';')[INDEX] -%}
            {%- set product = product_total.split(':')[0] -%}
            {%- set picture = '/local/shopping_list/'+ product +'.png' -%}
            
          {{
            {
              'type': 'custom:mushroom-template-card',
              'entity': 'todo.la_compra',
              'secondary': product_total,
              'multiline_secondary': 'true',
              'picture': picture,
              'layout': 'vertical',
              'fill_container': 'true',
              'tap_action': {
                'action': 'call-service',
                'service': 'todo.update_item',
                'target': {
                'entity_id': 'todo.la_compra'},
                'data': { 'item': product_total,'status': 'completed'}
               },
              'card_mod': {
                'style': 'ha-card { background: linear-gradient( rgba(238, 82, 79, 1), rgba(181, 42, 39, 1) ); --icon-size: 60px; --card-secondary-font-size: 11px; --secondary-text-color: #ffffff; };',
               },
            }
          }},
          {%- endfor %}

🔍 ¿Qué está pasando aquí?

  1. Tarjeta Condicional: La lista solo se muestra si hay al menos un objeto (state_not: '0'). Si la lista está vacía, no ocupa espacio.
  2. Auto Entities + Template: El bucle for INDEX in range(ITEMS) recorre cada producto de tu input_text.lista_compra.
  3. Imágenes Dinámicas: La línea picture: picture busca automáticamente un archivo .png en tu carpeta /www/shopping_list/ que se llame igual que el producto. Por eso es vital que los nombres coincidan.
  4. Acción de Tocar: Al pulsar sobre el producto, llamamos al servicio todo.update_item para marcarlo como completed. En ese instante, gracias a las automatizaciones que vemos en el vídeo, el producto desaparecerá de esta lista y pasará a la de "Recientes".
  5. Estilo Visual: Usamos un degradado rojo para que destaque y un tamaño de icono de 60px para que las fotos de los alimentos se vean perfectamente.

📸 Importante:

"Para que las fotos aparezcan, crea una carpeta en tu Home Assistant llamada www/shopping_list y sube ahí tus imágenes en formato PNG (ejemplo: tomate.png, leche.png). Si el nombre del producto tiene espacios, asegúrate de que el archivo también los tenga o ajusta el código del template."

Paso 7: El Historial: Recupera productos de tus "Compras Recientes"

¿Alguna vez has olvidado comprar algo que es un básico en tu casa? Con esta sección, aprovechamos el input_text.lista_compra_completado para mostrar los últimos productos que has marcado como comprados. Al tocarlos, volverán automáticamente a tu lista activa.

Utilizaremos una Bubble Card de tipo pop-up para que esta lista no ocupe espacio visual hasta que la necesitemos.

yaml
type: vertical-stack
cards:
  - type: custom:bubble-card
    card_type: pop-up
    hash: '#bought_items' # Este hash debe coincidir con el botón del menú
    icon: mdi:history
    name: Compras recientes
  - type: custom:auto-entities
    show_empty: false
    card:
      square: true
      type: grid
      columns: 3
    card_param: cards
    filter:
      template: |-
        {% set LISTA = states('input_text.lista_compra_completado') %}
        {% for INDEX in range(LISTA.split(';')|length-1) -%}
          {%- set product_total = LISTA.split(';')[INDEX] -%}
          {%- set product = product_total.split(':')[0] -%}
          {%- set picture = '/local/shopping_list/'+ product +'.png' -%}
        {{
          {
            'type': 'custom:mushroom-template-card',
            'entity': 'todo.la_compra',
            'secondary': product_total,
            'multiline_secondary': 'true',
            'picture': picture,
            'layout': 'vertical',
            'fill_container': 'true',
              'tap_action': {
                'action': 'call-service',
                'service': 'todo.update_item',
                'target': {
                'entity_id': 'todo.la_compra'},
                'data': { 'item': product_total,'status': 'needs_action'}
               },
            'card_mod': {
              'style': 'ha-card { background: linear-gradient( rgba(79, 171, 162, 1), rgba(38, 133, 124, 1) ); --icon-size: 60px; --card-secondary-font-size: 11px; --secondary-text-color: #ffffff; };',
             },
          }
        }},
        {%- endfor %}

💡 Puntos clave de esta configuración:

  • El Hash (#bought_items): Es el "ID" de este pop-up. Cuando en el menú de navegación pulsas el botón "Recientes", Home Assistant busca este hash y abre esta ventana.
  • Acción Inversa: A diferencia de la lista principal, aquí el tap_action usa el estado 'needs_action'. Esto significa: "saca este producto de completados y ponlo otra vez en la lista de pendientes".
  • Color Distintivo: Usamos un degradado turquesa/verde para diferenciar visualmente el historial de la lista de la compra activa (que es roja).
  • Lógica de Imágenes: Al igual que en la sección anterior, se cargan las fotos automáticamente desde tu carpeta local, manteniendo la coherencia visual en toda la interfaz.

Paso 7: 📂 El Catálogo Maestro: Organización por Categorías y Swipe

Para que encontrar productos sea un juego de niños, hemos diseñado un catálogo que puedes deslizar. En la primera "página" verás los productos agrupados por categorías (Frutas, Lácteos, etc.) con cabeceras visuales, y en la segunda, una lista alfabética de todo tu inventario.

Utilizamos un Pop-up de Bubble Card vinculado al hash #catalogue.

yaml
type: vertical-stack
cards:
  - type: custom:bubble-card
    card_type: pop-up
    hash: '#catalogue'
    icon: mdi:view-grid
    name: Catálogo
  - type: custom:swipe-card
    cards:
      # PÁGINA 1: Vista por Categorías
      - type: custom:auto-entities
        show_empty: false
        card_param: cards
        card:
          square: false
          type: grid
          columns: 3
        filter:
          template: |-
            {% set ns = namespace(result = [], categories = {}) %}
            {% set categories = states
              |selectattr('object_id', 'contains', 'shopping_list_cat')
              |sort(attribute='attributes.friendly_name')
              |map(attribute='entity_id')
              |list
            %}
            {% for cat in categories -%}
              {%- set name_cat = (state_attr(cat,'friendly_name')).split("Shopping List - cat - ")[1] -%}
              {%- set icon_cat = state_attr(cat,'icon') -%}
              {% for i in range(1, 4) %}
                {%- if i==2 -%}
                  {% set ns.result = ns.result + [
                    {
                      'type': 'custom:mushroom-template-card',
                      'secondary': name_cat,
                      'icon': icon_cat,
                      'layout': 'vertical',
                      'card_mod': {
                        'style': 'ha-card { background: linear-gradient( rgba(131, 58, 180, 1), rgba(4, 80, 236, 1) ); --icon-size: 0px; --card-secondary-font-size: 15px; --secondary-text-color: #ffffff;};',
                       },
                    }
                  ]%}
                {%- else -%}
                  {% set ns.result = ns.result + [
                    {
                      'type': 'custom:mushroom-template-card',
                      'secondary': none,
                      'icon': icon_cat,
                      'layout': 'vertical',
                      'card_mod': {
                        'style': 'ha-card { background: linear-gradient( rgba(131, 58, 180, 1), rgba(4, 80, 236, 1) ); --icon-size: 28px; --card-secondary-font-size: 15px; --secondary-text-color: #ffffff;};',
                       },
                    }
                  ]%}
                {%- endif %}                
              {%- endfor %}
              {% set items = states(cat).split(";") | sort -%}
              {% set list = states('input_text.lista_compra') %}
              {% for item in items -%}
                {%- set name_item = item | replace ('.','') -%}
                {%- set picture = '/local/shopping_list/'+ name_item +'.png' -%}
                {%- if item in list -%}
                  {% set ns.result = ns.result + [
                    {
                      'type': 'custom:mushroom-template-card',
                      'entity': 'todo.la_compra',
                      'secondary': name_item,
                      'multiline_secondary': 'true',
                      'picture': picture,
                      'layout': 'vertical',
                      'fill_container': 'true',
                      'tap_action': { 'action': 'none' },
                      'card_mod': {
                        'style': 'ha-card { background: linear-gradient( rgba(238, 82, 79, 1), rgba(181, 42, 39, 1) ); --icon-size: 60px; --card-secondary-font-size: 12px; --secondary-text-color: #ffffff;};',
                       },
                    }              
                  ]%}
                {%- else -%}
                  {% set ns.result = ns.result + [
                    {
                      'type': 'custom:mushroom-template-card',
                      'entity': 'todo.la_compra',
                      'secondary': name_item,
                      'multiline_secondary': 'true',
                      'picture': picture,
                      'layout': 'vertical',
                      'fill_container': 'true',
                      'tap_action': {
                        'action': 'call-service',
                        'service': 'todo.add_item',
                        'target': { 'entity_id': 'todo.la_compra'},
                        'data': { 'item': name_item }
                       },
                      'card_mod': {
                        'style': 'ha-card { background: linear-gradient( rgba(79, 171, 162, 1), rgba(38, 133, 124, 1) ); --icon-size: 60px; --card-secondary-font-size: 11px; --secondary-text-color: #ffffff; };',
                       },
                    }              
                  ]%}                
                {%- endif -%}
              {%- endfor %}
            {%- endfor %}
            {{ ns.result }}

      # PÁGINA 2: Vista Alfabética Completa
      - type: custom:auto-entities
        show_empty: false
        card:
          square: true
          type: grid
          columns: 3
        card_param: cards
        filter:
          template: |-
            {% set items = ((states
              |selectattr('object_id', 'contains', 'shopping_list_cat')
              |map(attribute='state'))
              |list
              |join(';')).split(';')
              |sort
            %}            
            {% set list = states('input_text.lista_compra') %}
            {% for item in items -%}
              {%- set product = item -%}
              {%- set picture = '/local/shopping_list/'+ product +'.png' -%}
              {%- if item in list -%}
              {{
                {
                  'type': 'custom:mushroom-template-card',
                  'entity': 'todo.la_compra',
                  'secondary': product,
                  'multiline_secondary': 'true',
                  'picture': picture,
                  'layout': 'vertical',
                  'fill_container': 'true',
                  'tap_action': { 'action': 'none' },
                  'card_mod': {
                    'style': 'ha-card { background: linear-gradient( rgba(238, 82, 79, 1), rgba(181, 42, 39, 1) ); --icon-size: 60px; --card-secondary-font-size: 12px; --secondary-text-color: #ffffff;};',
                   },
                }              
              }},
              {%- else -%}
              {{
                {
                  'type': 'custom:mushroom-template-card',
                  'entity': 'todo.la_compra',
                  'secondary': product,
                  'multiline_secondary': 'true',
                  'layout': 'vertical',
                  'fill_container': 'true',
                  'picture': picture,
                  'tap_action': {
                    'action': 'call-service',
                    'service': 'todo.add_item',
                    'target': { 'entity_id': 'todo.la_compra'},
                    'data': { 'item': product }
                   },
                  'card_mod': {
                    'style': 'ha-card { background: linear-gradient( rgba(79, 171, 162, 1), rgba(38, 133, 124, 1) ); --icon-size: 60px; --card-secondary-font-size: 11px; --secondary-text-color: #ffffff; };',
                   },
                }              
              }},
              {%- endif -%}
            {%- endfor %}

🧠 ¿Por qué este código es tan potente?

  1. Detección Automática: El código busca todas las entidades que contienen shopping_list_cat. Si mañana creas una categoría nueva, ¡aparecerá sola sin tocar el código!
  2. Cabeceras de Colores: Genera automáticamente una fila de 3 columnas para cada categoría (con degradado púrpura/azul) para que sepas qué estás viendo.
  3. Estado en Tiempo Real: Si un producto ya está en tu lista, aparecerá en rojo y no podrás pulsarlo. Si no está, aparecerá en verde y se añadirá con un toque.
  4. Swipe Card: Permite tener dos formas de ver la misma información en el mismo espacio. ¡Limpieza absoluta en el Dashboard!

Paso 8: ⚙️ El Motor: Sincronizando la lista con los sensores de texto

Para que las tarjetas visuales sepan qué iconos iluminar y qué fotos mostrar, necesitamos que los input_text que creamos al principio se actualicen automáticamente cada vez que añadimos o quitamos algo de nuestra lista de la compra (ya sea desde Home Assistant o desde la app de Bring).

Esta automatización detecta cualquier cambio y "traduce" la lista de tareas a una cadena de texto separada por puntos y coma.

Crea la siguiente automatización:

yaml
alias: "Bring - Actualizar sensor de texto con lista de la compra"
description: "Sincroniza la lista de tareas con los input_text para la interfaz visual"
trigger:
  - platform: state
    entity_id: todo.la_compra # <--- Cambia por tu entidad de lista
action:
  # 1. Obtenemos los productos PENDIENTES
  - service: todo.get_items
    target:
      entity_id: todo.la_compra
    data:
      status: needs_action
    response_variable: incompleted
    
  - variables:
      incompleted_items: |
        {%- for item in incompleted['todo.la_compra']['items'] -%}
            {{ item.summary }};
        {%- endfor -%}

  # 2. Guardamos los pendientes en el input_text.lista_compra
  - service: input_text.set_value
    target:
      entity_id: input_text.lista_compra
    data:
      value: "{{ incompleted_items }}"

  # 3. Obtenemos los productos COMPLETADOS (Historial)
  - service: todo.get_items
    target:
      entity_id: todo.la_compra
    data:
      status: completed
    response_variable: completed
    
  - variables:
      completed_items: |
        {%- for item in completed['todo.la_compra']['items'] -%}
            {{ item.summary }};
        {%- endfor -%}

  # 4. Guardamos los completados en el input_text.lista_compra_completado
  - service: input_text.set_value
    target:
      entity_id: input_text.lista_compra_completado
    data:
      value: "{{ completed_items }}"

🧠 ¿Cómo funciona esta lógica?

  1. Disparador (Trigger): En cuanto la entidad todo cambia (porque marcas un producto como comprado o añades uno nuevo), la automatización arranca.
  2. Servicio get_items: Es una función avanzada de Home Assistant que nos permite "leer" el contenido de la lista y guardarlo en una variable temporal (response_variable).
  3. Bucle For: Recorremos cada ítem de esa lista y le añadimos un ; al final. Esto crea el formato leche;huevos;pan; que nuestras tarjetas necesitan.
  4. Sincronización Total: Lo mejor de este sistema es que si añades algo desde la app móvil de Bring, la automatización se activará y verás aparecer el producto con su foto en tu Dashboard de Home Assistant casi al instante.

Paso 9: 🎨 El Toque Final: Imágenes y Nomenclatura

Para que en lugar de iconos genéricos veas las fotos reales de los productos, tenemos que seguir una regla de oro: el nombre del producto debe coincidir exactamente con el nombre del archivo de imagen.

1. Preparando la carpeta de imágenes

Home Assistant solo puede servir imágenes que estén dentro de la carpeta www.

  1. Entra en tu carpeta de configuración (donde está el configuration.yaml).
  2. Ve a la carpeta www (si no existe, créala).
  3. Crea una subcarpeta llamada shopping_list.
  4. La ruta final para tus fotos será: /local/shopping_list/.

2. El nombre del archivo

Si en tu catálogo o en Bring el producto se llama "Leche Desnatada", tu imagen debe guardarse exactamente como:

  • Leche Desnatada.png
💡 Yo recomiendo usar el formato PNG con fondo transparente y un tamaño de unos 512x512 píxeles. Esto hace que, al usar los degradados de colores en las tarjetas Mushroom, el producto parezca "flotar" sobre el botón y quede mucho más profesional.

3. ¿De dónde sacar los iconos?

Puedes usar las propias imágenes de la web de tu supermercado habitual o buscarlas en Google Imágenes. Solo tienes que descargarlas, renombrarlas y subirlas a tu Home Assistant (puedes usar el addon de Samba Share o el de File Editor para hacerlo rápido).

Y luego, si quieres una página de iconos bonitos, pues te recomiendo esta: https://flaticon.es

Resumen de funcionamiento:

Cuando el código de la tarjeta encuentra el producto "Tomate", busca automáticamente en: 'local/shopping_list/Tomate.png'

Si la imagen existe, ¡boom! Aparece tu lista visual. Si no existe, la tarjeta simplemente mostrará el nombre del producto sobre el fondo de color, para que nunca te quedes a ciegas.

Conclusión y Próximos Pasos

Hemos pasado de una lista de texto a un panel interactivo que cualquiera en casa querrá usar. Esta es solo la Parte 1; en la siguiente entrega veremos cómo añadir automáticamente los ingredientes de tus recetas favoritas a la lista de la compra. Por lo tanto, no esperes para leer la Parte 2, creación de recetas.

Si quieres ver cómo descargo las imágenes, cómo organizo las carpetas en el servidor y el código completo funcionando en tiempo real, no te pierdas el vídeo: 🛒💡Mejora la Lista de la Compra en Home Assistant. PARTE 1 en mi canal HectorziN | Domótica y Home Assistant.

Video relacionado

CUPONES ALIEXPRESS