Refactor alerts

This commit is contained in:
nemunaire 2022-08-14 15:32:52 +02:00
parent 084dce621c
commit 606895f63b
3 changed files with 111 additions and 87 deletions

15
main.py
View File

@ -68,16 +68,21 @@ def main():
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), 305)) image.paste(WeeklyWeatherModule().draw_module(config, int(480/1.6), 275), (480-int(480/1.6), 305))
# alerts
from modules.weather import WeatherAlertsModule
mod = WeatherAlertsModule().draw_module(config, 480, 200)
image.paste(mod, (0, 580-mod.height-5), mod)
# RATP weather # RATP weather
from modules.ratp import RATPWeatherModule from modules.ratp import RATPWeatherModule
ratp = RATPWeatherModule().draw_module(config, int(480/1.6), 94) ratp = RATPWeatherModule().draw_module(config, int(480/1.6), 94)
image.paste(ratp, (480-int(480/1.6), 205)) image.paste(ratp, (480-int(480/1.6), 205))
# alerts
alerts = []
from modules.weather import WeatherAlerts
alerts += WeatherAlerts().gen_alerts()
from modules import AlertsModule
mod = AlertsModule(alerts).draw_module(config, 480, 200)
image.paste(mod, (0, 580-mod.height-5), mod)
# températures # températures
from modules.weather import WeatherTemperatureModule from modules.weather import WeatherTemperatureModule
image.paste(WeatherTemperatureModule().draw_module(config, 480, 200), (0, 580)) image.paste(WeatherTemperatureModule().draw_module(config, 480, 200), (0, 580))

View File

@ -1,7 +1,7 @@
import os import os
from tempfile import NamedTemporaryFile from tempfile import NamedTemporaryFile
from PIL import Image, ImageDraw from PIL import Image, ImageDraw, ImageFont
class Config: class Config:
@ -58,6 +58,7 @@ class Config:
self.charts_opts = {'style': self.pygal_custom_style, 'show_legend': False, 'margin_right': 7, 'margin_left': 2, 'margin_bottom': 4, 'margin_top': 1} self.charts_opts = {'style': self.pygal_custom_style, 'show_legend': False, 'margin_right': 7, 'margin_left': 2, 'margin_bottom': 4, 'margin_top': 1}
class RuleModule: class RuleModule:
def __init__(self): def __init__(self):
@ -70,3 +71,86 @@ class RuleModule:
draw.rectangle((int((1-self.coeff) * width), 0, int(self.coeff * width), height), fill="black") draw.rectangle((int((1-self.coeff) * width), 0, int(self.coeff * width), height), fill="black")
return image return image
class AlertsModule:
def __init__(self, alerts=[]):
self.icon_size = 50
self.alerts = alerts
def draw_module(self, config, width, height):
image = Image.new('RGBA', (width, height), "#000")
draw = ImageDraw.Draw(image)
align = 0
if len(self.alerts) > 0:
fnt_R = ImageFont.truetype(config.fnt_R_path, 16)
fnt_B = ImageFont.truetype(config.fnt_RB_path, 16)
align = 9
for alert in self.alerts:
if alert["icon"] is not None:
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)
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], align + 3),
alert["subtitle"],
fill="white", anchor="lt", font=fnt_R
)
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
)
align += 7
image = image.crop((0,0,width, align))
return image
def display_longtext(draw, pos, text, font, anchor="lt", maxwidth=9999, **kwargs):
x,y = pos
lines = []
mainlines = text.split("\n")
for line in mainlines:
words = line.split(" ")
cur = ""
while len(words) > 0:
added = (" " if len(cur) > 0 else "") + words[0]
width = font.getsize(cur + added)[0]
if width < maxwidth:
words.pop(0)
cur += added
else:
lines.append(cur)
cur = words.pop(0)
if len(cur) > 0:
lines.append(cur)
line_height = font.getsize("test")[1]
if anchor[1] == "m":
y -= line_height * len(lines) / 2
elif anchor[1] == "b":
y -= line_height * len(lines)
for line in lines:
draw.text((x,y), line, font=font, anchor=anchor, **kwargs)
y += line_height
return line_height * len(lines)

View File

