Home Assistant integration for S-Bahn München public transport departures, covering all 152 known S-Bahn stations.
- Real-time departure information
- Config flow with a searchable station dropdown — no more guessing station IDs
- Filter by destination and line
- Delay information
- Platform information
- Multiple stations, each as its own config entry
- Shared polling per station via a
DataUpdateCoordinator
Click the button above, then "Add" to add this repository to HACS. Alternatively, add it manually:
- Open HACS in your Home Assistant instance
- Go to "Integrations"
- Click the three dots in the top right corner
- Select "Custom repositories"
- Add this repository URL
- Category: Integration
- Click "Add"
Either way, afterwards:
- Search for "S-Bahn München Live" in HACS and install it
- Restart Home Assistant
- Copy the
custom_components/sbahn_muenchen_livedirectory to your Home Assistantconfig/custom_componentsdirectory - Restart Home Assistant
- Go to Developer Tools → States
- Look for the new
sensor.*entity for the station you added - The state should show minutes until next departure
Go to Settings → Devices & Services → Add Integration and search for "S-Bahn München Live". Pick a station from the dropdown and, optionally, a custom name for the sensor.
After setup, use the integration's Configure button to adjust:
| Option | Default | Description |
|---|---|---|
destinations |
All | Comma-separated list of destinations to filter |
lines |
All | Comma-separated list of lines to filter (e.g. S1, S8) |
timeoffset |
0 | Minimum minutes until departure |
number |
5 | Maximum number of departures to show |
Note:
destinationsmatches as a case-insensitive substring, not an exact string — this is intentional: the same physical destination is reported with different text depending on which station asks. For example, a train to the airport shows up as"Flughafen/Airport ✈"at München Hbf, but as"Freising, Flughafen ✈"or"Flughafen ✈, Flughafen ✈"at München Ost. A filter of"Flughafen"matches all of these; the full exact string would silently miss most of them depending on the station.linesstill matches exactly (e.g.S1), since line names don't vary like this. If in doubt, set up the sensor without filters first and check itsdeparturesattribute in Developer Tools → States to see the real strings.
Existing configuration.yaml entries under sensor: - platform: sbahn_muenchen_live are
automatically imported as config entries on startup (with a repair
notification asking you to remove the YAML block afterwards). New YAML
configuration is not needed — use the UI going forward.
sensor:
- platform: sbahn_muenchen_live
nextdeparture:
- station: "Flughafen Besucherpark"
name: "Airport Departures"The sensor provides the following state and attributes:
State: Minutes until next departure
Attributes:
destination: Destination of the next departureline: Line name (e.g., "S1", "S8")type: Transport type (e.g., "S-Bahn")platform: Platform numberdelay: Delay in minutesicon: Material Design Icontrain_units: Number of coupled S-Bahn units (1–3) for this train, if known (see note below)departures: List of all upcoming departuresmessages: Service messages (currently empty — the geOps timetable endpoint doesn't provide any)
Note on
train_units: geOps only reports train formation (how many units are coupled together) for vehicles currently broadcasting live position data, via a separate realtime feed the integration keeps a single shared background connection open for (covering the whole network, reused across all configured stations). For trains without an active live position yet — usually further in the future —train_unitsisnulluntil that data arrives, closer to departure time.
type: entities
title: Munich Airport S-Bahn
entities:
- entity: sensor.airport_departures
secondary_info: last-updatedtype: custom:auto-entities
card:
type: entities
title: Airport Departures
filter:
template: |
{% for departure in state_attr('sensor.airport_departures', 'departures') %}
{{
{
'entity': 'sensor.airport_departures',
'name': departure.line + ' → ' + departure.destination,
'secondary_info': departure.time_in_mins | string + ' min' + (' +' + departure.delay | string + ' min' if departure.delay > 0 else '')
}
}},
{% endfor %}- Check that the selected station has current S-Bahn traffic
- Verify your internet connection
- Check Home Assistant logs for errors:
Settings > System > Logs - Try increasing the
numberoption to fetch more departures
- Ensure all dependencies are installed (websockets, certifi)
- Check Python version (requires Python 3.11+)
- Restart Home Assistant after installation
- Check for errors in the logs
- Check if the API is reachable:
wss://api.geops.io/realtime-ws/v1/ - Verify there are departures at the current time for that station
This integration uses data from the S-Bahn München Live Map provided by geOps.
The timetable data from the geOps Live Map API is more accurate and reliable than other public transport APIs because:
- Real-time updates: Direct connection to the live tracking system
- Precise timing: Actual timetable data with delay information
- High reliability: Used by the official S-Bahn München live map
- WebSocket connection: Instant updates without polling delays
The integration specifically uses only the timetable endpoint (GET timetable_{station_id}) for optimal performance and accuracy, rather than map/trajectory data. The station list (custom_components/sbahn_muenchen_live/stations.py) was generated once from the GET station_schematic endpoint, since geOps has no by-name station search API.
MIT License
- Data: geOps.io
- Integration structure inspired by the MVG integration
For issues, feature requests, or questions, please open an issue on GitHub.