From 0d6e416464e7435dec670f9023fb438ff305ef8b Mon Sep 17 00:00:00 2001 From: oberon Date: Mon, 16 Feb 2026 20:51:09 +0100 Subject: [PATCH] updated api.py --- app/routes/api.py | 97 ++++++++++++++++++++++++++--------------------- 1 file changed, 53 insertions(+), 44 deletions(-) diff --git a/app/routes/api.py b/app/routes/api.py index 031f47e..f12895b 100644 --- a/app/routes/api.py +++ b/app/routes/api.py @@ -1,30 +1,39 @@ # app/routes/api.py +import os +import time +import threading +import logging + import pygame -from flask import Blueprint, jsonify, request -from app.state import current_device, current_config +from flask import Blueprint, jsonify, request, current_app + +import app.state as state +from app.bluetooth.manager import MouldKing, advertiser, tracer +from app.utils.helpers import load_default_sounds + +logger = logging.getLogger(__name__) api_bp = Blueprint('api', __name__) @api_bp.route('/connect', methods=['POST']) def api_connect(): - global current_hub, current_module, current_device - if current_config is None: + if state.current_config is None: return jsonify({"success": False, "message": "Keine Konfiguration geladen"}), 400 try: - hub_id = int(current_config.get('hub_id', 0)) - hub_type = current_config.get('hub_type', '6channel') # '4channel' oder '6channel' + hub_id = int(state.current_config.get('hub_id', 0)) + hub_type = state.current_config.get('hub_type', '6channel') # '4channel' oder '6channel' # Alte Verbindung sauber trennen - if current_device is not None: + if state.current_device is not None: try: - current_device.Disconnect() + state.current_device.Disconnect() except: pass - if current_module is not None: + if state.current_module is not None: # ggf. Stop vor Disconnect try: - current_device.Stop() + state.current_device.Stop() except: pass @@ -38,21 +47,21 @@ def api_connect(): # Modul holen if hub_type.lower() in ['6channel', '6']: - current_module = mk.Module6_0() + state.current_module = mk.Module6_0() else: - current_module = mk.Module4_0() + state.current_module = mk.Module4_0() # Device auswählen (hub_id = 0,1,2 → Device0,1,2) device_attr = f'Device{hub_id}' - if not hasattr(current_module, device_attr): + if not hasattr(state.current_module, device_attr): raise ValueError(f"Hub-ID {hub_id} nicht unterstützt (max 0-2)") - current_device = getattr(current_module, device_attr) + state.current_device = getattr(state.current_module, device_attr) # Verbinden - current_device.Connect() + state.current_device.Connect() - current_hub = mk # falls später noch gebraucht + state.current_hub = mk # falls später noch gebraucht logger.info(f"Verbunden: {hub_type} Hub-ID {hub_id} → {device_attr}") return jsonify({"success": True, "message": f"Hub {hub_id} ({hub_type}) verbunden"}) @@ -65,21 +74,20 @@ def api_connect(): @api_bp.route('/reconnect', methods=['POST']) def api_reconnect(): - global current_device, current_module, current_hub - if current_config is None: + if state.current_config is None: return jsonify({"success": False, "message": "Keine Konfiguration geladen"}), 400 try: # Alte Verbindung sauber beenden, falls nötig - if current_device is not None: + if state.current_device is not None: try: - current_device.Disconnect() + state.current_device.Disconnect() except: pass # Neu verbinden (kopierter Code aus api_connect) - hub_id = int(current_config.get('hub_id', 0)) - hub_type = current_config.get('hub_type', '6channel') + hub_id = int(state.current_config.get('hub_id', 0)) + hub_type = state.current_config.get('hub_type', '6channel') mk = MouldKing() mk.SetAdvertiser(advertiser) @@ -89,18 +97,18 @@ def api_reconnect(): pass if hub_type.lower() in ['6channel', '6']: - current_module = mk.Module6_0() + state.current_module = mk.Module6_0() else: - current_module = mk.Module4_0() + state.current_module = mk.Module4_0() device_attr = f'Device{hub_id}' - if not hasattr(current_module, device_attr): + if not hasattr(state.current_module, device_attr): raise ValueError(f"Hub-ID {hub_id} nicht unterstützt") - current_device = getattr(current_module, device_attr) - current_device.Connect() + state.current_device = getattr(state.current_module, device_attr) + state.current_device.Connect() - current_hub = mk + state.current_hub = mk logger.info(f"Re-Connect erfolgreich: Hub {hub_id}") return jsonify({"success": True, "message": "Verbindung wiederhergestellt"}) @@ -113,8 +121,7 @@ def api_reconnect(): @api_bp.route('/control', methods=['POST']) def api_control(): - global current_device - if current_device is None: + if state.current_device is None: return jsonify({"success": False, "message": "Nicht verbunden"}), 400 try: @@ -134,7 +141,7 @@ def api_control(): channel_id = int(port) # Config-spezifische Anpassungen (invert, negative_only, on/off-Werte) - ch_cfg = next((c for c in current_config['channels'] if c['port'].upper() == port.upper()), None) + ch_cfg = next((c for c in state.current_config['channels'] if c['port'].upper() == port.upper()), None) if ch_cfg: if ch_cfg.get('invert', False): value = -value @@ -144,7 +151,7 @@ def api_control(): value = ch_cfg.get('on_value', 1.0) if value != 0 else ch_cfg.get('off_value', 0.0) # Echter Aufruf! - current_device.SetChannel(channel_id, value) + state.current_device.SetChannel(channel_id, value) logger.info(f"SetChannel({channel_id}, {value:.2f}) → Port {port}") return jsonify({"success": True}) @@ -157,13 +164,12 @@ def api_control(): @api_bp.route('/stop_all', methods=['POST']) def api_stop_all(): - global current_device - if current_device is None: + if state.current_device is None: return jsonify({"success": False, "message": "Nicht verbunden"}), 400 try: # Nur stoppen – KEIN Disconnect! - current_device.Stop() + state.current_device.Stop() logger.info("Alle Kanäle gestoppt (Verbindung bleibt bestehen)") return jsonify({"success": True, "message": "Alle Kanäle gestoppt"}) except Exception as e: @@ -174,9 +180,7 @@ def api_stop_all(): @api_bp.route('/status', methods=['GET']) def api_status(): - global current_device - - if current_device is not None: + if state.current_device is not None: return jsonify({ "connected": True, "message": "Verbunden" @@ -198,15 +202,20 @@ def api_play_sound(): if not sound_id: return jsonify({"success": False, "message": "Kein sound_id angegeben"}), 400 - # Sound aus aktueller Config suchen - if current_config is None or 'sounds' not in current_config: - return jsonify({"success": False, "message": "Keine Sounds in der aktuellen Konfiguration"}), 400 + # Sounds zusammenstellen: lokalspezifisch + globale Default-Sounds + config_sounds = state.current_config.get('sounds', []) if state.current_config else [] + global_sounds = load_default_sounds(current_app.config['CONFIG_DIR']) + all_sounds = list(config_sounds) + list(global_sounds) - sound_entry = next((s for s in current_config['sounds'] if s['id'] == sound_id), None) + if not all_sounds: + return jsonify({"success": False, "message": "Keine Sounds konfiguriert"}), 400 + + sound_entry = next((s for s in all_sounds if s.get('id') == sound_id), None) if not sound_entry: return jsonify({"success": False, "message": f"Sound mit ID '{sound_id}' nicht gefunden"}), 404 - file_path = os.path.join('sounds', sound_entry['file']) + sounds_dir = current_app.config['SOUNDS_DIR'] + file_path = os.path.join(sounds_dir, sound_entry['file']) if not os.path.exists(file_path): logger.error(f"Sound-Datei nicht gefunden: {file_path}") return jsonify({"success": False, "message": "Sound-Datei nicht gefunden"}), 404 @@ -256,4 +265,4 @@ def api_set_volume(): except Exception as e: logger.error(f"Volume-Fehler: {e}") return jsonify({"success": False, "message": str(e)}), 500 - pass \ No newline at end of file + pass