""" Configuration module for MIDI-to-Hue application. Handles loading, creating and validating configuration. """ import os import json from typing import Dict, Any, Optional # Default config file path DEFAULT_CONFIG_FILE = 'midi_hue_config.json' # Default MIDI-to-Hue mapping if no config file exists DEFAULT_CONFIG = { "midi_device": 1, # Index of MIDI device to use (from available inputs list) "update_interval_ms": 50, # Throttling interval in milliseconds "bridge_ip": "192.168.178.35", # Default Bridge IP "mappings": [ { "midi_channel": 5, "midi_control": 1, "light_name": "Zimmer Decke", "parameter": "bri", "value_transform": "value * 2" # MIDI range 0-127 to Hue brightness 0-254 }, { "midi_channel": 6, "midi_control": 1, "light_name": "Fernseher links", "parameter": "bri", "value_transform": "value * 2" # MIDI range 0-127 to Hue brightness 0-254 }, ] } class ConfigManager: """Manages configuration loading, validation and access.""" def __init__(self, config_file: str = DEFAULT_CONFIG_FILE): """Initialize the config manager with a specific config file.""" self.config_file = config_file self.config = self._load_or_create_config() def _load_or_create_config(self) -> Dict[str, Any]: """Load config from file or create with defaults if it doesn't exist.""" try: if os.path.exists(self.config_file): with open(self.config_file, 'r') as f: config = json.load(f) print(f"Loaded configuration from {self.config_file}") return config except Exception as e: print(f"Error loading config file: {e}") # If we get here, either the file doesn't exist or there was an error # Create the default config file with open(self.config_file, 'w') as f: json.dump(DEFAULT_CONFIG, f, indent=4) print(f"Created default configuration file at {self.config_file}") return DEFAULT_CONFIG def get(self, key: str, default: Any = None) -> Any: """Get a configuration value by key with a default fallback.""" return self.config.get(key, default) def get_mappings(self) -> list: """Get all mappings from the configuration.""" return self.config.get("mappings", []) def get_bridge_ip(self) -> str: """Get the Bridge IP address.""" return self.config.get("bridge_ip", "192.168.178.35") def get_update_interval_sec(self) -> float: """Get the update interval in seconds.""" update_interval_ms = self.config.get("update_interval_ms", 50) return update_interval_ms / 1000 # Convert to seconds def get_midi_device_index(self) -> int: """Get the MIDI device index.""" return self.config.get("midi_device", 1) def get_stt_config(self) -> Dict[str, Any]: """Get the speech-to-text configuration.""" default_stt_config = { "enabled": False, "audio_device_index": 1, "language": "de", "api_key": "", "api_endpoint": "https://api.openai.com/v1/audio/transcriptions", "midi_trigger": { "channel": 1, "note": 1, "type": "note_on" } } return self.config.get("speech_to_text", default_stt_config) def is_stt_enabled(self) -> bool: """Check if speech-to-text is enabled in the configuration.""" stt_config = self.get_stt_config() return stt_config.get("enabled", False) def get_stt_midi_trigger(self) -> Dict[str, Any]: """Get MIDI trigger configuration for speech-to-text.""" stt_config = self.get_stt_config() return stt_config.get("midi_trigger", {})