Refactor to generate the Widgets
This commit is contained in:
parent
381b02a15c
commit
0644bdc68f
86
main.py
86
main.py
@ -27,6 +27,7 @@
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import io
|
import io
|
||||||
import locale
|
import locale
|
||||||
|
import logging
|
||||||
import os.path
|
import os.path
|
||||||
import time
|
import time
|
||||||
|
|
||||||
@ -34,39 +35,52 @@ locale.setlocale(locale.LC_ALL, 'fr_FR.UTF-8')
|
|||||||
|
|
||||||
from PIL import Image, ImageDraw, ImageFont
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
|
|
||||||
|
class WidgetPlacement:
|
||||||
|
|
||||||
|
def __init__(self, module, *args, size, position, **kwargs):
|
||||||
|
self.module = module
|
||||||
|
self.args = args
|
||||||
|
self.size = size
|
||||||
|
self.position = position
|
||||||
|
self.kwargs = kwargs
|
||||||
|
|
||||||
|
|
||||||
def main(only_on_coming_evt=False):
|
def main(only_on_coming_evt=False):
|
||||||
image = Image.new('1', (480, 800), 255)
|
image = Image.new('1', (480, 800), 255)
|
||||||
#image = Image.new('L', (480, 800), 'white')
|
#image = Image.new('L', (480, 800), 'white')
|
||||||
draw = ImageDraw.Draw(image)
|
draw = ImageDraw.Draw(image)
|
||||||
|
|
||||||
|
shape = []
|
||||||
|
|
||||||
import modules
|
import modules
|
||||||
config = modules.Config()
|
config = modules.Config()
|
||||||
|
|
||||||
|
# alerts
|
||||||
|
alerts = []
|
||||||
|
|
||||||
# Weather
|
# Weather
|
||||||
|
|
||||||
# Current Weather
|
# Current Weather
|
||||||
from modules.weather import WeatherJumboCurrentModule
|
from modules.weather import WeatherJumboCurrentModule
|
||||||
image.paste(WeatherJumboCurrentModule().draw_module(config, 480, 150), (0, 0))
|
shape.append(WidgetPlacement(WeatherJumboCurrentModule, size=(480,150), position=(0,0)))
|
||||||
|
|
||||||
# rule
|
# rule
|
||||||
image.paste(modules.RuleModule().draw_module(config, 450, 1), (30, 142))
|
shape.append(WidgetPlacement(modules.RuleModule, size=(450, 1), position=(30, 142)))
|
||||||
|
|
||||||
# pluie
|
# pluie
|
||||||
from modules.weather import WeatherRainModule
|
from modules.weather import WeatherRainModule
|
||||||
image.paste(WeatherRainModule().draw_module(config, 480-int(480/1.6), 94), (0, 155))
|
shape.append(WidgetPlacement(WeatherRainModule, size=(480-int(480/1.6), 94), position=(0, 155)))
|
||||||
|
|
||||||
# moon phase
|
# moon phase
|
||||||
from modules.weather import WeatherMoonPhaseModule
|
from modules.weather import WeatherMoonPhaseModule
|
||||||
moon = WeatherMoonPhaseModule().draw_module(config, 65, 65)
|
shape.append(WidgetPlacement(WeatherMoonPhaseModule, size=(65, 65), position=(0, 113)))
|
||||||
image.paste(moon, (0, 113), moon)
|
|
||||||
|
|
||||||
# ical
|
# ical
|
||||||
from modules.ical import IcalModule
|
from modules.ical import IcalModule
|
||||||
ical = IcalModule(config)
|
shape.append(WidgetPlacement(IcalModule, config, size=(480-int(480/1.6), 255), position=(0, 250)))
|
||||||
cal = ical.draw_module(config, 480-int(480/1.6), 255)
|
|
||||||
image.paste(cal, (0, 250))
|
|
||||||
|
|
||||||
occuped_space = 0
|
occuped_space = 0
|
||||||
|
ical = IcalModule(config)
|
||||||
evt_coming = ical.non_local_event_coming(config) or ical.local_event_ending(config)
|
evt_coming = ical.non_local_event_coming(config) or ical.local_event_ending(config)
|
||||||
if evt_coming:
|
if evt_coming:
|
||||||
from modules.ratp import RATPNextStopModule
|
from modules.ratp import RATPNextStopModule
|
||||||
@ -80,25 +94,51 @@ def main(only_on_coming_evt=False):
|
|||||||
if occuped_space < 250:
|
if occuped_space < 250:
|
||||||
# weekly weather
|
# weekly weather
|
||||||
from modules.weather import WeeklyWeatherModule
|
from modules.weather import WeeklyWeatherModule
|
||||||
image.paste(WeeklyWeatherModule().draw_module(config, int(480/1.6), 275), (480-int(480/1.6), 255 + occuped_space))
|
shape.append(WidgetPlacement(WeeklyWeatherModule, size=(int(480/1.6), 275), position=(480-int(480/1.6), 255 + occuped_space)))
|
||||||
|
|
||||||
# RATP weather
|
# RATP weather
|
||||||
from modules.ratp import RATPWeatherModule
|
from modules.ratp import RATPWeatherModule
|
||||||
ratp = RATPWeatherModule().draw_module(config, int(480/1.6), 94)
|
shape.append(WidgetPlacement(RATPWeatherModule, size=(int(480/1.6), 94), position=(480-int(480/1.6), 155)))
|
||||||
image.paste(ratp, (480-int(480/1.6), 155))
|
alerts.append(RATPWeatherModule)
|
||||||
|
|
||||||
# Toolbar
|
# Toolbar
|
||||||
from modules.weather import WeatherToolbarModule
|
from modules.weather import WeatherToolbarModule
|
||||||
image.paste(WeatherToolbarModule().draw_module(config, 480, 50), (0, 530))
|
shape.append(WidgetPlacement(WeatherToolbarModule, size=(480, 50), position=(0, 530)))
|
||||||
|
|
||||||
# alerts
|
|
||||||
alerts = []
|
|
||||||
|
|
||||||
alerts += [a for a in RATPWeatherModule().gen_alerts()]
|
|
||||||
from modules.sncf import SNCFWeatherModule
|
from modules.sncf import SNCFWeatherModule
|
||||||
alerts += SNCFWeatherModule().gen_alerts("normandie")
|
alerts.append({"module": SNCFWeatherModule, "args": "normandie"})
|
||||||
from modules.weather import WeatherAlerts
|
from modules.weather import WeatherAlerts
|
||||||
alerts += WeatherAlerts().gen_alerts()
|
alerts.append(WeatherAlerts)
|
||||||
|
|
||||||
|
# sunrise/set
|
||||||
|
from modules.weather import WeatherSunModule
|
||||||
|
shape.append(WidgetPlacement(WeatherSunModule, size=(int(480/2), 20), position=(0, 780), start_align=5))
|
||||||
|
|
||||||
|
# Draw shapes
|
||||||
|
last_height = 0
|
||||||
|
last_y = 0
|
||||||
|
for s in shape:
|
||||||
|
try:
|
||||||
|
x,y = s.position
|
||||||
|
if y < 0:
|
||||||
|
y = last_height + last_y
|
||||||
|
width, height = s.size
|
||||||
|
if height < 0:
|
||||||
|
height = 480 - last_height - last_y
|
||||||
|
|
||||||
|
img = s.module(*s.args).draw_module(config, width, height, **s.kwargs)
|
||||||
|
if img.mode == "RGBA":
|
||||||
|
image.paste(img, (x,y), img)
|
||||||
|
else:
|
||||||
|
image.paste(img, (x,y))
|
||||||
|
except BaseException as e:
|
||||||
|
logging.exception(e)
|
||||||
|
alerts.append({
|
||||||
|
"title": "Impossible de dessiner " + s.module.__name__,
|
||||||
|
"description": type(e).__name__ + ": " + (e.message if hasattr(e, 'message') else str(e)),
|
||||||
|
"icon": "wi-earthquake.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
from modules import AlertsModule
|
from modules import AlertsModule
|
||||||
mod = AlertsModule(alerts).draw_module(config, 480, 330)
|
mod = AlertsModule(alerts).draw_module(config, 480, 330)
|
||||||
@ -116,10 +156,6 @@ def main(only_on_coming_evt=False):
|
|||||||
else:
|
else:
|
||||||
image.paste(WeatherTemperatureModule().draw_module(config, 480, 200), (0, 580))
|
image.paste(WeatherTemperatureModule().draw_module(config, 480, 200), (0, 580))
|
||||||
|
|
||||||
# sunrise/set
|
|
||||||
from modules.weather import WeatherSunModule
|
|
||||||
image.paste(WeatherSunModule().draw_module(config, int(480/2), 20, start_align=5), (0, 780))
|
|
||||||
|
|
||||||
fnt = ImageFont.truetype(config.fnt_R_path, 11)
|
fnt = ImageFont.truetype(config.fnt_R_path, 11)
|
||||||
draw.text(
|
draw.text(
|
||||||
(475, 798),
|
(475, 798),
|
||||||
@ -127,17 +163,17 @@ def main(only_on_coming_evt=False):
|
|||||||
fill="black", anchor="rb", font=fnt
|
fill="black", anchor="rb", font=fnt
|
||||||
)
|
)
|
||||||
|
|
||||||
|
logging.info("image generated")
|
||||||
try:
|
try:
|
||||||
import epd7in5
|
import epd7in5
|
||||||
#print("image generated")
|
|
||||||
|
|
||||||
epd = epd7in5.EPD()
|
epd = epd7in5.EPD()
|
||||||
epd.init()
|
epd.init()
|
||||||
#print("initialized")
|
logging.info("initialized")
|
||||||
|
|
||||||
epd.display(epd.getbuffer(image))
|
epd.display(epd.getbuffer(image))
|
||||||
|
|
||||||
#print("time to sleep")
|
logging.info("time to sleep")
|
||||||
epd.sleep()
|
epd.sleep()
|
||||||
|
|
||||||
except:
|
except:
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
|
import logging
|
||||||
from tempfile import NamedTemporaryFile
|
from tempfile import NamedTemporaryFile
|
||||||
|
|
||||||
from PIL import Image, ImageDraw, ImageFont
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
@ -90,6 +91,43 @@ class AlertsModule:
|
|||||||
self.icon_size = 50
|
self.icon_size = 50
|
||||||
self.alerts = alerts
|
self.alerts = alerts
|
||||||
|
|
||||||
|
def draw_alert(self, alert, width, image, draw, fnt_R, fnt_B, align, font_size):
|
||||||
|
if "icon" in alert and alert["icon"] is not None:
|
||||||
|
if callable(alert["icon"]):
|
||||||
|
icon_img = alert["icon"](size=int(font_size*self.icon_size/16))
|
||||||
|
image.paste(icon_img, (int(self.icon_size / 2 - font_size*self.icon_size/32), align))
|
||||||
|
else:
|
||||||
|
color_img = Image.new('RGB', (self.icon_size, self.icon_size), "#fff")
|
||||||
|
icon_img = Image.open("icons/" + alert["icon"]).resize((self.icon_size, self.icon_size))
|
||||||
|
image.paste(color_img, (0, align - 5), icon_img)
|
||||||
|
|
||||||
|
if "title" in alert:
|
||||||
|
draw.text(
|
||||||
|
((self.icon_size if alert["icon"] is not None else 0) - 5, align),
|
||||||
|
alert["title"],
|
||||||
|
fill="white", anchor="lt", font=fnt_B
|
||||||
|
)
|
||||||
|
if "subtitle" in alert and alert["subtitle"]:
|
||||||
|
draw.text(
|
||||||
|
((self.icon_size if alert["icon"] is not None else 0) + (fnt_B.getsize(alert["title"])[0] if "title" in alert else 0), align + 3),
|
||||||
|
alert["subtitle"],
|
||||||
|
fill="white", anchor="lt", font=fnt_R
|
||||||
|
)
|
||||||
|
|
||||||
|
if "title" in alert:
|
||||||
|
align += fnt_B.getsize(alert["title"])[1]
|
||||||
|
|
||||||
|
align += display_longtext(
|
||||||
|
draw,
|
||||||
|
(self.icon_size - 5, align),
|
||||||
|
alert["description"],
|
||||||
|
fill="white", font=fnt_R,
|
||||||
|
maxwidth=width-self.icon_size-5
|
||||||
|
)
|
||||||
|
|
||||||
|
return align + 7
|
||||||
|
|
||||||
|
|
||||||
def draw_module(self, config, width, height, font_size=16):
|
def draw_module(self, config, width, height, font_size=16):
|
||||||
image = Image.new('RGBA', (width, height), "#000")
|
image = Image.new('RGBA', (width, height), "#000")
|
||||||
draw = ImageDraw.Draw(image)
|
draw = ImageDraw.Draw(image)
|
||||||
@ -97,46 +135,32 @@ class AlertsModule:
|
|||||||
|
|
||||||
more_alerts = 0
|
more_alerts = 0
|
||||||
if len(self.alerts) > 0:
|
if len(self.alerts) > 0:
|
||||||
fnt_R = ImageFont.truetype(config.fnt_R_path, font_size)
|
fnt_R = ImageFont.truetype(config.fnt_R_path, font_size)
|
||||||
fnt_B = ImageFont.truetype(config.fnt_RB_path, font_size)
|
fnt_B = ImageFont.truetype(config.fnt_RB_path, font_size)
|
||||||
|
|
||||||
align = 9
|
align = 7
|
||||||
for alert in self.alerts:
|
for alert in self.alerts:
|
||||||
if alert["icon"] is not None:
|
args = []
|
||||||
if callable(alert["icon"]):
|
if isinstance(alert, dict) and "module" in alert:
|
||||||
icon_img = alert["icon"](size=int(font_size*self.icon_size/16))
|
args = alert["args"] if "args" in alert else []
|
||||||
image.paste(icon_img, (int(self.icon_size / 2 - font_size*self.icon_size/32), align))
|
alert = alert["module"]
|
||||||
else:
|
|
||||||
color_img = Image.new('RGB', (self.icon_size, self.icon_size), "#fff")
|
|
||||||
icon_img = Image.open("icons/" + alert["icon"]).resize((self.icon_size, self.icon_size))
|
|
||||||
image.paste(color_img, (0, align), icon_img)
|
|
||||||
|
|
||||||
if "title" in alert:
|
if isinstance(alert, type):
|
||||||
draw.text(
|
try:
|
||||||
((self.icon_size if alert["icon"] is not None else 0) - 5, align),
|
for alert in alert(*args).gen_alerts():
|
||||||
alert["title"],
|
align = self.draw_alert(alert, width, image, draw, fnt_R, fnt_B, align, font_size)
|
||||||
fill="white", anchor="lt", font=fnt_B
|
except BaseException as e:
|
||||||
)
|
logging.exception(e)
|
||||||
if "subtitle" in alert and alert["subtitle"]:
|
self.alerts.append({
|
||||||
draw.text(
|
"title": "Impossible de générer les alertes de " + alert.__name__,
|
||||||
((self.icon_size if alert["icon"] is not None else 0) + (fnt_B.getsize(alert["title"])[0] if "title" in alert else 0), align + 3),
|
"description": type(e).__name__ + ": " + (e.message if hasattr(e, 'message') else str(e)),
|
||||||
alert["subtitle"],
|
"icon": "wi-earthquake.png",
|
||||||
fill="white", anchor="lt", font=fnt_R
|
})
|
||||||
)
|
else:
|
||||||
|
align = self.draw_alert(alert, width, image, draw, fnt_R, fnt_B, align, font_size)
|
||||||
|
|
||||||
if "title" in alert:
|
if align > height:
|
||||||
align += fnt_B.getsize(alert["title"])[1]
|
more_alerts += 1
|
||||||
|
|
||||||
align += display_longtext(
|
|
||||||
draw,
|
|
||||||
(self.icon_size - 5, align),
|
|
||||||
alert["description"],
|
|
||||||
fill="white", font=fnt_R,
|
|
||||||
maxwidth=width-self.icon_size-5
|
|
||||||
)
|
|
||||||
align += 7
|
|
||||||
if align > height:
|
|
||||||
more_alerts += 1
|
|
||||||
|
|
||||||
image = image.crop((0,0,width, min(align, height)))
|
image = image.crop((0,0,width, min(align, height)))
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user