Cleaned up a bunch of typos, removed unused code and made it tidier.

This commit is contained in:
Nahuel Lofeudo 2025-01-12 14:35:04 +00:00
parent d9811d3f91
commit 03d22f47d7
5 changed files with 26 additions and 64 deletions

View File

@ -1,6 +1,6 @@
import datetime
class ArrivalTime():
class ArrivalTime:
""" Represents the arrival times of buses at one of the configured stops """
def __init__(self, stop_id: str, route_id: str, destination: str, due_in_seconds: int, is_added: bool = False) -> None:
@ -14,7 +14,7 @@ class ArrivalTime():
def due_in_minutes(self) -> int:
return int(self.due_in_seconds / 60)
def isDue(self) -> bool:
def is_due(self) -> bool:
return self.due_in_minutes < 1
def due_in_str(self) -> str:

View File

@ -6,7 +6,7 @@ class Config:
with open("config.yaml") as f:
self.config = yaml.safe_load(f.read())
# Pre-load some dictionaries to simplify lookups
# Preload some dictionaries to simplify lookups
self.walk_time_by_stop = {}
for s in self.config.get("stops", []):
self.walk_time_by_stop[str(s["stop_id"])] = s["walk_time"]

View File

@ -10,10 +10,9 @@ import refresh_feed
import requests
import sys
import time
import threading
import zipfile
class GTFSClient():
class GTFSClient:
def __init__(self, feed_url: str, gtfs_r_url: str, gtfs_r_api_key: str,
stop_codes: list[str], routes_for_stops: dict[str, str],
update_queue: queue.Queue, update_interval_seconds: int = 60):
@ -31,10 +30,10 @@ class GTFSClient():
except:
last_mtime = 0
refreshed, new_mtime = refresh_feed.update_local_file_from_url_v1(last_mtime, feed_name, feed_url)
_, new_mtime = refresh_feed.update_local_file_from_url_v1(last_mtime, feed_name, feed_url)
# Load the feed
self.feed = self._read_feed(feed_name, dist_units='km', stop_codes = stop_codes)
self.feed = self._read_feed(feed_name, dist_units='km')
gc.collect()
self.stop_ids = self.__wanted_stop_ids()
self.deltas = {}
@ -46,7 +45,7 @@ class GTFSClient():
if update_interval_seconds and update_queue:
self._update_interval_seconds = update_interval_seconds
def _read_feed(self, path: gk.Path, dist_units: str, stop_codes: list[str]) -> gk.Feed:
def _read_feed(self, path: str, dist_units: str) -> gk.Feed:
"""
NOTE: This helper method was extracted from gtfs_kit.feed to modify it
to only load the stop_times for the stops we are interested in,
@ -55,7 +54,7 @@ class GTFSClient():
This version also reads CSV data straight from the zip file to avoid
wearing out the Pi's SD card.
"""
FILES_TO_LOAD = [
files_to_load = [
# List of feed files to load. stop_times.txt is loaded separately.
'trips.txt',
'routes.txt',
@ -65,8 +64,7 @@ class GTFSClient():
'agency.txt'
]
path = gk.Path(path)
if not path.exists():
if not os.path.exists(path):
raise ValueError("Path {} does not exist".format(path))
print("Loading GTFS feed {}".format(path), file=sys.stderr)
@ -74,7 +72,7 @@ class GTFSClient():
feed_dict = {table: None for table in gk.cs.GTFS_REF["table"]}
with zipfile.ZipFile(path) as z:
for filename in FILES_TO_LOAD:
for filename in files_to_load:
table = filename.split(".")[0]
# read the file
with z.open(filename) as f:
@ -216,20 +214,22 @@ class GTFSClient():
next_buses.drop(index=ids_to_delete, inplace=True)
return next_buses
def __time_to_seconds(self, s: str) -> int:
@staticmethod
def __time_to_seconds(s: str) -> int:
sx = s.split(":")
if len(sx) != 3:
print("Malformed timestamp:", s)
return 0
return int(sx[0]) * 3600 + int(sx[1]) * 60 + int (sx[2])
def __due_in_seconds(self, time_str: str) -> int:
@staticmethod
def __due_in_seconds(time_str: str) -> int:
"""
Returns the number of seconds in the future that the time_str (format hh:mm:ss) is
"""
now = datetime.datetime.now().strftime("%H:%M:%S")
tnow = self.__time_to_seconds(now)
tstop = self.__time_to_seconds(time_str)
tnow = GTFSClient.__time_to_seconds(now)
tstop = GTFSClient.__time_to_seconds(time_str)
if tstop > tnow:
return tstop - tnow
else:
@ -251,8 +251,7 @@ class GTFSClient():
return destination
def __poll_gtfsr_deltas(self) -> list[map, set]:
def __poll_gtfsr_deltas(self) -> tuple[dict, list, list]:
try:
# Poll GTFS-R API
if self.gtfs_r_api_key != "":
@ -260,7 +259,7 @@ class GTFSClient():
response = requests.get(url = self.gtfs_r_url, headers = headers, timeout=(2, 10))
if response.status_code != 200:
print("GTFS-R sent non-OK response: {}\n{}".format(response.status_code, response.text))
return ({}, [], [])
return {}, [], []
deltas_json = json.loads(response.text)
else:
@ -277,7 +276,6 @@ class GTFSClient():
today = datetime.date.today().strftime("%Y%m%d")
for e in deltas_json.get("entity", []):
is_deleted = e.get("is_deleted") or False
try:
trip_update = e.get("trip_update")
trip = trip_update.get("trip")
@ -328,12 +326,12 @@ class GTFSClient():
print("Unsupported action:", trip_action)
except Exception as x:
print("Error parsing GTFS-R entry:", str(e))
raise(x)
raise x
return deltas, canceled_trips, added_stops
except Exception as e:
print("Polling for GTFS-R failed:", str(e))
return ({}, [], [])
return {}, [], []
def get_next_n_buses(self, num_entries: int) -> pd.core.frame.DataFrame:
@ -362,7 +360,7 @@ class GTFSClient():
self.added_stops = added_stops
arrivals = []
# take more entries than we need in case there are cancelations
# take more entries than we need in case there are cancellations
buses = self.get_next_n_buses(15)
for index, bus in buses.iterrows():
@ -374,7 +372,7 @@ class GTFSClient():
arrival = ArrivalTime(stop_id = bus["stop_code"],
route_id = bus["route_short_name"],
destination = bus["trip_headsign"],
due_in_seconds = self.__due_in_seconds(bus["arrival_time"]) + delta,
due_in_seconds = GTFSClient.__due_in_seconds(bus["arrival_time"]) + delta,
is_added = False
)
arrivals.append(arrival)

View File

@ -90,7 +90,7 @@ def update_screen(config: Config, updates: list[ArrivalTime]) -> None:
line = line_num,
route = update.route_id,
destination = update.destination,
time_left = 'Due' if update.isDue() else update.due_in_str(),
time_left = 'Due' if update.is_due() else update.due_in_str(),
time_color = lcd_color,
text_color = COLOR_LCD_GREEN if update.is_added else COLOR_LCD_AMBER
)
@ -146,7 +146,9 @@ def main():
update_queue=update_queue,
update_interval_seconds=config.update_interval_seconds)
# Schedule feed refresh, and force the first one
schedule.every(config.update_interval_seconds).seconds.do(scheduler.refresh)
scheduler.refresh()
# Main event loop
running = True

