225 lines
9.1 KiB
Python
225 lines
9.1 KiB
Python
"""
|
|
LadderToSCL - Conversor de Siemens LAD/FUP XML a SCL
|
|
|
|
Este script es parte de un conjunto de herramientas para convertir proyectos de Siemens LAD/FUP a SCL.
|
|
|
|
"""
|
|
# ToUpload/x3_generate_scl.py
|
|
# -*- coding: utf-8 -*-
|
|
import json
|
|
import os
|
|
import re
|
|
import argparse
|
|
import sys
|
|
import traceback
|
|
script_root = os.path.dirname(
|
|
os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
|
)
|
|
sys.path.append(script_root)
|
|
from backend.script_utils import load_configuration
|
|
|
|
# --- Importar Generadores Específicos ---
|
|
try:
|
|
from generators.generate_scl_db import generate_scl_for_db
|
|
from generators.generate_scl_code_block import generate_scl_for_code_block
|
|
from generators.generate_md_udt import generate_udt_markdown
|
|
from generators.generate_md_tag_table import generate_tag_table_markdown
|
|
from generators.generator_utils import (
|
|
format_variable_name,
|
|
generate_scl_declarations,
|
|
)
|
|
except ImportError as e:
|
|
print(
|
|
f"Error crítico: No se pudieron importar los módulos de 'generators': {e}",
|
|
file=sys.stderr,
|
|
)
|
|
sys.exit(1)
|
|
|
|
# --- Constantes ---
|
|
# SCL_OUTPUT_DIRNAME = "scl_output" # <-- Ya no se usa directamente en __main__, se lee de config
|
|
|
|
|
|
# --- Modificar generate_scl_or_markdown para usar el nuevo directorio de salida ---
|
|
def generate_scl_or_markdown(
|
|
processed_json_filepath, final_output_directory, project_root_dir
|
|
): # <-- MODIFICADO: Nombre del argumento
|
|
"""
|
|
Genera un archivo SCL o Markdown a partir del JSON procesado,
|
|
llamando a la función generadora apropiada y escribiendo el archivo
|
|
en el directorio de salida final (ej. 'scl_output').
|
|
Pasa project_root_dir a los generadores relevantes.
|
|
"""
|
|
if not os.path.exists(processed_json_filepath):
|
|
print(
|
|
f"Error: JSON procesado no encontrado: '{processed_json_filepath}'",
|
|
file=sys.stderr,
|
|
)
|
|
return False # Indicar fallo
|
|
|
|
print(f"Cargando JSON procesado desde: {processed_json_filepath}")
|
|
try:
|
|
with open(processed_json_filepath, "r", encoding="utf-8") as f:
|
|
data = json.load(f)
|
|
except Exception as e:
|
|
print(f"Error al cargar/parsear JSON procesado: {e}", file=sys.stderr)
|
|
traceback.print_exc(file=sys.stderr)
|
|
return False # Indicar fallo
|
|
|
|
block_name = data.get("block_name", "UnknownBlock")
|
|
block_type = data.get("block_type", "Unknown")
|
|
scl_block_name = format_variable_name(block_name) # Nombre SCL seguro
|
|
output_content = []
|
|
output_extension = ".scl" # Por defecto
|
|
|
|
print(
|
|
f"Generando salida para: {block_type} '{scl_block_name}' (Original: {block_name})"
|
|
)
|
|
|
|
# --- Selección del Generador y Extensión ---
|
|
generation_function = None
|
|
func_args = {"data": data}
|
|
if block_type == "GlobalDB":
|
|
print(" -> Modo de generación: DATA_BLOCK SCL")
|
|
generation_function = generate_scl_for_db
|
|
func_args["project_root_dir"] = project_root_dir
|
|
output_extension = ".scl"
|
|
elif block_type in ["FC", "FB", "OB"]:
|
|
print(f" -> Modo de generación: {block_type} SCL")
|
|
generation_function = generate_scl_for_code_block
|
|
func_args["project_root_dir"] = project_root_dir
|
|
output_extension = ".scl"
|
|
elif block_type == "PlcUDT":
|
|
print(" -> Modo de generación: UDT Markdown")
|
|
generation_function = generate_udt_markdown
|
|
# generate_udt_markdown no necesita project_root_dir por ahora
|
|
output_extension = ".md"
|
|
elif block_type == "PlcTagTable":
|
|
print(" -> Modo de generación: Tag Table Markdown")
|
|
generation_function = generate_tag_table_markdown
|
|
output_extension = ".md"
|
|
else:
|
|
print(
|
|
f"Error: Tipo de bloque desconocido '{block_type}'. No se generará archivo.",
|
|
file=sys.stderr,
|
|
)
|
|
return False # Indicar fallo
|
|
|
|
# --- Llamar a la función generadora ---
|
|
if generation_function:
|
|
try:
|
|
output_content = generation_function(**func_args)
|
|
except Exception as gen_e:
|
|
print(
|
|
f"Error durante la generación de contenido para {block_type} '{scl_block_name}': {gen_e}",
|
|
file=sys.stderr,
|
|
)
|
|
traceback.print_exc(file=sys.stderr)
|
|
return False # Indicar fallo
|
|
|
|
# --- Escritura del Archivo de Salida en el Directorio Final ---
|
|
output_filename_base = f"{scl_block_name}{output_extension}"
|
|
# El 'final_output_directory' ya viene calculado desde __main__
|
|
output_filepath = os.path.join(final_output_directory, output_filename_base)
|
|
|
|
print(
|
|
f" -> Escribiendo archivo de salida final en: {os.path.relpath(output_filepath)}"
|
|
)
|
|
try:
|
|
# Asegurar que el directorio de salida exista (ya debería estar hecho en __main__)
|
|
os.makedirs(os.path.dirname(output_filepath), exist_ok=True)
|
|
with open(output_filepath, "w", encoding="utf-8") as f:
|
|
for line in output_content:
|
|
f.write(line + "\n")
|
|
print(f"Generación de {output_extension.upper()} completada.")
|
|
return True # Indicar éxito
|
|
except Exception as e:
|
|
print(
|
|
f"Error al escribir el archivo final {output_extension.upper()}: {e}",
|
|
file=sys.stderr,
|
|
)
|
|
traceback.print_exc(file=sys.stderr)
|
|
return False # Indicar fallo
|
|
|
|
|
|
# --- Ejecución (MODIFICADO para usar SCL_OUTPUT_DIRNAME) ---
|
|
if __name__ == "__main__":
|
|
# Lógica para ejecución standalone
|
|
try:
|
|
import tkinter as tk
|
|
from tkinter import filedialog
|
|
except ImportError:
|
|
print("Error: Tkinter no está instalado. No se puede mostrar el diálogo de archivo.", file=sys.stderr)
|
|
tk = None
|
|
|
|
input_json_file = ""
|
|
project_root_dir = ""
|
|
|
|
if tk:
|
|
root = tk.Tk()
|
|
root.withdraw()
|
|
print("Por favor, selecciona el archivo JSON procesado de entrada (generado por x2)...")
|
|
input_json_file = filedialog.askopenfilename(
|
|
title="Selecciona el archivo JSON procesado de entrada (_processed.json)",
|
|
filetypes=[("Processed JSON files", "*_processed.json"), ("JSON files", "*.json"), ("All files", "*.*")]
|
|
)
|
|
if input_json_file:
|
|
print(f"Archivo JSON procesado seleccionado: {input_json_file}")
|
|
print("Por favor, selecciona el directorio raíz del proyecto XML (ej. la carpeta 'PLC')...")
|
|
project_root_dir = filedialog.askdirectory(
|
|
title="Selecciona el directorio raíz del proyecto XML"
|
|
)
|
|
if project_root_dir:
|
|
print(f"Directorio raíz del proyecto seleccionado: {project_root_dir}")
|
|
else:
|
|
print("No se seleccionó directorio raíz. Saliendo.", file=sys.stderr)
|
|
else:
|
|
print("No se seleccionó archivo JSON procesado. Saliendo.", file=sys.stderr)
|
|
root.destroy()
|
|
|
|
if input_json_file and project_root_dir:
|
|
# Calcular directorio de salida final
|
|
# <-- NUEVO: Leer nombre del directorio de salida desde la configuración -->
|
|
configs = load_configuration()
|
|
xml_parser_config = configs.get("XML Parser to SCL", {})
|
|
cfg_scl_output_dirname = xml_parser_config.get("scl_output_dir", "scl_output") # Leer con default
|
|
# <-- FIN NUEVO -->
|
|
|
|
final_output_dir = os.path.join(project_root_dir, cfg_scl_output_dirname) # Usar valor leído
|
|
|
|
print(f"(x3 - Standalone) Generando SCL/MD desde: '{os.path.relpath(input_json_file)}'")
|
|
print(f"(x3 - Standalone) Directorio de salida final: '{os.path.relpath(final_output_dir)}'")
|
|
print(f"(x3 - Standalone) Usando ruta raíz del proyecto: '{project_root_dir}' para buscar UDTs.")
|
|
|
|
# Asegurar que el directorio de salida final exista
|
|
try:
|
|
os.makedirs(final_output_dir, exist_ok=True)
|
|
except OSError as e:
|
|
print(
|
|
f"Error Crítico (x3): No se pudo crear el directorio de salida '{final_output_dir}': {e}",
|
|
file=sys.stderr,
|
|
)
|
|
# sys.exit(1) # No usar sys.exit
|
|
success = False # Marcar como fallo para evitar la llamada
|
|
else:
|
|
success = True # Marcar como éxito para proceder
|
|
|
|
if success: # Solo intentar si se pudo crear el directorio
|
|
try:
|
|
# Llamar a la función principal
|
|
success = generate_scl_or_markdown(
|
|
input_json_file, final_output_dir, project_root_dir
|
|
)
|
|
if success:
|
|
print("\nGeneración de SCL/MD completada exitosamente.")
|
|
else:
|
|
# La función generate_scl_or_markdown ya imprime el error
|
|
print(f"\nError durante la generación desde '{os.path.relpath(input_json_file)}'.", file=sys.stderr)
|
|
# sys.exit(1) # No usar sys.exit
|
|
except Exception as e:
|
|
print(f"Error Crítico no manejado en x3: {e}", file=sys.stderr)
|
|
traceback.print_exc(file=sys.stderr)
|
|
# sys.exit(1) # No usar sys.exit
|
|
else:
|
|
# Mensajes de cancelación ya impresos si aplica
|
|
pass
|