Änderungen an den Zugläufen?

This commit is contained in:
Julian Metzler 2022-06-12 14:27:27 +02:00
parent 99b603b3d0
commit 2884b47608
2 changed files with 339 additions and 339 deletions

View File

@ -1,6 +1,6 @@
certifi==2019.11.28 certifi==2019.11.28
chardet==3.0.4 chardet==3.0.4
idna==2.8 idna==2.8
pyserial==3.4 pyserial==3.4
requests==2.21.0 requests==2.21.0
urllib3==1.24.3 urllib3==1.24.3

666
run.py
View File

@ -1,333 +1,333 @@
import datetime import datetime
import hashlib import hashlib
import json import json
import time import time
import traceback import traceback
from db_infoscreen import DBInfoscreen from db_infoscreen import DBInfoscreen
from splitflap.krone import Krone8200Controller from splitflap.krone import Krone8200Controller
from splitflap.display import SplitFlapDisplay, CustomMapField from splitflap.display import SplitFlapDisplay, CustomMapField
from splitflap.exceptions import CommunicationError from splitflap.exceptions import CommunicationError
from util import timeout from util import timeout
RX_ADDRESS = (0x41, 0x41) RX_ADDRESS = (0x41, 0x41)
MAP_ROUTE = { MAP_ROUTE = {
0: "Halensee, Schöneberg, Südkreuz, Neukölln", 0: "Halensee, Schöneberg, Südkreuz, Neukölln",
1: "Schöneberg, Südkreuz, Neukölln, Baumschulenweg", 1: "Schöneberg, Südkreuz, Neukölln, Baumschulenweg",
2: "Schöneberg, Südkreuz, Neukölln, Schöneweide", 2: "Schöneberg, Südkreuz, Neukölln, Schöneweide",
3: "Schöneberg, Neukölln, Schöneweide, Grünau", 3: "Schöneberg, Neukölln, Schöneweide, Grünau",
4: "Gesundbrunnen, Schönhauser Allee, Ostkreuz, Treptower Park", 4: "Gesundbrunnen, Schönhauser Allee, Ostkreuz, Treptower Park",
5: "Gesundbrunnen, Schönhauser Allee, Ostkreuz, Neukölln", 5: "Gesundbrunnen, Schönhauser Allee, Ostkreuz, Neukölln",
6: "Gesundbrunnen, Ostkreuz, Neukölln, Südkreuz", 6: "Gesundbrunnen, Ostkreuz, Neukölln, Südkreuz",
7: "Gesundbrunnen, Ostkreuz, Neukölln, Schöneberg", 7: "Gesundbrunnen, Ostkreuz, Neukölln, Schöneberg",
8: "Westend", 8: "Westend",
9: "Westend, Jungfernheide", 9: "Westend, Jungfernheide",
10: "Westend, Jungfernheide, Westhafen", 10: "Westend, Jungfernheide, Westhafen",
11: "Westend, Jungfernheide, Westhafen, Gesundbrunnen", 11: "Westend, Jungfernheide, Westhafen, Gesundbrunnen",
12: "Westend, Jungfernheide, Gesundbrunnen, Schönhauser Allee", 12: "Westend, Jungfernheide, Gesundbrunnen, Schönhauser Allee",
13: "Jungfernheide, Gesundbrunnen, Schönhauser Allee, Ostkreuz", 13: "Jungfernheide, Gesundbrunnen, Schönhauser Allee, Ostkreuz",
14: "Gesundbrunnen, Ostkreuz, Schöneberg", 14: "Gesundbrunnen, Ostkreuz, Schöneberg",
15: "Halensee, Schöneberg, Südkreuz, Neukölln", 15: "Halensee, Schöneberg, Südkreuz, Neukölln",
16: "Schöneberg, Südkreuz, Neukölln, Ostkreuz", 16: "Schöneberg, Südkreuz, Neukölln, Ostkreuz",
17: "Schöneberg, Neukölln, Ostkreuz, Gesundbrunnen", 17: "Schöneberg, Neukölln, Ostkreuz, Gesundbrunnen",
18: "Halensee", 18: "Halensee",
19: "Halensee, Bundesplatz", 19: "Halensee, Bundesplatz",
20: "Halensee, Bundesplatz, Schöneberg", 20: "Halensee, Bundesplatz, Schöneberg",
21: "Halensee, Bundesplatz, Schöneberg, Südkreuz", 21: "Halensee, Bundesplatz, Schöneberg, Südkreuz",
22: "Schöneberg, Ostkreuz, Gesundbrunnen", 22: "Schöneberg, Ostkreuz, Gesundbrunnen",
23: "weiter als S2 über Buch", 23: "weiter als S2 über Buch",
24: "Jungfernheide, Gesundbrunnen", 24: "Jungfernheide, Gesundbrunnen",
25: "Jungfernheide, Gesundbrunnen, Bornholmer Straße, Schönholz", 25: "Jungfernheide, Gesundbrunnen, Bornholmer Straße, Schönholz",
26: "Westkreuz, Schöneberg, Südkreuz, Neukölln", 26: "Westkreuz, Schöneberg, Südkreuz, Neukölln",
27: "Westkreuz, Schöneberg, Neukölln, Baumschulenweg", 27: "Westkreuz, Schöneberg, Neukölln, Baumschulenweg",
28: "Westkreuz, Schöneberg, Neukölln, Schöneweide", 28: "Westkreuz, Schöneberg, Neukölln, Schöneweide",
29: "Westkreuz, Schöneberg, Schöneweide, Grünau", 29: "Westkreuz, Schöneberg, Schöneweide, Grünau",
30: "Gesundbrunnen, Ostkreuz, Schöneberg, Westkreuz", 30: "Gesundbrunnen, Ostkreuz, Schöneberg, Westkreuz",
31: "Westkreuz, Schöneberg, Neukölln, Ostkreuz", 31: "Westkreuz, Schöneberg, Neukölln, Ostkreuz",
32: "Westkreuz, Neukölln, Ostkreuz, Gesundbrunnen", 32: "Westkreuz, Neukölln, Ostkreuz, Gesundbrunnen",
33: "Westkreuz", 33: "Westkreuz",
34: "Westkreuz, Halensee", 34: "Westkreuz, Halensee",
35: "Westkreuz, Halensee, Bundesplatz", 35: "Westkreuz, Halensee, Bundesplatz",
36: "Westkreuz, Halensee, Bundesplatz, Schöneberg", 36: "Westkreuz, Halensee, Bundesplatz, Schöneberg",
37: "Westkreuz, Halensee, Schöneberg, Südkreuz", 37: "Westkreuz, Halensee, Schöneberg, Südkreuz",
38: "Westkreuz, Schöneberg, Ostkreuz, Gesundbrunnen", 38: "Westkreuz, Schöneberg, Ostkreuz, Gesundbrunnen",
39: "Jungfernheide", 39: "Jungfernheide",
40: "Jungfernheide, Westhafen", 40: "Jungfernheide, Westhafen",
41: "Jungfernheide, Westhafen, Gesundbrunnen", 41: "Jungfernheide, Westhafen, Gesundbrunnen",
42: "Jungfernheide, Westhafen, Gesundbrunnen, Schönhauser Allee", 42: "Jungfernheide, Westhafen, Gesundbrunnen, Schönhauser Allee",
43: "Jungfernheide, Gesundbrunnen, Bornholmer Straße", 43: "Jungfernheide, Gesundbrunnen, Bornholmer Straße",
44: "Schöneberg, Neukölln Kurzzug", 44: "Schöneberg, Neukölln Kurzzug",
45: "Neukölln, Schöneweide Kurzzug", 45: "Neukölln, Schöneweide Kurzzug",
46: "Gesundbrunnen, Ostkreuz Kurzzug", 46: "Gesundbrunnen, Ostkreuz Kurzzug",
47: "Westend Kurzzug", 47: "Westend Kurzzug",
48: "Westend, Jungfernheide Kurzzug", 48: "Westend, Jungfernheide Kurzzug",
49: "Jungfernheide, Gesundbrunnen Kurzzug", 49: "Jungfernheide, Gesundbrunnen Kurzzug",
50: "Schöneberg, Neukölln Kurzzug", 50: "Schöneberg, Neukölln Kurzzug",
51: "Neukölln, Ostkreuz Kurzzug", 51: "Neukölln, Ostkreuz Kurzzug",
52: "Halensee Kurzzug", 52: "Halensee Kurzzug",
53: "Halensee, Bundesplatz Kurzzug", 53: "Halensee, Bundesplatz Kurzzug",
54: "Halensee, Schöneberg Kurzzug", 54: "Halensee, Schöneberg Kurzzug",
55: "Schöneberg, Ostkreuz Kurzzug", 55: "Schöneberg, Ostkreuz Kurzzug",
56: "Westend, Gesundbrunnen Kurzzug", 56: "Westend, Gesundbrunnen Kurzzug",
57: "Gesundbrunnen, Bornholmer Straße Kurzzug", 57: "Gesundbrunnen, Bornholmer Straße Kurzzug",
58: "Gesundbrunnen, Schönholz Kurzzug", 58: "Gesundbrunnen, Schönholz Kurzzug",
59: "Westkreuz, Neukölln Kurzzug", 59: "Westkreuz, Neukölln Kurzzug",
60: "Westkreuz, Schöneweide Kurzzug", 60: "Westkreuz, Schöneweide Kurzzug",
61: "Ostkreuz, Gesundbrunnen Kurzzug", 61: "Ostkreuz, Gesundbrunnen Kurzzug",
62: "Westkreuz Kurzzug", 62: "Westkreuz Kurzzug",
63: "Westkreuz, Halensee Kurzzug", 63: "Westkreuz, Halensee Kurzzug",
64: "Westkreuz, Schöneberg Kurzzug", 64: "Westkreuz, Schöneberg Kurzzug",
65: "Westkreuz, Ostkreuz Kurzzug", 65: "Westkreuz, Ostkreuz Kurzzug",
66: "Jungfernheide Kurzzug", 66: "Jungfernheide Kurzzug",
67: "Jungfernheide, Gesundbrunnen Kurzzug", 67: "Jungfernheide, Gesundbrunnen Kurzzug",
68: "Gesundbrunnen, Ostkreuz, Südkreuz, Westkreuz", 68: "Gesundbrunnen, Ostkreuz, Südkreuz, Westkreuz",
69: "Westkreuz, Südkreuz, Ostkreuz, Gesundbrunnen", 69: "Westkreuz, Südkreuz, Ostkreuz, Gesundbrunnen",
70: "Gesundbrunnen, Schönhauser Allee Kurzzug", 70: "Gesundbrunnen, Schönhauser Allee Kurzzug",
71: "Messe Nord/ICC (Witzleben)", 71: "Messe Nord/ICC (Witzleben)",
72: "In die letzten 4 Wagen bitte nicht einsteigen", 72: "In die letzten 4 Wagen bitte nicht einsteigen",
73: "Zug fährt später", 73: "Zug fährt später",
74: "Ansage beachten", 74: "Ansage beachten",
75: "Kurzzug", 75: "Kurzzug",
76: "Ersatzverkehr", 76: "Ersatzverkehr",
77: "Zugverkehr unterbrochen", 77: "Zugverkehr unterbrochen",
78: "Zugverkehr unregelmäßig" 78: "Zugverkehr unregelmäßig"
} }
MAP_LINE = { MAP_LINE = {
1: "S1", 1: "S1",
3: "S2", 3: "S2",
5: "S3", 5: "S3",
7: "S4", 7: "S4",
9: "S5", 9: "S5",
11: "S6", 11: "S6",
13: "S7", 13: "S7",
15: "S8", 15: "S8",
17: "S9", 17: "S9",
19: "S10", 19: "S10",
21: "S75", 21: "S75",
23: "S85", 23: "S85",
25: "S86", 25: "S86",
27: "S25", 27: "S25",
29: "S45", 29: "S45",
31: "S46", 31: "S46",
33: "S26", 33: "S26",
35: "S41", 35: "S41",
37: "S42", 37: "S42",
39: "S47" 39: "S47"
} }
MAP_DESTINATION = { MAP_DESTINATION = {
0: "Alexanderplatz", 0: "Alexanderplatz",
1: "Ahrensfelde", 1: "Ahrensfelde",
2: "Anhalter Bahnhof", 2: "Anhalter Bahnhof",
3: "Baumschulenweg", 3: "Baumschulenweg",
4: "Bernau", 4: "Bernau",
5: "Birkenwerder", 5: "Birkenwerder",
6: "Blankenburg", 6: "Blankenburg",
7: "Blankenfelde", 7: "Blankenfelde",
8: "Buch", 8: "Buch",
9: "Bundesplatz", 9: "Bundesplatz",
10: "Charlottenburg", 10: "Charlottenburg",
11: "Erkner", 11: "Erkner",
12: "Falkensee", 12: "Falkensee",
13: "Friedrichshagen", 13: "Friedrichshagen",
14: "Friedrichstraße", 14: "Friedrichstraße",
15: "Schönefeld Flughafen", 15: "Schönefeld Flughafen",
16: "Frohnau", 16: "Frohnau",
17: "Gesundbrunnen", 17: "Gesundbrunnen",
18: "Greifswalder Straße", 18: "Greifswalder Straße",
19: "Grunewald", 19: "Grunewald",
20: "Grünau", 20: "Grünau",
21: "Halensee", 21: "Halensee",
22: "Ostbahnhof", 22: "Ostbahnhof",
23: "Hermannstraße", 23: "Hermannstraße",
24: "Hermsdorf", 24: "Hermsdorf",
25: "Henningsdorf", 25: "Henningsdorf",
26: "Hoppegarten (Markt)", 26: "Hoppegarten (Markt)",
27: "Karlshorst", 27: "Karlshorst",
28: "Königs Wusterhausen", 28: "Königs Wusterhausen",
29: "Köpenik", 29: "Köpenik",
30: "Lichtenberg", 30: "Lichtenberg",
31: "Lichtenrade", 31: "Lichtenrade",
32: "Lichterfeld Süd", 32: "Lichterfeld Süd",
33: "Mahlow", 33: "Mahlow",
34: "Mahlsdorf", 34: "Mahlsdorf",
35: "Marienfelde", 35: "Marienfelde",
36: "Nordbahnhof", 36: "Nordbahnhof",
37: "Olympiastadion", 37: "Olympiastadion",
38: "Oranienburg", 38: "Oranienburg",
39: "Ostkreuz", 39: "Ostkreuz",
40: "Südkreuz", 40: "Südkreuz",
41: "Pichelsberg", 41: "Pichelsberg",
42: "Potsdam Hbf", 42: "Potsdam Hbf",
43: "Potsdamer Platz", 43: "Potsdamer Platz",
44: "Westhafen", 44: "Westhafen",
45: "Rangsdorf", 45: "Rangsdorf",
46: "Spandau", 46: "Spandau",
47: "Schöneberg", 47: "Schöneberg",
48: "Schöneweide", 48: "Schöneweide",
49: "Schönholz", 49: "Schönholz",
50: "Sellheimbrücke", 50: "Sellheimbrücke",
51: "Spindlersfeld", 51: "Spindlersfeld",
52: "Rathaus Steglitz", 52: "Rathaus Steglitz",
53: "Strausberg", 53: "Strausberg",
54: "Strausberg Nord", 54: "Strausberg Nord",
55: "Streslow", 55: "Streslow",
56: "Tegel", 56: "Tegel",
57: "Tempelhof", 57: "Tempelhof",
58: "Wannsee", 58: "Wannsee",
59: "Warschauer Straße", 59: "Warschauer Straße",
60: "Westend", 60: "Westend",
61: "Westkreuz", 61: "Westkreuz",
62: "Zehlendorf", 62: "Zehlendorf",
63: "Zoologischer Garten", 63: "Zoologischer Garten",
64: "Zeuthen", 64: "Zeuthen",
65: "Berlin Hbf", 65: "Berlin Hbf",
66: "Landsberger Allee", 66: "Landsberger Allee",
67: "Marzahn", 67: "Marzahn",
68: "Neukölln", 68: "Neukölln",
69: "Pankow", 69: "Pankow",
70: "Schönhauser Allee", 70: "Schönhauser Allee",
71: "Springpfuhl", 71: "Springpfuhl",
72: "Treptower Park", 72: "Treptower Park",
73: "Ring ↻", 73: "Ring ↻",
74: "Ring ↺", 74: "Ring ↺",
75: "Gesundbrunnen/Ring", 75: "Gesundbrunnen/Ring",
76: "Beusselstraße", 76: "Beusselstraße",
77: "Wedding", 77: "Wedding",
78: "Nicht einsteigen" 78: "Nicht einsteigen"
} }
class BerlinSplitFlapDisplay(SplitFlapDisplay): class BerlinSplitFlapDisplay(SplitFlapDisplay):
route = CustomMapField(MAP_ROUTE, start_address=1, x=0, y=0, module_width=20, module_height=1, home_pos=99) route = CustomMapField(MAP_ROUTE, start_address=1, x=0, y=0, module_width=20, module_height=1, home_pos=99)
line = CustomMapField(MAP_LINE, start_address=2, x=0, y=1, module_width=4, module_height=1, home_pos=99) line = CustomMapField(MAP_LINE, start_address=2, x=0, y=1, module_width=4, module_height=1, home_pos=99)
destination = CustomMapField(MAP_DESTINATION, start_address=3, x=4, y=1, module_width=16, module_height=1, home_pos=99) destination = CustomMapField(MAP_DESTINATION, start_address=3, x=4, y=1, module_width=16, module_height=1, home_pos=99)
@timeout(30) @timeout(30)
def get_trains(dbi, station): def get_trains(dbi, station):
return dbi.get_trains(station) return dbi.get_trains(station)
def main(): def main():
controller = Krone8200Controller("/dev/serial/by-path/platform-3f980000.usb-usb-0:1.5.4:1.0-port0", RX_ADDRESS, debug=True) controller = Krone8200Controller("/dev/serial/by-path/platform-3f980000.usb-usb-0:1.5.4:1.0-port0", RX_ADDRESS, debug=True)
display = BerlinSplitFlapDisplay(controller) display = BerlinSplitFlapDisplay(controller)
dbi = DBInfoscreen("dbf.finalrewind.org") dbi = DBInfoscreen("dbf.finalrewind.org")
last_update = 0 last_update = 0
last_heartbeat = 0 last_heartbeat = 0
while True: while True:
now = time.time() now = time.time()
if now - last_heartbeat >= 10: if now - last_heartbeat >= 10:
print("\n" + "=" * 60 + "\n") print("\n" + "=" * 60 + "\n")
print("Sending heartbeat") print("Sending heartbeat")
controller.send_end_comm() controller.send_end_comm()
last_heartbeat = now last_heartbeat = now
continue continue
if now - last_update < 60: if now - last_update < 60:
time.sleep(1) time.sleep(1)
continue continue
print("\n" + "=" * 60 + "\n") print("\n" + "=" * 60 + "\n")
try: try:
trains = get_trains(dbi, "Berlin Westkreuz") trains = get_trains(dbi, "Berlin Westkreuz")
trains = dbi.calc_real_times(trains) trains = dbi.calc_real_times(trains)
display.clear() display.clear()
line = "" line = ""
dest = "" dest = ""
route = "" route = ""
trains.sort(key=dbi.time_sort) trains.sort(key=dbi.time_sort)
for train in trains: for train in trains:
# Only show trains within the next 3 minutes # Only show trains within the next 3 minutes
now_dt = datetime.datetime.now() now_dt = datetime.datetime.now()
departure_time = datetime.datetime.strptime(train['actualDeparture'] or train['actualArrival'], "%H:%M").time() departure_time = datetime.datetime.strptime(train['actualDeparture'] or train['actualArrival'], "%H:%M").time()
departure_date = (now_dt.date() + datetime.timedelta(days=1)) if (now_dt.time().hour - departure_time.hour) >= 2 else now_dt.date() departure_date = (now_dt.date() + datetime.timedelta(days=1)) if (now_dt.time().hour - departure_time.hour) >= 2 else now_dt.date()
departure_dt = datetime.datetime.combine(departure_date, departure_time) departure_dt = datetime.datetime.combine(departure_date, departure_time)
delta = departure_dt - now_dt delta = departure_dt - now_dt
if delta.total_seconds() / 60 > 3: if delta.total_seconds() / 60 > 3:
continue continue
line = "".join(train['train'].split()) line = "".join(train['train'].split())
display.line.set(line) display.line.set(line)
if line == "S41": if line == "S41":
dest = "Ring ↻" dest = "Ring ↻"
elif line == "S42": elif line == "S42":
dest = "Ring ↺" dest = "Ring ↺"
else: else:
dest = train['destination'].replace("Berlin-", "").replace("Berlin", "").replace("(S)", "").strip() dest = train['destination'].replace("Berlin-", "").replace("Berlin", "").replace("(S)", "").strip()
if dest == "Westkreuz": if dest == "Westkreuz":
dest = "Nicht einsteigen" dest = "Nicht einsteigen"
if dest not in MAP_DESTINATION.values(): if dest not in MAP_DESTINATION.values():
continue continue
display.destination.set(dest) display.destination.set(dest)
delay = train['delayDeparture'] or train['delayArrival'] or 0 delay = train['delayDeparture'] or train['delayArrival'] or 0
route = "" route = ""
if train['train'] == "Bus SEV": if train['train'] == "Bus SEV":
route = "Ersatzverkehr" route = "Ersatzverkehr"
elif all(map(lambda t: t['isCancelled'], trains[:20])): elif all(map(lambda t: t['isCancelled'], trains[:20])):
route = "Zugverkehr unterbrochen" route = "Zugverkehr unterbrochen"
elif all(map(lambda t: t['isCancelled'], trains[:5])): elif all(map(lambda t: t['isCancelled'], trains[:5])):
route = "Zugverkehr unregelmäßig" route = "Zugverkehr unregelmäßig"
elif train['isCancelled'] or delay > 60: elif train['isCancelled'] or delay > 60:
route = "Ansage beachten" route = "Ansage beachten"
elif delay > 2: elif delay > 2:
route = "Zug fährt später" route = "Zug fährt später"
elif line == "S41": elif line == "S41":
route = "Gesundbrunnen, Schönhauser Allee, Ostkreuz, Neukölln" route = "Gesundbrunnen, Schönhauser Allee, Ostkreuz, Neukölln"
elif line == "S42": elif line == "S42":
route = "Schöneberg, Neukölln, Ostkreuz, Gesundbrunnen" route = "Schöneberg, Neukölln, Ostkreuz, Gesundbrunnen"
elif line == "S46" and dest == "Königs Wusterhausen": elif line == "S46" and dest == "Königs Wusterhausen":
route = "Schöneberg, Südkreuz, Neukölln, Baumschulenweg" route = "Schöneberg, Südkreuz, Neukölln, Baumschulenweg"
elif line == "S46" and dest == "Westend": elif line == "S46" and dest == "Westend":
route = "Messe Nord/ICC (Witzleben)" route = "Messe Nord/ICC (Witzleben)"
elif dest == "": elif dest == "":
route = "Ansage beachten" route = "Ansage beachten"
display.route.set(route) display.route.set(route)
break break
print(display.render_ascii()) print(display.render_ascii())
try: try:
with open("status.json", 'r') as f: with open("status.json", 'r') as f:
status = json.load(f) status = json.load(f)
except (FileNotFoundError, ValueError): except (FileNotFoundError, ValueError):
status = {'displayHash': None} status = {'displayHash': None}
display_hash = hashlib.sha256(bytes(line + dest + route, 'utf-8')).hexdigest() display_hash = hashlib.sha256(bytes(line + dest + route, 'utf-8')).hexdigest()
update = True update = True
if status['displayHash'] == display_hash: if status['displayHash'] == display_hash:
print("No need to update display.") print("No need to update display.")
update = False update = False
else: else:
status['displayHash'] = display_hash status['displayHash'] = display_hash
if update: if update:
num_tries = 10 num_tries = 10
for i in range(num_tries): for i in range(num_tries):
try: try:
display.update() display.update()
break break
except CommunicationError: except CommunicationError:
print("Communication error! Retrying... {}/{}".format(i+1, num_tries)) print("Communication error! Retrying... {}/{}".format(i+1, num_tries))
time.sleep(5) time.sleep(5)
with open("status.json", 'w') as f: with open("status.json", 'w') as f:
json.dump(status, f) json.dump(status, f)
except: except:
traceback.print_exc() traceback.print_exc()
last_update = now last_update = now
if __name__ == "__main__": if __name__ == "__main__":
main() main()