Version Funcionante

This commit is contained in:
Miguel 2025-06-19 20:55:40 +02:00
parent 26bc892243
commit b74db36cf9
13 changed files with 36747 additions and 12020 deletions

204
backend/script_groups/TwinCat/.gitignore vendored Normal file
View File

@ -0,0 +1,204 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[codz]
*$py.class
# C extensions
*.so
*.scl
*.exp
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py.cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# UV
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
#uv.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
#poetry.toml
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.envrc
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
# Abstra
# Abstra is an AI-powered process automation framework.
# Ignore directories containing user credentials, local state, and settings.
# Learn more at https://abstra.io/docs
.abstra/
# Visual Studio Code
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
# and can be added to the global gitignore or merged into this file. However, if you prefer,
# you could uncomment the following to ignore the entire vscode folder
# .vscode/
# Ruff stuff:
.ruff_cache/
# PyPI configuration file
.pypirc
# Cursor
# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
# refer to https://docs.cursor.com/context/ignore-files
.cursorignore
.cursorindexingignore
# Marimo
marimo/_static/
marimo/_lsp/
__marimo__/

View File

@ -1,141 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import os
# Agregar el directorio padre al path
sys.path.append('.')
# Importar el convertidor
from x1_lad_converter import SimpleLadConverter
def test_arraytoreal():
"""Probar específicamente ARRAYTOREAL.EXP para verificar preservación de indentación"""
print("=== TEST: ARRAYTOREAL.EXP - Preservación de indentación ST ===")
print("-" * 60)
# Buscar el archivo
possible_paths = [
"ExportTwinCat/ARRAYTOREAL.EXP",
"../ExportTwinCat/ARRAYTOREAL.EXP",
"../../ExportTwinCat/ARRAYTOREAL.EXP",
"C:/Trabajo/SIDEL/13 - E5.007560 - Modifica O&U - SAE235/Reporte/ExportTwinCat/ARRAYTOREAL.EXP"
]
test_file = None
for path in possible_paths:
if os.path.exists(path):
test_file = path
break
if test_file is None:
print(f"❌ Error: No se encontró ARRAYTOREAL.EXP")
return
print(f"✓ Archivo encontrado: {test_file}")
print("-" * 60)
# Leer archivo original para mostrar indentación
print("📄 CÓDIGO ORIGINAL:")
with open(test_file, 'r', encoding='utf-8', errors='ignore') as f:
original_lines = f.readlines()
# Mostrar solo las líneas de código ST (después de (* @END_DECLARATION := '0' *))
st_start = False
for i, line in enumerate(original_lines):
if "@END_DECLARATION" in line:
st_start = True
continue
if st_start and line.strip() and not line.strip().startswith("END_FUNCTION"):
print(f" {i+1:2d}: '{line.rstrip()}'")
print("-" * 60)
# Crear convertidor
converter = SimpleLadConverter()
# Parsear archivo
print("🔍 PARSEANDO ARCHIVO...")
converter.parse_file(test_file)
print(f"\n📊 INFORMACIÓN DETECTADA:")
print(f" ✓ Tipo: {getattr(converter, 'program_type', 'PROGRAM')}")
print(f" ✓ Nombre: {converter.program_name}")
print(f" ✓ Path: {converter.program_path}")
print(f" ✓ Variables: {list(converter.var_sections.keys())}")
print(f" ✓ Código ST: {'' if converter.st_main_code else 'No'}")
if converter.st_main_code:
print(f"\n📝 CÓDIGO ST EXTRAÍDO ({len(converter.st_main_code)} caracteres):")
for i, line in enumerate(converter.st_main_code.split('\n')[:10], 1):
print(f" {i:2d}: '{line}'")
# Generar código SCL
print(f"\n📝 GENERANDO CÓDIGO SCL...")
scl_code = converter.convert_to_structured()
# Guardar archivo de prueba
output_file = "test_arraytoreal_indent.scl"
with open(output_file, 'w', encoding='utf-8') as f:
f.write(scl_code)
print(f" ✓ Guardado en: {output_file}")
# Mostrar código SCL generado
print(f"\n📄 CÓDIGO SCL GENERADO:")
lines = scl_code.split('\n')
# Encontrar línea donde empieza el código ST
st_start_line = -1
for i, line in enumerate(lines):
if "Código ST original" in line:
st_start_line = i
break
if st_start_line > -1:
# Mostrar desde el código ST hasta el final de la función
for i in range(st_start_line, min(st_start_line + 20, len(lines))):
if i < len(lines):
line = lines[i]
if line.strip() and ("END_FUNCTION" in line or "END_PROGRAM" in line):
print(f" {i+1:2d}: {line}")
break
print(f" {i+1:2d}: {line}")
# Verificar preservación de indentación
print(f"\n🔍 VERIFICANDO PRESERVACIÓN DE INDENTACIÓN:")
if converter.st_main_code:
original_lines = converter.st_main_code.split('\n')
scl_lines = scl_code.split('\n')
# Encontrar líneas con indentación en el original
original_indented = []
for line in original_lines:
if line.startswith('\t') or line.startswith(' '):
original_indented.append(line)
# Verificar que se preserven en el SCL
if original_indented:
print(f" 📋 Líneas con indentación original: {len(original_indented)}")
print(f" Ejemplo: '{original_indented[0]}'" if original_indented else "")
# Verificar si aparecen en el SCL preservadas
preserved_count = 0
for orig_line in original_indented:
for scl_line in scl_lines:
if orig_line.strip() in scl_line and orig_line.startswith(('\t', ' ')):
preserved_count += 1
break
print(f" ✅ Indentación preservada: {preserved_count}/{len(original_indented)} líneas")
else:
print(f" No se encontraron líneas con indentación específica")
else:
print(f" ⚠ No hay código ST para verificar")
return scl_code
if __name__ == "__main__":
test_arraytoreal()

