Display next stop just before an event
This commit is contained in:
parent
c85fff1dd9
commit
e380d544d9
26
main.py
26
main.py
@ -60,20 +60,30 @@ def main():
|
||||
moon = WeatherMoonPhaseModule().draw_module(config, 65, 65)
|
||||
image.paste(moon, (0, 113), moon)
|
||||
|
||||
# weekly weather
|
||||
from modules.weather import WeeklyWeatherModule
|
||||
image.paste(WeeklyWeatherModule().draw_module(config, int(480/1.6), 275), (480-int(480/1.6), 255))
|
||||
# ical
|
||||
from modules.ical import IcalModule
|
||||
ical = IcalModule(config)
|
||||
cal = ical.draw_module(config, 480-int(480/1.6), 255)
|
||||
image.paste(cal, (0, 250))
|
||||
|
||||
occuped_space = 0
|
||||
evt_coming = ical.event_coming(config)
|
||||
if evt_coming:
|
||||
from modules.ratp import RATPNextStopModule
|
||||
nstops = RATPNextStopModule().draw_module(config, ["RB/cite+universitaire", "M7/porte+d'italie"], int(480/1.6), 275)
|
||||
image.paste(nstops, (480-int(480/1.6), 255))
|
||||
occuped_space = nstops.height
|
||||
|
||||
if occuped_space < 250:
|
||||
# weekly weather
|
||||
from modules.weather import WeeklyWeatherModule
|
||||
image.paste(WeeklyWeatherModule().draw_module(config, int(480/1.6), 275), (480-int(480/1.6), 255 + occuped_space))
|
||||
|
||||
# RATP weather
|
||||
from modules.ratp import RATPWeatherModule
|
||||
ratp = RATPWeatherModule().draw_module(config, int(480/1.6), 94)
|
||||
image.paste(ratp, (480-int(480/1.6), 155))
|
||||
|
||||
# ical
|
||||
from modules.ical import IcalModule
|
||||
cal = IcalModule(config).draw_module(config, 480-int(480/1.6), 255)
|
||||
image.paste(cal, (0, 250))
|
||||
|
||||
# Toolbar
|
||||
from modules.weather import WeatherToolbarModule
|
||||
image.paste(WeatherToolbarModule().draw_module(config, 480, 50), (0, 530))
|
||||
|
@ -155,6 +155,16 @@ class IcalModule:
|
||||
|
||||
return situations, conjoncturels, start_station, end_station, place
|
||||
|
||||
def event_coming(self, config):
|
||||
now = datetime.now(tz=pytz.timezone('Europe/Paris'))
|
||||
coming = datetime.now(tz=pytz.timezone('Europe/Paris')) + timedelta(minutes=80)
|
||||
|
||||
for evt in self.get_events(config):
|
||||
# Looking only the first event
|
||||
start = evt["start"]
|
||||
return now < start and start < coming
|
||||
return False
|
||||
|
||||
def draw_module(self, config, width, height, line_height=19):
|
||||
now = datetime.now(tz=pytz.timezone('Europe/Paris'))
|
||||
events = self.get_events(config, now + timedelta(weeks=1), now)
|
||||
|
108
modules/ratp.py
108
modules/ratp.py
@ -1,4 +1,5 @@
|
||||
from datetime import datetime, timedelta, timezone
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import urllib.parse
|
||||
@ -61,6 +62,48 @@ class IDFMAPI:
|
||||
self._cached_file = ".ratp-%s.cache"
|
||||
self.cache_time = 5
|
||||
|
||||
def get_schedules(self, mode, line, station, way="A+R"):
|
||||
if mode == "M":
|
||||
mode = "metros"
|
||||
elif mode == "R":
|
||||
mode = "rers"
|
||||
elif mode == "T":
|
||||
mode = "tramways"
|
||||
elif mode == "B":
|
||||
mode = "buses"
|
||||
elif mode == "N":
|
||||
mode = "noctiliens"
|
||||
|
||||
cache_file = self._cached_file % ("schedule-" + mode + "-" + line + "-" + hashlib.md5((mode + line + station + way).encode()).hexdigest())
|
||||
|
||||
req = urllib.request.Request("https://ratp.p0m.fr/api/schedules/%s/%s/%s/%s" % (mode, line, station, way))
|
||||
try:
|
||||
with urllib.request.urlopen(req) as f:
|
||||
with open(cache_file, 'wb') as fd:
|
||||
fd.write(f.read())
|
||||
except ConnectionResetError:
|
||||
pass
|
||||
except urllib.error.URLError:
|
||||
pass
|
||||
except urllib.error.HTTPError:
|
||||
pass
|
||||
|
||||
with open(cache_file) as f:
|
||||
res = json.load(f)
|
||||
|
||||
# Convert time to hours
|
||||
if mode != "rers":
|
||||
now = datetime.fromisoformat(res["_metadata"]["date"])
|
||||
|
||||
for i in range(len(res["result"]["schedules"])):
|
||||
if "message" in res["result"]["schedules"][i]:
|
||||
if res["result"]["schedules"][i]["message"] == "A l'approche" or res["result"]["schedules"][i]["message"] == "A l'arret":
|
||||
res["result"]["schedules"][i]["message"] = now.strftime("%H:%M")
|
||||
elif res["result"]["schedules"][i]["message"].endswith(" mn"):
|
||||
res["result"]["schedules"][i]["message"] = (now + timedelta(minutes=int(res["result"]["schedules"][i]["message"].split(" ")[0]))).strftime("%H:%M")
|
||||
|
||||
return res["result"]["schedules"]
|
||||
|
||||
def get_weather(self):
|
||||
ret = {}
|
||||
|
||||
@ -104,14 +147,14 @@ class IDFMAPI:
|
||||
|
||||
fnt_icon = ImageFont.truetype(IDFMAPI.fnt_RB_path, size-3)
|
||||
|
||||
if mode == "metros":
|
||||
if mode == "M" or mode == "metros":
|
||||
draw.ellipse((0, 0, width, size), fill=fill)
|
||||
elif mode == "tramways":
|
||||
elif mode == "T" or mode == "tramways":
|
||||
if fill == "black":
|
||||
draw.rectangle((0, 0, width, size), fill=fill)
|
||||
draw.rectangle((0, 0, width, 1), fill=fill if fill != "black" else "gray")
|
||||
draw.rectangle((0, size-2, width, size), fill=fill if fill != "black" else "gray")
|
||||
elif mode == "rers":
|
||||
elif mode == "R" or mode == "rers":
|
||||
draw.rounded_rectangle((0, 0, width, size), radius=4, fill=fill)
|
||||
else:
|
||||
draw.rectangle((0, 0, width, size), fill=fill)
|
||||
@ -205,3 +248,62 @@ class RATPWeatherModule:
|
||||
align_y += 10
|
||||
|
||||
return image
|
||||
|
||||
|
||||
class RATPNextStopModule:
|
||||
|
||||
def draw_module(self, config, stops, width, height, line_height=17):
|
||||
image = Image.new('RGB', (width, height), '#fff')
|
||||
draw = ImageDraw.Draw(image)
|
||||
|
||||
fnt_R = ImageFont.truetype(IDFMAPI.fnt_R_path, line_height)
|
||||
fnt_B = ImageFont.truetype(IDFMAPI.fnt_RB_path, line_height)
|
||||
|
||||
align = 0
|
||||
|
||||
api = IDFMAPI()
|
||||
for stop in stops:
|
||||
tmp = stop.split("/")
|
||||
mode = tmp[0][0]
|
||||
line = tmp[0][1:]
|
||||
if 1 < len(tmp) < 3:
|
||||
prep = {}
|
||||
for s in api.get_schedules(mode, line, *tmp[1:]):
|
||||
if s["destination"] not in prep:
|
||||
prep[s["destination"]] = []
|
||||
prep[s["destination"]].append(s)
|
||||
|
||||
icon = IDFMAPI.get_line_icon(mode, line, int(line_height*(1.5 if len(prep.keys()) > 1 else 1)))
|
||||
image.paste(icon, (0, align), icon)
|
||||
|
||||
max_dest = 64
|
||||
for dest, msgs in prep.items():
|
||||
align_x = line_height * 2
|
||||
|
||||
sz = fnt_B.getsize(dest)[0]
|
||||
while sz > max_dest:
|
||||
dest = dest[:-1]
|
||||
sz = fnt_B.getsize(dest)[0]
|
||||
|
||||
draw.text(
|
||||
(align_x, align),
|
||||
dest,
|
||||
font=fnt_B, anchor="lt", fill="black"
|
||||
)
|
||||
|
||||
align_x += max_dest + int(line_height/2.5)
|
||||
|
||||
for msg in [] + msgs + msgs:
|
||||
draw.text(
|
||||
(align_x, align),
|
||||
msg["message"],
|
||||
font=fnt_R, anchor="lt", fill="black"
|
||||
)
|
||||
align_x += fnt_R.getsize(msg["message"])[0] + int(line_height/2.5)
|
||||
|
||||
align += line_height
|
||||
align += int(line_height * 0.33)
|
||||
|
||||
image = image.crop((0,0,width, min(align, height)))
|
||||
|
||||
return image
|
||||
|
Loading…
Reference in New Issue
Block a user