#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Script de prueba para verificar la conversión de ACTIONs LAD """ import sys import os # Agregar el directorio padre al path sys.path.append('..') # Importar el convertidor from x1_lad_converter import SimpleLadConverter def test_pattern_detection(): """Probar la detección de patrones ??? vs Function Blocks directos""" print("=== TEST: Detección de patrones ??? vs Function Blocks ===") print("Basado en tu observación sobre los patrones LAD de TwinCAT") print("-" * 60) # Crear archivo de ejemplo que simule los patrones que identificaste test_content = """(* @PATH := '/TASK1_PID/PID_Controllers/Test_Program' *) PROGRAM Test_Pattern_Program VAR mDummy : BOOL; mFillerEstSlew : SlewLimit; mFillingHead_PID : FB41_PIDController; END_VAR _LD_BODY _NETWORKS : 4 _NETWORK _COMMENT Patrón 1: ACTION call con ??? _END_COMMENT _LD_ASSIGN _EMPTY _EXPRESSION _POSITIV ENABLELIST : 1 _ASSIGN _FUNCTIONBLOCK ??? _BOX_EXPR : 0 _ENABLED _EXPRESSION _POSITIV Test_Pattern_Program.Read_Analog _OUTPUTS : 0 _EXPRESSION _POSITIV _OUTPUTS : 1 _OUTPUT _POSITIV _NO_SET mDummy ENABLELIST_END _OUTPUTS : 0 _NETWORK _COMMENT Patrón 2: Function Block directo _END_COMMENT _LD_ASSIGN _EMPTY _EXPRESSION _POSITIV ENABLELIST : 1 _ASSIGN _FUNCTIONBLOCK mFillerEstSlew _BOX_EXPR : 4 _ENABLED _OPERAND _EXPRESSION _POSITIV gInputValue _OPERAND _EXPRESSION _POSITIV gSlewMax _OPERAND _EXPRESSION _POSITIV gCycle _EXPRESSION _POSITIV SlewLimit _OUTPUTS : 1 _OUTPUT _POSITIV _NO_SET mDummy ENABLELIST_END _OUTPUTS : 0 _NETWORK _COMMENT Patrón 3: Otra ACTION call con ??? _END_COMMENT _LD_ASSIGN _EMPTY _EXPRESSION _POSITIV ENABLELIST : 1 _ASSIGN _FUNCTIONBLOCK ??? _BOX_EXPR : 0 _ENABLED _EXPRESSION _POSITIV Test_Pattern_Program.Calculations _OUTPUTS : 0 _EXPRESSION _POSITIV _OUTPUTS : 1 _OUTPUT _POSITIV _NO_SET mDummy ENABLELIST_END _OUTPUTS : 0 _NETWORK _COMMENT Patrón 4: Function Block PID directo _END_COMMENT _LD_ASSIGN _EMPTY _EXPRESSION _POSITIV ENABLELIST : 1 _ASSIGN _FUNCTIONBLOCK mFillingHead_PID _BOX_EXPR : 20 _ENABLED _OPERAND _EXPRESSION _POSITIV gSetpoint _OPERAND _EXPRESSION _POSITIV gProcessValue _EXPRESSION _POSITIV FB41_PIDController _OUTPUTS : 1 _OUTPUT _POSITIV _NO_SET mPIDOutput ENABLELIST_END _OUTPUTS : 0 END_PROGRAM ACTION Read_Analog: _LD_BODY _NETWORKS : 1 _NETWORK _COMMENT ACTION de ejemplo _END_COMMENT _LD_ASSIGN _LD_CONTACT gAnalogEnable _EXPRESSION _POSITIV _EXPRESSION _POSITIV ENABLELIST : 1 _ASSIGN _FUNCTION ReadAnalogIn _OUTPUTS : 1 _OUTPUT _POSITIV _NO_SET gAnalogValue ENABLELIST_END _OUTPUTS : 0 END_ACTION ACTION Calculations: gCalculatedValue := gInputA + gInputB * 2.5; mDummy := TRUE; END_ACTION """ # Escribir archivo de prueba test_file = "test_pattern_example.exp" with open(test_file, 'w', encoding='utf-8') as f: f.write(test_content) print(f"✓ Archivo de prueba creado: {test_file}") print("-" * 60) # Crear convertidor converter = SimpleLadConverter() # Parsear archivo print("🔍 PARSEANDO ARCHIVO...") converter.parse_file(test_file) print(f"\n📊 RESUMEN:") print(f" ✓ Programa: {converter.program_name}") print(f" ✓ Redes encontradas: {len(converter.networks)}") print(f" ✓ ACTIONs encontradas: {list(converter.actions.keys())}") # Analizar tipos de llamadas encontradas action_calls = [] function_blocks = [] print(f"\n📋 ANÁLISIS DETALLADO DE REDES:") for network in converter.networks: print(f" Red {network['id']}: {network['comment']}") if network['logic']: logic_type = network['logic']['type'] logic_name = network['logic'].get('name', 'Sin nombre') if logic_type == 'ACTION_CALL': action_calls.append(logic_name) print(f" ✓ PATRÓN ???: ACTION call → {logic_name}") elif logic_type == 'FUNCTION_BLOCK': function_blocks.append(logic_name) print(f" ✓ PATRÓN DIRECTO: Function Block → {logic_name}") else: print(f" ℹ Otro tipo: {logic_type} → {logic_name}") else: print(f" ⚠ Sin lógica detectada") print(f"\n🔍 LLAMADAS DETECTADAS:") print(f" 📞 ACTION calls (patrón ???): {len(action_calls)}") for call in action_calls: print(f" • {call}") print(f" 🔧 Function Blocks (directos): {len(function_blocks)}") for fb in function_blocks: print(f" • {fb}") # Generar código SCL para verificar print(f"\n📝 GENERANDO CÓDIGO SCL...") scl_code = converter.convert_to_structured() # Guardar archivo de prueba output_file = "test_pattern_output.scl" with open(output_file, 'w', encoding='utf-8') as f: f.write(scl_code) print(f" ✓ Guardado en: {output_file}") # Mostrar sección relevante del código generado lines = scl_code.split('\n') print(f"\n📄 CÓDIGO SCL GENERADO (sección principal):") # Buscar sección principal main_start = -1 main_end = -1 for i, line in enumerate(lines): if "CÓDIGO PRINCIPAL" in line: main_start = i elif main_start > -1 and "END_PROGRAM" in line: main_end = i + 1 break if main_start > -1: section_lines = lines[main_start:main_end] if main_end > -1 else lines[main_start:main_start+20] for i, line in enumerate(section_lines, main_start+1): print(f" {i:2d}: {line}") # Limpiar archivos temporales try: os.remove(test_file) print(f"\n🧹 Archivo temporal eliminado: {test_file}") except: pass print(f"\n✅ CONCLUSIÓN:") print(f" Tu observación es CORRECTA:") print(f" • _FUNCTIONBLOCK + ??? = ACTION call") print(f" • _FUNCTIONBLOCK + nombre_directo = Function Block") print(f" • El parser ahora detecta ambos patrones correctamente!") if __name__ == "__main__": test_pattern_detection()