From 9e8a4561bede8e12ae97731386515df0521b381c Mon Sep 17 00:00:00 2001 From: admar Date: Sun, 28 May 2023 23:15:55 +0200 Subject: [PATCH] Added icons for UVI, pollen and AQI --- README.md | 14 ++++---- clock.kv | 15 +++++++++ clock.py | 96 +++++++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 103 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 370d5d5..c106082 100644 --- a/README.md +++ b/README.md @@ -2,17 +2,19 @@ A wake-up light for Raspberry Pi -# To do / ideas in no specific order: -* calendar +# To do +* better icons (especially for sun in reading light / wake-up light) * sensors for indoor air quality -* icons for pollen, outdoor air quality and UV index -* kodi client (via webbrowser?) -* moonshine (esp32 + ledstrip + MQTT) -* bluetooth speaker: https://www.collabora.com/news-and-blog/blog/2022/09/02/using-a-raspberry-pi-as-a-bluetooth-speaker-with-pipewire-wireplumber/ * replace VLC with GStreamer * exit / reboot buttons in settings * start automatically and fullscreen on RPi * read only filesystem? + +# Ideas in no specific order: +* moonshine (esp32 + ledstrip + MQTT) +* calendar +* kodi client (via webbrowser?) +* bluetooth speaker: https://www.collabora.com/news-and-blog/blog/2022/09/02/using-a-raspberry-pi-as-a-bluetooth-speaker-with-pipewire-wireplumber/ * icon when media play is manually enabled? * icon when wake up light is manually enabled? * 2 / 3 finger tap == light on diff --git a/clock.kv b/clock.kv index 615eef2..9478bdf 100644 --- a/clock.kv +++ b/clock.kv @@ -33,6 +33,21 @@ size: self.size pos: self.pos + Image: + id: icon_uvi + size: 0.9*min(root.size), 0.9*min(root.size) + pos_hint: {"center_x": 0.5, "center_y": 0.64} + + Image: + id: icon_pollen + size: 0.9*min(root.size), 0.9*min(root.size) + pos_hint: {"center_x": 0.42, "center_y": 0.5} + + Image: + id: icon_aqi + size: 0.9*min(root.size), 0.9*min(root.size) + pos_hint: {"center_x": 0.58, "center_y": 0.5} + FloatLayout id: face size_hint: None, None diff --git a/clock.py b/clock.py index 4df171e..c0be6f5 100644 --- a/clock.py +++ b/clock.py @@ -15,6 +15,11 @@ from hsluv import hsluv_to_rgb, rgb_to_hsluv import requests import urllib.parse +from kivy.core.image import Image as CoreImage +from kivy.uix.image import Image as kiImage +from PIL import Image, ImageChops +from io import BytesIO + def is_arm(): if (uname()[4][:3] == 'arm') or (uname()[4][:7] == 'aarch64'): return True @@ -606,24 +611,31 @@ class MyClockWidget(FloatLayout): self.draw_list_curr_frame.append(["Color", reference.canvas, color[0], color[1], color[2]]) self.draw_list_curr_frame.append(["Ellipse", reference.canvas, [2 * r, 2 * r], p]) - def draw_precipitation_aqi_expectation(self, x, x_thresholds, location): + def calculate_colors(self, x, x_thresholds): + colors = [] + for i in range(0, len(x)): + idx = 0 + for l in x_thresholds: + if l > x[i]: + break + idx = idx + 1 + + if idx >= len(self.aqi_colors): + idx = len(self.aqi_colors) - 1 + + colors.append(self.aqi_colors[idx]) + return colors + + def draw_precipitation_paqi_expectation(self, x, x_thresholds, location): if len(x) == 0: return face_plate = self.ids["face_plate"] with face_plate.canvas: + colors = self.calculate_colors(x[:12], x_thresholds) + for i in range(0, 12): - idx = 0 - for l in x_thresholds: - if l > x[i]: - break - idx = idx + 1 - - if idx >= len(self.aqi_colors): - idx = len(self.aqi_colors) - 1 - - color = self.aqi_colors[idx] - + color = colors[i] R = face_plate.size[0] / 2 r = R / 10 tmp_x = 0.5 + location*math.sin(2 * math.pi * i/12) @@ -634,10 +646,61 @@ class MyClockWidget(FloatLayout): def draw_precipitation_expectation(self): - self.draw_precipitation_aqi_expectation(self.precipitation, self.precipitation_thresholds, 0.45) + self.draw_precipitation_paqi_expectation(self.precipitation, self.precipitation_thresholds, 0.45) - def draw_aqi_expectation(self): - self.draw_precipitation_aqi_expectation(self.paqi, self.paqi_thresholds, 0.32) + def draw_paqi_expectation(self): + self.draw_precipitation_paqi_expectation(self.paqi, self.paqi_thresholds, 0.32) + + def draw_icon_helper(self, color, img_source, label): + c = (int(256 * color[0]), int(256 * color[1]), int(256 * color[2]), int(256)) + tmp = Image.new('RGBA', img_source.size, color = c) + img_modified = ImageChops.multiply(tmp, img_source) + + data = BytesIO() + img_modified.save(data, format='png') + data.seek(0) + im = CoreImage(BytesIO(data.read()), ext='png') + + icon = self.ids[label] + icon.texture = im.texture + + def draw_icon_uvi(self): + if hasattr(self, 'image_uvi') == False: + self.image_uvi = Image.open("icons/uvi.png") + + colors = self.calculate_colors(self.uvi[:1], self.uvi_thresholds) + color = colors[0] + + if hasattr(self, 'uvi_color_prev') == False or self.uvi_color_prev != color: + self.uvi_color_prev = color + self.draw_icon_helper(color, self.image_uvi, "icon_uvi") + + def draw_icon_pollen(self): + if hasattr(self, 'image_pollen') == False: + self.image_pollen = Image.open("icons/pollen.png") + + colors = self.calculate_colors(self.pollen[:12], self.pollen_thresholds) + color = colors[self.pollen.index(max(self.pollen[:12]))] + + if hasattr(self, 'pollen_color_prev') == False or self.pollen_color_prev != color: + self.pollen_color_prev = color + self.draw_icon_helper(color, self.image_pollen, "icon_pollen") + + def draw_icon_aqi(self): + if hasattr(self, 'image_aqi') == False: + self.image_aqi = Image.open("icons/aqi.png") + + colors = self.calculate_colors(self.aqi[:12], self.aqi_thresholds) + color = colors[self.aqi.index(max(self.aqi[:12]))] + + if hasattr(self, 'aqi_color_prev') == False or self.aqi_color_prev != color: + self.aqi_color_prev = color + self.draw_icon_helper(color, self.image_aqi, "icon_aqi") + + def draw_icons(self): + self.draw_icon_uvi() + self.draw_icon_pollen() + self.draw_icon_aqi() def draw_face(self): self.draw_numbers() @@ -660,7 +723,8 @@ class MyClockWidget(FloatLayout): self.face_numbers[i].text = "" self.draw_precipitation_expectation() - self.draw_aqi_expectation() + self.draw_paqi_expectation() + self.draw_icons() else: with face_plate.canvas: color = self.theme.color_numbers