Skip to content

Repository files navigation

TMB Pantalles

Rèplica digital d'alta fidelitat de les pantalles d'informació en temps real del Metro de Barcelona (TMB).

Pensada per a amants del transport que vulguin muntar una pantalla temàtica a casa: propers trens, destí, sentit i alertes de servei amb l'estètica oficial de la xarxa, configurable via URL.

Live Demo React TypeScript Vite Tailwind CSS License: MIT

Pantalla en mode panell Pantalla amb alerta activa

Idioma: Català · Castellano



Català

Resolució recomanada.

  • Màxima fidelitat: pantalla tipus barra / ultrapanoràmica 2,8:1, equivalent al llenç natiu 1512 × 540. La franja omple la pantalla de punta a punta, com els panells reals d'andana.
  • Ús general / futur: Full HD 1920 × 1080 (16:9). Aquí la franja actual es mostra centrada; és la resolució que requerirà la propera versió amb estacions amb transbordament (16:9).

Taula de continguts

Característiques

  • Temps real des de l'API oficial de TMB (api.tmb.cat/v1).
  • Configurador integrat: línia i estació de tota la xarxa, resoltes dinàmicament des de l'API.
  • Càlcul de minuts en client comparant temps_arribada (Unix ts) amb el rellotge del sistema; mostra Entra als darrers 15 s.
  • Alertes duals: oficials (endpoint alerts) i personalitzades (Rodalies, FGC, Tram… amb títol, text, colors i icona).
  • URLs autoconfigurables: tota la configuració del panell viatja en query params.
  • Mode kiosk: amaga el botó de configuració; es reobre amb la tecla c.

Stack tecnològic

Capa Tecnologia
UI React 19
Llenguatge TypeScript 5.9
Build Vite 7
Estils Tailwind CSS 4 (@tailwindcss/postcss)
Routing React Router 7 (/, /credits, /docs)
Icones lucide-react
Utils d'estil class-variance-authority, clsx, tailwind-merge

Arquitectura

El configurador serialitza l'estat del panell a la URL; la pantalla el deserialitza en carregar, consulta l'API de TMB i renderitza amb el càlcul de minuts fet en client.

flowchart LR
    A[Configurator.tsx] -->|generateShareableUrl| B[URL amb query params]
    B -->|parseConfigFromUrl| C[Home.tsx / estat]
    C --> D[services/tmbApi.ts]
    D <-->|transit · itransit · alerts| E[(TMB API v1)]
    D -->|calculateTimeRemaining| F[MetroScreen.tsx]
    C --> F
    F --> G[Panell HDMI]
Loading
Mòdul Rol
pages/Home.tsx Orquestrador: carrega config (URL o defaults), estat i escalat del llenç
components/Configurator.tsx Configuració, alertes personalitzades, tecla c, pantalla completa
components/MetroScreen.tsx Render del panell
services/tmbApi.ts Accés a l'API + calculateTimeRemaining
utils/urlGenerator.ts Serialització/parse de la config a la URL
config/api.config.ts Credencials, BASE_URL, DEFAULT_PANEL_CONFIG
types/tmb.ts Contractes de l'API

Estructura del projecte

src/
├─ components/  Configurator.tsx · MetroScreen.tsx · ui/select.tsx
├─ config/      api.config.ts
├─ constants/   texts.ts
├─ pages/       Home.tsx · Credits.tsx · Documentation.tsx
├─ services/    tmbApi.ts
├─ types/       tmb.ts
├─ utils/       urlGenerator.ts
└─ App.tsx · main.tsx
public/         lineas/ · transport-icons/ · alertas/

Posada en marxa

Requereix Node 20.19+ (Vite 7) i credencials de TMB Developer.

git clone https://github.com/00b1b1/tmb-pantalles.git
cd tmb-pantalles
npm install
cp .env.example .env   # edita les claus
npm run dev

Variables d'entorn

VITE_TMB_APP_ID=el_teu_app_id
VITE_TMB_APP_KEY=la_teva_app_key

Al ser una app de client, Vite injecta les VITE_* al bundle: són visibles al navegador. Per a producció, restringeix l'ús de l'App Key al portal de TMB o intermedia amb un proxy.

Scripts

Script Acció
npm run dev Dev server (HMR)
npm run build tsc -b + build de Vite
npm run preview Serveix el build
npm run lint ESLint

Configuració per URL

Cada panell es defineix per query params (generateShareableUrl() els genera, parseConfigFromUrl() els llegeix).

