Zaragoza Tram
September 1, 2026 · View on GitHub
¡Bienvenido a la integración Zaragoza Tram para Home Assistant!
Esta integración te permite crear sensores que muestran el tiempo restante para la llegada de los dos próximos tranvías a una parada específica de Zaragoza.
Los datos se obtienen gracias a la API proporcionada por el Ayuntamiento de Zaragoza:
API REST Zaragoza
🧪 Novedad en beta: soporte de autobús urbano
Desde
v1.2.0-beta.1la integración también soporta autobuses urbanos, además del tranvía. Está en fase beta: el tranvía sigue funcionando exactamente igual que siempre, pero la parte de bus es nueva y agradecemos que la probéis y reportéis cualquier problema en Issues.Para instalar la beta desde HACS:
- Ve a la integración Zaragoza Tram dentro de HACS.
- Menú ⋮ → Redownload (o desde la ficha del repositorio) y activa "Show beta versions" / "Mostrar versiones beta".
- Elige la versión
1.2.0-beta.1(o la beta más reciente) e instala.- Reinicia Home Assistant.
Mientras esté en beta, los usuarios que no activen esa opción seguirán recibiendo la última versión estable sin cambios.
Índice
Instalación
1. Manual
- Descarga los archivos de este repositorio.
- Copia la carpeta
zaragoza_tramdentro del directoriocustom_componentsde tu configuración de Home Assistant.- Si la carpeta
custom_componentsno existe, créala en la raíz de tu configuración.
- Si la carpeta
- Reinicia Home Assistant.
2. Usando HACS
- Añade este repositorio como repositorio personalizado en HACS.
- Busca "Zaragoza Tram" en HACS e instálalo.
- Reinicia Home Assistant.
Configuración
Desde la Interfaz de Usuario
- Ve a Ajustes → Dispositivos e Integraciones.
- Haz clic en el botón "+" y busca "Zaragoza Tram".
- Elige Tranvía o Bus.
Tranvía: selecciona la parada de la lista desplegable y ¡listo! Tendrás dos sensores (próximo y siguiente tranvía).
Bus: primero eliges cómo identificar la parada:
- Buscar la parada en el listado: escribe parte de la dirección (o el número de línea) y elige entre los resultados. También puedes escribir directamente el código oficial de la marquesina (
PA00100) en este mismo campo — si lo reconoce, te lleva directo a esa parada sin pasar por la lista de resultados. - Ya sé el código de la parada: escribe el código tal cual aparece en la marquesina/app oficial (
PA00100) o el número de poste (100).
Después, opcionalmente puedes filtrar por línea. Si dejas la línea en blanco, eliges entre:
- Próximo y siguiente (cualquier línea): dos sensores con las dos llegadas más próximas a la parada, sea cual sea la línea (la línea de cada llegada va en el atributo
linea, ya que puede cambiar de una actualización a otra). - Una entidad por línea: un par de sensores (próximo/siguiente) por cada línea que pase por esa parada.
Las peticiones a la API de bus (que falla con cierta frecuencia) se reintentan automáticamente hasta 3 veces antes de dejar el sensor con el último dato conocido.
Cambiar línea o modo sin recrear la integración
Las entradas de bus tienen un botón Configurar (Ajustes → Dispositivos y servicios → tu entrada de bus → ⚙️ Configurar) que permite cambiar la línea filtrada o pasar de "combinado" a "una entidad por línea" (y viceversa) sin borrar la integración ni perder el historial de las entidades que no cambian. Las de tranvía no tienen nada que configurar ahí.
Ejemplos de tarjetas Lovelace (opcionales)
Puedes mostrar la información de los sensores en tu panel de Home Assistant usando tarjetas personalizadas.
Estos ejemplos son opcionales y requieren instalar los siguientes complementos desde HACS si quieres usarlos:
- Para el ejemplo sencillo: Mushroom Cards
- Para el ejemplo avanzado: button-card
Ejemplo sencillo con Mushroom Cards

