import json import os import logging from flask import Flask, render_template, jsonify, request, send_from_directory, redirect, url_for from mkconnect.mouldking.MouldKing import MouldKing from mkconnect.tracer.TracerConsole import TracerConsole from mkconnect.advertiser.AdvertiserBTSocket import AdvertiserBTSocket app = Flask(__name__) app.config['CONFIG_DIR'] = 'configs' os.makedirs(app.config['CONFIG_DIR'], exist_ok=True) # Logging setup logging.basicConfig(filename='app.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') tracer = TracerConsole() advertiser = AdvertiserBTSocket() current_hub = None current_config = None def load_configs(): configs = [] for file in os.listdir(app.config['CONFIG_DIR']): if file.endswith('.json'): with open(os.path.join(app.config['CONFIG_DIR'], file)) as f: cfg = json.load(f) cfg['filename'] = file configs.append(cfg) return configs @app.route('/') def index(): return render_template('index.html', configs=load_configs()) @app.route('/load_config/') def load_config(filename): global current_config path = os.path.join(app.config['CONFIG_DIR'], filename) if not os.path.exists(path): return "Config not found", 404 with open(path) as f: current_config = json.load(f) current_config['filename'] = filename return redirect(url_for('control_page')) @app.route('/control') def control_page(): if not current_config: return redirect(url_for('index')) return render_template('control.html', config=current_config) @app.route('/api/connect', methods=['POST']) def connect(): global current_hub if not current_config: return jsonify({"error": "Keine Config geladen"}), 400 try: hub_id = current_config['hub_id'] current_hub = MouldKing(hub_id=hub_id, advertiser=advertiser, tracer=tracer) current_hub.connect() logging.info(f"Verbunden mit Hub {hub_id} für {current_config['name']}") return jsonify({"status": "connected"}) except Exception as e: logging.error(f"Connect-Fehler: {str(e)}") return jsonify({"error": str(e)}), 500 @app.route('/api/control', methods=['POST']) def control(): if not current_hub: return jsonify({"error": "Nicht verbunden"}), 400 data = request.json port = data['port'] value = float(data['value']) ch = next((c for c in current_config['channels'] if c['port'] == port), None) if not ch: return jsonify({"error": "Port nicht in Config"}), 400 if ch.get('negative_only', False) and value > 0: value = -abs(value) # Force negative if ch.get('invert', False): value = -value if ch['type'] != 'motor': value = ch.get('on_value', 1.0) if value != 0 else ch.get('off_value', 0.0) try: current_hub.set_motor(channel=port, power=value) # Passe an reale Methode an logging.info(f"Control: {port} @ {value}") return jsonify({"status": "ok"}) except Exception as e: logging.error(f"Control-Fehler: {str(e)}") return jsonify({"error": str(e)}), 500 @app.route('/api/stop_all', methods=['POST']) def stop_all(): if current_hub: current_hub.stop_all() logging.info("Alle gestoppt") return jsonify({"status": "ok"}) @app.route('/admin') def admin(): return render_template('admin.html', configs=load_configs()) @app.route('/admin/edit/', methods=['GET', 'POST']) def edit_config(filename): path = os.path.join(app.config['CONFIG_DIR'], filename) if request.method == 'POST': data = request.form['config'] with open(path, 'w') as f: json.dump(json.loads(data), f, indent=4) return redirect(url_for('admin')) if not os.path.exists(path): return "Not found", 404 with open(path) as f: config = json.load(f) return render_template('edit.html', config=json.dumps(config, indent=4), filename=filename) @app.route('/admin/logs') def view_logs(): with open('app.log') as f: logs = f.read() return render_template('logs.html', logs=logs) @app.route('/configs/') def serve_config_file(filename): return send_from_directory(app.config['CONFIG_DIR'], filename) if __name__ == '__main__': app.run(host='0.0.0.0', port=5050, debug=True)