@ -6,6 +6,7 @@ from PIL import Image, ImageDraw, ImageFont
import pygal import pygal
from . import display_longtext
from .weather_api import WeatherAPI from .weather_api import WeatherAPI
def draw_format_infos(infos, width, height, fnt_R, fnt_B, label_margin, align_height=0, margin_bf_first=True, **kwargs): def draw_format_infos(infos, width, height, fnt_R, fnt_B, label_margin, align_height=0, margin_bf_first=True, **kwargs):
@ -39,39 +40,6 @@ def draw_format_infos(infos, width, height, fnt_R, fnt_B, label_margin, align_he
return image return image
def display_longtext(draw, pos, text, font, anchor="lt", maxwidth=9999, **kwargs):
x,y = pos
lines = []
mainlines = text.split("\n")
for line in mainlines:
words = line.split(" ")
cur = ""
while len(words) > 0:
added = (" " if len(cur) > 0 else "") + words[0]
width = font.getsize(cur + added)[0]
if width < maxwidth:
words.pop(0)
cur += added
else:
lines.append(cur)
cur = words.pop(0)
if len(cur) > 0:
lines.append(cur)
line_height = font.getsize("test")[1]
if anchor[1] == "m":
y -= line_height * len(lines) / 2
elif anchor[1] == "b":
y -= line_height * len(lines)
for line in lines:
draw.text((x,y), line, font=font, anchor=anchor, **kwargs)
y += line_height
return line_height * len(lines)
class WeatherToolbarModule: class WeatherToolbarModule:
def __init__(self): def __init__(self):
@ -330,24 +298,13 @@ class WeeklyWeatherModule:
return image return image
class WeatherAlertsModule: class WeatherAlerts:
def __init__(self): def gen_alerts(self):
self.icon_size = 50 alerts = []
def draw_module(self, config, width, height):
image = Image.new('RGBA', (width, height), "#000")
draw = ImageDraw.Draw(image)
align = 0
if WeatherAPI().has_alerts(): if WeatherAPI().has_alerts():
alerts = WeatherAPI().get_alerts() for alert in WeatherAPI().get_alerts():
fnt_R = ImageFont.truetype(config.fnt_R_path, 16)
fnt_B = ImageFont.truetype(config.fnt_RB_path, 16)
align = 9
for alert in alerts:
if alert["severity"] == "watch" or alert["title"].startswith("Moderate"): if alert["severity"] == "watch" or alert["title"].startswith("Moderate"):
icon = "wi-small-craft-advisory.png" icon = "wi-small-craft-advisory.png"
elif alert["severity"] == "warning": elif alert["severity"] == "warning":
@ -355,43 +312,21 @@ class WeatherAlertsModule:
else: else:
icon = None icon = None
if icon is not None:
color_img = Image.new('RGB', (self.icon_size, self.icon_size), "#fff")
icon_img = Image.open("icons/" + icon).resize((self.icon_size, self.icon_size))
image.paste(color_img, (0, align - 5), icon_img)
draw.text(
(self.icon_size - 5, align),
alert["title"],
fill="white", anchor="lt", font=fnt_B
)
startTime = WeatherAPI().read_timestamp(alert["time"]) startTime = WeatherAPI().read_timestamp(alert["time"])
endTime = WeatherAPI().read_timestamp(alert["expires"]) endTime = WeatherAPI().read_timestamp(alert["expires"])
# Show alert timing if under a day # Show alert timing if under a day
if startTime.hour != endTime.hour: if startTime.hour != endTime.hour:
draw.text( subtitle = startTime.strftime(("%x " if startTime.day != datetime.now().day else "") + "%X") + " - " + endTime.strftime(("%x " if startTime.day != endTime.day else "") + "%X")
(self.icon_size + fnt_B.getsize(alert["title"])[0], align + 3),
startTime.strftime(("%x " if startTime.day != datetime.now().day else "") + "%X") + " - " + endTime.strftime(("%x " if startTime.day != endTime.day else "") + "%X"),
fill="white", anchor="lt", font=fnt_R
)
elif startTime.day != datetime.now().day: elif startTime.day != datetime.now().day:
draw.text( subtitle = startTime.strftime("%x")
(self.icon_size + fnt_B.getsize(alert["title"])[0], align + 3), else:
startTime.strftime("%x"), subtitle = ""
fill="white", anchor="lt", font=fnt_R
)
align += fnt_B.getsize(alert["title"])[1] alerts.append({
"icon": icon,
"title": alert["title"],
"subtitle": subtitle,
"description": alert["description"],
})
align += display_longtext( return alerts
draw,
(self.icon_size - 5, align),
alert["description"],
fill="white", font=fnt_R,
maxwidth=width-self.icon_size-5
)
align += 7
image = image.crop((0,0,width, align))
return image