View File

@ -1,37 +0,0 @@
(* Código SCL generado desde LAD TwinCAT *)
(* Convertidor mejorado con SymPy - Estructura DNF preferida *)
(* Path original: \/Functions_Collection *)
FUNCTION ArrayToReal : REAL
VAR_INPUT
mIn_Value : POINTER TO BYTE;
END_VAR
VAR
i : INT;
p : UDINT;
p1 : UDINT;
mPoint : POINTER TO BYTE;
mPoint1 : POINTER TO BYTE;
mTemp : REAL;
END_VAR
(* === CÓDIGO PRINCIPAL === *)
(* Código ST original *)
(* @END_DECLARATION := '0' *)
mPoint := ADR(mTemp);
FOR i := 3 TO 0 BY -1
DO
p1 := mIn_Value;
mPoint1 := p1 + i;
mPoint^ := mPoint1^;
p := mPoint ;
p := p + 1 ;
mPoint := p ;
END_FOR
ArrayToReal := mTemp;
END_FUNCTION
END_FUNCTION

View File

@ -1,294 +0,0 @@
#!/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()

View File

@ -1,329 +0,0 @@
(* Código SCL generado desde LAD TwinCAT *)
(* Convertidor mejorado con SymPy - Estructura DNF preferida *)
(* Path original: \/TASK1_PID\/PID_Controllers\/Filling_Valve_PID *)
PROGRAM _Filling_Head_PID_Ctrl
VAR_OUTPUT
EN_Out : BOOL ;
END_VAR
VAR
mFillerProdSlew : REAL ;
mFillerEstSlew : SlewLimit ;
mKp_Loss : REAL ;
mR_KP : REAL ;
mR_TI : REAL ;
mR_TD : REAL ;
_Hold_int_PID : BOOL ;
_Init_int_PID : BOOL ;
mManual_Value : REAL ;
mReal_FF_value : REAL ;
mReal_Max_FF : REAL ;
mLMN_FAC : REAL ;
mDeadBand : REAL ;
mInit_Int_PID : REAL ;
mHr_Hs : REAL ;
mFillingHead_PID : FB41_PIDController;
mI_Sel_FillHead : BOOL ;
mP_Sel_FillHead : BOOL ;
mD_Sel_FillHead : BOOL ;
mPID_FillHead_OUT : REAL ;
mPIDFillHeadProp : REAL ;
mPIDFillHeadInt : REAL ;
mPIDFillHeadDer : REAL ;
mP3_Freq_Flted : LowPassFilter ;
mDiffTransducer_Flted : LowPassFilter ;
mFillValve1Press_Flted : LowPassFilter ;
mFillingHead_KP_PID : FB41_PIDController;
mFillHead_PID_En : BOOL ;
mI_Sel_FillHead_KP : BOOL ;
mP_Sel_FillHead_KP : BOOL ;
mD_Sel_FillHead_KP : BOOL ;
mPID_FillHead_KP_OUT : REAL ;
mPIDFillHead_KP_Prop : REAL ;
mPIDFillHead_KP_Int : REAL ;
mPIDFillHead_KP_Der : REAL ;
_Hold_int_KP_PID : BOOL ;
_Init_int_KP_PID : BOOL ;
mManual_KP_Value : REAL ;
mReal_KP_FF_value : REAL ;
mDead_KP_Band : REAL ;
mInit_Int_KP_PID : REAL ;
mFillingHeadPIDStat : StatisticalAnalisys ;
mHeadKP_SlewLimit : SlewLimit ;
mHead_KP_Temp : REAL ;
mOutWordToVFC : WORD ;
mRealTemp : REAL ;
mAnalogInTemp : Peripherial ;
mReset_Int_ONS : R_TRIG ;
mReset_Int : BOOL ;
mEn_ProdPressLoss : TON ;
mStartFillTON : TON ;
mStopFillTP : TP ;
mStopFillingN_ONS : F_TRIG ;
mFillerFilling : BOOL ;
mStopFilling : BOOL;
mDummy : BOOL ;
mDiffSensFaultEn: TON;
END_VAR
(* === CÓDIGO PRINCIPAL === *)
(* Código LAD convertido *)
// Red 2
// Llamada a función: _Filling_Head_PID_Ctrl.Read_Analog
CALL _Filling_Head_PID_Ctrl.Read_Analog();
mDummy := TRUE; // ACTION ejecutada
// Red 3
// Llamada a función: _Filling_Head_PID_Ctrl._KP_PID_Ctrl
CALL _Filling_Head_PID_Ctrl._KP_PID_Ctrl();
mDummy := TRUE; // ACTION ejecutada
// Red 4
// Llamada a función: _Filling_Head_PID_Ctrl.Calcolous
CALL _Filling_Head_PID_Ctrl.Calcolous();
mDummy := TRUE; // ACTION ejecutada
// Red 5
// Llamada a función: gProd_Flow
mDummy := gProd_Flow();
// Red 6
// Llamada a función: mFillerEstSlew
// Sin optimización SymPy
IF mFillerEstSlew(_POSITIV) THEN
mDummy := TRUE;
ELSE
mDummy := FALSE;
END_IF;
// Red 7
// Llamada a función: mStopFillTP
// Sin optimización SymPy
IF mStopFillTP() THEN
mDummy := TRUE;
ELSE
mDummy := FALSE;
END_IF;
// Red 1
// Sin optimización SymPy
IF NOT gAlwaysOff THEN
mP_Sel_FillHead := TRUE;
ELSE
mP_Sel_FillHead := FALSE;
END_IF;
// Red 8
// Sin optimización SymPy
IF NOT gAlwaysOff THEN
mI_Sel_FillHead := TRUE;
ELSE
mI_Sel_FillHead := FALSE;
END_IF;
// Red 9
// Sin optimización SymPy
IF NOT gAlwaysOff THEN
mD_Sel_FillHead := TRUE;
ELSE
mD_Sel_FillHead := FALSE;
END_IF;
// Red 10
// Sin optimización SymPy
IF (gBlenderCIPMode OR gBlenderRinseMode) THEN
g_Head_CIP_Rinse := TRUE;
ELSE
g_Head_CIP_Rinse := FALSE;
END_IF;
// Red 11
// Sin optimización SymPy
IF ((NOT gH_P3_ProductPump_Auto AND gH_P3_ProductPump_Manual) OR g_Head_Drain OR (gH_EV62_Status AND g_Head_CIP_Rinse) OR gP_PID_Head_Manual) THEN
g_MAN_Head := TRUE;
ELSE
g_MAN_Head := FALSE;
END_IF;
// Red 12
// Sin optimización SymPy
IF ((((gP_PID_Head_Enable OR (NOT gProdPipeRunOut_Done AND gBlendFillStartUp_Done)) AND gInFillerEV46Enable AND NOT gFlrCO2ValveEV46Pos_Fault AND gInFillerEV62Enable AND NOT gProdValveEV62Pos_Fault AND NOT gDiffSensor_Analog_Fault) OR (g_Head_CIP_Rinse AND gBlenderRun_Latch) OR g_MAN_Head OR gP_PID_Head_Manual) AND gH_Blender_OPT_BlendFillSystem) THEN
g_Head_PID_Enable := TRUE;
ELSE
g_Head_PID_Enable := FALSE;
END_IF;
// Red 14
// Llamada a función: gHead_PID_Max_Freq
mDummy := gHead_PID_Max_Freq();
// Red 15
// Llamada a función: gH_ProcessSetup_FillerDiameter
mDummy := gH_ProcessSetup_FillerDiameter();
// Red 16
// Llamada a función: mReal_FF_value
mDummy := mReal_FF_value();
// Red 17
// Llamada a función: mManual_Value
mDummy := mManual_Value();
// Red 18
// Llamada a función: _Filling_Head_PID_Ctrl.Write_Analog
CALL _Filling_Head_PID_Ctrl.Write_Analog();
mDummy := TRUE; // ACTION ejecutada
// Red 13
CALL _Filling_Head_PID_Ctrl.Write_Analog();
mDummy := TRUE; // ACTION ejecutada
END_PROGRAM
(* === SUBFUNCIONES (ACTIONs convertidas) === *)
PROCEDURE _Filling_Head_PID_Ctrl__KP_PID_Ctrl
(* Convertida desde ACTION *)
(* Código LAD convertido a SCL *)
// Red 1
IF NOT gAlwaysOff THEN
mI_Sel_FillHead_KP := TRUE;
ELSE
mI_Sel_FillHead_KP := FALSE;
END_IF;
// Red 2
IF NOT gAlwaysOff THEN
mP_Sel_FillHead_KP := TRUE;
ELSE
mP_Sel_FillHead_KP := FALSE;
END_IF;
// Red 3
IF NOT gAlwaysOff THEN
mD_Sel_FillHead_KP := TRUE;
ELSE
mD_Sel_FillHead_KP := FALSE;
END_IF;
// Red 4
IF mFillHead_PID_En THEN
mR_KP := TRUE;
ELSE
mR_KP := FALSE;
END_IF;
END_PROCEDURE
PROCEDURE _Filling_Head_PID_Ctrl_Calcolous
(* Convertida desde ACTION *)
(* Código ST original *)
gHead_PID_Cycle := gPID_Cycle_Time ;
mLMN_FAC := 1.0 ;
mDeadBand := 0.0 ;
mKp_Loss := gH_ProcessSetup_KProdLoss ;
IF gH_ProcessSetup_BPFillingValvePID<>0 THEN
(* IF gHeadPIDCtrlOk THEN*)
mHead_KP_Temp := 100 / gH_ProcessSetup_BPFillingValvePID ;
(* ELSE
mHead_KP_Temp := 50 / gH_ProcessSetup_BPFillingValvePID ;
END_IF*)
END_IF
mHeadKP_SlewLimit(i_InValue:=mHead_KP_Temp, i_SlewMax:=0.01, i_Cycle:=gHead_PID_Cycle, out:=mR_KP) ;
mR_TI := gH_ProcessSetup_TIFillingValvePID ;
mR_TD := gH_ProcessSetup_TDFillingValvePID ;
mManual_Value := 0.0 ;
IF NOT gH_P3_ProductPump_Auto AND gH_P3_ProductPump_Manual THEN
mManual_Value := gH_P3_ProductPumpFC_Manual ;
mLMN_FAC := 1.0 ;
ELSIF g_MAN_Head AND NOT g_Head_CIP_Rinse THEN
mManual_Value := gHead_PID_Manual_Value ;
mLMN_FAC := 1.0 ;
ELSIF g_Head_Drain THEN
mManual_Value := 0.0 ;
mLMN_FAC := 1.0 ;
ELSIF g_Head_CIP_Rinse AND gBlenderRinseMode THEN
mManual_Value :=gH_ProcessSetup_RinseProdPumpFreq ;
mLMN_FAC := 1.0 ;
ELSIF g_Head_CIP_Rinse THEN
mManual_Value :=gH_ProcessSetup_CIPProdPumpFreq ;
mLMN_FAC := 1.0 ;
ELSIF g_Head_PID_Enable AND gH_P3_ProductPump_Auto THEN
gH_P3_ProductPumpFC_Manual := mmH2O_TO_Freq(mPID_FillHead_OUT,gH_ProcessSetup_KProdPump) ;
mManual_Value := 0.0 ;
mLMN_FAC := 1.0 ;
ELSE
mManual_Value := 0.0 ;
mLMN_FAC := 0.0 ;
END_IF
END_PROCEDURE
PROCEDURE _Filling_Head_PID_Ctrl_PID_Monitor
(* Convertida desde ACTION *)
(* Código LAD convertido a SCL *)
// Red 2
// Llamada a función: mFillingHeadPIDStat
IF mFillingHeadPIDStat(_POSITIV) THEN
mDummy := TRUE;
ELSE
mDummy := FALSE;
END_IF;
// Red 1
IF gHeadPIDCtrlOk THEN
gHeadPIDCtrlOk := TRUE;
ELSE
gHeadPIDCtrlOk := FALSE;
END_IF;
END_PROCEDURE
PROCEDURE _Filling_Head_PID_Ctrl_Read_Analog
(* Convertida desde ACTION *)
(* Código LAD convertido a SCL *)
// Red 1
IF NOT gH_Blender_OPT_Simulation THEN
gDiffSensor_Analog_Fault := TRUE;
ELSE
gDiffSensor_Analog_Fault := FALSE;
END_IF;
END_PROCEDURE
PROCEDURE _Filling_Head_PID_Ctrl_Reset_Integral
(* Convertida desde ACTION *)
(* Código ST original *)
mInit_Int_PID := 0.0 ;
_Init_int_PID := TRUE ;
END_PROCEDURE
PROCEDURE _Filling_Head_PID_Ctrl_Write_Analog
(* Convertida desde ACTION *)
(* Código LAD convertido a SCL *)
// Red 1
IF NOT gH_Blender_OPT_Simulation THEN
gProduct_VFC_MainRefValue := TRUE;
ELSE
gProduct_VFC_MainRefValue := FALSE;
END_IF;
END_PROCEDURE

