Globale Deklarationen zur Skeletterzeugung aus der Config laden

This commit is contained in:
2026-07-07 09:20:21 +02:00
parent b6103e205b
commit cbed41da66
3 changed files with 49 additions and 25 deletions
+47 -23
View File
@@ -7,8 +7,11 @@ Datenquellen (Pfade ueber Umgebungsvariablen aus bin\\setenv.bat):
ST500592_10_5-14_ILS-<n>_TIA.xlsx (PLC Tags + Constants)
ST500592_10_5-9_ILS_positions.json (Positionen, VERW, mappings)
PV_RESULTS Zielordner fuer die erzeugten Dateien
PV_CFG optional: create_skel.cfg ueberschreibt die globalen
Definitionen (Templates, Vokabular)
PV_CFG Ordner mit skel.cfg (JSON) — enthaelt die globalen
Definitionen (Dateinamen, Vokabular, FB-Typ-Regeln,
SCL-Templates). Wird beim Programmstart geladen und
ersetzt die eingebauten Defaults vollstaendig, wenn
vorhanden. Ohne skel.cfg laufen die Defaults unten weiter.
Erzeugt je Steuerung UH01..UH05:
skeleton_UH0x.json JSON-Zwischendatei-Skeleton (Kap. 14 im
@@ -20,7 +23,6 @@ Aufruf: bin\\create_skel.bat [--uh 1..5] [--no-scl]
"""
import argparse
import configparser
import json
import os
import re
@@ -34,16 +36,22 @@ except ImportError:
sys.exit("openpyxl fehlt — bitte bin\\install_py.bat ausfuehren.")
# ============================================================================
# GLOBALE DEFINITIONEN
# Alle folgenden Bloecke sind bewusst als Modul-Konstanten definiert, damit
# sie spaeter unveraendert in eine .cfg (PV_CFG\create_skel.cfg) ausgelagert
# werden koennen. load_cfg() ueberschreibt sie, wenn die Datei existiert.
# GLOBALE DEFINITIONEN (eingebaute Defaults)
# Alle folgenden Bloecke sind bewusst als Modul-Konstanten definiert. Sie
# sind zugleich der Inhalt von cfg\\skel.cfg (JSON) — load_cfg() liest diese
# Datei aus PV_CFG beim Programmstart und ersetzt die Defaults hier 1:1
# durch ihren Inhalt. Ohne skel.cfg (z.B. Erststart, Datei geloescht) bleiben
# die Defaults unten aktiv, das Skript funktioniert also auch dann.
# ============================================================================
#: Dateinamen der Eingabelisten ({n} = ILS-Nummer 1..5)
FILES = {
"tia_xlsx": "ST500592_10_5-14_ILS-{n}_TIA.xlsx",
"positions_json": "ST500592_10_5-9_ILS_positions.json",
# Routing / Zusammenhalt der TROs (hmf-connect-v1, extrahiert aus
# doc/TRO_Graph_UH01-UH05.dot) — fuer die kuenftige Topologie-Auswertung
"connect_json": "connect.json",
"connect_ini": "connect.ini",
}
#: VERW-Vokabular (Positions-JSON) -> Signalrolle
@@ -270,29 +278,45 @@ FBTYPE_TEMPLATE = {
# Ende der globalen Definitionen
# ============================================================================
#: Schluessel in skel.cfg -> Modul-Konstante, die beim Laden ersetzt wird
_CFG_KEYS = {
"files": "FILES",
"verw_roles": "VERW_ROLES",
"comment_roles": "COMMENT_ROLES",
"fbtype_rules": "FBTYPE_RULES",
"unit_re": "UNIT_RE",
"area_res": "AREA_RES",
"scl_templates": "SCL_TEMPLATES",
"fbtype_template": "FBTYPE_TEMPLATE",
}
def load_cfg():
"""Ueberschreibt die globalen Definitionen aus PV_CFG\\create_skel.cfg.
"""Laedt cfg\\skel.cfg (JSON) aus PV_CFG und ersetzt die globalen
Definitionen (FILES, VERW_ROLES, ..., SCL_TEMPLATES) durch ihren Inhalt.
Unterstuetzte Sektionen: [files], [verw_roles], [scl_templates].
Werte in [scl_templates] sind mehrzeilige Raw-Strings.
Fehlt PV_CFG oder die Datei, bleiben die eingebauten Defaults oben aktiv
(Cold-Start-Faehigkeit ohne Konfigurationsdatei).
"""
cfg_dir = os.environ.get("PV_CFG")
if not cfg_dir:
return
cfg_file = Path(cfg_dir) / "create_skel.cfg"
cfg_dir = os.environ.get("PV_CFG", Path(__file__).resolve().parent.parent / "cfg")
cfg_file = Path(cfg_dir) / "skel.cfg"
if not cfg_file.exists():
print(f"Hinweis: {cfg_file} nicht gefunden — verwende eingebaute Defaults.")
return
print(f"Lade Konfiguration: {cfg_file}")
cp = configparser.ConfigParser(interpolation=None)
cp.read(cfg_file, encoding="utf-8")
if cp.has_section("files"):
FILES.update(cp["files"])
if cp.has_section("verw_roles"):
VERW_ROLES.update(cp["verw_roles"])
if cp.has_section("scl_templates"):
for key, val in cp["scl_templates"].items():
SCL_TEMPLATES[key] = val.replace("\\n", "\n")
data = json.loads(cfg_file.read_text(encoding="utf-8"))
globals_ = globals()
for cfg_key, const_name in _CFG_KEYS.items():
if cfg_key not in data:
continue
value = data[cfg_key]
# Listen von Listen (comment_roles, fbtype_rules, area_res) als
# Tupel normalisieren, damit das Unpacking im Code unveraendert bleibt
if const_name in ("COMMENT_ROLES", "AREA_RES"):
value = [tuple(item) for item in value]
globals_[const_name] = value
def project_paths():