Paràmetre Tipus Req. Default Descripció
line string Nom de línia (L4)
station number Codi d'estació
direction number No 1 Sentit/andana
alerts boolean No false Alertes oficials
emergency boolean No true Avís d'emergència
hideConfig boolean No false Amaga el botó (kiosk)
alertIds number[] No [] IDs d'alertes actives (coma)
customAlerts string No Alertes pròpies (JSON + Base64)
/?line=L4&station=428&direction=1&hideConfig=true

Mode kiosk

Amb hideConfig=true (o el toggle) s'oculta el botó de configuració; es reobre amb la tecla c. El configurador també alterna pantalla completa via requestFullscreen().

API de TMB

Base: https://api.tmb.cat/v1 (totes les crides adjunten app_id i app_key).

Funció Endpoint
fetchAllLines() transit/linies/metro/
fetchLineStations(lineCode) transit/linies/metro/{lineCode}/estacions
fetchStationInfo(stationId, lineId) itransit/metro/estacions/{stationId}?codi_linia={lineId}
fetchLineAlerts(lineName) alerts/metro/channels/WEB/routes/{lineName}

calculateTimeRemaining() opera sobre timestamps Unix (ms): retorna mm:ss, col·lapsa a N min quan escau, i mostra Entra als darrers 15 s.

Gestió de textos

Textos centralitzats a src/constants/texts.ts (objecte APP_TEXTS). Modifica'ls per editar o traduir tota la interfície.

Desplegament (Vercel)

Preset Vite (build npm run build, output dist) i defineix VITE_TMB_APP_ID / VITE_TMB_APP_KEY a Environment Variables.

Autohospedatge amb Docker

Build de producció servida per nginx (amb fallback SPA per a les rutes de React Router). Les claus VITE_* s'incrusten en temps de build, per això es passen com a build args.

Dockerfile, nginx.conf i docker-compose.yml inclosos al repo. Aixecar:

cp .env.example .env          # VITE_TMB_APP_ID / VITE_TMB_APP_KEY
docker compose up -d --build

Disponible a http://localhost:8080. Reconstruir després de canvis: docker compose up -d --build.

Raspberry Pi (kiosk per HDMI)