View File

@ -1,76 +0,0 @@
(* Código SCL generado desde LAD TwinCAT *)
(* Convertidor mejorado con SymPy - Estructura DNF preferida *)
(* Path original: \/TASK2_ControlMain\/CIP *)
PROGRAM CentralCIP_Ctrl
VAR_OUTPUT
EN_Out : BOOL ;
END_VAR
VAR
mReadCIP_Block : ADSREAD ;
mReadCIP_Busy : BOOL ;
mReadCIP_Read : BOOL ;
mReadCIP_Error : BOOL ;
mReadCIP_ErrorCode : UDINT ;
mDummy : BOOL ;
mCIPCommFault : TON;
END_VAR
(* === CÓDIGO PRINCIPAL === *)
(* Código LAD convertido *)
// Red 1
// Red 2
// Red 4
// Llamada a función: ???
// Sin optimización SymPy
IF ???() THEN
mDummy := TRUE;
ELSE
mDummy := FALSE;
END_IF;
// Red 3
// Sin optimización SymPy
IF (gH_Blender_OPT_CIPSignalExchange AND gBlenderCIPMode AND NOT gCIPReceiveData.AliveBit AND mCIPCommFault(_POSITIV)) THEN
gCIPCommFault := TRUE;
ELSE
gCIPCommFault := FALSE;
END_IF;
END_PROGRAM
(* === SUBFUNCIONES (ACTIONs convertidas) === *)
PROCEDURE CentralCIP_Ctrl_SignalsInterchange
(* Convertida desde ACTION *)
(* Código LAD convertido a SCL *)
// Red 1
IF (NOT mReadCIP_Read AND NOT mReadCIP_Busy) THEN
mReadCIP_Read := TRUE;
ELSE
mReadCIP_Read := FALSE;
END_IF;
// Red 3
// Llamada a función: mReadCIP_Block
IF mReadCIP_Block(_POSITIV) THEN
mDummy := TRUE;
ELSE
mDummy := FALSE;
END_IF;
// Red 2
IF mReadCIP_Block(_POSITIV) THEN
mReadCIP_Busy := TRUE;
ELSE
mReadCIP_Busy := FALSE;
END_IF;
END_PROCEDURE

