mgokg commited on
Commit
047910f
·
verified ·
1 Parent(s): 2387771

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +190 -1
app.py CHANGED
@@ -1,5 +1,194 @@
1
  import gradio as gr
2
  import requests
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  from datetime import datetime, timedelta
4
  import xml.etree.ElementTree as ET
5
  import json
@@ -125,4 +314,4 @@ with gr.Blocks(title="DB JSON Fahrplan", theme=gr.themes.Soft()) as demo:
125
  btn.click(fn=ui_wrapper, inputs=[dep_input, dest_input, cid_input, akey_input], outputs=output)
126
 
127
  if __name__ == "__main__":
128
- demo.launch()
 
1
  import gradio as gr
2
  import requests
3
+ from datetime import datetime
4
+ import xml.etree.ElementTree as ET
5
+
6
+ def get_station_info(pattern, client_id, api_key):
7
+ """
8
+ Sucht über die Timetables API nach einem Bahnhof und gibt EVA-Nummer
9
+ und den korrekten Namen zurück.
10
+ """
11
+ url = f"https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/station/{pattern}"
12
+
13
+ headers = {
14
+ 'DB-Client-Id': client_id,
15
+ 'DB-Api-Key': api_key,
16
+ 'accept': 'application/xml'
17
+ }
18
+
19
+ try:
20
+ response = requests.get(url, headers=headers, timeout=10)
21
+ response.raise_for_status()
22
+
23
+ root = ET.fromstring(response.content)
24
+ stations = []
25
+ for station in root.findall('station'):
26
+ stations.append({
27
+ 'name': station.get('name'),
28
+ 'eva': station.get('eva')
29
+ })
30
+
31
+ # Falls Stationen gefunden wurden, nehmen wir die erste (beste Übereinstimmung)
32
+ return stations[0] if stations else None
33
+
34
+ except Exception as e:
35
+ print(f"Fehler bei Stationssuche: {e}")
36
+ return None
37
+
38
+ def search_connections(departure, destination, client_id, api_key):
39
+ """Sucht Verbindungen zwischen zwei Bahnhöfen"""
40
+
41
+ if not departure or not destination:
42
+ return "❌ Bitte Abfahrts- und Zielort eingeben"
43
+
44
+ if not client_id or not api_key:
45
+ return "❌ Bitte Client ID und API Key eingeben"
46
+
47
+ # 1. IBNR (EVA) für Abfahrtsort ermitteln
48
+ dep_info = get_station_info(departure, client_id, api_key)
49
+ if not dep_info:
50
+ return f"❌ Abfahrtsort '{departure}' wurde nicht gefunden."
51
+
52
+ # 2. IBNR (EVA) für Zielort ermitteln (für genaueres Matching im Pfad)
53
+ dest_info = get_station_info(destination, client_id, api_key)
54
+ if not dest_info:
55
+ return f"❌ Zielort '{destination}' wurde nicht gefunden."
56
+
57
+ departure_eva = dep_info['eva']
58
+ departure_name = dep_info['name']
59
+ destination_name = dest_info['name']
60
+
61
+ # Aktuelles Datum und Stunde
62
+ now = datetime.now()
63
+ datum = now.strftime("%y%m%d") # YYMMDD
64
+ stunde = now.strftime("%H") # HH
65
+
66
+ # API-Aufruf für den Fahrplan
67
+ url = f"https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/plan/{departure_eva}/{datum}/{stunde}"
68
+
69
+ headers = {
70
+ "DB-Client-Id": client_id,
71
+ "DB-Api-Key": api_key,
72
+ "accept": "application/xml"
73
+ }
74
+
75
+ try:
76
+ response = requests.get(url, headers=headers, timeout=10)
77
+
78
+ if response.status_code != 200:
79
+ return f"❌ API Fehler beim Abrufen des Fahrplans: {response.status_code}"
80
+
81
+ root = ET.fromstring(response.content)
82
+ connections = []
83
+
84
+ for train in root.findall('.//s'):
85
+ dp = train.find('dp')
86
+ if dp is None:
87
+ continue
88
+
89
+ # Route des Zugs (ppth = planned path)
90
+ path = dp.get('ppth', '')
91
+
92
+ # Prüfen ob Zielort im Pfad enthalten ist
93
+ # Wir prüfen sowohl den eingegebenen Namen als auch den gefundenen offiziellen Namen
94
+ if destination_name.lower() in path.lower() or destination.lower() in path.lower():
95
+ # Zugdetails extrahieren
96
+ tl = train.find('tl') # Train Label
97
+ train_class = tl.get('c', '') # z.B. ICE
98
+ train_number = tl.get('n', '') # z.B. 123
99
+ full_train_name = f"{train_class} {train_number}"
100
+
101
+ planned_time = dp.get('pt', '')
102
+ platform = dp.get('pp', 'n/a')
103
+
104
+ if len(planned_time) == 10: # Format YYMMDDHHMM
105
+ planned_time = f"{planned_time[8:10]}:{planned_time[10:12]}"
106
+ elif len(planned_time) == 4:
107
+ planned_time = f"{planned_time[:2]}:{planned_time[2:]}"
108
+
109
+ route = ' → '.join(path.split('|'))
110
+
111
+ connections.append({
112
+ 'train': full_train_name,
113
+ 'time': planned_time,
114
+ 'platform': platform,
115
+ 'route': route
116
+ })
117
+
118
+ if not connections:
119
+ return f"ℹ️ Keine direkten Verbindungen von {departure_name} nach {destination_name} gefunden.\n(Suche im Zeitraum {now.strftime('%H:00')} - {int(now.strftime('%H'))+1}:00 Uhr)"
120
+
121
+ result = f"🚆 Verbindungen von: {departure_name}\n"
122
+ result += f"🏁 Ziel: {destination_name}\n"
123
+ result += f"📅 Datum: {now.strftime('%d.%m.%Y')}\n\n"
124
+
125
+ for i, conn in enumerate(connections[:15], 1):
126
+ result += f"─────────────────────────────────\n"
127
+ result += f"{i}. {conn['train']}\n"
128
+ result += f" ⏰ Abfahrt: {conn['time']} Uhr\n"
129
+ result += f" ���� Gleis: {conn['platform']}\n"
130
+ result += f" 🗺️ Route: {conn['route'][:100]}...\n\n"
131
+
132
+ return result
133
+
134
+ except Exception as e:
135
+ return f"❌ Fehler: {str(e)}"
136
+
137
+ # Gradio Interface
138
+ with gr.Blocks(title="DB Timetable API - Live Suche", theme=gr.themes.Soft()) as demo:
139
+ gr.Markdown(
140
+ """
141
+ # 🚆 DB Live-Fahrplanauskunft
142
+ Ermittelt automatisch die IBNR (EVA-Nummer) und sucht nach Verbindungen.
143
+ """
144
+ )
145
+
146
+ with gr.Row():
147
+ with gr.Column():
148
+ client_id_input = gr.Textbox(label="DB Client ID", type="password")
149
+ api_key_input = gr.Textbox(label="DB API Key", type="password")
150
+
151
+ with gr.Row():
152
+ with gr.Column():
153
+ departure_input = gr.Textbox(
154
+ label="Abfahrtsort",
155
+ placeholder="z.B. Berlin Hbf oder Frankfurt"
156
+ )
157
+ with gr.Column():
158
+ destination_input = gr.Textbox(
159
+ label="Zielort",
160
+ placeholder="z.B. München Hbf"
161
+ )
162
+
163
+ search_button = gr.Button("🔍 Verbindungen suchen", variant="primary")
164
+
165
+ output = gr.Textbox(label="Ergebnisse", lines=20)
166
+
167
+ gr.Markdown(
168
+ """
169
+ ### ℹ️ Funktionsweise
170
+ 1. Die App sendet Ihren Suchbegriff an den `/station` Endpoint.
171
+ 2. Die erste gefundene **EVA-Nummer (IBNR)** wird für die Abfrage genutzt.
172
+ 3. Der Fahrplan für die aktuelle Stunde wird abgerufen.
173
+ 4. Es wird gefiltert, ob der Zielbahnhof im geplanten Fahrtverlauf vorkommt.
174
+ """
175
+ )
176
+
177
+ search_button.click(
178
+ fn=search_connections,
179
+ inputs=[departure_input, destination_input, client_id_input, api_key_input],
180
+ outputs=output
181
+ )
182
+
183
+ if __name__ == "__main__":
184
+ demo.launch()
185
+
186
+
187
+
188
+
189
+ """
190
+ import gradio as gr
191
+ import requests
192
  from datetime import datetime, timedelta
193
  import xml.etree.ElementTree as ET
194
  import json
 
314
  btn.click(fn=ui_wrapper, inputs=[dep_input, dest_input, cid_input, akey_input], outputs=output)
315
 
316
  if __name__ == "__main__":
317
+ """