This commit is contained in:
Remy Moll
2022-01-01 14:51:13 +01:00
parent bf4b02902b
commit f468332843
52 changed files with 3272 additions and 3419 deletions

View File

@@ -1,178 +1,178 @@
from PIL import Image, ImageDraw, ImageFont
import numpy as np
import datetime
import time
# bulky hard-coded values:
from . import shapes
digits = shapes.digits
weather_categories = shapes.weather_categories
digit_position = [[2,4], [2,10], [9,4], [9,10]]
days = np.append(np.zeros((15,16)), np.array([0,1,0,1,0,1,0,1,0,1,0,1,1,0,1,1])).reshape((16,16))
class MatrixOperations():
"""Helper functions to generate frequently-used images"""
def __init__(self, shape=[16,16]):
self.shape = shape
# shape is going to be (16,32) for the moment
self.primary = [200, 200, 200]
self.secondary = [10, 200, 10]
self.error = [200, 10, 10]
def time_converter(self, top="", bottom=""):
"""Converts 4-digit time to a 16x16 pixel-matrix
returns: np.array"""
# nshape = (self.shape[0], int(self.shape[1]/2))
nshape = (16, 16)
pixels = np.zeros(nshape, dtype=np.uint8)
if bottom == "" or top == "":
top = datetime.datetime.now().strftime("%H")
bottom = datetime.datetime.now().strftime("%M")
if len(top) < 2:
top = "0" * (2 - len(top)) + top
if len(bottom) < 2:
bottom = "0" * (2 - len(bottom)) + bottom
if ("-" in top and len(top) > 2) or ("-" in bottom and len(bottom) > 2):
time_split = 4*["-"]
elif "error" in top and "error" in bottom:
time_split = 4*["error"]
else:
time_split = [i for i in top] + [i for i in bottom]
if "-1" in top and len(top) != 2:
time_split = ["-1", top[-1]] + [i for i in bottom]
if "-1" in bottom and len(bottom) != 2:
time_split = [i for i in top] + ["-1", bottom[-1]]
for i in range(4):
x = digit_position[i][0]
y = digit_position[i][1]
number = digits[time_split[i]]
pixels[x: x + 5, y: y + 3] = np.array(number)
return pixels
def date_converter(self):
# nshape = (self.shape[0], int(self.shape[1]/2))
nshape = (16, 16)
today = datetime.datetime.today()
weekday = datetime.datetime.weekday(today)
# size of the reduced array according to weekday
size = [2,4,6,8,10,13,16]
pixels = days.copy() #base color background
lrow = np.append(pixels[15,:size[weekday]], [0 for i in range(16 - size[weekday])])
lrow = np.append(np.zeros((15,16)), lrow).reshape(nshape)
pixels += lrow
return pixels
def weather_converter(self, name):
"""Fills one half of the screen with weather info."""
# nshape = (self.shape[0], int(self.shape[1]/2))
nshape = (16, 16)
result = np.zeros(nshape)
cwd = __file__.replace("\\","/") # for windows
cwd = cwd.rsplit("/", 1)[0] # the current working directory (where this file is)
if len(cwd) == 0:
cwd = "."
icon_spritesheet = cwd + "/weather-icons.bmp"
icons = Image.open(icon_spritesheet)
icons_full = np.array(icons)
icon_loc = ["sun","moon","sun and clouds", "moon and clouds", "cloud","fog and clouds","2 clouds", "3 clouds", "rain and cloud", "rain and clouds", "rain and cloud and sun", "rain and cloud and moon", "thunder and cloud", "thunder and cloud and moon", "snow and cloud", "snow and cloud and moon", "fog","fog night"]
#ordered 1 2 \n 3 4 \ 5 5 ...
if name == "":
name = "error"
name = weather_categories[name]
try:
iy, ix = int(icon_loc.index(name)/2), icon_loc.index(name)%2
# x and y coords
except:
return np.zeros((*nshape,3))
icon_single = icons_full[16*iy:16*(iy + 1),16*ix:16*(ix + 1),...]
return icon_single
def matrix_add_depth(self, matrix, colors = []):
"""transforms a 2d-array with 0,1,2 to a 3d-array with the rgb values for primary and secondary color"""
c1 = self.primary
c2 = self.secondary
c3 = self.error
if len(colors) > 0:
c1 = colors[0]
if len(colors) > 1:
c2 = colors[1]
if len(colors) > 2:
c3 = colors[2]
if len(colors) > 3:
print("Too many colors")
r3 = np.zeros((matrix.shape[0],matrix.shape[1],3),dtype=int)
for i in range(matrix.shape[0]):
for j in range(matrix.shape[1]):
t = int(matrix[i, j])
if t == 0:
r3[i, j, :] = [0,0,0]
elif t == 1:
r3[i, j, :] = c1
elif t == 2:
r3[i, j, :] = c2
else:
r3[i, j, :] = c3
return r3
def clock_face(self, weather):
"""weather as a dict"""
hour = self.time_converter()
day = self.date_converter()
face1 = hour + day
# time + date:
face1_3d = self.matrix_add_depth(face1)
# weather icons
face2_3d = self.weather_converter(weather["weather"])
# weather temps
face3 = self.time_converter(top=str(weather["low"]), bottom=str(weather["high"]))
face3 = np.concatenate((face3[:8,...],2*face3[8:,...]))
face3_3d = self.matrix_add_depth(face3,[[0, 102, 255],[255, 102, 0]])
return [face1_3d, face2_3d, face3_3d]
def text_converter(self, text, height, color):
"""Converts a text to a pixel-matrix
returns: np.array((16, x, 3))"""
font = ImageFont.truetype("verdanab.ttf", height)
size = font.getsize(text)
img = Image.new("1",size,"black")
draw = ImageDraw.Draw(img)
draw.text((0, 0), text, "white", font=font)
pixels = np.array(img, dtype=np.uint8)
pixels3d = self.matrix_add_depth(pixels, color)
return pixels3d
def get_fallback(self):
hour = self.time_converter()
day = self.date_converter()
face1 = hour + day
face1_3d = self.matrix_add_depth(face1)
face2_3d = face3_3d = np.zeros((16,16,3))
from PIL import Image, ImageDraw, ImageFont
import numpy as np
import datetime
import time
# bulky hard-coded values:
from . import shapes
digits = shapes.digits
weather_categories = shapes.weather_categories
digit_position = [[2,4], [2,10], [9,4], [9,10]]
days = np.append(np.zeros((15,16)), np.array([0,1,0,1,0,1,0,1,0,1,0,1,1,0,1,1])).reshape((16,16))
class MatrixOperations():
"""Helper functions to generate frequently-used images"""
def __init__(self, shape=[16,16]):
self.shape = shape
# shape is going to be (16,32) for the moment
self.primary = [200, 200, 200]
self.secondary = [10, 200, 10]
self.error = [200, 10, 10]
def time_converter(self, top="", bottom=""):
"""Converts 4-digit time to a 16x16 pixel-matrix
returns: np.array"""
# nshape = (self.shape[0], int(self.shape[1]/2))
nshape = (16, 16)
pixels = np.zeros(nshape, dtype=np.uint8)
if bottom == "" or top == "":
top = datetime.datetime.now().strftime("%H")
bottom = datetime.datetime.now().strftime("%M")
if len(top) < 2:
top = "0" * (2 - len(top)) + top
if len(bottom) < 2:
bottom = "0" * (2 - len(bottom)) + bottom
if ("-" in top and len(top) > 2) or ("-" in bottom and len(bottom) > 2):
time_split = 4*["-"]
elif "error" in top and "error" in bottom:
time_split = 4*["error"]
else:
time_split = [i for i in top] + [i for i in bottom]
if "-1" in top and len(top) != 2:
time_split = ["-1", top[-1]] + [i for i in bottom]
if "-1" in bottom and len(bottom) != 2:
time_split = [i for i in top] + ["-1", bottom[-1]]
for i in range(4):
x = digit_position[i][0]
y = digit_position[i][1]
number = digits[time_split[i]]
pixels[x: x + 5, y: y + 3] = np.array(number)
return pixels
def date_converter(self):
# nshape = (self.shape[0], int(self.shape[1]/2))
nshape = (16, 16)
today = datetime.datetime.today()
weekday = datetime.datetime.weekday(today)
# size of the reduced array according to weekday
size = [2,4,6,8,10,13,16]
pixels = days.copy() #base color background
lrow = np.append(pixels[15,:size[weekday]], [0 for i in range(16 - size[weekday])])
lrow = np.append(np.zeros((15,16)), lrow).reshape(nshape)
pixels += lrow
return pixels
def weather_converter(self, name):
"""Fills one half of the screen with weather info."""
# nshape = (self.shape[0], int(self.shape[1]/2))
nshape = (16, 16)
result = np.zeros(nshape)
cwd = __file__.replace("\\","/") # for windows
cwd = cwd.rsplit("/", 1)[0] # the current working directory (where this file is)
if len(cwd) == 0:
cwd = "."
icon_spritesheet = cwd + "/weather-icons.bmp"
icons = Image.open(icon_spritesheet)
icons_full = np.array(icons)
icon_loc = ["sun","moon","sun and clouds", "moon and clouds", "cloud","fog and clouds","2 clouds", "3 clouds", "rain and cloud", "rain and clouds", "rain and cloud and sun", "rain and cloud and moon", "thunder and cloud", "thunder and cloud and moon", "snow and cloud", "snow and cloud and moon", "fog","fog night"]
#ordered 1 2 \n 3 4 \ 5 5 ...
if name == "":
name = "error"
name = weather_categories[name]
try:
iy, ix = int(icon_loc.index(name)/2), icon_loc.index(name)%2
# x and y coords
except:
return np.zeros((*nshape,3))
icon_single = icons_full[16*iy:16*(iy + 1),16*ix:16*(ix + 1),...]
return icon_single
def matrix_add_depth(self, matrix, colors = []):
"""transforms a 2d-array with 0,1,2 to a 3d-array with the rgb values for primary and secondary color"""
c1 = self.primary
c2 = self.secondary
c3 = self.error
if len(colors) > 0:
c1 = colors[0]
if len(colors) > 1:
c2 = colors[1]
if len(colors) > 2:
c3 = colors[2]
if len(colors) > 3:
print("Too many colors")
r3 = np.zeros((matrix.shape[0],matrix.shape[1],3),dtype=int)
for i in range(matrix.shape[0]):
for j in range(matrix.shape[1]):
t = int(matrix[i, j])
if t == 0:
r3[i, j, :] = [0,0,0]
elif t == 1:
r3[i, j, :] = c1
elif t == 2:
r3[i, j, :] = c2
else:
r3[i, j, :] = c3
return r3
def clock_face(self, weather):
"""weather as a dict"""
hour = self.time_converter()
day = self.date_converter()
face1 = hour + day
# time + date:
face1_3d = self.matrix_add_depth(face1)
# weather icons
face2_3d = self.weather_converter(weather["weather"])
# weather temps
face3 = self.time_converter(top=str(weather["low"]), bottom=str(weather["high"]))
face3 = np.concatenate((face3[:8,...],2*face3[8:,...]))
face3_3d = self.matrix_add_depth(face3,[[0, 102, 255],[255, 102, 0]])
return [face1_3d, face2_3d, face3_3d]
def text_converter(self, text, height, color):
"""Converts a text to a pixel-matrix
returns: np.array((16, x, 3))"""
font = ImageFont.truetype("verdanab.ttf", height)
size = font.getsize(text)
img = Image.new("1",size,"black")
draw = ImageDraw.Draw(img)
draw.text((0, 0), text, "white", font=font)
pixels = np.array(img, dtype=np.uint8)
pixels3d = self.matrix_add_depth(pixels, color)
return pixels3d
def get_fallback(self):
hour = self.time_converter()
day = self.date_converter()
face1 = hour + day
face1_3d = self.matrix_add_depth(face1)
face2_3d = face3_3d = np.zeros((16,16,3))
return [face1_3d, face2_3d, face3_3d]

