# lghs/lab architecture

> Architecture diagram of the GitHub repository lghs/lab, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-10-01). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/lghs/lab
- Repository: https://github.com/lghs/lab

## Overview

Little Android Brother is an Android TV/tablet home-screen dashboard for the Liège Hackerspace. Android launches MainActivity, which starts camera tiles and coordinates lifecycle-bound polling and flows; the result is a live dashboard showing door/cameras, weather, Deliveroo, music, TEC buses and SNCB trains. Transport data additionally depends on periodically refreshed configuration and generated schedules. The graph preserves the documented integrations; unsampled implementations are represented by their exact source paths, and edges are limited to calls or relationships visible in excerpts or README.

Main entry points: [`app/src/main/java/be/lghs/lab/MainActivity.kt`](https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/MainActivity.kt) (Dashboard activity), [`app/src/main/java/be/lghs/lab/data/TransportConfig.kt`](https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/data/TransportConfig.kt) (Transport config), [`app/src/main/java/be/lghs/lab/data/Renderer.kt`](https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/data/Renderer.kt) (Streaming renderers), [`app/src/main/java/be/lghs/lab/data/Mpd.kt`](https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/data/Mpd.kt) (MPD playback)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_app["Android dashboard"]
  node_activity["Dashboard activity<br/>[MainActivity.kt]"]
  node_boot["Boot receiver<br/>[BootReceiver.kt]"]
  node_layout["Dashboard layout<br/>[DashboardLayout.kt]"]
  node_camera["Camera tiles<br/>[CameraTileView.kt]"]
  node_info["Info panel<br/>[InfoPanel.kt]"]
  node_transportpanel["Departure board<br/>[TransportPanel.kt]"]
  node_musicpanel["Music panel<br/>[MusicPanel.kt]"]
end

subgraph group_transport["Transport boards"]
  node_transportconfig["Transport config<br/>[TransportConfig.kt]"]
  node_tec["TEC departures<br/>[Tec.kt]"]
  node_trains["SNCB departures<br/>[Trains.kt]"]
end

subgraph group_music["Music playback"]
  node_mpd["MPD playback<br/>[Mpd.kt]"]
  node_renderer["Streaming renderers<br/>[Renderer.kt]"]
end

subgraph group_data["Status and data"]
  node_door["Door status<br/>[Nuki.kt]"]
  node_deliveroo["Delivery status<br/>[Deliveroo.kt]"]
  node_weather["Weather forecast<br/>[Weather.kt]"]
  node_http["HTTP client<br/>[Http.kt]"]
  node_config["Device config<br/>[Config.kt]"]
end

node_resident(("Resident"))
node_unifi{{"UniFi Protect"}}
node_nukibridge{{"Nuki bridge"}}
node_deliverooapi{{"Deliveroo endpoint"}}
node_openmeteo{{"Open-Meteo"}}
node_moode{{"moOde"}}
node_tecapi{{"TEC GTFS-RT"}}
node_irail{{"iRail"}}
node_dashboardfiles["Dashboard config<br/>[transport.json]"]

node_resident -->|"opens"| node_activity
node_boot -->|"starts"| node_activity
node_activity -->|"starts"| node_camera
node_camera -->|"streams"| node_unifi
node_activity -->|"polls"| node_door
node_door -->|"reads state"| node_nukibridge
node_activity -->|"polls"| node_deliveroo
node_deliveroo -->|"fetches"| node_deliverooapi
node_activity -->|"polls"| node_weather
node_weather -->|"fetches"| node_openmeteo
node_activity -->|"updates"| node_info
node_activity -->|"awaits config"| node_transportconfig
node_transportconfig -->|"loads defaults"| node_dashboardfiles
node_transportconfig -->|"fetches remote config"| node_http
node_transportconfig -->|"supplies schedules"| node_tecapi
node_activity -->|"fetches departures"| node_tec
node_tec -->|"reads delays"| node_tecapi
node_activity -->|"fetches routes"| node_trains
node_trains -->|"queries"| node_irail
node_activity -->|"shows departures"| node_transportpanel
node_activity -->|"collects playback"| node_mpd
node_activity -->|"collects playback"| node_renderer
node_renderer -->|"overrides when active"| node_mpd
node_activity -->|"shows playback"| node_musicpanel
node_mpd -->|"controls via MPD"| node_moode
node_renderer -->|"reads metadata"| node_moode
node_mpd -->|"uses"| node_http
node_renderer -->|"uses"| node_http
node_musicpanel -->|"loads covers"| node_http
node_config -->|"provides stream URLs"| node_camera

