From c937450f92ca7e7f5375d260abc8a019b5dc7923 Mon Sep 17 00:00:00 2001 From: Christoph Haas Date: Sun, 11 Jan 2026 16:20:31 +0100 Subject: [PATCH] many works --- .gitignore | 2 ++ README | 19 +++++++++++++ lib/display.py | 63 +++++++++++++++++++++++++++++++------------- lib/helpers.py | 24 +++++++++++++++++ main.py | 6 ++++- scenes/bitcoin.py | 47 +++++++++++++++++++++++++++++++++ scenes/helloworld.py | 26 +++++++----------- 7 files changed, 151 insertions(+), 36 deletions(-) create mode 100644 .gitignore create mode 100644 README create mode 100644 lib/helpers.py create mode 100644 scenes/bitcoin.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c62f456 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +**pyc + diff --git a/README b/README new file mode 100644 index 0000000..a8b6c9a --- /dev/null +++ b/README @@ -0,0 +1,19 @@ +verschiedene threads zur auswahl, die vom flask gestartet/gestoppt werden können. + +- statisches bild anzeigen und sich beenden +- + +ein task, der die ganze zeit im hintergrund läuft. +- statisches bild anzeigen +- eine Routine + +ein globales bild. (locking?) +die einzelnen + +https://github.com/hzeller/rpi-rgb-led-matrix + +./main.py +curl http://localhost:6000/start/helloworld +feh --reload 0.15 image.png + +https://pypi.org/project/finnhub-python/ diff --git a/lib/display.py b/lib/display.py index 7f71362..3ad61e4 100644 --- a/lib/display.py +++ b/lib/display.py @@ -1,24 +1,51 @@ from rgbmatrix import RGBMatrix, RGBMatrixOptions +from PIL import ImageFont, Image # Das Bild nur speichern. Nicht die LED-Matrix ansteuern. -DEV = True +DEV = False +#DEV = True -if not DEV: - options = RGBMatrixOptions() - options.rows = 64 - options.cols = 64 - options.chain_length = 2 - options.parallel = 1 - options.hardware_mapping = 'regular' # change if using Adafruit HAT, e.g. 'adafruit-hat' - options.gpio_slowdown = 4 # try 2, 4, or even 5 - options.disable_hardware_pulsing = True +matrix = None - matrix = RGBMatrix(options=options) - matrix_width = 64 * options.chain_length - matrix_height = 64 +MATRIX_HEIGHT = 64 +MATRIX_WIDTH = 64 +NUMBER_OF_PANELS = 4 + +class MyMatrix: + def __init__(self): + #self.matrix_width = options.cols * options.chain_length + #self.matrix_height = options.rows + + try: + self.font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-ExtraLight.ttf", 18) + except IOError: + self.font = ImageFont.load_default() + + if not DEV: + options = RGBMatrixOptions() + options.rows = MATRIX_HEIGHT + options.cols = MATRIX_WIDTH + options.chain_length = NUMBER_OF_PANELS + options.parallel = 1 + options.hardware_mapping = 'regular' # change if using Adafruit HAT, e.g. 'adafruit-hat' + options.gpio_slowdown = 5 # try 2, 4, or even 5 + options.disable_hardware_pulsing = True + options.drop_privileges = False + + self.matrix = RGBMatrix(options=options) + + def show(self, image): + """Save the image to disk in DEV mode. Or send it to the LED matrix panel.""" + if DEV: + image.save('image.png') + elif matrix: + self.matrix.SetImage(image) + else: + print("Not in dev mode. And matrix not initialized.") + + def buffer(self): + """Get an image buffer with the right dimensions""" + return Image.new("RGB", (MATRIX_WIDTH * NUMBER_OF_PANELS, MATRIX_HEIGHT)) + +matrix = MyMatrix() -def do(image): - if DEV: - image.save('image.png') - else: - matrix.SetImage(image) diff --git a/lib/helpers.py b/lib/helpers.py new file mode 100644 index 0000000..e04929d --- /dev/null +++ b/lib/helpers.py @@ -0,0 +1,24 @@ +def triangle(image_draw, offset_x, offset_y, direction, width, height): + """Show triangle. Direction is -1 (down) or 1 (up).""" + points = [] + color = None + + if direction==1: + points = [ + (width/2, 0), # n + (0, height), # sw + (width, height) # se + ] + color = (0, 255, 0) # green + else: + points = [ + (width/2, height), # s + (0, 0), # nw + (width,0) # ne + ] + color = (255, 0, 0) # red + + # Draw a filled green triangle + points = [(x+offset_x, y+offset_y) for (x,y) in points] + image_draw.polygon(points, fill=color) + diff --git a/main.py b/main.py index dab96bc..03af24d 100755 --- a/main.py +++ b/main.py @@ -6,6 +6,8 @@ from time import sleep import importlib import os from PIL import Image +#from lib.display import show +import lib.display SCENES_DIR = 'scenes' scenes = {} @@ -48,7 +50,8 @@ def start_animation(scene_name): # Reset stop event and start new thread stop_event.clear() - animation_thread = Thread(target=scenes[scene_name].start, args=(image_buffer, stop_event), daemon=True) + #animation_thread = Thread(target=scenes[scene_name].start, args=(image_buffer, stop_event), daemon=True) + animation_thread = Thread(target=scenes[scene_name].start, args=(stop_event,), daemon=True) animation_thread.start() @app.route("/start/") @@ -66,3 +69,4 @@ def stop(): if __name__ == "__main__": app.run(debug=True, port=6000) + diff --git a/scenes/bitcoin.py b/scenes/bitcoin.py new file mode 100644 index 0000000..6ca873f --- /dev/null +++ b/scenes/bitcoin.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 + +import time +from PIL import Image, ImageDraw +from lib import display + +# Replace with your free Finnhub API key +API_KEY = "d3t8099r01qigeg1s7cgd3t8099r01qigeg1s7d0" +import finnhub +finnhub_client = finnhub.Client(api_key="d3t8099r01qigeg1s7cgd3t8099r01qigeg1s7d0") + +def get_bitcoin_price(): + symbol = "BINANCE:BTCEUR" + data = finnhub_client.quote(symbol) + return data['c'] + +def start(image_buffer, stop_event, text="Hello World!"): + last_price = None + trend = None + while not stop_event.is_set(): + image_buffer = Image.new("RGB", (128, 64)) + draw = ImageDraw.Draw(image_buffer) + + price = get_bitcoin_price() + + # Trend berechnen + if last_price: + if price > last_price: + trend = 1 + elif price < last_price: + trend = -1 + + display.triangle(draw, 0, 0, trend, width=16, height=32) + + text = f"BTC: {price:.0f}€" + + draw.text((20, 0), text, fill=(255, 255, 255), font=display.font) + + display.do(image_buffer) + + last_price = price + # Alle 10 Sekunden einen neuen Kurs holen. Jede Sekunde auf "stop" horchen. + for i in range(1,10): + if stop_event.is_set(): + return + + time.sleep(1) diff --git a/scenes/helloworld.py b/scenes/helloworld.py index abc1c94..d23055a 100644 --- a/scenes/helloworld.py +++ b/scenes/helloworld.py @@ -3,29 +3,21 @@ import io from time import sleep from PIL import Image, ImageDraw, ImageFont -from lib import display +#from lib import display +import lib.display -# TODO: Derive from number of panels and panel size -matrix_height = 64 -matrix_width = 64 * 2 - -# Load a font (use a TTF font file of your choice) -try: - font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 12) -except IOError: - font = ImageFont.load_default() - -def start(image_buffer, stop_event, text="Hello World!"): +def start(stop_event, text="Hello World!"): t = 0 while not stop_event.is_set(): - image_buffer = Image.new("RGB", (128, 64)) + #image_buffer = Image.new("RGB", (lib.display.matrix_width, lib.display.matrix_height)) + image_buffer = lib.display.matrix.buffer() draw = ImageDraw.Draw(image_buffer) - draw.text((0, 0), f"Hello World {t}", fill=(255, 255, 255), font=font) + draw.text((0, 0), f"Hello World {t}", fill=(255, 255, 255), font=lib.display.matrix.font) t += 1 print(t) - #image_buffer.save('image.png') - display.do(image_buffer) + lib.display.matrix.show(image_buffer) + + #sleep(0.2) - sleep(0.2)