📊 Wie es funktioniert
1
RFID-Scan
NFC-Karte an RFID-Reader halten. Serial-Port-Thread liest die Tag-ID in Echtzeit.
→
2
Lookup
JSON-Config checkt: Ist dieser Tag mit einem Video oder YouTube-Link verknüpft?
→
3
Wiedergabe
YouTube: Firefox-Kiosk mit Embed-HTML. Lokal: VLC --fullscreen --play-and-exit.
→
4
Wechsel
Gleiche Karte = Stop. Andere Karte = aktuelles Video beenden, neues starten.
💻 Echter Code aus dem Projekt
RFID-Listener-Thread: Serielle Schnittstelle mit Karten-Logik
import serial, threading, subprocess, json, tempfile
class RFIDVLCApp:
def listen_for_rfid(self):
"""Fortlaufend RFID-Tags vom COM-Port lesen"""
current_browser_process = None
while not self.stop_thread:
try:
with serial.Serial(
port=self.config["comport"],
baudrate=self.config["baudrate"],
timeout=1) as ser:
while not self.stop_thread:
line = ser.readline().decode("utf-8").strip()
if not line:
continue
tag_id = line
self.last_read_tag = tag_id
print(f"RFID-Tag: {tag_id}")
if tag_id not in self.config["cards"]:
print("Kein Video für diesen Tag")
continue
media_path = self.config["cards"][tag_id]
# Gleicher Tag = Stop
if current_browser_process and self.last_read_tag == tag_id:
current_browser_process.terminate()
current_browser_process = None
# Anderer Tag = Wechsel
elif current_browser_process and self.last_read_tag != tag_id:
current_browser_process.terminate()
current_browser_process = None
YouTube vs. lokales Video – automatische Erkennung
# YouTube-Link erkannt?
if media_path.startswith("http"):
# HTML mit Embed-Player erstellen
html_file = create_youtube_html(media_path)
current_browser_process = subprocess.Popen([
"C:\\Program Files\\Mozilla Firefox\\firefox.exe",
"--kiosk", html_file])
else:
# Lokales Video mit VLC
current_browser_process = subprocess.Popen([
self.config["vlc_path"],
"--fullscreen",
"--play-and-exit",
media_path])
except serial.SerialException as e:
print(f"[Warnung] COM-Port: {e}")
YouTube-Embed-HTML-Generator für Kiosk-Mode
def create_youtube_html(youtube_link):
"""HTML-Datei mit YouTube-Embed im Vollbild"""
video_id = youtube_link.split("v=")[-1].split("&")[0]
embed_link = f"https://www.youtube.com/embed/{video_id}?autoplay=1&rel=0"
html_content = f"""<!DOCTYPE html>
<html><head><style>
body, html {{ margin:0; padding:0; height:100%; overflow:hidden; }}
iframe {{ position:absolute; top:0; left:0;
width:100%; height:100%; border:none; }}
</style></head><body>
<iframe src="{embed_link}" allowfullscreen></iframe>
</body></html>"""
with tempfile.NamedTemporaryFile(
delete=False, suffix=".html") as f:
f.write(html_content.encode('utf-8'))
return f.name
Setup-Fenster: Karten-Management mit F12
def show_setup(self, event=None):
"""F12 öffnet passwortgeschütztes Setup"""
password = simpledialog.askstring(
"Setup", "Passwort:", show='*')
if password == DEFAULT_PASSWORD:
self.open_setup_window()
def setup_window(self):
# COM-Port-Dropdown (erkennt verfügbare Ports)
com_ports = [port.device
for port in serial.tools.list_ports.comports()]
port_dropdown = tk.OptionMenu(
setup_win, self.com_port_var, *com_ports)
# Baudrate-Dropdown
baud_rates = [9600, 19200, 38400, 57600, 115200]
baudrate_dropdown = tk.OptionMenu(
setup_win, self.baudrate_var, *baud_rates)
# VLC-Pfad konfigurierbar
self.vlc_path_var = tk.StringVar(
value=r"C:\Program Files (x86)\VideoLAN\VLC\vlc.exe")
🎯 Einsatzszenarien
Museen & Ausstellungen
Besucher halten NFC-Karte an Leser → Infovideo zum Exponat startet. Keine Touchscreens, hygienisch, intuitiv.
Kinder-Lernstationen
„Tomi" (TVTOM) – Kinder legen Bildkarten auf und sehen Lernvideos. Spielerisch, selbsterklärend.
Industrie-Schulung
Mitarbeiter-Karte = persönliches Schulungsvideo. Maschinen-Karte = Wartungsanleitung. Direkt am Arbeitsplatz.