View File

@ -73,41 +73,3 @@ def update_local_file_from_url_v1(last_mtime, local_file, url):
print('No need to refresh feed.', file=sys.stderr)
return updated, mtime
# v2: download remote file conditionally, with HTTP's If-Modified-Since header.
# This requires the remote server to support both sending the Last-Modified
# header and receiving the If-Modified-Since header.
#
def update_local_file_from_url_v2(last_mtime, local_file, url):
# Get the remote file, but only if it has changed
r = requests.get(url, headers={
'If-Modified-Since': ts_to_httpdate(last_mtime)
})
updated, mtime = False, last_mtime
if r.status_code == requests.codes.ok:
# File is updated and we just downloaded the content
updated = True
# write new content to local file
write_file_with_time(local_file, r.content, mtime)
# Update our notion of the file's last modification time
if 'Last-Modified' in r.headers:
mtime = httpdate_to_ts(r.headers['Last-Modified'])
else:
print('HEY! no Last-Modified header for {}'.format(url),
file=sys.stderr)
elif r.status_code == requests.codes.not_modified:
# Successful call, but no updates to file
print('As of {}, server says {} is the same'.format(time.ctime(), url))
else:
# http request failed
print('HEY! get for {} returned {}'.format(url, r.status_code),
file=sys.stderr)
return updated, mtime