View File

@ -1,98 +0,0 @@
(* Código SCL generado desde LAD TwinCAT *)
(* Convertidor mejorado con SymPy - Estructura DNF preferida *)
(* Path original: /TASK1_PID/PID_Controllers/Test_Program *)
PROGRAM Test_Pattern_Program
VAR
mDummy : BOOL;
mFillerEstSlew : SlewLimit;
mFillingHead_PID : FB41_PIDController;
END_VAR
(* === CÓDIGO PRINCIPAL === *)
(* Código LAD convertido *)
// Red 2
// Llamada a función: Test_Pattern_Program.Read_Analog
CALL Test_Pattern_Program.Read_Analog();
mDummy := TRUE; // ACTION ejecutada
// Red 1
// Patrón 1: ACTION call con ???
CALL Test_Pattern_Program.Read_Analog();
mDummy := TRUE; // ACTION ejecutada
// Red 4
// Llamada a función: mFillerEstSlew
// Sin optimización SymPy
IF mFillerEstSlew(_POSITIV) THEN
mDummy := TRUE;
ELSE
mDummy := FALSE;
END_IF;
// Red 3
// Patrón 2: Function Block directo
// Sin optimización SymPy
IF mFillerEstSlew(_POSITIV) THEN
mDummy := TRUE;
ELSE
mDummy := FALSE;
END_IF;
// Red 6
// Llamada a función: Test_Pattern_Program.Calculations
CALL Test_Pattern_Program.Calculations();
mDummy := TRUE; // ACTION ejecutada
// Red 5
// Patrón 3: Otra ACTION call con ???
CALL Test_Pattern_Program.Calculations();
mDummy := TRUE; // ACTION ejecutada
// Red 8
// Llamada a función: mFillingHead_PID
// Sin optimización SymPy
IF mFillingHead_PID(_POSITIV) THEN
mDummy := TRUE;
ELSE
mDummy := FALSE;
END_IF;
// Red 7
// Patrón 4: Function Block PID directo
// Sin optimización SymPy
IF mFillingHead_PID(_POSITIV) THEN
mPIDOutput := TRUE;
ELSE
mPIDOutput := FALSE;
END_IF;
END_PROGRAM
(* === SUBFUNCIONES (ACTIONs convertidas) === *)
PROCEDURE Test_Pattern_Program_Read_Analog
(* Convertida desde ACTION *)
(* Código LAD convertido a SCL *)
// Red 1
// ACTION de ejemplo
IF gAnalogEnable THEN
gAnalogValue := TRUE;
ELSE
gAnalogValue := FALSE;
END_IF;
END_PROCEDURE
PROCEDURE Test_Pattern_Program_Calculations
(* Convertida desde ACTION *)
(* Código ST original *)
gCalculatedValue := gInputA + gInputB * 2.5;
mDummy := TRUE;
END_PROCEDURE

