#!/usr/bin/env python3 """ IR Capture Script - Führt mode2 --device /dev/lirc1 aus - Wandelt pulse/space/timeout in mark/space JSON um - Speichert die JSON-Datei im gewünschten Format - Fügt optional einen neuen Command in die Config ein """ import subprocess import json import sys import re from pathlib import Path # === Anpassbare Pfade === DEVICE = "/dev/lirc1" IR_SENDER_DIR = Path("/home/till/IrSender2") CONFIG_FILE = IR_SENDER_DIR / "config.json" # ggf. anpassen IR_SEND_SCRIPT = IR_SENDER_DIR / "ir_send.py" CARRIER = 38000 REPEAT = 1 def capture_mode2(): """Startet mode2 und liest pulse/space/timeout-Daten.""" print(f"Starte mode2 auf {DEVICE} ...") print("Drücke jetzt die Taste auf der Fernbedienung.") print("Warte auf Signal (timeout = Ende). Mit Ctrl+C abbrechen.\n") try: proc = subprocess.Popen( ["mode2", "--device", DEVICE], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1 ) except FileNotFoundError: print("Fehler: 'mode2' nicht gefunden. Ist LIRC installiert?") sys.exit(1) except PermissionError: print(f"Fehler: Keine Berechtigung für {DEVICE}. Mit sudo ausführen?") sys.exit(1) signals = [] try: for line in proc.stdout: line = line.strip() if not line: continue m = re.match(r"^(pulse|space|timeout)\s+(\d+)$", line, re.IGNORECASE) if not m: continue kind, duration = m.group(1).lower(), int(m.group(2)) if kind == "timeout": signals.append({"type": "space", "duration": duration}) print(f" space {duration} (timeout → Signalende)") print("\nTimeout erkannt – Signal aufgenommen.") break typ = "mark" if kind == "pulse" else "space" signals.append({"type": typ, "duration": duration}) print(f" {typ:5} {duration}") except KeyboardInterrupt: print("\nAbbruch durch Benutzer – vorhandene Daten werden verwendet.") finally: proc.terminate() try: proc.wait(timeout=1) except subprocess.TimeoutExpired: proc.kill() return signals def save_json(signals, filename: Path): """ Speichert das Signal im gewünschten Format: - Jedes { "type": "...", "duration": N } steht in EINER Zeile - Kein Zeilenumbruch zwischen type und duration """ lines = [] lines.append('{') lines.append(f' "carrier": {CARRIER},') lines.append(f' "repeat": {REPEAT},') lines.append(' "signal": [') for i, s in enumerate(signals): comma = "," if i < len(signals) - 1 else "" # Wichtig: alles in einer Zeile lines.append(f' {{ "type": "{s["type"]}", "duration": {s["duration"]} }}{comma}') lines.append(' ]') lines.append('}') content = "\n".join(lines) + "\n" with open(filename, "w", encoding="utf-8") as f: f.write(content) print(f"\nJSON gespeichert: {filename}") def add_command_to_config(command_name: str, json_filename: str, web_title: str): """Fügt einen neuen Command in die Config-Datei ein.""" if not CONFIG_FILE.exists(): print(f"Warnung: Config-Datei {CONFIG_FILE} nicht gefunden – Command wird nicht hinzugefügt.") return with open(CONFIG_FILE, "r", encoding="utf-8") as f: config = json.load(f) if "commands" not in config: config["commands"] = {} if command_name in config["commands"]: print(f"Warnung: Command '{command_name}' existiert bereits – wird überschrieben.") config["commands"][command_name] = { "description": f"Send IR command {json_filename}", "web_title": web_title, "web_enabled": True, "timeout_seconds": 10, "command": [ "python3", str(IR_SEND_SCRIPT), str(IR_SENDER_DIR / json_filename) ] } # Backup anlegen backup = CONFIG_FILE.with_suffix(".json.bak") CONFIG_FILE.rename(backup) print(f"Backup der Config erstellt: {backup}") with open(CONFIG_FILE, "w", encoding="utf-8") as f: json.dump(config, f, indent=2, ensure_ascii=False) print(f"Command '{command_name}' zur Config hinzugefügt.") def main(): print("=== IR Capture → JSON + Config ===\n") signals = capture_mode2() if not signals: print("Keine Daten empfangen. Abbruch.") sys.exit(1) print(f"\n{len(signals)} Einträge aufgenommen.") while True: name = input("Dateiname (ohne .json, z.B. hektagonYellow): ").strip() if name and re.match(r"^[a-zA-Z0-9_\-]+$", name): break print("Nur Buchstaben, Zahlen, _ und - erlaubt.") json_path = IR_SENDER_DIR / f"{name}.json" save_json(signals, json_path) add = input("\nSoll ein neuer Command in die Config eingetragen werden? [j/N]: ").strip().lower() if add in ("j", "y", "ja", "yes"): cmd_name = input(f"Command-Name (Standard: {name}): ").strip() or name web_title = input(f"Web-Titel (Standard: {name}): ").strip() or name add_command_to_config(cmd_name, f"{name}.json", web_title) print("\nFertig!") if __name__ == "__main__": main()