ParamManagerScripts/backend/script_groups/TwinCat/test_converter.py

294 lines
6.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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()