Reproductor dedicat que serveix la teva pròpia build (no la demo) i arrenca en kiosk. Ligero: Pi OS Lite + Docker + cage (compositor Wayland d'una sola app) + Chromium. Recomanat Pi 4/5 per compilar; en plaques petites, aixeca el contenidor en un altre host de la LAN i apunta la URL a http://IP:8080.

1. OS + Docker. Flasheja Raspberry Pi OS Lite (64-bit) (hostname, SSH i Wi‑Fi des de l'Imager). Després:

curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker "$USER"   # torna a iniciar sessió

2. Servir la build. Segueix Autohospedatge amb Docker → panell a http://localhost:8080.

3. Resolució HDMI. A /boot/firmware/cmdline.txt (mateixa línia, video= al final):

  • 16:9: video=HDMI-A-1:1920x1080@60
  • Barra 2,8:1 (~1512×540): video=HDMI-A-1:1512x540M@60 — el sufix M genera el modeline CVT (el monitor l'ha d'acceptar).
  • Vertical: afegeix ,rotate=90.

4. Kiosk.

sudo apt install -y --no-install-recommends cage chromium-browser
cat > ~/kiosk.sh <<'EOF'
#!/usr/bin/env bash
URL="http://localhost:8080/?line=L4&station=428&direction=1&hideConfig=true"
exec chromium-browser --kiosk "$URL" --ozone-platform=wayland \
  --noerrdialogs --disable-infobars --disable-session-crashed-bubble \
  --check-for-update-interval=31536000
EOF
chmod +x ~/kiosk.sh

5. Autoarranque. sudo raspi-configConsole Autologin. A ~/.bash_profile:

[ "$(tty)" = "/dev/tty1" ] && exec cage -- ~/kiosk.sh

sudo reboot i el panell omple la pantalla.

Opcional: reinici diari 0 4 * * * /sbin/reboot (sudo crontab -e); apagat nocturn amb wlr-randr --output HDMI-A-1 --off / --on.

Paleta oficial

Mostra Ús Hex
Vermell TMB #C8102E
Groc alerta #FFE501
Fons #FFFFFF
Text / detalls #000000

Icones de transport: TMB-Barcelona/TMB-Icons.

Crèdits i llicència

Desenvolupat per a la comunitat de transport de Barcelona per Ahmed Bibi. Llicència MIT.

Projecte no oficial de Transports Metropolitans de Barcelona (TMB). Marques, colors i iconografia pertanyen als seus titulars.



Castellano

Resolución recomendada.

  • Máxima fidelidad: pantalla tipo barra / ultrapanorámica 2,8:1, equivalente al lienzo nativo 1512 × 540. La franja llena la pantalla de punta a punta, como los paneles reales de andén.
  • Uso general / futuro: Full HD 1920 × 1080 (16:9). Aquí la franja actual se muestra centrada; es la resolución que requerirá la próxima versión con estaciones con transbordo (16:9).

Tabla de contenidos

Características

  • Tiempo real desde la API oficial de TMB (api.tmb.cat/v1).
  • Configurador integrado: línea y estación de toda la red, resueltas dinámicamente desde la API.
  • Cálculo de minutos en cliente comparando temps_arribada (Unix ts) con el reloj del sistema; muestra Entra en los últimos 15 s.
  • Alertas duales: oficiales (endpoint alerts) y personalizadas (Rodalies, FGC, Tram… con título, texto, colores e icono).
  • URLs autoconfigurables: toda la configuración del panel viaja en query params.
  • Modo kiosk: oculta el botón de configuración; se reabre con la tecla c.

Stack tecnológico

Capa Tecnología
UI React 19
Lenguaje TypeScript 5.9
Build Vite 7
Estilos Tailwind CSS 4 (@tailwindcss/postcss)
Routing React Router 7 (/, /credits, /docs)
Iconos lucide-react
Utils de estilo class-variance-authority, clsx, tailwind-merge

Arquitectura

El configurador serializa el estado del panel en la URL; la pantalla lo deserializa al cargar, consulta la API de TMB y renderiza con el cálculo de minutos hecho en cliente.

flowchart LR
    A[Configurator.tsx] -->|generateShareableUrl| B[URL con query params]
    B -->|parseConfigFromUrl| C[Home.tsx / estado]
    C --> D[services/tmbApi.ts]
    D <-->|transit · itransit · alerts| E[(TMB API v1)]
    D -->|calculateTimeRemaining| F[MetroScreen.tsx]
    C --> F
    F --> G[Panel HDMI]
Loading
Módulo Rol
pages/Home.tsx Orquestador: carga config (URL o defaults), estado y escalado del lienzo
components/Configurator.tsx Configuración, alertas personalizadas, tecla c, pantalla completa
components/MetroScreen.tsx Render del panel
services/tmbApi.ts Acceso a la API + calculateTimeRemaining
utils/urlGenerator.ts Serialización/parse de la config en la URL
config/api.config.ts Credenciales, BASE_URL, DEFAULT_PANEL_CONFIG
types/tmb.ts Contratos de la API

Estructura del proyecto

src/
├─ components/  Configurator.tsx · MetroScreen.tsx · ui/select.tsx
├─ config/      api.config.ts
├─ constants/   texts.ts
├─ pages/       Home.tsx · Credits.tsx · Documentation.tsx
├─ services/    tmbApi.ts
├─ types/       tmb.ts
├─ utils/       urlGenerator.ts
└─ App.tsx · main.tsx
public/         lineas/ · transport-icons/ · alertas/

Puesta en marcha

Requiere Node 20.19+ (Vite 7) y credenciales de TMB Developer.

git clone https://github.com/00b1b1/tmb-pantalles.git
cd tmb-pantalles
npm install
cp .env.example .env   # edita las claves
npm run dev

Variables de entorno

VITE_TMB_APP_ID=tu_app_id
VITE_TMB_APP_KEY=tu_app_key

Al ser una app de cliente, Vite inyecta las VITE_* en el bundle: son visibles en el navegador. Para producción, restringe el uso de la App Key en el portal de TMB o intermedia con un proxy.

Scripts

Script Acción
npm run dev Dev server (HMR)
npm run build tsc -b + build de Vite
npm run preview Sirve el build
npm run lint ESLint

Configuración por URL

Cada panel se define por query params (generateShareableUrl() los genera, parseConfigFromUrl() los lee).

Parámetro Tipo Req. Default Descripción
line string Nombre de línea (L4)
station number Código de estación
direction number No 1 Sentido/andén
alerts boolean No false Alertas oficiales
emergency boolean No true Aviso de emergencia
hideConfig boolean No false Oculta el botón (kiosk)
alertIds number[] No [] IDs de alertas activas (coma)
customAlerts string No Alertas propias (JSON + Base64)
/?line=L4&station=428&direction=1&hideConfig=true

Modo kiosk

Con hideConfig=true (o el toggle) se oculta el botón de configuración; se reabre con la tecla c. El configurador también alterna pantalla completa vía requestFullscreen().

API de TMB

Base: https://api.tmb.cat/v1 (todas las llamadas adjuntan app_id y app_key).

Función Endpoint
fetchAllLines() transit/linies/metro/
fetchLineStations(lineCode) transit/linies/metro/{lineCode}/estacions
fetchStationInfo(stationId, lineId) itransit/metro/estacions/{stationId}?codi_linia={lineId}
fetchLineAlerts(lineName) alerts/metro/channels/WEB/routes/{lineName}

calculateTimeRemaining() opera sobre timestamps Unix (ms): devuelve mm:ss, colapsa a N min cuando procede, y muestra Entra en los últimos 15 s.

Gestión de textos

Textos centralizados en src/constants/texts.ts (objeto APP_TEXTS). Modifícalos para editar o traducir toda la interfaz.

Despliegue (Vercel)

Preset Vite (build npm run build, output dist) y define VITE_TMB_APP_ID / VITE_TMB_APP_KEY en Environment Variables.

Autohospedaje con Docker

Build de producción servida por nginx (con fallback SPA para las rutas de React Router). Las claves VITE_* se hornean en tiempo de build, por eso se pasan como build args.

Dockerfile, nginx.conf y docker-compose.yml incluidos en el repo. Levantar:

cp .env.example .env          # VITE_TMB_APP_ID / VITE_TMB_APP_KEY
docker compose up -d --build

Disponible en http://localhost:8080. Reconstruir tras cambios: docker compose up -d --build.

Raspberry Pi (kiosk por HDMI)

Reproductor dedicado que sirve tu propia build (no la demo) y arranca en kiosk. Ligero: Pi OS Lite + Docker + cage (compositor Wayland de una sola app) + Chromium. Recomendado Pi 4/5 para compilar; en placas pequeñas, levanta el contenedor en otro host de la LAN y apunta la URL a http://IP:8080.

1. OS + Docker. Flashea Raspberry Pi OS Lite (64-bit) (hostname, SSH y Wi‑Fi desde el Imager). Después:

curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker "$USER"   # vuelve a iniciar sesión

2. Servir la build. Sigue Autohospedaje con Docker → panel en http://localhost:8080.

3. Resolución HDMI. En /boot/firmware/cmdline.txt (misma línea, video= al final):

  • 16:9: video=HDMI-A-1:1920x1080@60
  • Barra 2,8:1 (~1512×540): video=HDMI-A-1:1512x540M@60 — el sufijo M genera el modeline CVT (el monitor debe aceptarlo).
  • Vertical: añade ,rotate=90.

4. Kiosk.

sudo apt install -y --no-install-recommends cage chromium-browser
cat > ~/kiosk.sh <<'EOF'
#!/usr/bin/env bash
URL="http://localhost:8080/?line=L4&station=428&direction=1&hideConfig=true"
exec chromium-browser --kiosk "$URL" --ozone-platform=wayland \
  --noerrdialogs --disable-infobars --disable-session-crashed-bubble \
  --check-for-update-interval=31536000
EOF
chmod +x ~/kiosk.sh

5. Autoarranque. sudo raspi-configConsole Autologin. En ~/.bash_profile:

[ "$(tty)" = "/dev/tty1" ] && exec cage -- ~/kiosk.sh

sudo reboot y el panel llena la pantalla.

Opcional: reinicio diario 0 4 * * * /sbin/reboot (sudo crontab -e); apagado nocturno con wlr-randr --output HDMI-A-1 --off / --on.

Paleta oficial

Muestra Uso Hex
Rojo TMB #C8102E
Amarillo alerta #FFE501
Fondo #FFFFFF
Texto / detalles #000000

Iconos de transporte: TMB-Barcelona/TMB-Icons.

Créditos y licencia

Desarrollado para la comunidad de transporte de Barcelona por Ahmed Bibi. Licencia MIT.

Proyecto no oficial de Transports Metropolitans de Barcelona (TMB). Marcas, colores e iconografía pertenecen a sus titulares.

About

Rèplica de les pantalles d'usuari de TMB Metro Barcelona amb dades oficials en viu

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages