Files
KX-Bridge-Release/config_loader.py
viewit 2a12ecca51 chore: sync v0.9.2 – README/CHANGELOG DE+EN, config_loader, aktuelle Bridge-Quelldateien
- README.md (EN), README.de.md (DE) – README.en.md entfernt
- CHANGELOG.md (EN), CHANGELOG.de.md (DE)
- config_loader.py neu (config.ini statt .env)
- kobrax_moonraker_bridge.py, kobrax_client.py, env_loader.py aktualisiert
- Dockerfile, docker-compose.yml, VERSION auf 0.9.2

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 14:53:23 +02:00

144 lines
5.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
config_loader.py lädt Verbindungsparameter aus config/config.ini (primär)
oder .env (Fallback / Migration).
Umgebungsvariablen haben immer Vorrang.
"""
import os
import sys
import pathlib
import configparser
_BASE = pathlib.Path(sys.executable).parent if getattr(sys, "frozen", False) else pathlib.Path(__file__).parent
CONFIG_SECTION_CONNECTION = "connection"
CONFIG_SECTION_PRINT = "print"
CONFIG_SECTION_BRIDGE = "bridge"
def _find_config_file() -> pathlib.Path | None:
for base in (_BASE, _BASE.parent):
p = base / "config" / "config.ini"
if p.is_file():
return p
return None
def _find_env_file() -> pathlib.Path | None:
for base in (_BASE, _BASE.parent):
p = base / ".env"
if p.is_file():
return p
return None
def _load_env_file(path: pathlib.Path):
"""Lädt .env-Datei als Fallback setzt nur Keys die noch nicht in os.environ sind."""
with open(path, encoding="utf-8") as f:
for line in f:
line = line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
key, _, val = line.partition("=")
key = key.strip()
val = val.strip()
if key and key not in os.environ:
os.environ[key] = val
def _load_config_file(path: pathlib.Path):
"""Lädt config.ini und setzt Keys in os.environ (nur wenn nicht bereits gesetzt)."""
cfg = configparser.ConfigParser()
cfg.read(path, encoding="utf-8")
mapping = {
"PRINTER_IP": (CONFIG_SECTION_CONNECTION, "printer_ip"),
"MQTT_PORT": (CONFIG_SECTION_CONNECTION, "mqtt_port"),
"MQTT_USERNAME": (CONFIG_SECTION_CONNECTION, "username"),
"MQTT_PASSWORD": (CONFIG_SECTION_CONNECTION, "password"),
"MODE_ID": (CONFIG_SECTION_CONNECTION, "mode_id"),
"DEVICE_ID": (CONFIG_SECTION_CONNECTION, "device_id"),
"DEFAULT_AMS_SLOT": (CONFIG_SECTION_PRINT, "default_ams_slot"),
"AUTO_LEVELING": (CONFIG_SECTION_PRINT, "auto_leveling"),
}
for env_key, (section, option) in mapping.items():
if env_key not in os.environ:
try:
val = cfg.get(section, option)
if val:
os.environ[env_key] = val
except (configparser.NoSectionError, configparser.NoOptionError):
pass
def migrate_env_to_config(env_path: pathlib.Path, config_path: pathlib.Path):
"""Einmalige Migration: .env → config.ini anlegen."""
env_vals: dict[str, str] = {}
with open(env_path, encoding="utf-8") as f:
for line in f:
line = line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
k, _, v = line.partition("=")
env_vals[k.strip()] = v.strip()
config_path.parent.mkdir(parents=True, exist_ok=True)
cfg = configparser.ConfigParser()
cfg[CONFIG_SECTION_CONNECTION] = {
"printer_ip": env_vals.get("PRINTER_IP", ""),
"mqtt_port": env_vals.get("MQTT_PORT", "9883"),
"username": env_vals.get("MQTT_USERNAME", ""),
"password": env_vals.get("MQTT_PASSWORD", ""),
"mode_id": env_vals.get("MODE_ID", ""),
"device_id": env_vals.get("DEVICE_ID", ""),
}
cfg[CONFIG_SECTION_PRINT] = {
"default_ams_slot": env_vals.get("DEFAULT_AMS_SLOT", "auto"),
"auto_leveling": env_vals.get("AUTO_LEVELING", "1"),
}
cfg[CONFIG_SECTION_BRIDGE] = {
"poll_interval": "3",
}
with open(config_path, "w", encoding="utf-8") as f:
f.write("# KX-Bridge Konfigurationsdatei\n")
f.write("# Automatisch migriert aus .env\n\n")
cfg.write(f)
def find_config_path() -> pathlib.Path:
"""Gibt den Pfad zur config.ini zurück (auch wenn sie noch nicht existiert)."""
for base in (_BASE, _BASE.parent):
config_dir = base / "config"
if config_dir.is_dir():
return config_dir / "config.ini"
return _BASE / "config" / "config.ini"
# ─── Laden ───────────────────────────────────────────────────────────────────
_config_path = _find_config_file()
_env_path = _find_env_file()
if _config_path:
_load_config_file(_config_path)
elif _env_path:
# Kein config.ini vorhanden → aus .env migrieren
_target = find_config_path()
migrate_env_to_config(_env_path, _target)
_load_config_file(_target)
_config_path = _target
def get(key: str, default: str = "") -> str:
return os.environ.get(key, default)
# Häufig verwendete Shortcuts
PRINTER_IP = get("PRINTER_IP", "")
MQTT_PORT = int(get("MQTT_PORT", "9883"))
USERNAME = get("MQTT_USERNAME", "")
PASSWORD = get("MQTT_PASSWORD", "")
MODE_ID = get("MODE_ID", "")
DEVICE_ID = get("DEVICE_ID", "")
DEFAULT_AMS_SLOT = get("DEFAULT_AMS_SLOT", "auto")
AUTO_LEVELING = int(get("AUTO_LEVELING","1"))