From cbed41da66e5da658ea7bd71ff979596525f615d Mon Sep 17 00:00:00 2001 From: Michael Stangl Date: Tue, 7 Jul 2026 09:20:21 +0200 Subject: [PATCH] Globale Deklarationen zur Skeletterzeugung aus der Config laden --- bin/create_skel.bat | 2 +- doc/Json_Layout-Konzept.md | 2 +- lib/create_skel.py | 70 +++++++++++++++++++++++++------------- 3 files changed, 49 insertions(+), 25 deletions(-) diff --git a/bin/create_skel.bat b/bin/create_skel.bat index 9e12e39..637d7a3 100644 --- a/bin/create_skel.bat +++ b/bin/create_skel.bat @@ -2,7 +2,7 @@ REM ================================================================ REM HundM_Fortna - Skeleton-Generator aufrufen REM -REM Liest die Eingabelisten (%PV_EINGABEN%) und erzeugt je Steuerung +REM Liest die Eingabelisten (%PV_DATA%) und erzeugt je Steuerung REM ein Skeleton der JSON-Zwischendatei sowie ein SCL-Grundgeruest REM nach %PV_RESULTS%. REM ================================================================ diff --git a/doc/Json_Layout-Konzept.md b/doc/Json_Layout-Konzept.md index dea50fa..2fa8022 100644 --- a/doc/Json_Layout-Konzept.md +++ b/doc/Json_Layout-Konzept.md @@ -1182,7 +1182,7 @@ Nicht aus den Listen ableitbar bleiben: Timings, Priority-Manager, Release-Ausdr #### 14.5 Skeleton-Generator -Das Skript [lib/create_skel.py](../lib/create_skel.py) (Aufruf ueber `bin\create_skel.bat`) liest die Eingabelisten und erzeugt je Steuerung ein Skeleton der JSON-Zwischendatei (`results/skeleton_UH0x.json`) sowie ein SCL-Grundgeruest. Die SCL-Aufruf-Templates sind als globale Definitionen im Skript hinterlegt und koennen spaeter in eine `.cfg` ausgelagert werden. +Das Skript [lib/create_skel.py](../lib/create_skel.py) (Aufruf ueber `bin\create_skel.bat`) liest die Eingabelisten und erzeugt je Steuerung ein Skeleton der JSON-Zwischendatei (`results/skeleton_UH0x.json`) sowie ein SCL-Grundgeruest. Die globalen Definitionen (Dateinamen, `VERW`-Vokabular, FB-Typ-Regeln, SCL-Aufruf-Templates) sind als JSON in [cfg/skel.cfg](../cfg/skel.cfg) ausgelagert und werden beim Programmstart aus `PV_CFG` geladen; ohne diese Datei laufen die im Skript eingebauten Defaults weiter (Cold-Start-faehig). --- diff --git a/lib/create_skel.py b/lib/create_skel.py index 04d6e71..6798f60 100644 --- a/lib/create_skel.py +++ b/lib/create_skel.py @@ -7,8 +7,11 @@ Datenquellen (Pfade ueber Umgebungsvariablen aus bin\\setenv.bat): ST500592_10_5-14_ILS-_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():