""" moOde Radio Controller Flask-Webapp zur Steuerung des moOde Audio Players Offizielles API-Format (aus setup_guide.md Abschnitt 6.1): Alle Befehle gehen an: GET http:///command/?cmd=BEFEHL Beispiele: get_currentsong -> aktuellen Song/Sender + Status + Lautstaerke toggle_play_pause -> Play/Stop (Radio) / Play/Pause (Dateien) set_volume N -> Lautstaerke absolut setzen (0-100) set_volume -up N -> Lautstaerke um N erhoehen set_volume -dn N -> Lautstaerke um N verringern set_volume -mute -> Mute umschalten """ import os import requests from flask import Flask, jsonify, render_template, request BASE_DIR = os.path.dirname(os.path.abspath(__file__)) app = Flask(__name__, template_folder=os.path.join(BASE_DIR, "templates")) MOODE_URL = "http://10.2.196.29" MOODE_CMD = f"{MOODE_URL}/command/" def moode_cmd(cmd: str) -> dict: """ Sendet einen Befehl an die moOde REST API. Offizielles Format: GET /command/?cmd=BEFEHL (entspricht: curl -G -S -s --data-urlencode "cmd=BEFEHL" http://moode/command/) """ try: r = requests.get(MOODE_CMD, params={"cmd": cmd}, timeout=5) r.raise_for_status() try: return {"ok": True, "data": r.json()} except Exception: return {"ok": True, "data": r.text.strip()} except requests.exceptions.ConnectionError: return {"ok": False, "error": f"moOde nicht erreichbar ({MOODE_URL})"} except requests.exceptions.Timeout: return {"ok": False, "error": "Verbindungs-Timeout"} except Exception as e: return {"ok": False, "error": str(e)} @app.route("/") def index(): return render_template("index.html", moode_url=MOODE_URL) @app.route("/api/play", methods=["POST"]) def play(): """Play/Stop umschalten - bei Radio: play/stop, bei Dateien: play/pause""" return jsonify(moode_cmd("toggle_play_pause")) @app.route("/api/stop", methods=["POST"]) def stop(): """Dasselbe Toggle - moOde kennt keinen separaten Stop-Befehl ueber die REST API""" return jsonify(moode_cmd("toggle_play_pause")) @app.route("/api/volume", methods=["POST"]) def volume(): level = request.json.get("level") if level is None: return jsonify({"ok": False, "error": "Kein Lautstaerke-Wert angegeben."}) level = int(level) if not (0 <= level <= 100): return jsonify({"ok": False, "error": "Lautstaerke muss zwischen 0 und 100 liegen."}) # Laut Doku: cmd=set_volume N (N = absoluter Wert 0-100) return jsonify(moode_cmd(f"set_volume {level}")) @app.route("/api/status") def status(): """ get_currentsong liefert laut Doku volume, mute und state bereits mit - ein einziger API-Aufruf reicht fuer den kompletten Status. """ return jsonify(moode_cmd("get_currentsong")) if __name__ == "__main__": print(f"moOde Controller gestartet -> http://localhost:5555 (Player: {MOODE_URL})") app.run(debug=True, host="0.0.0.0", port=5555)