type: vertical-stack
cards:
- type: custom:mushroom-title-card
title: 🚋 Próximos Tranvías - Plaza España
subtitle: Zaragoza
- type: horizontal-stack
cards:
- type: custom:mushroom-entity-card
entity: sensor.tranvia_1_plaza_espana_dir_mago_de_oz
name: Próximo tranvía
icon: mdi:tram
icon_color: green
primary_info: state
secondary_info: none
layout: vertical
tap_action:
action: more-info
- type: custom:mushroom-entity-card
entity: sensor.tranvia_2_plaza_espana_dir_mago_de_oz
name: Siguiente tranvía
icon: mdi:tram
icon_color: blue
primary_info: state
secondary_info: none
layout: vertical
tap_action:
action: more-info
Ejemplo avanzado para Plaza España (Dirección: Mago de Oz)

type: vertical-stack
cards:
- type: custom:button-card
name: 🚋 Plaza España
label: "Dir: Mago de Oz"
color_type: card
styles:
card:
- background: "linear-gradient(120deg, #1976d2 0%, #43a047 100%)"
- color: white
- font-size: 22px
- font-weight: bold
- padding: 20px
- border-radius: 20px
- box-shadow: 0 8px 18px rgba(25,118,210,0.13)
name:
- font-size: 26px
- font-weight: bold
label:
- font-size: 17px
- color: "#e3f2fd"
- padding-top: 6px
- type: horizontal-stack
cards:
- type: custom:button-card
entity: sensor.tranvia_1_plaza_espana_dir_mago_de_oz
name: Próximo
icon: mdi:tram
color_type: icon
show_state: true
show_name: true
show_label: true
state_display: |
[[[
return entity.state + " min";
]]]
label: |
[[[
let mins = parseInt(entity.state);
if (!isNaN(mins)) {
let date = new Date();
date.setMinutes(date.getMinutes() + mins);
let h = date.getHours().toString().padStart(2,'0');
let m = date.getMinutes().toString().padStart(2,'0');
return "Llega a las " + h + ":" + m;
} else {
return "Sin datos";
}
]]]
styles:
card:
- background: "linear-gradient(120deg, #43a047 80%, #a5d6a7 100%)"
- color: white
- font-size: 18px
- font-weight: bold
- border-radius: 20px
- box-shadow: 0 4px 14px rgba(67,160,71,0.18)
- padding: 24px
- transition: box-shadow 0.3s
icon:
- color: white
- width: 56px
- height: 56px
- animation: >
[[[ return (entity.state < 5) ? "bounce 1s infinite" : "none"; ]]]
name:
- font-size: 20px
- padding-top: 8px
state:
- font-size: 30px
- font-weight: bold
- padding-top: 10px
label:
- font-size: 16px
- color: "#e8f5e9"
- padding-top: 8px
extra_styles: |
@keyframes bounce {
0%, 100% { transform: translateY(0);}
50% { transform: translateY(-10px);}
}
tap_action:
action: more-info
hold_action:
action: none
double_tap_action:
action: none
triggers_update: all
- type: custom:button-card
entity: sensor.tranvia_2_plaza_espana_dir_mago_de_oz
name: Siguiente
icon: mdi:tram
color_type: icon
show_state: true
show_name: true
show_label: true
state_display: |
[[[
return entity.state + " min";
]]]
label: |
[[[
let mins = parseInt(entity.state);
if (!isNaN(mins)) {
let date = new Date();
date.setMinutes(date.getMinutes() + mins);
let h = date.getHours().toString().padStart(2,'0');
let m = date.getMinutes().toString().padStart(2,'0');
return "Llega a las " + h + ":" + m;
} else {
return "Sin datos";
}
]]]
styles:
card:
- background: "linear-gradient(120deg, #1565c0 80%, #90caf9 100%)"
- color: white
- font-size: 18px
- font-weight: bold
- border-radius: 20px
- box-shadow: 0 4px 14px rgba(21,101,192,0.18)
- padding: 24px
- transition: box-shadow 0.3s
icon:
- color: white
- width: 56px
- height: 56px
name:
- font-size: 20px
- padding-top: 8px
state:
- font-size: 30px
- font-weight: bold
- padding-top: 10px
label:
- font-size: 16px
- color: "#e3f2fd"
- padding-top: 8px
tap_action:
action: more-info
hold_action:
action: none
double_tap_action:
action: none
triggers_update: all
Ejemplo con Mushroom Cards para bus (modo combinado)
⚠️ En modo "Próximo y siguiente (cualquier línea)" la línea de cada llegada NO aparece en el estado del sensor, solo como atributo
linea(porque puede cambiar de una actualización a otra — mira más arriba por qué). El diálogo estándar "más información" de Home Assistant no muestra ese atributo para un sensor normal, así que para verlo en el panel de un vistazo necesitas una tarjeta como esta (o consultarlo en Herramientas de desarrollo → Estados). Si prefieres tenerlo siempre visible sin depender de una tarjeta, usa el modo "Una entidad por línea" en su lugar.
En modo "Próximo y siguiente (cualquier línea)" la línea de cada llegada puede cambiar entre actualizaciones, así que en vez de una mushroom-entity-card normal usamos una mushroom-template-card para mostrar juntos el estado y el atributo linea. Cambia los entity por los tuyos (los ves en Ajustes → Dispositivos y servicios → Entidades).
type: vertical-stack
cards:
- type: custom:mushroom-title-card
title: 🚌 Próximo Bus - Av. Ejemplo
subtitle: Parada 100
- type: horizontal-stack
cards:
- type: custom:mushroom-template-card
entity: sensor.bus_proximo_parada_100
primary: "Línea {{ state_attr(entity, 'linea') }}"
secondary: "{{ states(entity) }} min"
icon: mdi:bus
icon_color: green
layout: vertical
tap_action:
action: more-info
- type: custom:mushroom-template-card
entity: sensor.bus_siguiente_parada_100
primary: "Línea {{ state_attr(entity, 'linea') }}"
secondary: "{{ states(entity) }} min"
icon: mdi:bus
icon_color: blue
layout: vertical
tap_action:
action: more-info
Ejemplo con button-card para bus (modo "una entidad por línea")
En modo "Una entidad por línea" cada línea tiene su propio par de sensores, así que aquí la línea sí es fija y se puede poner directamente en el nombre de cada tarjeta (sin plantillas). Ejemplo con tres líneas (10, 20 y 30) de la parada 100 — ajusta los entity y las líneas a las tuyas.
type: vertical-stack
cards:
- type: custom:button-card
name: 🚌 Av. Ejemplo
label: "Parada 100"
color_type: card
styles:
card:
- background: "linear-gradient(120deg, #ef6c00 0%, #f9a825 100%)"
- color: white
- font-size: 22px
- font-weight: bold
- padding: 20px
- border-radius: 20px
- box-shadow: 0 8px 18px rgba(230,108,0,0.13)
name:
- font-size: 26px
- font-weight: bold
label:
- font-size: 17px
- color: "#fff3e0"
- padding-top: 6px
- type: horizontal-stack
cards:
- type: custom:button-card
entity: sensor.bus_10_proximo_parada_100
name: Línea 10
icon: mdi:bus
color_type: icon
show_state: true
show_name: true
state_display: |
[[[
return entity.state + " min";
]]]
styles:
card:
- background: "linear-gradient(120deg, #43a047 80%, #a5d6a7 100%)"
- color: white
- font-weight: bold
- border-radius: 20px
- padding: 16px
state:
- font-size: 24px
- font-weight: bold
tap_action:
action: more-info
- type: custom:button-card
entity: sensor.bus_20_proximo_parada_100
name: Línea 20
icon: mdi:bus
color_type: icon
show_state: true
show_name: true
state_display: |
[[[
return entity.state + " min";
]]]
styles:
card:
- background: "linear-gradient(120deg, #1565c0 80%, #90caf9 100%)"
- color: white
- font-weight: bold
- border-radius: 20px
- padding: 16px
state:
- font-size: 24px
- font-weight: bold
tap_action:
action: more-info
- type: custom:button-card
entity: sensor.bus_30_proximo_parada_100
name: Línea 30
icon: mdi:bus
color_type: icon
show_state: true
show_name: true
state_display: |
[[[
return entity.state + " min";
]]]
styles:
card:
- background: "linear-gradient(120deg, #6a1b9a 80%, #ce93d8 100%)"
- color: white
- font-weight: bold
- border-radius: 20px
- padding: 16px
state:
- font-size: 24px
- font-weight: bold
tap_action:
action: more-info