Integration with a SQL database, human-readable output of departures

This commit is contained in:
Christopher Teutsch 2019-05-16 14:11:29 +02:00
parent 5e7434b20b
commit 0fa0126dbc
Signed by: iwonder
GPG Key ID: 0EE33D788D50130D
2 changed files with 94 additions and 31 deletions

View File

@ -6,6 +6,23 @@ from pprint import pprint, pformat
import datetime import datetime
import pause import pause
import sys import sys
import mysql.connector
TABLE = """
CREATE TABLE IF NOT EXISTS vrr (
line_code varchar(9) not null,
direction_code varchar(1) not null,
station_id int not null,
orig_datetime datetime not null,
status enum('on_time', 'early', 'late', 'cancelled', 'no_data') not null,
delay_value int default null,
primary key (line_code, direction_code, station_id, orig_datetime));
"""
# CONFIGURATION
USE_MODES = []
USE_STATION_ID = 20021002
USE_LINES = []
class MOT: class MOT:
@ -30,16 +47,8 @@ lines_filter = [
] ]
def t(s: str) -> str: def make_request_data(station_id: int, result_count: int = 8, modes: List = MOT.ALL_MODES,
""" lines: List[str] = ALL_LINES) -> dict:
Encode a string to be used as a station identifier.
:param s: a string to encode
:return: the encoded string
"""
return s.replace(' ', '+')
def make_request_data(station_id: int, result_count: int = 8, modes: List = MOT.ALL_MODES, lines: List[str] = ALL_LINES) -> dict:
""" """
Prepare a request data dictionary to put into get_data() Prepare a request data dictionary to put into get_data()
:param station_id: an EFA station ID :param station_id: an EFA station ID
@ -81,7 +90,7 @@ def make_request_data(station_id: int, result_count: int = 8, modes: List = MOT.
if lines is ALL_LINES: if lines is ALL_LINES:
request_data['useAllLines'] = 1 request_data['useAllLines'] = 1
else: else:
lines_dictarr = [{'data': t(v)} for v in lines] lines_dictarr = [{'data': v.replace(' ', '+')} for v in lines]
request_data['linesFilter'] = json.dumps(lines_dictarr) request_data['linesFilter'] = json.dumps(lines_dictarr)
request_data['useAllLines'] = 0 request_data['useAllLines'] = 0
@ -116,9 +125,12 @@ def is_early(trip: dict) -> bool:
return False return False
# Pretty-print the reply data. def is_on_time(trip: dict) -> bool:
"""print("Data:") return int(trip['delay']) == 0
pprint(reply_data)"""
def has_realtime(trip: dict) -> bool:
return trip['delay'] != ''
def fixup_data(d: dict) -> dict: def fixup_data(d: dict) -> dict:
@ -129,13 +141,20 @@ def fixup_data(d: dict) -> dict:
def print_trip(trip: dict) -> None: def print_trip(trip: dict) -> None:
trip_part = "The {}:{} {} (???:{}: :{}) service to {} ".format(trip['orgHour'], trip['orgMinute'], trip['lineNumber'], trip['lineCode'], trip['directionCode'], trip['direction']) trip_part = "The {}:{} {} (???:{}: :{}) service to {} ".format(trip['orgHour'], trip['orgMinute'],
if is_cancelled(trip): trip['lineNumber'], trip['lineCode'],
print(trip_part + "is cancelled.") trip['directionCode'], trip['direction'])
elif is_late(trip): if has_realtime(trip):
print(trip_part + "is {} minutes late.".format(trip['delay'])) if is_cancelled(trip):
elif is_early(trip): print(trip_part + "is cancelled.")
print(trip_part + "is {} minutes early.".format(-trip['delay'])) elif is_late(trip):
print(trip_part + "is {} minutes late.".format(trip['delay']))
elif is_early(trip):
print(trip_part + "is {} minutes early.".format(-trip['delay']))
elif is_on_time(trip):
print(trip_part + "is on time.")
else:
print(trip_part + "has no real-time data.")
def get_next_refresh(data: dict): def get_next_refresh(data: dict):
@ -147,37 +166,80 @@ def get_next_refresh(data: dict):
times.sort() times.sort()
for time in times: for time in times:
if (datetime.datetime.fromtimestamp(time) - datetime.datetime.now()) > datetime.timedelta(seconds=30): if (datetime.datetime.fromtimestamp(time) - datetime.datetime.now()) > datetime.timedelta(seconds=30):
if (datetime.datetime.fromtimestamp(time)-datetime.datetime.now()) > datetime.timedelta(minutes=5): if (datetime.datetime.fromtimestamp(time) - datetime.datetime.now()) > datetime.timedelta(minutes=5):
return (datetime.datetime.now()+datetime.timedelta(minutes=5)).timestamp() return (datetime.datetime.now() + datetime.timedelta(minutes=5)).timestamp()
return time return time
return (datetime.datetime.now() + datetime.timedelta(seconds=60)).timestamp() return (datetime.datetime.now() + datetime.timedelta(seconds=60)).timestamp()
def update(): def _make_delay_value_for_sql(value: str or int or None) -> int or None:
if value == '':
value = None
else:
value = int(value)
return value
def _make_status_value_for_sql(trip: dict) -> str:
if not has_realtime(trip):
status = 'no_data'
else:
if is_late(trip):
status = 'late'
elif is_cancelled(trip):
status = 'cancelled'
elif is_early(trip):
status = 'early'
elif is_on_time(trip):
status = 'on_time'
else:
raise ValueError("unknown delay value")
return status
def update(station_id: int):
reply_data = get_data( reply_data = get_data(
make_request_data( make_request_data(
20021002, station_id,
8, 8,
lines=lines_filter lines=lines_filter
) )
) )
reply_data = fixup_data(reply_data)
for trip in reply_data['departureData']: for trip in reply_data['departureData']:
print_trip(trip) print_trip(trip)
return reply_data return reply_data
def wait(): def wait(cxn: mysql.connector.MySQLConnection, station_id: int):
data = update() lines_filter = [
'rbg:70070: :H', # U70 -> Düsseldorf Hbf
'rbg:70070: :R', # U70 -> Krefeld Rheinstr
'rbg:70076: :H', # U76 -> Düsseldorf Hbf
'rbg:70076: :R', # U76 -> Krefeld Rheinstr
]
cur = cxn.cursor()
while True: while True:
data = update(station_id)
for t in data['departureData']:
cur.execute('REPLACE INTO vrr '
'(line_code, direction_code, station_id, orig_datetime, status, delay_value)'
' VALUES (%s, %s, %s, '
'from_unixtime(%s), %s, %s)',
(t['lineCode'], t['directionCode'], station_id,
t['orgFullTime'], _make_status_value_for_sql(t), _make_delay_value_for_sql(t['delay'])
))
cxn.commit()
next_refresh = get_next_refresh(data) next_refresh = get_next_refresh(data)
print("Sleeping until " + datetime.datetime.fromtimestamp(next_refresh).isoformat(), file=sys.stderr) print("Sleeping until " + datetime.datetime.fromtimestamp(next_refresh).isoformat(), file=sys.stderr)
pause.until(next_refresh) pause.until(next_refresh)
data = update()
def main(): def main():
wait() cxn = mysql.connector.connect(user='vrr', password='vrr', host='127.0.0.1', database='vrr')
cursor = cxn.cursor()
cursor.execute(TABLE)
wait(cxn, USE_STATION_ID)
main() main()

View File

@ -1,2 +1,3 @@
requests requests
pause pause
mysql-connector-python