Open-Meteo's geocoder is built for city-level weather lookups -- it knows
"Münster" but has no idea what "Münster Hauptbahnhof" means, so any
specific station name failed to resolve. Reused it from Weather without
checking it actually fit this use case.
The db_info reference project sidesteps this entirely by requiring the
user to pick existing Home Assistant person/zone entities, which already
carry precise coordinates from HA's own location system -- no equivalent
here, so this needed real geocoding.
Switched geocode() to query the same EFA instances' XML_STOPFINDER_REQUEST
endpoint instead -- the same system that answers the trip request, so
location resolution is guaranteed consistent with what trip planning
understands. Verified live: correctly resolves specific stations ("Münster
Hauptbahnhof" -> "Münster (Westf), Hbf", even the "Muenster" ue-spelling
the user actually typed), plain city names (falls back to the main
station), and district/neighborhood names (e.g. "Hiltrup" -> the actual
Hiltrup stop, not just the vague suburb entry) -- all via matchQuality
scoring and the API's own isBest flag. Re-verified the full pipeline
end-to-end through the real Flask route afterward.
New screens/journey.py, ported and simplified from github.com/EiS94/db_info
(a Home Assistant integration). Deliberately uses only the regional EFA
(Elektronische Fahrplanauskunft) backends the reference project queries
(VRR prioritized for NRW routes, falling back to Bavaria/BW instances) and
drops its bahn.de-internal-API source entirely -- that's DB's own
infrastructure, exactly the kind of thing DB has been actively blocking
(see the Departures screen). EFA instances are run by regional transit
authorities, not DB, so they aren't part of that clampdown. Also dropped
the reference project's parallel async fetch-and-score-all-sources
machinery for simple sequential fallback, matching this project's fully
synchronous style.
Verified against live VRR data for a real NRW route (Münster -> Dortmund):
real trains, platforms, transfer counts, even a night bus connection.
Caught a real bug during that live test: EFA returns UTC timestamps (Z
suffix), and datetime.fromisoformat() parses that correctly into an
aware datetime, but strftime() on an aware datetime prints its own
stored hour/minute rather than converting to local time first --
everything displayed 2 hours behind (CEST is UTC+2), which looked like
"next" departures had already left. Fixed by converting with
astimezone() before formatting; re-verified live afterward that
departures now correctly show after the query time.
Settings: origin/destination resolved via Open-Meteo's free geocoding
(same pattern as Weather's city field), how many connections to show
(1/2/3/5), and its own configurable update interval.