Actualización del script x0_main.py y mejora en la gestión de logs

- Se implementó un nuevo sistema de argumentos para permitir el procesamiento de múltiples PLCs desde un directorio de trabajo.
- Se mejoró la lógica de búsqueda de archivos XML, eliminando la dependencia de un subdirectorio específico.
- Se actualizaron los logs de ejecución para reflejar el estado exitoso del procesamiento y se añadieron detalles sobre los archivos encontrados y procesados.
- Se generaron nuevos archivos de salida en formato Markdown y se mejoró la estructura de los logs para facilitar la comprensión del proceso.
This commit is contained in:
Miguel 2025-06-12 21:44:58 +02:00
parent 04084e7289
commit e70852ecf1
4 changed files with 33513 additions and 50 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -162,72 +162,116 @@ def check_skip_status(
# --- Bloque Principal ---
if __name__ == "__main__":
# -------------------------------------------------------------------------
# 1. Analizar argumentos de línea de comandos
# --plc-dir : ruta al PLC a procesar directamente (modo interno)
# Si NO se pasa el flag, el script actuará como "orquestador" detectando
# todos los PLCs bajo el working_directory y lanzándose a sí mismo para
# cada uno de ellos.
# -------------------------------------------------------------------------
arg_parser = argparse.ArgumentParser(description="Convertidor XML→SCL (multi-PLC)")
arg_parser.add_argument("--plc-dir", dest="plc_dir", help="Ruta del PLC a procesar (uso interno).", default=None)
cli_args, _ = arg_parser.parse_known_args()
# Cargar configuración
configs = load_configuration()
working_directory = configs.get("working_directory")
# -------------------------------------------------------------------------
# 2. Si NO se indicó --plc-dir ⇒ modo ORQUESTADOR
# Detecta todos los PLC (subdirectorios con al menos un .xml) y lanza
# este mismo script para cada uno con el flag --plc-dir.
# -------------------------------------------------------------------------
if cli_args.plc_dir is None:
if not working_directory or not os.path.isdir(working_directory):
print("Error: 'working_directory' inválido en la configuración.", file=sys.stderr)
sys.exit(1)
# Detectar PLCs como subdirectorios que contengan al menos un XML
detected_plc_dirs = []
for entry in os.listdir(working_directory):
cand_path = os.path.join(working_directory, entry)
if os.path.isdir(cand_path):
if glob.glob(os.path.join(cand_path, "**", "*.xml"), recursive=True):
detected_plc_dirs.append(cand_path)
# Si no se encontró ningún PLC (quizás el working_directory ya ES el PLC)
if not detected_plc_dirs:
detected_plc_dirs = [working_directory]
# Ejecutar secuencialmente el script para cada PLC
overall_exit_code = 0
for plc_dir in detected_plc_dirs:
print(f"\n=== Lanzando procesamiento para PLC: {os.path.basename(plc_dir)} ===")
ret = subprocess.call([sys.executable, os.path.abspath(__file__), "--plc-dir", plc_dir])
if ret != 0:
overall_exit_code = 1 # Registrar fallo global si algún PLC falla
sys.exit(overall_exit_code)
# -------------------------------------------------------------------------
# 3. Modo INTERNO (se recibió --plc-dir) ⇒ procesar sólo ese PLC
# -------------------------------------------------------------------------
xml_project_dir = os.path.abspath(cli_args.plc_dir)
if not os.path.isdir(xml_project_dir):
print(f"Error: El directorio PLC especificado no existe: {xml_project_dir}", file=sys.stderr)
sys.exit(1)
# Usaremos el nombre del PLC para diferenciar los logs
plc_name_safe = os.path.basename(xml_project_dir.strip(os.sep))
# ---------------------------------------------------------------------
# 3.1 Leer parámetros específicos del grupo para reutilizarlos más abajo
# ---------------------------------------------------------------------
xml_parser_config = configs.get("level2", {})
# <-- NUEVO: Leer parámetros de configuración para x3, x4, x5 -->
# xml_parser_config = configs.get("XML Parser to SCL", {})
cfg_scl_output_dirname = xml_parser_config.get("scl_output_dir", "scl_output")
cfg_xref_output_dirname = xml_parser_config.get("xref_output_dir", "xref_output")
cfg_xref_source_subdir = xml_parser_config.get("xref_source_subdir", "source")
cfg_call_xref_filename = xml_parser_config.get("call_xref_filename", "xref_calls_tree.md")
cfg_db_usage_xref_filename = xml_parser_config.get("db_usage_xref_filename", "xref_db_usage_summary.md")
cfg_plc_tag_xref_filename = xml_parser_config.get("plc_tag_xref_filename", "xref_plc_tags_summary.md")
# Ensure max_call_depth is an integer
# Conversión de enteros con control de errores
try:
cfg_max_call_depth = int(xml_parser_config.get("max_call_depth", 5))
except (ValueError, TypeError):
print("Advertencia: Valor inválido para 'max_call_depth' en la configuración. Usando valor por defecto 5.", file=sys.stderr)
cfg_max_call_depth = 5
# Ensure max_users_list is an integer
try:
cfg_max_users_list = int(xml_parser_config.get("max_users_list", 20))
except (ValueError, TypeError):
print("Advertencia: Valor inválido para 'max_users_list' en la configuración. Usando valor por defecto 20.", file=sys.stderr)
cfg_max_users_list = 20
cfg_aggregated_filename = xml_parser_config.get("aggregated_filename", "full_project_representation.md")
# <-- FIN NUEVO -->
# Generar un nombre de log específico por PLC
log_filename_dynamic = f"log_{plc_name_safe}.txt"
log_filepath = os.path.join(
os.path.dirname(os.path.abspath(__file__)), log_filename_dynamic
)
# Directorio donde se encuentra este script (x0_main.py)
script_dir = os.path.dirname(os.path.abspath(__file__))
# <-- MODIFICADO: Abrir archivo log -->
log_filepath = os.path.join(
os.path.dirname(os.path.abspath(__file__)), LOG_FILENAME
)
with open(
log_filepath, "w", encoding="utf-8"
) as log_f: # Usar 'a' para añadir al log
log_message("=" * 40 + " LOG START " + "=" * 40, log_f)
# --- PARTE 1: BUSCAR ARCHIVOS ---
# <-- MODIFICADO: Apuntar al subdirectorio 'PLC' dentro del working_directory -->
plc_subdir_name = "PLC" # Nombre estándar del subdirectorio de TIA Portal
xml_project_dir = os.path.join(working_directory, plc_subdir_name)
# Se trabaja exclusivamente dentro del PLC indicado.
log_message(
f"Directorio de trabajo base configurado: '{working_directory}'", log_f
)
log_message(
f"Buscando archivos XML recursivamente en el subdirectorio: '{xml_project_dir}'", log_f
f"Buscando archivos XML recursivamente en: '{xml_project_dir}'", log_f
)
# Verificar si el directorio PLC existe
if not os.path.isdir(xml_project_dir):
log_message(
f"Error: El subdirectorio '{plc_subdir_name}' no existe dentro de '{working_directory}'. "
f"Se esperaba encontrar la estructura del proyecto TIA Portal en '{xml_project_dir}'.",
log_f,
also_print=False,
)
print(
f"Error: El subdirectorio '{plc_subdir_name}' no existe dentro de '{working_directory}'. "
f"Asegúrese de que la ruta del directorio de trabajo apunte a la carpeta que *contiene* la carpeta '{plc_subdir_name}'.", file=sys.stderr
)
sys.exit(1)
# Patrón de búsqueda global para todos los PLC
search_pattern = os.path.join(xml_project_dir, "**", "*.xml")
xml_files_found = glob.glob(search_pattern, recursive=True)
if not xml_files_found:
@ -423,7 +467,7 @@ if __name__ == "__main__":
log_message(f"Se encontraron {len(filtered_scl_files)} archivos .scl existentes para copiar:", log_f)
for src_scl_path in filtered_scl_files:
relative_scl_path = os.path.relpath(src_scl_path, xml_project_dir)
dest_scl_path = os.path.join(scl_output_dir, os.path.basename(src_scl_path)) # Copy directly into scl_output_dir
dest_scl_path = os.path.join(scl_output_dir, os.path.basename(src_scl_path)) # Copia directa al scl_output del PLC
# Check if a file with the same name was already generated from XML
if os.path.exists(dest_scl_path):
@ -513,7 +557,8 @@ if __name__ == "__main__":
run_x5 = False
if run_x5:
output_agg_file = os.path.join(working_directory, cfg_aggregated_filename) # Usar valor de config
# El archivo agregado se guarda dentro del PLC para mantener salidas separadas
output_agg_file = os.path.join(xml_project_dir, cfg_aggregated_filename)
log_message(
f"Ejecutando x5 (aggregate_outputs) sobre: {xml_project_dir}, salida agregada en: {output_agg_file}",
log_f
@ -590,7 +635,7 @@ if __name__ == "__main__":
log_message(final_console_message, log_f) # Loguear mensaje final
print(
f"\n{final_console_message} Consulta '{LOG_FILENAME}' para detalles."
f"\n{final_console_message} Consulta '{log_filename_dynamic}' para detalles."
) # Mostrar mensaje en consola
log_message("="*41 + " LOG END " + "="*42, log_f)

14975
data/log.txt

File diff suppressed because it is too large Load Diff