View File

@ -1,139 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import os
# Agregar el directorio padre al path
sys.path.append('.')
# Importar el convertidor
from x1_lad_converter import SimpleLadConverter
def test_filling_head_pid():
"""Probar específicamente _FILLING_HEAD_PID_CTRL.EXP con parser mejorado"""
print("=== TEST: _FILLING_HEAD_PID_CTRL.EXP con parser mejorado ===")
print("Verificando detección de patrones ??? para ACTION calls")
print("-" * 60)
# Buscar el archivo
possible_paths = [
"ExportTwinCat/_FILLING_HEAD_PID_CTRL.EXP",
"../ExportTwinCat/_FILLING_HEAD_PID_CTRL.EXP",
"../../ExportTwinCat/_FILLING_HEAD_PID_CTRL.EXP",
"C:/Trabajo/SIDEL/13 - E5.007560 - Modifica O&U - SAE235/Reporte/ExportTwinCat/_FILLING_HEAD_PID_CTRL.EXP"
]
test_file = None
for path in possible_paths:
if os.path.exists(path):
test_file = path
break
if test_file is None:
print(f"❌ Error: No se encontró _FILLING_HEAD_PID_CTRL.EXP")
return
print(f"✓ Archivo encontrado: {test_file}")
print("-" * 60)
# Crear convertidor
converter = SimpleLadConverter()
# Parsear archivo
print("🔍 PARSEANDO ARCHIVO CON PARSER MEJORADO...")
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 = []
unresolved_calls = []
print(f"\n🔍 ANÁLISIS DE REDES:")
for i, network in enumerate(converter.networks):
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)
if logic_name == '???':
unresolved_calls.append(f"Red {network['id']}")
print(f" ❌ Red {network['id']}: ACTION call SIN RESOLVER → {logic_name}")
else:
print(f" ✅ Red {network['id']}: ACTION call RESUELTO → {logic_name}")
elif logic_type == 'FUNCTION_BLOCK':
function_blocks.append(logic_name)
print(f" 🔧 Red {network['id']}: Function Block → {logic_name}")
else:
print(f" Red {network['id']}: {logic_type}{logic_name}")
print(f"\n📈 ESTADÍSTICAS:")
print(f" 📞 ACTION calls encontradas: {len(action_calls)}")
print(f" ✅ Resueltas: {len([x for x in action_calls if x != '???'])}")
print(f" ❌ Sin resolver: {len([x for x in action_calls if x == '???'])}")
print(f" 🔧 Function Blocks: {len(function_blocks)}")
if unresolved_calls:
print(f"\n⚠ REDES CON PROBLEMAS:")
for call in unresolved_calls:
print(f"{call}")
# 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_filling_head_debug.scl"
with open(output_file, 'w', encoding='utf-8') as f:
f.write(scl_code)
print(f" ✓ Guardado en: {output_file}")
# Buscar problemas en el código generado
lines = scl_code.split('\n')
problem_lines = []
for i, line in enumerate(lines, 1):
if '???' in line:
problem_lines.append(f"Línea {i}: {line.strip()}")
if problem_lines:
print(f"\n⚠ PROBLEMAS EN CÓDIGO SCL GENERADO:")
for problem in problem_lines:
print(f"{problem}")
else:
print(f"\n✅ CÓDIGO SCL SIN PROBLEMAS ??? DETECTADOS")
# Mostrar sección principal del código generado
print(f"\n📄 CÓDIGO PRINCIPAL (primeras 30 líneas relevantes):")
main_start = -1
for i, line in enumerate(lines):
if "CÓDIGO PRINCIPAL" in line:
main_start = i
break
if main_start > -1:
relevant_lines = []
for i in range(main_start, min(main_start + 50, len(lines))):
line = lines[i]
if ('CALL ' in line or
'Red ' in line or
'IF ' in line or
'mDummy :=' in line):
relevant_lines.append(f" {i+1:3d}: {line}")
for line in relevant_lines[:30]:
print(line)
if len(relevant_lines) > 30:
print(f" ... ({len(relevant_lines) - 30} líneas más)")
return scl_code
if __name__ == "__main__":
test_filling_head_pid()

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -15,5 +15,5 @@
"xref_source_subdir": "source" "xref_source_subdir": "source"
}, },
"level3": {}, "level3": {},
"working_directory": "C:\\Trabajo\\SIDEL\\13 - E5.007560 - Modifica O&U - SAE235\\Reporte\\ExportTia" "working_directory": "D:\\Trabajo\\VM\\44 - 98050 - Fiera\\Reporte\\ExportsTia\\Source"
} }

