168 lines
5.5 KiB
Python
168 lines
5.5 KiB
Python
import numpy as np
|
|
from PIL import Image, ImageDraw, ImageFont
|
|
from time import sleep
|
|
from datetime import datetime
|
|
import logging
|
|
import signal
|
|
import sys
|
|
|
|
from requests import RequestException
|
|
|
|
|
|
from lib.image.rgb565 import convert_rgb_to_rgb565_numpy
|
|
from lib.terminal import disable_cursor, enable_cursor, restore_screen, was_key_pressed
|
|
from lib.lifedata import get_status_data
|
|
|
|
SCREEN_WIDTH_PIXELS = 900
|
|
SCREEN_HEIGHT_PIXELS = 1440
|
|
MARGIN_PIXELS = 15
|
|
|
|
CLOCK_SIZE_MULTIPLIER = (900 - 2 * MARGIN_PIXELS) / 243
|
|
STATUS_SIZE_MULTIPLIER = 2
|
|
|
|
CLOCK_WIDTH_PIXELS = 243
|
|
CLOCK_HEIGHT_PIXELS = 70
|
|
|
|
|
|
def signal_handler(signal, frame):
|
|
logging.info('You pressed Ctrl+C!')
|
|
restore_screen('/dev/tty1')
|
|
enable_cursor('/dev/tty1')
|
|
sys.exit(0)
|
|
|
|
signal.signal(signal.SIGINT, signal_handler)
|
|
|
|
#capture also ctrl+c
|
|
signal.signal(signal.SIGTERM, signal_handler)
|
|
|
|
disable_cursor('/dev/tty1')
|
|
|
|
img = Image.new('RGB', (SCREEN_WIDTH_PIXELS,SCREEN_HEIGHT_PIXELS))
|
|
draw = ImageDraw.Draw(img)
|
|
|
|
|
|
def draw_label(label, x, y):
|
|
label_font = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', CLOCK_HEIGHT_PIXELS // 2)
|
|
label_text_color = (0, 255//2, 0)
|
|
draw.text((x,y), label, font=label_font, fill=label_text_color, anchor='rb')
|
|
|
|
|
|
def draw_clock_digits(x, y, size ,hours, minutes, blink_second, color=(0, 255, 0)):
|
|
"""
|
|
Draws clock digits at the specified position.
|
|
"""
|
|
current_time = f'{hours}:{minutes}'
|
|
# Blink logic
|
|
if ':' in current_time and datetime.now().second % 2 == blink_second:
|
|
current_time = current_time.replace(":", " ")
|
|
|
|
draw_digits(x, y, size, current_time, color)
|
|
|
|
def draw_digits(x, y, size, digits, color=(0, 255, 0)):
|
|
"""
|
|
Draws clock digits at the specified position.
|
|
"""
|
|
font_path = "/usr/share/fonts/truetype/dseg/DSEG14Classic-BoldItalic.ttf"
|
|
font = ImageFont.truetype(font_path, int(CLOCK_HEIGHT_PIXELS * size))
|
|
|
|
draw.text((x, y), digits, font=font, fill=color)
|
|
|
|
def draw_clock():
|
|
x = SCREEN_WIDTH_PIXELS - CLOCK_WIDTH_PIXELS * CLOCK_SIZE_MULTIPLIER - MARGIN_PIXELS
|
|
y = MARGIN_PIXELS
|
|
now = datetime.now()
|
|
hours = now.strftime("%H")
|
|
minutes = now.strftime("%M")
|
|
|
|
draw_clock_digits(x, y, CLOCK_SIZE_MULTIPLIER, hours, minutes, 0)
|
|
#draw_label('Time:', x - MARGIN_PIXELS, y + CLOCK_HEIGHT_PIXELS)
|
|
|
|
|
|
def draw_death_clock():
|
|
x = SCREEN_WIDTH_PIXELS - CLOCK_WIDTH_PIXELS * STATUS_SIZE_MULTIPLIER - MARGIN_PIXELS
|
|
y = MARGIN_PIXELS + CLOCK_HEIGHT_PIXELS * CLOCK_SIZE_MULTIPLIER + 2 * MARGIN_PIXELS
|
|
|
|
death_date = datetime.strptime("08/23/2026", "%m/%d/%Y").date()
|
|
today = datetime.today().date()
|
|
days_until_death = (death_date - today).days
|
|
|
|
color = (0, 255, 0)
|
|
|
|
draw_digits(x, y, STATUS_SIZE_MULTIPLIER, f'{days_until_death:4}', color)
|
|
draw_label('death:', x - MARGIN_PIXELS, y + CLOCK_HEIGHT_PIXELS * STATUS_SIZE_MULTIPLIER)
|
|
|
|
def draw_journal_minutes(status):
|
|
x = SCREEN_WIDTH_PIXELS - CLOCK_WIDTH_PIXELS * STATUS_SIZE_MULTIPLIER - MARGIN_PIXELS
|
|
y = MARGIN_PIXELS + CLOCK_HEIGHT_PIXELS * CLOCK_SIZE_MULTIPLIER + CLOCK_HEIGHT_PIXELS * STATUS_SIZE_MULTIPLIER + 4 * MARGIN_PIXELS
|
|
|
|
elapsed_minutes = status['journal_updated_minutes']
|
|
|
|
hours = elapsed_minutes // 60
|
|
minutes = elapsed_minutes % 60
|
|
|
|
if elapsed_minutes <=15:
|
|
color = (0, 255, 0)
|
|
elif elapsed_minutes <= 20:
|
|
color = (255, 255, 0)
|
|
else:
|
|
color = (255, 0, 0)
|
|
|
|
draw_clock_digits(x, y, STATUS_SIZE_MULTIPLIER, f'{hours:02}', f'{minutes:02}', 1, color)
|
|
draw_label('Journal:', x - MARGIN_PIXELS, y + CLOCK_HEIGHT_PIXELS * STATUS_SIZE_MULTIPLIER)
|
|
|
|
|
|
def draw_fasting(status):
|
|
x = SCREEN_WIDTH_PIXELS - CLOCK_WIDTH_PIXELS * STATUS_SIZE_MULTIPLIER - MARGIN_PIXELS
|
|
y = MARGIN_PIXELS + CLOCK_HEIGHT_PIXELS * CLOCK_SIZE_MULTIPLIER + CLOCK_HEIGHT_PIXELS * STATUS_SIZE_MULTIPLIER * 2 + 6 * MARGIN_PIXELS
|
|
|
|
if 'fasting' in status and status['fasting']:
|
|
label = 'Breakfast'
|
|
date = datetime.strptime(status['fast']['projected_end'], "%Y-%m-%d %H:%M:%S")
|
|
delta = date - datetime.now()
|
|
hours = delta.seconds // 3600
|
|
minutes = (delta.seconds // 60) % 60
|
|
color = (0, 255, 0)
|
|
else:
|
|
label = 'Fasting'
|
|
date = datetime.now().replace(hour=16, minute=0, second=0, microsecond=0)
|
|
if date > datetime.now():
|
|
delta = date - datetime.now()
|
|
color = (0, 255, 0)
|
|
else:
|
|
delta = datetime.now() - date
|
|
color = (255, 0, 0)
|
|
|
|
hours = delta.seconds // 3600
|
|
minutes = (delta.seconds // 60) % 60
|
|
|
|
draw_clock_digits(x, y, STATUS_SIZE_MULTIPLIER, f'{hours:02}', f'{minutes:02}', 1, color)
|
|
draw_label(f'{label}:', x - MARGIN_PIXELS, y + CLOCK_HEIGHT_PIXELS * STATUS_SIZE_MULTIPLIER)
|
|
|
|
def clear_status_area():
|
|
x = 0
|
|
y = MARGIN_PIXELS + CLOCK_HEIGHT_PIXELS * CLOCK_SIZE_MULTIPLIER + 2 * MARGIN_PIXELS
|
|
draw.rectangle([x, y, SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS], fill=(0, 0, 0))
|
|
|
|
|
|
while True:
|
|
draw_clock()
|
|
draw_death_clock()
|
|
try:
|
|
status = get_status_data()
|
|
|
|
draw_journal_minutes(status)
|
|
# draw_fasting(status)
|
|
|
|
except RequestException as e:
|
|
logging.error(f'Error fetching status data: {e}')
|
|
clear_status_area()
|
|
|
|
|
|
rotated_img = img.rotate(90, expand=True)
|
|
img_rgb565 = convert_rgb_to_rgb565_numpy(rotated_img)
|
|
with open('/dev/fb0', 'wb') as fb:
|
|
fb.write(img_rgb565)
|
|
img = Image.new('RGB', (SCREEN_WIDTH_PIXELS,SCREEN_HEIGHT_PIXELS))
|
|
draw = ImageDraw.Draw(img)
|
|
sleep(1)
|