click node_activity "https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/MainActivity.kt"
click node_boot "https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/BootReceiver.kt"
click node_layout "https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/ui/DashboardLayout.kt"
click node_camera "https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/CameraTileView.kt"
click node_door "https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/data/Nuki.kt"
click node_deliveroo "https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/data/Deliveroo.kt"
click node_weather "https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/data/Weather.kt"
click node_info "https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/ui/InfoPanel.kt"
click node_transportconfig "https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/data/TransportConfig.kt"
click node_tec "https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/data/Tec.kt"
click node_trains "https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/data/Trains.kt"
click node_transportpanel "https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/ui/TransportPanel.kt"
click node_mpd "https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/data/Mpd.kt"
click node_renderer "https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/data/Renderer.kt"
click node_musicpanel "https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/ui/MusicPanel.kt"
click node_http "https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/data/Http.kt"
click node_config "https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/Config.kt"
click node_dashboardfiles "https://github.com/lghs/lab/blob/main/dashboard/transport.json"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_activity,node_boot,node_layout,node_camera,node_info,node_transportpanel,node_musicpanel toneBlue
class node_transportconfig,node_tec,node_trains toneAmber
class node_mpd,node_renderer toneMint
class node_door,node_deliveroo,node_weather,node_http,node_config toneRose
class node_resident,node_unifi,node_nukibridge,node_deliverooapi,node_openmeteo,node_moode,node_tecapi,node_irail toneIndigo
class node_dashboardfiles toneTeal
```

## Components

### Android dashboard

- [Dashboard activity](https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/MainActivity.kt): `app/src/main/java/be/lghs/lab/MainActivity.kt`
- [Boot receiver](https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/BootReceiver.kt): `app/src/main/java/be/lghs/lab/BootReceiver.kt`
- [Dashboard layout](https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/ui/DashboardLayout.kt): `app/src/main/java/be/lghs/lab/ui/DashboardLayout.kt`
- [Camera tiles](https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/CameraTileView.kt): `app/src/main/java/be/lghs/lab/CameraTileView.kt`
- [Info panel](https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/ui/InfoPanel.kt): `app/src/main/java/be/lghs/lab/ui/InfoPanel.kt`
- [Departure board](https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/ui/TransportPanel.kt): `app/src/main/java/be/lghs/lab/ui/TransportPanel.kt`
- [Music panel](https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/ui/MusicPanel.kt): `app/src/main/java/be/lghs/lab/ui/MusicPanel.kt`

### Transport boards

- [Transport config](https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/data/TransportConfig.kt): `app/src/main/java/be/lghs/lab/data/TransportConfig.kt`
- [TEC departures](https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/data/Tec.kt): `app/src/main/java/be/lghs/lab/data/Tec.kt`
- [SNCB departures](https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/data/Trains.kt): `app/src/main/java/be/lghs/lab/data/Trains.kt`

### Music playback

- [MPD playback](https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/data/Mpd.kt): `app/src/main/java/be/lghs/lab/data/Mpd.kt`
- [Streaming renderers](https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/data/Renderer.kt): `app/src/main/java/be/lghs/lab/data/Renderer.kt`

### Status and data

- [Door status](https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/data/Nuki.kt): `app/src/main/java/be/lghs/lab/data/Nuki.kt`
- [Delivery status](https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/data/Deliveroo.kt): `app/src/main/java/be/lghs/lab/data/Deliveroo.kt`
- [Weather forecast](https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/data/Weather.kt): `app/src/main/java/be/lghs/lab/data/Weather.kt`
- [HTTP client](https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/data/Http.kt): `app/src/main/java/be/lghs/lab/data/Http.kt`
- [Device config](https://github.com/lghs/lab/blob/main/app/src/main/java/be/lghs/lab/Config.kt): `app/src/main/java/be/lghs/lab/Config.kt`

### Other components

- **Resident**
- **UniFi Protect**
- **Nuki bridge**
- **Deliveroo endpoint**
- **Open-Meteo**
- **moOde**
- **TEC GTFS-RT**
- **iRail**
- [Dashboard config](https://github.com/lghs/lab/blob/main/dashboard/transport.json): `dashboard/transport.json`

## Connections

- Resident → Dashboard activity: opens (evidence: `README.md`)
- Boot receiver → Dashboard activity: starts (evidence: `app/src/main/java/be/lghs/lab/BootReceiver.kt`)
- Dashboard activity → Camera tiles: starts (evidence: `app/src/main/java/be/lghs/lab/MainActivity.kt`)
- Camera tiles → UniFi Protect: streams (evidence: `README.md`)
- Dashboard activity → Door status: polls (evidence: `app/src/main/java/be/lghs/lab/MainActivity.kt`)
- Door status → Nuki bridge: reads state (evidence: `app/src/main/java/be/lghs/lab/data/Nuki.kt`)
- Dashboard activity → Delivery status: polls (evidence: `app/src/main/java/be/lghs/lab/MainActivity.kt`)
- Delivery status → Deliveroo endpoint: fetches (evidence: `app/src/main/java/be/lghs/lab/data/Deliveroo.kt`)
- Dashboard activity → Weather forecast: polls (evidence: `app/src/main/java/be/lghs/lab/MainActivity.kt`)
- Weather forecast → Open-Meteo: fetches (evidence: `app/src/main/java/be/lghs/lab/data/Weather.kt`)
- Dashboard activity → Info panel: updates (evidence: `app/src/main/java/be/lghs/lab/MainActivity.kt`)
- Dashboard activity → Transport config: awaits config (evidence: `app/src/main/java/be/lghs/lab/MainActivity.kt`)
- Transport config → Dashboard config: loads defaults (evidence: `README.md`)
- Transport config → HTTP client: fetches remote config (evidence: `app/src/main/java/be/lghs/lab/data/TransportConfig.kt`)
- Transport config → TEC GTFS-RT: supplies schedules (evidence: `README.md`)
- Dashboard activity → TEC departures: fetches departures (evidence: `app/src/main/java/be/lghs/lab/MainActivity.kt`)
- TEC departures → TEC GTFS-RT: reads delays (evidence: `README.md`)
- Dashboard activity → SNCB departures: fetches routes (evidence: `app/src/main/java/be/lghs/lab/MainActivity.kt`)
- SNCB departures → iRail: queries (evidence: `README.md`)
- Dashboard activity → Departure board: shows departures (evidence: `app/src/main/java/be/lghs/lab/MainActivity.kt`)
- Dashboard activity → MPD playback: collects playback (evidence: `app/src/main/java/be/lghs/lab/MainActivity.kt`)
- Dashboard activity → Streaming renderers: collects playback (evidence: `app/src/main/java/be/lghs/lab/MainActivity.kt`)
- Streaming renderers → MPD playback: overrides when active
- Dashboard activity → Music panel: shows playback (evidence: `app/src/main/java/be/lghs/lab/MainActivity.kt`)
- MPD playback → moOde: controls via MPD (evidence: `README.md`)
- Streaming renderers → moOde: reads metadata (evidence: `app/src/main/java/be/lghs/lab/data/Renderer.kt`)
- MPD playback → HTTP client: uses (evidence: `app/src/main/java/be/lghs/lab/data/Mpd.kt`)
- Streaming renderers → HTTP client: uses (evidence: `app/src/main/java/be/lghs/lab/data/Renderer.kt`)
- Music panel → HTTP client: loads covers (evidence: `app/src/main/java/be/lghs/lab/ui/MusicPanel.kt`)
- Device config → Camera tiles: provides stream URLs (evidence: `app/src/main/java/be/lghs/lab/Config.kt`)
