# app.py import os import json import logging from flask import Flask, render_template, redirect, url_for, send_from_directory, request, jsonify app = Flask(__name__) # Konfiguration app.config['CONFIG_DIR'] = 'configs' os.makedirs(app.config['CONFIG_DIR'], exist_ok=True) # Logging logging.basicConfig( filename='app.log', level=logging.INFO, format='%(asctime)s | %(levelname)-8s | %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) logger = logging.getLogger(__name__) def load_configs(): """Liest alle .json Dateien aus dem configs-Ordner""" configs = [] if not os.path.exists(app.config['CONFIG_DIR']): return configs for filename in os.listdir(app.config['CONFIG_DIR']): if filename.lower().endswith('.json'): path = os.path.join(app.config['CONFIG_DIR'], filename) try: with open(path, 'r', encoding='utf-8') as f: data = json.load(f) data['filename'] = filename # Optional: name fallback, falls nicht vorhanden data.setdefault('name', filename.replace('.json', '').replace('_', ' ').title()) configs.append(data) except Exception as e: logger.error(f"Fehler beim Laden von {filename}: {e}") return sorted(configs, key=lambda x: x.get('name', '')) @app.route('/') def index(): configs = load_configs() return render_template('index.html', configs=configs) current_config = None current_filename = None @app.route('/load_config/') def load_config(filename): global current_config, current_filename path = os.path.join(app.config['CONFIG_DIR'], filename) if not os.path.exists(path): return "Konfigurationsdatei nicht gefunden", 404 try: with open(path, 'r', encoding='utf-8') as f: current_config = json.load(f) current_config['filename'] = filename current_filename = filename logger.info(f"Konfiguration geladen: {filename}") return redirect(url_for('control_page')) except Exception as e: logger.error(f"Fehler beim Laden der Config {filename}: {e}") return "Fehler beim Laden der Konfiguration", 500 @app.route('/control') def control_page(): if current_config is None: return redirect(url_for('index')) return render_template('control.html', config=current_config) # Neue API-Route (Platzhalter – später echte Bluetooth-Steuerung) @app.route('/api/connect', methods=['POST']) def api_connect(): # Hier kommt später der echte Code mit MouldKing # Aktuell nur simuliert if current_config is None: return jsonify({"success": False, "message": "Keine Konfiguration geladen"}), 400 logger.info(f"Simulierter Connect zu Hub {current_config.get('hub_id')}") return jsonify({ "success": True, "message": "Verbunden (Simulation)", "hub_id": current_config.get('hub_id') }) @app.route('/api/control', methods=['POST']) def api_control(): # Platzhalter für spätere echte Steuerung data = request.get_json() logger.info(f"Steuerbefehl empfangen: {data}") return jsonify({"success": True, "message": "Befehl gesendet (Simulation)"}) @app.route('/api/stop_all', methods=['POST']) def api_stop_all(): logger.info("Alle stoppen (Simulation)") return jsonify({"success": True, "message": "Alle Kanäle gestoppt"}) @app.route('/admin') def admin(): return render_template('admin.html') if __name__ == '__main__': app.run(host='0.0.0.0', port=5055, debug=True)