""" Load settings from config.ini (or config.example.ini if no config.ini). Paths are relative to the project root (directory containing config.py). """ import os from configparser import ConfigParser _ROOT = os.path.dirname(os.path.abspath(__file__)) _CONFIG_DIR = _ROOT _CONFIG_FILE = os.path.join(_CONFIG_DIR, 'config.ini') _EXAMPLE_FILE = os.path.join(_CONFIG_DIR, 'config.example.ini') def _get_parser(): p = ConfigParser() if os.path.isfile(_CONFIG_FILE): p.read(_CONFIG_FILE, encoding='utf-8') elif os.path.isfile(_EXAMPLE_FILE): p.read(_EXAMPLE_FILE, encoding='utf-8') return p def get(section, key, fallback=None, type_=str): p = _get_parser() if not p.has_section(section) or not p.has_option(section, key): return fallback raw = p.get(section, key) if type_ is int: return int(raw) if type_ is float: return float(raw) if type_ is bool: return raw.strip().lower() in ('1', 'true', 'yes', 'on') return raw # Plotter def plotter_port(): return get('plotter', 'port', fallback='/dev/ttyUSB0') def plotter_baudrate(): return get('plotter', 'baudrate', fallback=9600, type_=int) def plotter_timeout(): return get('plotter', 'timeout', fallback=15, type_=int) def plotter_center_at_origin(): return get('plotter', 'center_at_origin', fallback=False, type_=bool) # Web UI def webui_host(): return get('webui', 'host', fallback='0.0.0.0') def webui_port(): return get('webui', 'port', fallback=5000, type_=int) def webui_max_upload_mb(): return get('webui', 'max_upload_mb', fallback=16, type_=int) def webui_secret_key(): return os.environ.get('SECRET_KEY') or get('webui', 'secret_key', fallback='change-me-in-production')