View File

@ -1,9 +1,9 @@
{ {
"path": "C:\\Trabajo\\SIDEL\\13 - E5.007560 - Modifica O&U - SAE235\\Reporte\\ExportTia", "path": "D:\\Trabajo\\VM\\44 - 98050 - Fiera\\Reporte\\ExportsTia\\Source",
"history": [ "history": [
"D:\\Trabajo\\VM\\44 - 98050 - Fiera\\Reporte\\ExportsTia\\Source",
"C:\\Trabajo\\SIDEL\\13 - E5.007560 - Modifica O&U - SAE235\\Reporte\\ExportTia", "C:\\Trabajo\\SIDEL\\13 - E5.007560 - Modifica O&U - SAE235\\Reporte\\ExportTia",
"D:\\Trabajo\\VM\\22 - 93841 - Sidel - Tilting\\Reporte\\TiaExports", "D:\\Trabajo\\VM\\22 - 93841 - Sidel - Tilting\\Reporte\\TiaExports",
"D:\\Trabajo\\VM\\44 - 98050 - Fiera\\Reporte\\ExportsTia\\Source",
"C:\\Trabajo\\SIDEL\\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\\Reporte\\SourceDoc\\SourceXML", "C:\\Trabajo\\SIDEL\\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\\Reporte\\SourceDoc\\SourceXML",
"C:\\Trabajo\\SIDEL\\06 - E5.007363 - Modifica O&U - SAE196 (cip integrato)\\Reporte\\IOExport" "C:\\Trabajo\\SIDEL\\06 - E5.007363 - Modifica O&U - SAE196 (cip integrato)\\Reporte\\IOExport"
] ]

17675
data/log.txt

File diff suppressed because it is too large Load Diff