294 lines
6.0 KiB
Python
294 lines
6.0 KiB
Python
#!/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() |