View File

@@ -1,103 +1,103 @@
import numpy as np
digits = {
"1" : np.array([
[0,0,1],
[0,0,1],
[0,0,1],
[0,0,1],
[0,0,1]]),
"2" : np.array([
[1,1,1],
[0,0,1],
[1,1,1],
[1,0,0],
[1,1,1]]),
"3" : np.array([
[1,1,1],
[0,0,1],
[1,1,1],
[0,0,1],
[1,1,1]]),
"4" : np.array([
[1,0,1],
[1,0,1],
[1,1,1],
[0,0,1],
[0,0,1]]),
"5" : np.array([
[1,1,1],
[1,0,0],
[1,1,1],
[0,0,1],
[1,1,1]]),
"6" : np.array([
[1,1,1],
[1,0,0],
[1,1,1],
[1,0,1],
[1,1,1]]),
"7" : np.array([
[1,1,1],
[0,0,1],
[0,0,1],
[0,0,1],
[0,0,1]]),
"8" : np.array([
[1,1,1],
[1,0,1],
[1,1,1],
[1,0,1],
[1,1,1]]),
"9" : np.array([
[1,1,1],
[1,0,1],
[1,1,1],
[0,0,1],
[1,1,1]]),
"0" : np.array([
[1,1,1],
[1,0,1],
[1,0,1],
[1,0,1],
[1,1,1]]),
"-" : np.array([
[0,0,0],
[0,0,0],
[1,1,1],
[0,0,0],
[0,0,0]]),
"-1" : np.array([
[0,0,1],
[0,0,1],
[1,1,1],
[0,0,1],
[0,0,1]]),
"error" : np.array([
[1,0,1],
[1,0,1],
[0,1,0],
[1,0,1],
[1,0,1]]),
}
weather_categories = {
"Clouds": "cloud",
"Rain": "rain and cloud",
"Thunderstorm": "thunder and cloud",
"Drizzle": "rain and cloud",
"Snow": "snow and cloud",
"Clear": "sun",
"Mist": "fog and clouds",
"Smoke": "Smoke",
"Haze": "Haze",
"Dust": "Dust",
"Fog": "fog",
"Sand": "Sand",
"Dust": "Dust",
"Ash": "Ash",
"Squal": "Squal",
"Tornado": "Tornado",
"error" : "moon"
import numpy as np
digits = {
"1" : np.array([
[0,0,1],
[0,0,1],
[0,0,1],
[0,0,1],
[0,0,1]]),
"2" : np.array([
[1,1,1],
[0,0,1],
[1,1,1],
[1,0,0],
[1,1,1]]),
"3" : np.array([
[1,1,1],
[0,0,1],
[1,1,1],
[0,0,1],
[1,1,1]]),
"4" : np.array([
[1,0,1],
[1,0,1],
[1,1,1],
[0,0,1],
[0,0,1]]),
"5" : np.array([
[1,1,1],
[1,0,0],
[1,1,1],
[0,0,1],
[1,1,1]]),
"6" : np.array([
[1,1,1],
[1,0,0],
[1,1,1],
[1,0,1],
[1,1,1]]),
"7" : np.array([
[1,1,1],
[0,0,1],
[0,0,1],
[0,0,1],
[0,0,1]]),
"8" : np.array([
[1,1,1],
[1,0,1],
[1,1,1],
[1,0,1],
[1,1,1]]),
"9" : np.array([
[1,1,1],
[1,0,1],
[1,1,1],
[0,0,1],
[1,1,1]]),
"0" : np.array([
[1,1,1],
[1,0,1],
[1,0,1],
[1,0,1],
[1,1,1]]),
"-" : np.array([
[0,0,0],
[0,0,0],
[1,1,1],
[0,0,0],
[0,0,0]]),
"-1" : np.array([
[0,0,1],
[0,0,1],
[1,1,1],
[0,0,1],
[0,0,1]]),
"error" : np.array([
[1,0,1],
[1,0,1],
[0,1,0],
[1,0,1],
[1,0,1]]),
}
weather_categories = {
"Clouds": "cloud",
"Rain": "rain and cloud",
"Thunderstorm": "thunder and cloud",
"Drizzle": "rain and cloud",
"Snow": "snow and cloud",
"Clear": "sun",
"Mist": "fog and clouds",
"Smoke": "Smoke",
"Haze": "Haze",
"Dust": "Dust",
"Fog": "fog",
"Sand": "Sand",
"Dust": "Dust",
"Ash": "Ash",
"Squal": "Squal",
"Tornado": "Tornado",
"error" : "moon"
}

View File

@@ -1,30 +1,30 @@
from threading import Timer
import time
class RepeatedTimer(object):
def __init__(self, interval, function, *args, **kwargs):
self._timer = None
self.interval = interval
self.function = function
self.args = args
self.kwargs = kwargs
self.is_running = False
self.next_call = time.time()
self.start()
def _run(self):
self.is_running = False
self.start()
self.function(*self.args, **self.kwargs)
def start(self):
if not self.is_running:
self.next_call += self.interval
self._timer = Timer(self.next_call - time.time(), self._run)
self._timer.start()
self.is_running = True
def stop(self):
self._timer.cancel()
self.is_running = False
from threading import Timer
import time
class RepeatedTimer(object):
def __init__(self, interval, function, *args, **kwargs):
self._timer = None
self.interval = interval
self.function = function
self.args = args
self.kwargs = kwargs
self.is_running = False
self.next_call = time.time()
self.start()
def _run(self):
self.is_running = False
self.start()
self.function(*self.args, **self.kwargs)
def start(self):
if not self.is_running:
self.next_call += self.interval
self._timer = Timer(self.next_call - time.time(), self._run)
self._timer.start()
self.is_running = True
def stop(self):
self._timer.cancel()
self.is_running = False