pixelserver2/apps/digi_clock.py

111 lines
3.9 KiB
Python
Raw Normal View History

2024-10-28 17:10:03 +00:00
#!/usr/bin/env python3
import sys
import os
import numpy as np
import pygame
from datetime import datetime
import math
# Displaygröße
Nx = int(sys.argv[1]) # Breite des Displays (z.B. 80)
Ny = int(sys.argv[2]) # Höhe des Displays (z.B. 40)
# Initialize pygame
pygame.init()
pygame.font.init()
# Pfad zur Pixelfont im Verzeichnis "apps"
font_path = os.path.join('.', 'PressStart2P-Regular.ttf') # Pfad zur Schriftart
# Schriftart mit optimierter Größe laden (z.B. 16px bis 20px)
font_size = 16 # Geeignete Schriftgröße wählen
font = pygame.font.Font(font_path, font_size)
clock = pygame.time.Clock()
time_elapsed = 0 # Zeit-Tracker für den Farbverlauf
# Feste Farbe für den Rand (Türkis)
border_color = (64, 224, 208) # RGB-Werte für Türkis
# Funktion zur Berechnung der RGB-Farbe basierend auf der Zeit und der Position des Zeichens
def calculate_color(time_elapsed, position, total_length):
"""Berechnet eine RGB-Farbe basierend auf der verstrichenen Zeit und der Position des Zeichens."""
frequency = 2 * math.pi / total_length # Frequenz für den Regenbogenverlauf
phase_shift = position * frequency # Verschiebung der Phase pro Zeichen
r = int((math.sin(time_elapsed + phase_shift) + 1) * 127.5)
g = int((math.sin(time_elapsed + phase_shift + 2 * math.pi / 3) + 1) * 127.5)
b = int((math.sin(time_elapsed + phase_shift + 4 * math.pi / 3) + 1) * 127.5)
return (r, g, b)
# Funktion zum Rendern des Rahmens
def render_border(display_surface, Nx, Ny, border_color):
"""Zeichnet den Rahmen mit einer festen Farbe."""
# Obere Linie des Rahmens
for x in range(Nx):
display_surface.set_at((x, 0), border_color) # Oben
# Rechte Linie des Rahmens
for y in range(1, Ny - 1):
display_surface.set_at((Nx - 1, y), border_color) # Rechts
# Untere Linie des Rahmens
for x in range(Nx - 1, -1, -1):
display_surface.set_at((x, Ny - 1), border_color) # Unten
# Linke Linie des Rahmens
for y in range(Ny - 2, 0, -1):
display_surface.set_at((0, y), border_color) # Links
# Funktion zum Zeichnen der Uhrzeit
def render_time(display_surface, Nx, Ny, font, current_time, time_elapsed):
"""Zeichnet die aktuelle Uhrzeit mittig auf das Display."""
# Reduzierter Zeichenabstand (85% der Schriftgröße)
character_spacing = font_size * 0.95
# Breite des gesamten Textes berechnen
text_width = len(current_time) * character_spacing
# Horizontale und vertikale Zentrierung
x_offset = (Nx - text_width) // 2
y_offset = (Ny - font_size) // 2
# Zeichnen der Uhrzeit
for i, char in enumerate(current_time):
# Berechne die Farbe für das aktuelle Zeichen
text_color = calculate_color(time_elapsed, i, len(current_time))
# Rendern des Zeichens
text = font.render(char, True, text_color)
text_rect = text.get_rect(topleft=(x_offset + i * character_spacing, y_offset))
# Zeichen auf das Display zeichnen
display_surface.blit(text, text_rect)
# Hauptprogramm zur Anzeige der Uhrzeit
while True:
# Zeit seit Beginn des Programms
time_elapsed += clock.get_time() / 1000.0 # in Sekunden
# Aktuelle Zeit abrufen
now = datetime.now()
current_time = now.strftime("%H:%M") # Uhrzeit im Format HH:MM
# Ein leeres Display für die Uhrzeit erstellen
display_surface = pygame.Surface((Nx, Ny))
display_surface.fill((0, 0, 0)) # Hintergrund schwarz
# Rahmen zeichnen
render_border(display_surface, Nx, Ny, border_color)
# Uhrzeit zeichnen (Aufruf der neuen Funktion)
render_time(display_surface, Nx, Ny, font, current_time, time_elapsed)
# Sicherstellen, dass das Bild die korrekten Dimensionen hat und der Framebuffer vollständig ist
out = pygame.surfarray.array3d(display_surface).transpose((1, 0, 2)).astype(np.uint8).tobytes()
# Framebuffer zum Server senden
os.write(1, out)
clock.tick(30) # 30 FPS für flüssigen Farbverlauf