Compare commits
5 Commits
be3b333491
...
734e6637bc
Author | SHA1 | Date |
---|---|---|
|
734e6637bc | |
|
6150c719ca | |
|
0488624d64 | |
|
e70852ecf1 | |
|
04084e7289 |
|
@ -25,6 +25,9 @@ share/python-wheels/
|
||||||
.installed.cfg
|
.installed.cfg
|
||||||
*.egg
|
*.egg
|
||||||
MANIFEST
|
MANIFEST
|
||||||
|
*.txt
|
||||||
|
*.json
|
||||||
|
|
||||||
|
|
||||||
# PyInstaller
|
# PyInstaller
|
||||||
# Usually these files are written by a python script from a template
|
# Usually these files are written by a python script from a template
|
||||||
|
|
69
app.py
69
app.py
|
@ -33,6 +33,37 @@ websocket_connections = set()
|
||||||
# --- Globals for Tray Icon ---
|
# --- Globals for Tray Icon ---
|
||||||
tray_icon = None
|
tray_icon = None
|
||||||
|
|
||||||
|
# --- Parámetros para envío por lotes de logs ---
|
||||||
|
BATCH_FLUSH_INTERVAL = 0.5 # segundos
|
||||||
|
broadcast_buffer = [] # Almacena líneas formateadas pendientes de envío
|
||||||
|
buffer_lock = threading.Lock() # Sincroniza acceso al buffer
|
||||||
|
|
||||||
|
def _broadcast_flush_loop():
|
||||||
|
"""Hilo que vacía el buffer de logs cada BATCH_FLUSH_INTERVAL segundos."""
|
||||||
|
while True:
|
||||||
|
time.sleep(BATCH_FLUSH_INTERVAL)
|
||||||
|
with buffer_lock:
|
||||||
|
if not broadcast_buffer:
|
||||||
|
continue
|
||||||
|
batch = "\n".join(broadcast_buffer)
|
||||||
|
broadcast_buffer.clear()
|
||||||
|
_send_batch_to_clients(batch)
|
||||||
|
|
||||||
|
def _send_batch_to_clients(batch_message: str):
|
||||||
|
"""Envía un bloque de texto a todas las conexiones WebSocket activas."""
|
||||||
|
dead_connections = set()
|
||||||
|
for ws in list(websocket_connections):
|
||||||
|
try:
|
||||||
|
if ws.connected:
|
||||||
|
ws.send(batch_message + "\n")
|
||||||
|
except Exception:
|
||||||
|
dead_connections.add(ws)
|
||||||
|
websocket_connections.difference_update(dead_connections)
|
||||||
|
|
||||||
|
# Iniciar hilo de vaciado en segundo plano (ahora que las dependencias están definidas)
|
||||||
|
flusher_thread = threading.Thread(target=_broadcast_flush_loop, daemon=True)
|
||||||
|
flusher_thread.start()
|
||||||
|
|
||||||
|
|
||||||
@sock.route("/ws")
|
@sock.route("/ws")
|
||||||
def handle_websocket(ws):
|
def handle_websocket(ws):
|
||||||
|
@ -49,49 +80,34 @@ def handle_websocket(ws):
|
||||||
|
|
||||||
|
|
||||||
def broadcast_message(message):
|
def broadcast_message(message):
|
||||||
"""Envía un mensaje a todas las conexiones WebSocket activas y guarda en log."""
|
"""Acumula mensajes en un buffer y los envía por lotes cada 500 ms."""
|
||||||
dead_connections = set()
|
|
||||||
timestamp = datetime.now().strftime("[%H:%M:%S] ")
|
timestamp = datetime.now().strftime("[%H:%M:%S] ")
|
||||||
|
|
||||||
# Normalize input to a list of messages
|
# Normalizar entrada a lista de mensajes
|
||||||
if isinstance(message, list):
|
if isinstance(message, list):
|
||||||
messages = message
|
messages = message
|
||||||
else:
|
else:
|
||||||
# Si es un solo mensaje, dividirlo en líneas
|
|
||||||
messages = [line.strip() for line in message.splitlines() if line.strip()]
|
messages = [line.strip() for line in message.splitlines() if line.strip()]
|
||||||
|
|
||||||
# Procesar cada mensaje
|
|
||||||
for raw_msg in messages:
|
for raw_msg in messages:
|
||||||
# Limpiar timestamps duplicados al inicio del mensaje
|
# Limpiar timestamps duplicados al inicio del mensaje
|
||||||
while raw_msg.startswith("[") and "]" in raw_msg:
|
while raw_msg.startswith("[") and "]" in raw_msg:
|
||||||
try:
|
try:
|
||||||
closing_bracket = raw_msg.index("]") + 1
|
closing_bracket = raw_msg.index("]") + 1
|
||||||
if raw_msg[1 : closing_bracket - 1].replace(":", "").isdigit():
|
if raw_msg[1:closing_bracket - 1].replace(":", "").isdigit():
|
||||||
raw_msg = raw_msg[closing_bracket:].strip() # Update raw_msg itself
|
raw_msg = raw_msg[closing_bracket:].strip()
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
except:
|
except ValueError:
|
||||||
break
|
break
|
||||||
|
|
||||||
# Log the raw message using the config_manager's logger
|
# Registrar en archivo (la clase Logger añade timestamp propio)
|
||||||
# The logger will handle its own timestamping for the file.
|
|
||||||
config_manager.append_log(raw_msg)
|
config_manager.append_log(raw_msg)
|
||||||
|
|
||||||
# Format message with timestamp *for WebSocket broadcast*
|
# Formatear para el WebSocket y añadir al buffer
|
||||||
formatted_msg_for_ws = f"{timestamp}{raw_msg}"
|
formatted_msg_for_ws = f"{timestamp}{raw_msg}"
|
||||||
|
with buffer_lock:
|
||||||
# Enviar a todos los clientes WebSocket
|
broadcast_buffer.append(formatted_msg_for_ws)
|
||||||
for ws in list(websocket_connections):
|
|
||||||
try:
|
|
||||||
if ws.connected: # Check if ws is still connected before sending
|
|
||||||
ws.send(
|
|
||||||
f"{formatted_msg_for_ws}\n"
|
|
||||||
) # Use the correct variable name here
|
|
||||||
except Exception:
|
|
||||||
dead_connections.add(ws) # Collect dead connections
|
|
||||||
|
|
||||||
# Limpiar conexiones muertas
|
|
||||||
websocket_connections.difference_update(dead_connections)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/api/execute_script", methods=["POST"])
|
@app.route("/api/execute_script", methods=["POST"])
|
||||||
|
@ -1053,3 +1069,8 @@ if __name__ == "__main__":
|
||||||
print(f"Error al iniciar el icono de notificación: {e}", file=sys.stderr)
|
print(f"Error al iniciar el icono de notificación: {e}", file=sys.stderr)
|
||||||
|
|
||||||
print("Aplicación finalizada.")
|
print("Aplicación finalizada.")
|
||||||
|
|
||||||
|
# --- Iniciar hilo de vaciado en segundo plano (única vez) ---
|
||||||
|
# flusher_thread = threading.Thread(target=_broadcast_flush_loop, daemon=True)
|
||||||
|
# flusher_thread.start()
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,251 +1,199 @@
|
||||||
--- Log de Ejecución: x4.py ---
|
--- Log de Ejecución: x4.py ---
|
||||||
Grupo: ObtainIOFromProjectTia
|
Grupo: ObtainIOFromProjectTia
|
||||||
Directorio de Trabajo: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\SourceDoc\SourceXML
|
Directorio de Trabajo: D:\Trabajo\VM\22 - 93841 - Sidel - Tilting\Reporte\TiaExports
|
||||||
Inicio: 2025-05-20 12:12:51
|
Inicio: 2025-06-13 11:14:30
|
||||||
Fin: 2025-05-20 12:20:01
|
Fin: 2025-06-13 11:16:43
|
||||||
Duración: 0:07:09.648304
|
Duración: 0:02:13.165274
|
||||||
Estado: SUCCESS (Código de Salida: 0)
|
Estado: SUCCESS (Código de Salida: 0)
|
||||||
|
|
||||||
--- SALIDA ESTÁNDAR (STDOUT) ---
|
--- SALIDA ESTÁNDAR (STDOUT) ---
|
||||||
--- TIA Portal Cross-Reference Exporter ---
|
--- Exportador de Referencias Cruzadas de TIA Portal ---
|
||||||
|
Versión de TIA Portal detectada: 19.0 (de la extensión .ap19)
|
||||||
|
|
||||||
Selected Project: C:/Trabajo/SIDEL/09 - SAE452 - Diet as Regular - San Giovanni in Bosco/Reporte/SourceDoc/Migration/SAE452/SAE452.ap18
|
Proyecto seleccionado: D:/Trabajo/VM/22 - 93841 - Sidel - Tilting/InLavoro/PLC/93841_PLC_28/93841_PLC_28.ap19
|
||||||
Using Base Export Directory: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\SourceDoc\SourceXML
|
Usando directorio base de exportación: D:\Trabajo\VM\22 - 93841 - Sidel - Tilting\Reporte\TiaExports
|
||||||
|
|
||||||
Connecting to TIA Portal V18.0...
|
Conectando a TIA Portal V19.0...
|
||||||
2025-05-20 12:12:56,780 [1] INFO Siemens.TiaPortal.OpennessApi18.Implementations.Global OpenPortal - Start TIA Portal, please acknowledge the security dialog.
|
2025-06-13 11:14:34,713 [1] INFO Siemens.TiaPortal.OpennessApi19.Implementations.Global OpenPortal - Start TIA Portal, please acknowledge the security dialog.
|
||||||
2025-05-20 12:12:56,804 [1] INFO Siemens.TiaPortal.OpennessApi18.Implementations.Global OpenPortal - With user interface
|
2025-06-13 11:14:34,731 [1] INFO Siemens.TiaPortal.OpennessApi19.Implementations.Global OpenPortal - With user interface
|
||||||
Connected to TIA Portal.
|
Conectado a TIA Portal.
|
||||||
2025-05-20 12:13:30,582 [1] INFO Siemens.TiaPortal.OpennessApi18.Implementations.Portal GetProcessId - Process id: 21952
|
2025-06-13 11:14:58,165 [1] INFO Siemens.TiaPortal.OpennessApi19.Implementations.Portal GetProcessId - Process id: 30140
|
||||||
Portal Process ID: 21952
|
ID del proceso del Portal: 30140
|
||||||
Opening project: SAE452.ap18...
|
Abriendo proyecto: 93841_PLC_28.ap19...
|
||||||
2025-05-20 12:13:31,077 [1] INFO Siemens.TiaPortal.OpennessApi18.Implementations.Portal OpenProject - Open project... C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\SourceDoc\Migration\SAE452\SAE452.ap18
|
2025-06-13 11:14:58,500 [1] INFO Siemens.TiaPortal.OpennessApi19.Implementations.Portal OpenProject - Open project... D:\Trabajo\VM\22 - 93841 - Sidel - Tilting\InLavoro\PLC\93841_PLC_28\93841_PLC_28.ap19
|
||||||
Project opened successfully.
|
Proyecto abierto exitosamente.
|
||||||
2025-05-20 12:14:15,234 [1] INFO Siemens.TiaPortal.OpennessApi18.Implementations.Project GetPlcs - Found plc CPU 315F-2 PN/DP with parent name _SSAE0452
|
2025-06-13 11:15:29,701 [1] INFO Siemens.TiaPortal.OpennessApi19.Implementations.Project GetPlcs - Found plc VM 1512 with parent name ET 200SP station_1
|
||||||
Found 1 PLC(s). Starting cross-reference export process...
|
2025-06-13 11:15:30,551 [1] INFO Siemens.TiaPortal.OpennessApi19.Implementations.Project GetPlcs - Found plc SIDEL Transport Example with parent name S71500/ET200MP station_1
|
||||||
|
Se encontraron 2 PLC(s). Iniciando proceso de exportación de referencias cruzadas...
|
||||||
|
|
||||||
--- Processing PLC: CPU 315F-2 PN/DP ---
|
--- Procesando PLC: VM 1512 ---
|
||||||
|
|
||||||
[PLC: CPU 315F-2 PN/DP] Exporting Program Block Cross-References...
|
[PLC: VM 1512] Exportando referencias cruzadas de bloques de programa...
|
||||||
Target: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\SourceDoc\SourceXML\CPU 315F-2 PN\DP\ProgramBlocks_CR
|
Destino: D:\Trabajo\VM\22 - 93841 - Sidel - Tilting\Reporte\TiaExports\VM 1512\ProgramBlocks_CR
|
||||||
Found 410 program blocks.
|
Se encontraron 201 bloques de programa.
|
||||||
Processing block: ISOonTCP_or_TCP_Protocol...
|
Procesando bloque: FC General COM...
|
||||||
Exporting cross-references for ISOonTCP_or_TCP_Protocol...
|
Exportando referencias cruzadas para FC General COM...
|
||||||
Processing block: PIDControl...
|
Procesando bloque: From_SIDEL...
|
||||||
Exporting cross-references for PIDControl...
|
Exportando referencias cruzadas para From_SIDEL...
|
||||||
Processing block: DETAIL_DP_DIAG...
|
Procesando bloque: To_SIDEL...
|
||||||
Exporting cross-references for DETAIL_DP_DIAG...
|
Exportando referencias cruzadas para To_SIDEL...
|
||||||
Processing block: Net Dosing Sys Prof...
|
Procesando bloque: DB Early Restart Blower...
|
||||||
Exporting cross-references for Net Dosing Sys Prof...
|
Exportando referencias cruzadas para DB Early Restart Blower...
|
||||||
Processing block: ICS Profibus Comm...
|
Procesando bloque: DB Early Restart Filler...
|
||||||
Exporting cross-references for ICS Profibus Comm...
|
Exportando referencias cruzadas para DB Early Restart Filler...
|
||||||
Processing block: GNS DriveDiag...
|
Procesando bloque: DB Early Restart SynchroBlock...
|
||||||
Exporting cross-references for GNS DriveDiag...
|
Exportando referencias cruzadas para DB Early Restart SynchroBlock...
|
||||||
Processing block: HMI_Blender_Parameters...
|
Procesando bloque: FB Early Restart...
|
||||||
Exporting cross-references for HMI_Blender_Parameters...
|
Exportando referencias cruzadas para FB Early Restart...
|
||||||
Processing block: HMI Drive...
|
Procesando bloque: DB Signal Transport...
|
||||||
Exporting cross-references for HMI Drive...
|
Exportando referencias cruzadas para DB Signal Transport...
|
||||||
Processing block: GNS DriveDiagMain...
|
Procesando bloque: FC Signal Transport...
|
||||||
Exporting cross-references for GNS DriveDiagMain...
|
Exportando referencias cruzadas para FC Signal Transport...
|
||||||
Processing block: Integral...
|
Procesando bloque: DB Lube - Dry Ecolab...
|
||||||
Exporting cross-references for Integral...
|
Exportando referencias cruzadas para DB Lube - Dry Ecolab...
|
||||||
Processing block: LowPassFilter...
|
Procesando bloque: FB Lube - Water/Dry...
|
||||||
Exporting cross-references for LowPassFilter...
|
Exportando referencias cruzadas para FB Lube - Water/Dry...
|
||||||
Processing block: SlewLimit...
|
Procesando bloque: FB Lube - Dry Ecolab...
|
||||||
Exporting cross-references for SlewLimit...
|
Exportando referencias cruzadas para FB Lube - Dry Ecolab...
|
||||||
Processing block: MSE Slope...
|
Procesando bloque: FB Lube - EcoLab VM...
|
||||||
Exporting cross-references for MSE Slope...
|
Exportando referencias cruzadas para FB Lube - EcoLab VM...
|
||||||
Processing block: Statistical_Analisys...
|
Procesando bloque: FB Lube - Ecolab...
|
||||||
Exporting cross-references for Statistical_Analisys...
|
Exportando referencias cruzadas para FB Lube - Ecolab...
|
||||||
Processing block: Blender_Variables...
|
Procesando bloque: DB LUBE - Ecolab...
|
||||||
Exporting cross-references for Blender_Variables...
|
Exportando referencias cruzadas para DB LUBE - Ecolab...
|
||||||
Processing block: BrixTracking_ProdSamples...
|
Procesando bloque: FC Ttop Configuration...
|
||||||
Exporting cross-references for BrixTracking_ProdSamples...
|
Exportando referencias cruzadas para FC Ttop Configuration...
|
||||||
Processing block: Procedure_Variables...
|
Procesando bloque: FC Ttop Run...
|
||||||
Exporting cross-references for Procedure_Variables...
|
Exportando referencias cruzadas para FC Ttop Run...
|
||||||
Processing block: Blender_Constants...
|
Procesando bloque: FC Ttop Alarms...
|
||||||
Exporting cross-references for Blender_Constants...
|
Exportando referencias cruzadas para FC Ttop Alarms...
|
||||||
Processing block: BrixTracking_SampleTime...
|
Procesando bloque: DB Ttop Run...
|
||||||
Exporting cross-references for BrixTracking_SampleTime...
|
Exportando referencias cruzadas para DB Ttop Run...
|
||||||
Processing block: Delay...
|
Procesando bloque: DB Ttop Motor CFG...
|
||||||
Exporting cross-references for Delay...
|
Exportando referencias cruzadas para DB Ttop Motor CFG...
|
||||||
Processing block: CO2Tracking_ProdSamples...
|
Procesando bloque: DB Ttop Alarm...
|
||||||
Exporting cross-references for CO2Tracking_ProdSamples...
|
Exportando referencias cruzadas para DB Ttop Alarm...
|
||||||
Processing block: CO2Tracking_SampleTime...
|
Procesando bloque: FC Ttop Motor 31...
|
||||||
Exporting cross-references for CO2Tracking_SampleTime...
|
Exportando referencias cruzadas para FC Ttop Motor 31...
|
||||||
Processing block: Interlocking_Variables...
|
Procesando bloque: FC Ttop Motor 32...
|
||||||
Exporting cross-references for Interlocking_Variables...
|
Exportando referencias cruzadas para FC Ttop Motor 32...
|
||||||
Processing block: System_RunOut_Variables...
|
Procesando bloque: FC Ttop Motor 34...
|
||||||
Exporting cross-references for System_RunOut_Variables...
|
Exportando referencias cruzadas para FC Ttop Motor 34...
|
||||||
Processing block: CIP_Program_Variables...
|
Procesando bloque: FC Ttop Motor 35...
|
||||||
Exporting cross-references for CIP_Program_Variables...
|
Exportando referencias cruzadas para FC Ttop Motor 35...
|
||||||
Processing block: Filler_Head_Variables...
|
Procesando bloque: FC Ttop Motor 36...
|
||||||
Exporting cross-references for Filler_Head_Variables...
|
Exportando referencias cruzadas para FC Ttop Motor 36...
|
||||||
Processing block: Filling_Time_Tranfer_DB...
|
Procesando bloque: DB Ttop Motor 31...
|
||||||
Exporting cross-references for Filling_Time_Tranfer_DB...
|
Exportando referencias cruzadas para DB Ttop Motor 31...
|
||||||
Processing block: Blender_Variables_Pers...
|
Procesando bloque: DB Ttop Motor 32...
|
||||||
Exporting cross-references for Blender_Variables_Pers...
|
Exportando referencias cruzadas para DB Ttop Motor 32...
|
||||||
Processing block: HMI_Alarms...
|
Procesando bloque: DB Ttop Motor 34...
|
||||||
Exporting cross-references for HMI_Alarms...
|
Exportando referencias cruzadas para DB Ttop Motor 34...
|
||||||
Processing block: HMI_Local_CIP_Variables...
|
Procesando bloque: DB Ttop Motor 35...
|
||||||
Exporting cross-references for HMI_Local_CIP_Variables...
|
Exportando referencias cruzadas para DB Ttop Motor 35...
|
||||||
Processing block: HMI_Service...
|
Procesando bloque: DB Ttop Minimotor Cfg 32...
|
||||||
Exporting cross-references for HMI_Service...
|
Exportando referencias cruzadas para DB Ttop Minimotor Cfg 32...
|
||||||
Processing block: HMI_Variables_Cmd...
|
Procesando bloque: DB Ttop Minimotor Data 32...
|
||||||
Exporting cross-references for HMI_Variables_Cmd...
|
Exportando referencias cruzadas para DB Ttop Minimotor Data 32...
|
||||||
Processing block: HMI_Variables_Status...
|
Procesando bloque: DB Ttop Motor 36...
|
||||||
Exporting cross-references for HMI_Variables_Status...
|
Exportando referencias cruzadas para DB Ttop Motor 36...
|
||||||
Processing block: HMI_Device...
|
Procesando bloque: FB Ttop Dryer...
|
||||||
Exporting cross-references for HMI_Device...
|
Exportando referencias cruzadas para FB Ttop Dryer...
|
||||||
Processing block: HMI_Instrument...
|
Procesando bloque: FB Ttop Energy Saving...
|
||||||
Exporting cross-references for HMI_Instrument...
|
Exportando referencias cruzadas para FB Ttop Energy Saving...
|
||||||
Processing block: HMI_Digital...
|
Procesando bloque: FB SKID...
|
||||||
Exporting cross-references for HMI_Digital...
|
Exportando referencias cruzadas para FB SKID...
|
||||||
Processing block: HMI_PID...
|
Procesando bloque: FC Analog Sensor Process...
|
||||||
Exporting cross-references for HMI_PID...
|
Exportando referencias cruzadas para FC Analog Sensor Process...
|
||||||
Processing block: HMI_ICS...
|
Procesando bloque: FC Valve...
|
||||||
Exporting cross-references for HMI_ICS...
|
Exportando referencias cruzadas para FC Valve...
|
||||||
Processing block: HMI_Device_AVS...
|
Procesando bloque: FB SpeedRegulation...
|
||||||
Exporting cross-references for HMI_Device_AVS...
|
Exportando referencias cruzadas para FB SpeedRegulation...
|
||||||
Processing block: Profibus_Variables...
|
Procesando bloque: FC Simple PID...
|
||||||
Exporting cross-references for Profibus_Variables...
|
Exportando referencias cruzadas para FC Simple PID...
|
||||||
Processing block: Input_CheckFlowMetersSta...
|
Procesando bloque: FC Scale Real...
|
||||||
Exporting cross-references for Input_CheckFlowMetersSta...
|
Exportando referencias cruzadas para FC Scale Real...
|
||||||
Processing block: Input_DigitalScanner...
|
Procesando bloque: FB Correct Speed F/Pulses...
|
||||||
Exporting cross-references for Input_DigitalScanner...
|
Exportando referencias cruzadas para FB Correct Speed F/Pulses...
|
||||||
Processing block: ProductLiterInTank...
|
ERROR GENERAL al exportar referencias cruzadas para el bloque FB Correct Speed F/Pulses: OpennessAccessException: Unexpected exception - no exception message available.
|
||||||
Exporting cross-references for ProductLiterInTank...
|
ERROR al acceder a los bloques de programa para exportar referencias cruzadas: OpennessAccessException: Access to a disposed object of type 'Siemens.Engineering.SW.Blocks.FB' is not possible.
|
||||||
Processing block: ProductAvailable...
|
|
||||||
Exporting cross-references for ProductAvailable...
|
|
||||||
Processing block: T_Timer...
|
|
||||||
Exporting cross-references for T_Timer...
|
|
||||||
Processing block: SEL_I...
|
|
||||||
Exporting cross-references for SEL_I...
|
|
||||||
Processing block: _StepMove...
|
|
||||||
Exporting cross-references for _StepMove...
|
|
||||||
Processing block: ProductPipeDrain_Seq...
|
|
||||||
Exporting cross-references for ProductPipeDrain_Seq...
|
|
||||||
Processing block: ProductPipeDrain...
|
|
||||||
Exporting cross-references for ProductPipeDrain...
|
|
||||||
Processing block: ProductPipeRunOut_Seq...
|
|
||||||
Exporting cross-references for ProductPipeRunOut_Seq...
|
|
||||||
Processing block: SEL_R...
|
|
||||||
Exporting cross-references for SEL_R...
|
|
||||||
Processing block: ProductPipeRunOut...
|
|
||||||
Exporting cross-references for ProductPipeRunOut...
|
|
||||||
Processing block: LIMIT_I...
|
|
||||||
Exporting cross-references for LIMIT_I...
|
|
||||||
Processing block: System_Run_Out...
|
|
||||||
Exporting cross-references for System_Run_Out...
|
|
||||||
Processing block: System_Run_Out_Data...
|
|
||||||
Exporting cross-references for System_Run_Out_Data...
|
|
||||||
ERROR accessing Program Blocks for cross-reference export: RemotingException: El objeto '/bd68de4c_3307_463d_b3ce_57a1378b3bde/lnycb9uriadrpgmom_mjdspm_249.rem' se desconectó o no existe en el servidor.
|
|
||||||
|
|
||||||
[PLC: CPU 315F-2 PN/DP] Exporting PLC Tag Table Cross-References...
|
TIA Portal has either been disposed or stopped running.
|
||||||
Target: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\SourceDoc\SourceXML\CPU 315F-2 PN\DP\PlcTags_CR
|
|
||||||
Found 2 Tag Tables.
|
|
||||||
Processing Tag Table: Default tag table...
|
|
||||||
Exporting cross-references for Default tag table...
|
|
||||||
Processing Tag Table: STEP7 classic symbols...
|
|
||||||
Exporting cross-references for STEP7 classic symbols...
|
|
||||||
Tag Table CR Export Summary: Exported=2, Skipped/Errors=0
|
|
||||||
|
|
||||||
[PLC: CPU 315F-2 PN/DP] Exporting PLC Data Type (UDT) Cross-References...
|
[PLC: VM 1512] Exportando referencias cruzadas de tablas de variables...
|
||||||
Target: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\SourceDoc\SourceXML\CPU 315F-2 PN\DP\PlcDataTypes_CR
|
Destino: D:\Trabajo\VM\22 - 93841 - Sidel - Tilting\Reporte\TiaExports\VM 1512\PlcTags_CR
|
||||||
Found 21 UDTs.
|
ERROR al acceder a las tablas de variables para exportar referencias cruzadas: SerializationException: No se puede encontrar el ensamblado 'Siemens.Engineering, Version=19.0.0.0, Culture=neutral, PublicKeyToken=d29ec89bac048f84'.
|
||||||
Processing UDT: AnyPoint...
|
|
||||||
Exporting cross-references for AnyPoint...
|
|
||||||
Processing UDT: FunctionButton...
|
|
||||||
Exporting cross-references for FunctionButton...
|
|
||||||
Processing UDT: TADDR_PAR...
|
|
||||||
Exporting cross-references for TADDR_PAR...
|
|
||||||
Processing UDT: Device...
|
|
||||||
Exporting cross-references for Device...
|
|
||||||
Processing UDT: AnalogInstrument...
|
|
||||||
Exporting cross-references for AnalogInstrument...
|
|
||||||
Processing UDT: DigitalInstrument...
|
|
||||||
Exporting cross-references for DigitalInstrument...
|
|
||||||
Processing UDT: PID...
|
|
||||||
Exporting cross-references for PID...
|
|
||||||
Processing UDT: EHS16...
|
|
||||||
Exporting cross-references for EHS16...
|
|
||||||
Processing UDT: Danfoss Diag...
|
|
||||||
Exporting cross-references for Danfoss Diag...
|
|
||||||
Processing UDT: QCO Timer...
|
|
||||||
Exporting cross-references for QCO Timer...
|
|
||||||
Processing UDT: QCO Phase...
|
|
||||||
Exporting cross-references for QCO Phase...
|
|
||||||
Processing UDT: ReportCIPSimpleData...
|
|
||||||
Exporting cross-references for ReportCIPSimpleData...
|
|
||||||
Processing UDT: CIP_WaitEvent_Type...
|
|
||||||
Exporting cross-references for CIP_WaitEvent_Type...
|
|
||||||
Processing UDT: CIP_Step_Type_New...
|
|
||||||
Exporting cross-references for CIP_Step_Type_New...
|
|
||||||
Processing UDT: CIP_Simple_Type...
|
|
||||||
Exporting cross-references for CIP_Simple_Type...
|
|
||||||
Processing UDT: CIP_Link_Type...
|
|
||||||
Exporting cross-references for CIP_Link_Type...
|
|
||||||
Processing UDT: CIP_Step_Type...
|
|
||||||
Exporting cross-references for CIP_Step_Type...
|
|
||||||
Processing UDT: Recipe_Prod...
|
|
||||||
Exporting cross-references for Recipe_Prod...
|
|
||||||
Processing UDT: ICS Hndsk receive signal...
|
|
||||||
Exporting cross-references for ICS Hndsk receive signal...
|
|
||||||
Processing UDT: ICS Hndsk send signal...
|
|
||||||
Exporting cross-references for ICS Hndsk send signal...
|
|
||||||
Processing UDT: TCON_PAR...
|
|
||||||
Exporting cross-references for TCON_PAR...
|
|
||||||
UDT CR Export Summary: Exported=21, Skipped/Errors=0
|
|
||||||
|
|
||||||
[PLC: CPU 315F-2 PN/DP] Attempting to Export System Block Cross-References...
|
[PLC: VM 1512] Exportando referencias cruzadas de tipos de datos PLC (UDTs)...
|
||||||
Target: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\SourceDoc\SourceXML\CPU 315F-2 PN\DP\SystemBlocks_CR
|
Destino: D:\Trabajo\VM\22 - 93841 - Sidel - Tilting\Reporte\TiaExports\VM 1512\PlcDataTypes_CR
|
||||||
Found 12 system blocks (using get_system_blocks).
|
ERROR al acceder a los UDTs para exportar referencias cruzadas: SerializationException: No se puede encontrar el ensamblado 'Siemens.Engineering, Version=19.0.0.0, Culture=neutral, PublicKeyToken=d29ec89bac048f84'.
|
||||||
Processing System Block: TIM_S5TI...
|
|
||||||
Exporting cross-references for TIM_S5TI...
|
|
||||||
Processing System Block: REPLACE...
|
|
||||||
Exporting cross-references for REPLACE...
|
|
||||||
Processing System Block: LIMIT...
|
|
||||||
Exporting cross-references for LIMIT...
|
|
||||||
Processing System Block: NE_STRNG...
|
|
||||||
Exporting cross-references for NE_STRNG...
|
|
||||||
Processing System Block: TURCV...
|
|
||||||
Exporting cross-references for TURCV...
|
|
||||||
Processing System Block: TUSEND...
|
|
||||||
Exporting cross-references for TUSEND...
|
|
||||||
Processing System Block: PID_Continuos...
|
|
||||||
Exporting cross-references for PID_Continuos...
|
|
||||||
Processing System Block: TDISCON...
|
|
||||||
Exporting cross-references for TDISCON...
|
|
||||||
Processing System Block: TCON...
|
|
||||||
Exporting cross-references for TCON...
|
|
||||||
Processing System Block: TRCV...
|
|
||||||
Exporting cross-references for TRCV...
|
|
||||||
Processing System Block: TSEND...
|
|
||||||
Exporting cross-references for TSEND...
|
|
||||||
Processing System Block: DT_DATE...
|
|
||||||
Exporting cross-references for DT_DATE...
|
|
||||||
System Block CR Export Summary: Exported=12, Skipped/Errors=0
|
|
||||||
|
|
||||||
[PLC: CPU 315F-2 PN/DP] Attempting to Export Software Unit Cross-References...
|
[PLC: VM 1512] Intentando exportar referencias cruzadas de bloques de sistema...
|
||||||
Target: C:\Trabajo\SIDEL\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\Reporte\SourceDoc\SourceXML\CPU 315F-2 PN\DP\SoftwareUnits_CR
|
Destino: D:\Trabajo\VM\22 - 93841 - Sidel - Tilting\Reporte\TiaExports\VM 1512\SystemBlocks_CR
|
||||||
Found 0 Software Units.
|
ERROR al acceder/procesar bloques de sistema para exportar referencias cruzadas: SerializationException: No se puede encontrar el ensamblado 'Siemens.Engineering, Version=19.0.0.0, Culture=neutral, PublicKeyToken=d29ec89bac048f84'.
|
||||||
Software Unit CR Export Summary: Exported=0, Skipped/Errors=0
|
|
||||||
|
|
||||||
--- Finished processing PLC: CPU 315F-2 PN/DP ---
|
[PLC: VM 1512] Intentando exportar referencias cruzadas de unidades de software...
|
||||||
|
Destino: D:\Trabajo\VM\22 - 93841 - Sidel - Tilting\Reporte\TiaExports\VM 1512\SoftwareUnits_CR
|
||||||
|
ERROR al acceder/procesar unidades de software para exportar referencias cruzadas: SerializationException: No se puede encontrar el ensamblado 'Siemens.Engineering, Version=19.0.0.0, Culture=neutral, PublicKeyToken=d29ec89bac048f84'.
|
||||||
|
|
||||||
Cross-reference export process completed.
|
--- Finalizado el procesamiento del PLC: VM 1512 ---
|
||||||
|
|
||||||
Closing TIA Portal...
|
Ocurrió un error inesperado: OpennessAccessException: Access to a disposed object of type 'Siemens.Engineering.HW.DeviceItemImpl' is not possible.
|
||||||
2025-05-20 12:19:54,187 [1] INFO Siemens.TiaPortal.OpennessApi18.Implementations.Portal ClosePortal - Close TIA Portal
|
|
||||||
TIA Portal closed.
|
|
||||||
|
|
||||||
Script finished.
|
TIA Portal has either been disposed or stopped running.
|
||||||
|
|
||||||
|
Cerrando TIA Portal...
|
||||||
|
2025-06-13 11:16:43,486 [1] INFO Siemens.TiaPortal.OpennessApi19.Implementations.Portal ClosePortal - Close TIA Portal
|
||||||
|
TIA Portal cerrado.
|
||||||
|
|
||||||
|
Script finalizado.
|
||||||
|
|
||||||
--- ERRORES (STDERR) ---
|
--- ERRORES (STDERR) ---
|
||||||
|
2025-06-13 11:16:43,458 [1] ERROR Siemens.TiaPortal.OpennessApi19.Implementations.ProgramBlock ExportCrossReferences -
|
||||||
|
Siemens.TiaPortal.OpennessContracts.OpennessAccessException: Unexpected exception - no exception message available.
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
File "D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\ObtainIOFromProjectTia\x4.py", line 99, in export_plc_cross_references
|
File "D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\ObtainIOFromProjectTia\x4.py", line 128, in export_plc_cross_references
|
||||||
|
block.export_cross_references(
|
||||||
|
ValueError: OpennessAccessException: Unexpected exception - no exception message available.
|
||||||
|
2025-06-13 11:16:43,462 [1] ERROR Siemens.TiaPortal.OpennessApi19.Implementations.ProgramBlock GetName -
|
||||||
|
Siemens.TiaPortal.OpennessContracts.OpennessAccessException: Access to a disposed object of type 'Siemens.Engineering.SW.Blocks.FB' is not possible.
|
||||||
|
|
||||||
|
TIA Portal has either been disposed or stopped running.
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\ObtainIOFromProjectTia\x4.py", line 124, in export_plc_cross_references
|
||||||
block_name = block.get_name()
|
block_name = block.get_name()
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
ValueError: RemotingException: El objeto '/bd68de4c_3307_463d_b3ce_57a1378b3bde/lnycb9uriadrpgmom_mjdspm_249.rem' se desconectó o no existe en el servidor.
|
ValueError: OpennessAccessException: Access to a disposed object of type 'Siemens.Engineering.SW.Blocks.FB' is not possible.
|
||||||
|
|
||||||
|
TIA Portal has either been disposed or stopped running.
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\ObtainIOFromProjectTia\x4.py", line 164, in export_plc_cross_references
|
||||||
|
tag_tables = plc.get_plc_tag_tables()
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
ValueError: SerializationException: No se puede encontrar el ensamblado 'Siemens.Engineering, Version=19.0.0.0, Culture=neutral, PublicKeyToken=d29ec89bac048f84'.
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\ObtainIOFromProjectTia\x4.py", line 207, in export_plc_cross_references
|
||||||
|
udts = plc.get_user_data_types()
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
ValueError: SerializationException: No se puede encontrar el ensamblado 'Siemens.Engineering, Version=19.0.0.0, Culture=neutral, PublicKeyToken=d29ec89bac048f84'.
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\ObtainIOFromProjectTia\x4.py", line 251, in export_plc_cross_references
|
||||||
|
system_blocks = plc.get_system_blocks()
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
ValueError: SerializationException: No se puede encontrar el ensamblado 'Siemens.Engineering, Version=19.0.0.0, Culture=neutral, PublicKeyToken=d29ec89bac048f84'.
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\ObtainIOFromProjectTia\x4.py", line 305, in export_plc_cross_references
|
||||||
|
software_units = plc.get_software_units()
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
ValueError: SerializationException: No se puede encontrar el ensamblado 'Siemens.Engineering, Version=19.0.0.0, Culture=neutral, PublicKeyToken=d29ec89bac048f84'.
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\ObtainIOFromProjectTia\x4.py", line 415, in <module>
|
||||||
|
export_plc_cross_references(
|
||||||
|
File "D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\ObtainIOFromProjectTia\x4.py", line 105, in export_plc_cross_references
|
||||||
|
plc_name = plc.get_name()
|
||||||
|
^^^^^^^^^^^^^^
|
||||||
|
ValueError: OpennessAccessException: Access to a disposed object of type 'Siemens.Engineering.HW.DeviceItemImpl' is not possible.
|
||||||
|
|
||||||
|
TIA Portal has either been disposed or stopped running.
|
||||||
|
|
||||||
--- FIN DEL LOG ---
|
--- FIN DEL LOG ---
|
||||||
|
|
|
@ -5,5 +5,5 @@
|
||||||
},
|
},
|
||||||
"level2": {},
|
"level2": {},
|
||||||
"level3": {},
|
"level3": {},
|
||||||
"working_directory": "D:\\Trabajo\\VM\\44 - 98050 - Fiera\\Reporte\\ExportsTia\\Source"
|
"working_directory": "D:\\Trabajo\\VM\\22 - 93841 - Sidel - Tilting\\Reporte\\TiaExports"
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"x1.py": {
|
"x1.py": {
|
||||||
"display_name": "1: Exportar Lógica desde TIA Portal v18 en XML",
|
"display_name": "1: Exportar Lógica desde TIA Portal v18,v19,v20 en XML",
|
||||||
"short_description": "Exporta la lógica del PLC desde TIA Portal en archivos XML y SCL.",
|
"short_description": "Exporta la lógica del PLC desde TIA Portal en archivos XML y SCL.",
|
||||||
"long_description": "Este script utiliza TIA Portal Openness para exportar la lógica de un PLC en formato XML y SCL. Permite seleccionar un proyecto de TIA Portal y genera los archivos de exportación en el directorio configurado.\n***\n**Lógica Principal:**\n\n1. **Configuración:** Carga parámetros desde `ParamManagerScripts` (directorio de trabajo, versión de TIA Portal).\n2. **Selección de Proyecto:** Abre un cuadro de diálogo para seleccionar el archivo del proyecto de TIA Portal.\n3. **Conexión a TIA Portal:** Utiliza la API de TIA Openness para conectarse al portal y abrir el proyecto seleccionado.\n4. **Exportación:** Exporta la lógica del PLC en archivos XML y SCL al directorio configurado.\n5. **Cierre:** Cierra la conexión con TIA Portal al finalizar.",
|
"long_description": "Este script utiliza TIA Portal Openness para exportar la lógica de un PLC en formato XML y SCL. Permite seleccionar un proyecto de TIA Portal y genera los archivos de exportación en el directorio configurado.\n***\n**Lógica Principal:**\n\n1. **Configuración:** Carga parámetros desde `ParamManagerScripts` (directorio de trabajo, versión de TIA Portal).\n2. **Selección de Proyecto:** Abre un cuadro de diálogo para seleccionar el archivo del proyecto de TIA Portal.\n3. **Conexión a TIA Portal:** Utiliza la API de TIA Openness para conectarse al portal y abrir el proyecto seleccionado.\n4. **Exportación:** Exporta la lógica del PLC en archivos XML y SCL al directorio configurado.\n5. **Cierre:** Cierra la conexión con TIA Portal al finalizar.",
|
||||||
"hidden": false
|
"hidden": false
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"path": "D:\\Trabajo\\VM\\44 - 98050 - Fiera\\Reporte\\ExportsTia\\Source",
|
"path": "D:\\Trabajo\\VM\\22 - 93841 - Sidel - Tilting\\Reporte\\TiaExports",
|
||||||
"history": [
|
"history": [
|
||||||
|
"D:\\Trabajo\\VM\\22 - 93841 - Sidel - Tilting\\Reporte\\TiaExports",
|
||||||
"D:\\Trabajo\\VM\\44 - 98050 - Fiera\\Reporte\\ExportsTia\\Source",
|
"D:\\Trabajo\\VM\\44 - 98050 - Fiera\\Reporte\\ExportsTia\\Source",
|
||||||
"C:\\Trabajo\\SIDEL\\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\\Reporte\\SourceDoc\\SourcdSD",
|
"C:\\Trabajo\\SIDEL\\09 - SAE452 - Diet as Regular - San Giovanni in Bosco\\Reporte\\SourceDoc\\SourcdSD",
|
||||||
"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"
|
||||||
|
|
|
@ -7,6 +7,7 @@ from tkinter import filedialog
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
|
from pathlib import Path # Import Path
|
||||||
|
|
||||||
script_root = os.path.dirname(
|
script_root = os.path.dirname(
|
||||||
os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
||||||
|
@ -15,11 +16,15 @@ sys.path.append(script_root)
|
||||||
from backend.script_utils import load_configuration
|
from backend.script_utils import load_configuration
|
||||||
|
|
||||||
# --- Configuration ---
|
# --- Configuration ---
|
||||||
TIA_PORTAL_VERSION = "18.0" # Target TIA Portal version (e.g., "18.0")
|
# Supported TIA Portal versions mapping (extension -> version)
|
||||||
|
SUPPORTED_TIA_VERSIONS = {
|
||||||
|
".ap18": "18.0",
|
||||||
|
".ap19": "19.0",
|
||||||
|
".ap20": "20.0"
|
||||||
|
}
|
||||||
|
|
||||||
EXPORT_OPTIONS = None # Use default export options
|
EXPORT_OPTIONS = None # Use default export options
|
||||||
KEEP_FOLDER_STRUCTURE = (
|
KEEP_FOLDER_STRUCTURE = True # Replicate TIA project folder structure in export directory
|
||||||
True # Replicate TIA project folder structure in export directory
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- TIA Scripting Import Handling ---
|
# --- TIA Scripting Import Handling ---
|
||||||
# Check if the TIA_SCRIPTING environment variable is set
|
# Check if the TIA_SCRIPTING environment variable is set
|
||||||
|
@ -59,6 +64,33 @@ except Exception as e:
|
||||||
|
|
||||||
# --- Functions ---
|
# --- Functions ---
|
||||||
|
|
||||||
|
def get_supported_filetypes():
|
||||||
|
"""Returns the supported file types for TIA Portal projects."""
|
||||||
|
filetypes = []
|
||||||
|
for ext, version in SUPPORTED_TIA_VERSIONS.items():
|
||||||
|
version_major = version.split('.')[0]
|
||||||
|
filetypes.append((f"TIA Portal V{version_major} Projects", f"*{ext}"))
|
||||||
|
|
||||||
|
# Add option to show all supported files
|
||||||
|
all_extensions = " ".join([f"*{ext}" for ext in SUPPORTED_TIA_VERSIONS.keys()])
|
||||||
|
filetypes.insert(0, ("All TIA Portal Projects", all_extensions))
|
||||||
|
|
||||||
|
return filetypes
|
||||||
|
|
||||||
|
def detect_tia_version(project_file_path):
|
||||||
|
"""Detects TIA Portal version based on file extension."""
|
||||||
|
file_path = Path(project_file_path)
|
||||||
|
file_extension = file_path.suffix.lower()
|
||||||
|
|
||||||
|
if file_extension in SUPPORTED_TIA_VERSIONS:
|
||||||
|
detected_version = SUPPORTED_TIA_VERSIONS[file_extension]
|
||||||
|
print(f"Versión de TIA Portal detectada: {detected_version} (de la extensión {file_extension})")
|
||||||
|
return detected_version
|
||||||
|
else:
|
||||||
|
print(f"ADVERTENCIA: Extensión de archivo no reconocida '{file_extension}'. Extensiones soportadas: {list(SUPPORTED_TIA_VERSIONS.keys())}")
|
||||||
|
# Default to version 18.0 for backward compatibility
|
||||||
|
print("Usando por defecto TIA Portal V18.0")
|
||||||
|
return "18.0"
|
||||||
|
|
||||||
def select_project_file():
|
def select_project_file():
|
||||||
"""Opens a dialog to select a TIA Portal project file."""
|
"""Opens a dialog to select a TIA Portal project file."""
|
||||||
|
@ -66,16 +98,11 @@ def select_project_file():
|
||||||
root.withdraw() # Hide the main tkinter window
|
root.withdraw() # Hide the main tkinter window
|
||||||
file_path = filedialog.askopenfilename(
|
file_path = filedialog.askopenfilename(
|
||||||
title="Select TIA Portal Project File",
|
title="Select TIA Portal Project File",
|
||||||
filetypes=[
|
filetypes=get_supported_filetypes()
|
||||||
(
|
|
||||||
f"TIA Portal V{TIA_PORTAL_VERSION} Projects",
|
|
||||||
f"*.ap{TIA_PORTAL_VERSION.split('.')[0]}",
|
|
||||||
)
|
|
||||||
], # e.g. *.ap18
|
|
||||||
)
|
)
|
||||||
root.destroy()
|
root.destroy()
|
||||||
if not file_path:
|
if not file_path:
|
||||||
print("No project file selected. Exiting.")
|
print("No se seleccionó ningún archivo de proyecto. Saliendo.")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
return file_path
|
return file_path
|
||||||
|
|
||||||
|
@ -95,7 +122,7 @@ def select_export_directory():
|
||||||
def export_plc_data(plc, export_base_dir):
|
def export_plc_data(plc, export_base_dir):
|
||||||
"""Exports Blocks, UDTs, and Tag Tables from a given PLC."""
|
"""Exports Blocks, UDTs, and Tag Tables from a given PLC."""
|
||||||
plc_name = plc.get_name()
|
plc_name = plc.get_name()
|
||||||
print(f"\n--- Processing PLC: {plc_name} ---")
|
print(f"\n--- Procesando PLC: {plc_name} ---")
|
||||||
|
|
||||||
# Define base export path for this PLC
|
# Define base export path for this PLC
|
||||||
plc_export_dir = os.path.join(export_base_dir, plc_name)
|
plc_export_dir = os.path.join(export_base_dir, plc_name)
|
||||||
|
@ -104,143 +131,140 @@ def export_plc_data(plc, export_base_dir):
|
||||||
# --- Export Program Blocks ---
|
# --- Export Program Blocks ---
|
||||||
blocks_exported = 0
|
blocks_exported = 0
|
||||||
blocks_skipped = 0
|
blocks_skipped = 0
|
||||||
print(f"\n[PLC: {plc_name}] Exporting Program Blocks...")
|
print(f"\n[PLC: {plc_name}] Exportando bloques de programa...")
|
||||||
xml_blocks_path = os.path.join(plc_export_dir, "ProgramBlocks_XML")
|
xml_blocks_path = os.path.join(plc_export_dir, "ProgramBlocks_XML")
|
||||||
scl_blocks_path = os.path.join(plc_export_dir, "ProgramBlocks_SCL")
|
scl_blocks_path = os.path.join(plc_export_dir, "ProgramBlocks_SCL")
|
||||||
os.makedirs(xml_blocks_path, exist_ok=True)
|
os.makedirs(xml_blocks_path, exist_ok=True)
|
||||||
os.makedirs(scl_blocks_path, exist_ok=True)
|
os.makedirs(scl_blocks_path, exist_ok=True)
|
||||||
print(f" XML Target: {xml_blocks_path}")
|
print(f" Destino XML: {xml_blocks_path}")
|
||||||
print(f" SCL Target: {scl_blocks_path}")
|
print(f" Destino SCL: {scl_blocks_path}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
program_blocks = plc.get_program_blocks() #
|
program_blocks = plc.get_program_blocks()
|
||||||
print(f" Found {len(program_blocks)} program blocks.")
|
print(f" Se encontraron {len(program_blocks)} bloques de programa.")
|
||||||
for block in program_blocks:
|
for block in program_blocks:
|
||||||
block_name = block.get_name() # Assuming get_name() exists
|
block_name = block.get_name()
|
||||||
print(f" Processing block: {block_name}...")
|
print(f" Procesando bloque: {block_name}...")
|
||||||
try:
|
try:
|
||||||
if not block.is_consistent(): #
|
if not block.is_consistent():
|
||||||
print(f" Compiling block {block_name}...")
|
print(f" Compilando bloque {block_name}...")
|
||||||
block.compile() #
|
block.compile()
|
||||||
if not block.is_consistent():
|
if not block.is_consistent():
|
||||||
print(
|
print(
|
||||||
f" WARNING: Block {block_name} inconsistent after compile. Skipping."
|
f" ADVERTENCIA: Bloque {block_name} inconsistente después de compilar. Omitiendo."
|
||||||
)
|
)
|
||||||
blocks_skipped += 1
|
blocks_skipped += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
print(f" Exporting {block_name} as XML...")
|
print(f" Exportando {block_name} como XML...")
|
||||||
block.export(
|
block.export(
|
||||||
target_directory_path=xml_blocks_path, #
|
target_directory_path=xml_blocks_path,
|
||||||
export_options=EXPORT_OPTIONS, #
|
export_options=EXPORT_OPTIONS,
|
||||||
export_format=ts.Enums.ExportFormats.SimaticML, #
|
export_format=ts.Enums.ExportFormats.SimaticML,
|
||||||
keep_folder_structure=KEEP_FOLDER_STRUCTURE,
|
keep_folder_structure=KEEP_FOLDER_STRUCTURE,
|
||||||
) #
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
prog_language = block.get_property(name="ProgrammingLanguage")
|
prog_language = block.get_property(name="ProgrammingLanguage")
|
||||||
if prog_language == "SCL":
|
if prog_language == "SCL":
|
||||||
print(f" Exporting {block_name} as SCL...")
|
print(f" Exportando {block_name} como SCL...")
|
||||||
block.export(
|
block.export(
|
||||||
target_directory_path=scl_blocks_path,
|
target_directory_path=scl_blocks_path,
|
||||||
export_options=EXPORT_OPTIONS,
|
export_options=EXPORT_OPTIONS,
|
||||||
export_format=ts.Enums.ExportFormats.ExternalSource, #
|
export_format=ts.Enums.ExportFormats.ExternalSource,
|
||||||
keep_folder_structure=KEEP_FOLDER_STRUCTURE,
|
keep_folder_structure=KEEP_FOLDER_STRUCTURE,
|
||||||
)
|
)
|
||||||
except Exception as prop_ex:
|
except Exception as prop_ex:
|
||||||
print(
|
print(
|
||||||
f" Could not get ProgrammingLanguage for {block_name}. Skipping SCL. Error: {prop_ex}"
|
f" No se pudo obtener el lenguaje de programación para {block_name}. Omitiendo SCL. Error: {prop_ex}"
|
||||||
)
|
)
|
||||||
|
|
||||||
blocks_exported += 1
|
blocks_exported += 1
|
||||||
except Exception as block_ex:
|
except Exception as block_ex:
|
||||||
print(f" ERROR exporting block {block_name}: {block_ex}")
|
print(f" ERROR exportando bloque {block_name}: {block_ex}")
|
||||||
blocks_skipped += 1
|
blocks_skipped += 1
|
||||||
print(
|
print(
|
||||||
f" Program Blocks Export Summary: Exported={blocks_exported}, Skipped/Errors={blocks_skipped}"
|
f" Resumen de exportación de bloques: Exportados={blocks_exported}, Omitidos/Errores={blocks_skipped}"
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f" ERROR processing Program Blocks: {e}")
|
print(f" ERROR procesando bloques de programa: {e}")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
# --- Export PLC Data Types (UDTs) ---
|
# --- Export PLC Data Types (UDTs) ---
|
||||||
udts_exported = 0
|
udts_exported = 0
|
||||||
udts_skipped = 0
|
udts_skipped = 0
|
||||||
print(f"\n[PLC: {plc_name}] Exporting PLC Data Types (UDTs)...")
|
print(f"\n[PLC: {plc_name}] Exportando tipos de datos PLC (UDTs)...")
|
||||||
udt_export_path = os.path.join(plc_export_dir, "PlcDataTypes")
|
udt_export_path = os.path.join(plc_export_dir, "PlcDataTypes")
|
||||||
os.makedirs(udt_export_path, exist_ok=True)
|
os.makedirs(udt_export_path, exist_ok=True)
|
||||||
print(f" Target: {udt_export_path}")
|
print(f" Destino: {udt_export_path}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
udts = plc.get_user_data_types() #
|
udts = plc.get_user_data_types()
|
||||||
print(f" Found {len(udts)} UDTs.")
|
print(f" Se encontraron {len(udts)} UDTs.")
|
||||||
for udt in udts:
|
for udt in udts:
|
||||||
udt_name = udt.get_name() #
|
udt_name = udt.get_name()
|
||||||
print(f" Processing UDT: {udt_name}...")
|
print(f" Procesando UDT: {udt_name}...")
|
||||||
try:
|
try:
|
||||||
if not udt.is_consistent(): #
|
if not udt.is_consistent():
|
||||||
print(f" Compiling UDT {udt_name}...")
|
print(f" Compilando UDT {udt_name}...")
|
||||||
udt.compile() #
|
udt.compile()
|
||||||
if not udt.is_consistent():
|
if not udt.is_consistent():
|
||||||
print(
|
print(
|
||||||
f" WARNING: UDT {udt_name} inconsistent after compile. Skipping."
|
f" ADVERTENCIA: UDT {udt_name} inconsistente después de compilar. Omitiendo."
|
||||||
)
|
)
|
||||||
udts_skipped += 1
|
udts_skipped += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
print(f" Exporting {udt_name}...")
|
print(f" Exportando {udt_name}...")
|
||||||
udt.export(
|
udt.export(
|
||||||
target_directory_path=udt_export_path, #
|
target_directory_path=udt_export_path,
|
||||||
export_options=EXPORT_OPTIONS, #
|
export_options=EXPORT_OPTIONS,
|
||||||
# export_format defaults to SimaticML for UDTs
|
|
||||||
keep_folder_structure=KEEP_FOLDER_STRUCTURE,
|
keep_folder_structure=KEEP_FOLDER_STRUCTURE,
|
||||||
) #
|
)
|
||||||
udts_exported += 1
|
udts_exported += 1
|
||||||
except Exception as udt_ex:
|
except Exception as udt_ex:
|
||||||
print(f" ERROR exporting UDT {udt_name}: {udt_ex}")
|
print(f" ERROR exportando UDT {udt_name}: {udt_ex}")
|
||||||
udts_skipped += 1
|
udts_skipped += 1
|
||||||
print(
|
print(
|
||||||
f" UDT Export Summary: Exported={udts_exported}, Skipped/Errors={udts_skipped}"
|
f" Resumen de exportación de UDTs: Exportados={udts_exported}, Omitidos/Errores={udts_skipped}"
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f" ERROR processing UDTs: {e}")
|
print(f" ERROR procesando UDTs: {e}")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
# --- Export PLC Tag Tables ---
|
# --- Export PLC Tag Tables ---
|
||||||
tags_exported = 0
|
tags_exported = 0
|
||||||
tags_skipped = 0
|
tags_skipped = 0
|
||||||
print(f"\n[PLC: {plc_name}] Exporting PLC Tag Tables...")
|
print(f"\n[PLC: {plc_name}] Exportando tablas de variables PLC...")
|
||||||
tags_export_path = os.path.join(plc_export_dir, "PlcTags")
|
tags_export_path = os.path.join(plc_export_dir, "PlcTags")
|
||||||
os.makedirs(tags_export_path, exist_ok=True)
|
os.makedirs(tags_export_path, exist_ok=True)
|
||||||
print(f" Target: {tags_export_path}")
|
print(f" Destino: {tags_export_path}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
tag_tables = plc.get_plc_tag_tables() #
|
tag_tables = plc.get_plc_tag_tables()
|
||||||
print(f" Found {len(tag_tables)} Tag Tables.")
|
print(f" Se encontraron {len(tag_tables)} tablas de variables.")
|
||||||
for table in tag_tables:
|
for table in tag_tables:
|
||||||
table_name = table.get_name() #
|
table_name = table.get_name()
|
||||||
print(f" Processing Tag Table: {table_name}...")
|
print(f" Procesando tabla de variables: {table_name}...")
|
||||||
try:
|
try:
|
||||||
# Note: Consistency check might not be available/needed for tag tables like blocks/UDTs
|
print(f" Exportando {table_name}...")
|
||||||
print(f" Exporting {table_name}...")
|
|
||||||
table.export(
|
table.export(
|
||||||
target_directory_path=tags_export_path, #
|
target_directory_path=tags_export_path,
|
||||||
export_options=EXPORT_OPTIONS, #
|
export_options=EXPORT_OPTIONS,
|
||||||
# export_format defaults to SimaticML for Tag Tables
|
|
||||||
keep_folder_structure=KEEP_FOLDER_STRUCTURE,
|
keep_folder_structure=KEEP_FOLDER_STRUCTURE,
|
||||||
) #
|
)
|
||||||
tags_exported += 1
|
tags_exported += 1
|
||||||
except Exception as table_ex:
|
except Exception as table_ex:
|
||||||
print(f" ERROR exporting Tag Table {table_name}: {table_ex}")
|
print(f" ERROR exportando tabla de variables {table_name}: {table_ex}")
|
||||||
tags_skipped += 1
|
tags_skipped += 1
|
||||||
print(
|
print(
|
||||||
f" Tag Table Export Summary: Exported={tags_exported}, Skipped/Errors={tags_skipped}"
|
f" Resumen de exportación de tablas de variables: Exportados={tags_exported}, Omitidos/Errores={tags_skipped}"
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f" ERROR processing Tag Tables: {e}")
|
print(f" ERROR procesando tablas de variables: {e}")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
print(f"\n--- Finished processing PLC: {plc_name} ---")
|
print(f"\n--- Finalizado el procesamiento del PLC: {plc_name} ---")
|
||||||
|
|
||||||
|
|
||||||
# --- Main Script ---
|
# --- Main Script ---
|
||||||
|
@ -250,75 +274,76 @@ if __name__ == "__main__":
|
||||||
configs = load_configuration()
|
configs = load_configuration()
|
||||||
working_directory = configs.get("working_directory")
|
working_directory = configs.get("working_directory")
|
||||||
|
|
||||||
print("--- TIA Portal Data Exporter (Blocks, UDTs, Tags) ---")
|
print("--- Exportador de datos TIA Portal (Bloques, UDTs, Variables) ---")
|
||||||
|
|
||||||
# Validate working directory
|
# Validate working directory
|
||||||
if not working_directory or not os.path.isdir(working_directory):
|
if not working_directory or not os.path.isdir(working_directory):
|
||||||
print("ERROR: Working directory not set or invalid in configuration.")
|
print("ERROR: Directorio de trabajo no configurado o inválido.")
|
||||||
print("Please configure the working directory using the main application.")
|
print("Por favor configure el directorio de trabajo usando la aplicación principal.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# 1. Select Project File, Export Directory comes from config
|
# 1. Select Project File, Export Directory comes from config
|
||||||
project_file = select_project_file()
|
project_file = select_project_file()
|
||||||
export_dir = working_directory # Use working directory from config
|
export_dir = working_directory # Use working directory from config
|
||||||
|
|
||||||
print(f"\nSelected Project: {project_file}")
|
# 2. Detect TIA Portal version from project file
|
||||||
print(f"Using Export Directory (Working Directory): {export_dir}")
|
tia_version = detect_tia_version(project_file)
|
||||||
|
|
||||||
|
print(f"\nProyecto seleccionado: {project_file}")
|
||||||
|
print(f"Usando directorio de exportación (Directorio de trabajo): {export_dir}")
|
||||||
|
|
||||||
portal_instance = None
|
portal_instance = None
|
||||||
project_object = None
|
project_object = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 2. Connect to TIA Portal
|
# 3. Connect to TIA Portal with detected version
|
||||||
print(f"\nConnecting to TIA Portal V{TIA_PORTAL_VERSION}...")
|
print(f"\nConectando a TIA Portal V{tia_version}...")
|
||||||
portal_instance = ts.open_portal(
|
portal_instance = ts.open_portal(
|
||||||
version=TIA_PORTAL_VERSION,
|
version=tia_version,
|
||||||
portal_mode=ts.Enums.PortalMode.WithGraphicalUserInterface,
|
portal_mode=ts.Enums.PortalMode.WithGraphicalUserInterface,
|
||||||
)
|
)
|
||||||
print("Connected to TIA Portal.")
|
print("Conectado a TIA Portal.")
|
||||||
print(f"Portal Process ID: {portal_instance.get_process_id()}") #
|
print(f"ID del proceso del Portal: {portal_instance.get_process_id()}")
|
||||||
|
|
||||||
# 3. Open Project
|
# 4. Open Project
|
||||||
print(f"Opening project: {os.path.basename(project_file)}...")
|
print(f"Abriendo proyecto: {os.path.basename(project_file)}...")
|
||||||
project_object = portal_instance.open_project(project_file_path=project_file) #
|
project_object = portal_instance.open_project(project_file_path=project_file)
|
||||||
if project_object is None:
|
if project_object is None:
|
||||||
print("Project might already be open, attempting to get handle...")
|
print("El proyecto podría estar ya abierto, intentando obtener el manejador...")
|
||||||
project_object = portal_instance.get_project() #
|
project_object = portal_instance.get_project()
|
||||||
if project_object is None:
|
if project_object is None:
|
||||||
raise Exception("Failed to open or get the specified project.")
|
raise Exception("No se pudo abrir u obtener el proyecto especificado.")
|
||||||
print("Project opened successfully.")
|
print("Proyecto abierto exitosamente.")
|
||||||
|
|
||||||
# 4. Get PLCs
|
# 5. Get PLCs
|
||||||
plcs = project_object.get_plcs() #
|
plcs = project_object.get_plcs()
|
||||||
if not plcs:
|
if not plcs:
|
||||||
print("No PLC devices found in the project.")
|
print("No se encontraron dispositivos PLC en el proyecto.")
|
||||||
else:
|
else:
|
||||||
print(f"Found {len(plcs)} PLC(s). Starting export process...")
|
print(f"Se encontraron {len(plcs)} PLC(s). Iniciando proceso de exportación...")
|
||||||
|
|
||||||
# 5. Iterate and Export Data for each PLC
|
# 6. Iterate and Export Data for each PLC
|
||||||
for plc_device in plcs:
|
for plc_device in plcs:
|
||||||
export_plc_data(
|
export_plc_data(plc=plc_device, export_base_dir=export_dir)
|
||||||
plc=plc_device, export_base_dir=export_dir
|
|
||||||
) # Pass export_dir
|
|
||||||
|
|
||||||
print("\nExport process completed.")
|
print("\nProceso de exportación completado.")
|
||||||
|
|
||||||
except ts.TiaException as tia_ex:
|
except ts.TiaException as tia_ex:
|
||||||
print(f"\nTIA Portal Openness Error: {tia_ex}")
|
print(f"\nError de TIA Portal Openness: {tia_ex}")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
print(f"\nERROR: Project file not found at {project_file}")
|
print(f"\nERROR: Archivo de proyecto no encontrado en {project_file}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"\nAn unexpected error occurred: {e}")
|
print(f"\nOcurrió un error inesperado: {e}")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
finally:
|
finally:
|
||||||
# 6. Cleanup
|
# 7. Cleanup
|
||||||
if portal_instance:
|
if portal_instance:
|
||||||
try:
|
try:
|
||||||
print("\nClosing TIA Portal...")
|
print("\nCerrando TIA Portal...")
|
||||||
portal_instance.close_portal() #
|
portal_instance.close_portal()
|
||||||
print("TIA Portal closed.")
|
print("TIA Portal cerrado.")
|
||||||
except Exception as close_ex:
|
except Exception as close_ex:
|
||||||
print(f"Error during TIA Portal cleanup: {close_ex}")
|
print(f"Error durante la limpieza de TIA Portal: {close_ex}")
|
||||||
|
|
||||||
print("\nScript finished.")
|
print("\nScript finalizado.")
|
||||||
|
|
|
@ -8,7 +8,7 @@ from tkinter import filedialog
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
from pathlib import Path # Import Path for easier path manipulation
|
from pathlib import Path
|
||||||
|
|
||||||
script_root = os.path.dirname(
|
script_root = os.path.dirname(
|
||||||
os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
||||||
|
@ -17,14 +17,19 @@ sys.path.append(script_root)
|
||||||
from backend.script_utils import load_configuration
|
from backend.script_utils import load_configuration
|
||||||
|
|
||||||
# --- Configuration ---
|
# --- Configuration ---
|
||||||
TIA_PORTAL_VERSION = "18.0" # Target TIA Portal version (e.g., "18.0")
|
# Supported TIA Portal versions mapping (extension -> version)
|
||||||
|
SUPPORTED_TIA_VERSIONS = {
|
||||||
|
".ap18": "18.0",
|
||||||
|
".ap19": "19.0",
|
||||||
|
".ap20": "20.0"
|
||||||
|
}
|
||||||
|
|
||||||
# Filter for cross-references. Based on documentation:
|
# Filter for cross-references. Based on documentation:
|
||||||
# 1: 'AllObjects', 2: 'ObjectsWithReferences', 3: 'ObjectsWithoutReferences', 4: 'UnusedObjects'
|
# 1: 'AllObjects', 2: 'ObjectsWithReferences', 3: 'ObjectsWithoutReferences', 4: 'UnusedObjects'
|
||||||
# Using 1 to export all. 0 might also work as a default in some API versions.
|
# Using 1 to export all. 0 might also work as a default in some API versions.
|
||||||
CROSS_REF_FILTER = 1
|
CROSS_REF_FILTER = 1
|
||||||
|
|
||||||
# --- TIA Scripting Import Handling ---
|
# --- TIA Scripting Import Handling ---
|
||||||
# (Same import handling as x1.py)
|
|
||||||
if os.getenv("TIA_SCRIPTING"):
|
if os.getenv("TIA_SCRIPTING"):
|
||||||
sys.path.append(os.getenv("TIA_SCRIPTING"))
|
sys.path.append(os.getenv("TIA_SCRIPTING"))
|
||||||
else:
|
else:
|
||||||
|
@ -33,209 +38,225 @@ else:
|
||||||
try:
|
try:
|
||||||
import siemens_tia_scripting as ts
|
import siemens_tia_scripting as ts
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print("ERROR: Failed to import 'siemens_tia_scripting'.")
|
print("ERROR: Error al importar 'siemens_tia_scripting'.")
|
||||||
print("Ensure:")
|
print("Asegúrese de que:")
|
||||||
print(f"1. TIA Portal Openness for V{TIA_PORTAL_VERSION} is installed.")
|
print("1. TIA Portal Openness está instalado.")
|
||||||
print(
|
print(
|
||||||
"2. The 'siemens_tia_scripting' Python module is installed (pip install ...) or"
|
"2. El módulo 'siemens_tia_scripting' de Python está instalado (pip install ...) o"
|
||||||
)
|
)
|
||||||
print(
|
print(
|
||||||
" the path to its binaries is set in the 'TIA_SCRIPTING' environment variable."
|
" la ruta a sus binarios está configurada en la variable de entorno 'TIA_SCRIPTING'."
|
||||||
)
|
)
|
||||||
print(
|
print(
|
||||||
"3. You are using a compatible Python version (e.g., 3.12.X as per documentation)."
|
"3. Está usando una versión compatible de Python (ej. 3.12.X según la documentación)."
|
||||||
)
|
)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"An unexpected error occurred during import: {e}")
|
print(f"Ocurrió un error inesperado durante la importación: {e}")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# --- Functions ---
|
# --- Functions ---
|
||||||
|
|
||||||
|
def get_supported_filetypes():
|
||||||
|
"""Returns the supported file types for TIA Portal projects."""
|
||||||
|
filetypes = []
|
||||||
|
for ext, version in SUPPORTED_TIA_VERSIONS.items():
|
||||||
|
version_major = version.split('.')[0]
|
||||||
|
filetypes.append((f"TIA Portal V{version_major} Projects", f"*{ext}"))
|
||||||
|
|
||||||
|
# Add option to show all supported files
|
||||||
|
all_extensions = " ".join([f"*{ext}" for ext in SUPPORTED_TIA_VERSIONS.keys()])
|
||||||
|
filetypes.insert(0, ("All TIA Portal Projects", all_extensions))
|
||||||
|
|
||||||
|
return filetypes
|
||||||
|
|
||||||
|
def detect_tia_version(project_file_path):
|
||||||
|
"""Detects TIA Portal version based on file extension."""
|
||||||
|
file_path = Path(project_file_path)
|
||||||
|
file_extension = file_path.suffix.lower()
|
||||||
|
|
||||||
|
if file_extension in SUPPORTED_TIA_VERSIONS:
|
||||||
|
detected_version = SUPPORTED_TIA_VERSIONS[file_extension]
|
||||||
|
print(f"Versión de TIA Portal detectada: {detected_version} (de la extensión {file_extension})")
|
||||||
|
return detected_version
|
||||||
|
else:
|
||||||
|
print(f"ADVERTENCIA: Extensión de archivo no reconocida '{file_extension}'. Extensiones soportadas: {list(SUPPORTED_TIA_VERSIONS.keys())}")
|
||||||
|
# Default to version 18.0 for backward compatibility
|
||||||
|
print("Usando por defecto TIA Portal V18.0")
|
||||||
|
return "18.0"
|
||||||
|
|
||||||
def select_project_file():
|
def select_project_file():
|
||||||
"""Opens a dialog to select a TIA Portal project file."""
|
"""Opens a dialog to select a TIA Portal project file."""
|
||||||
root = tk.Tk()
|
root = tk.Tk()
|
||||||
root.withdraw() # Hide the main tkinter window
|
root.withdraw()
|
||||||
file_path = filedialog.askopenfilename(
|
file_path = filedialog.askopenfilename(
|
||||||
title="Select TIA Portal Project File",
|
title="Seleccionar archivo de proyecto TIA Portal",
|
||||||
filetypes=[
|
filetypes=get_supported_filetypes()
|
||||||
(
|
|
||||||
f"TIA Portal V{TIA_PORTAL_VERSION} Projects",
|
|
||||||
f"*.ap{TIA_PORTAL_VERSION.split('.')[0]}",
|
|
||||||
)
|
|
||||||
], # e.g. *.ap18
|
|
||||||
)
|
)
|
||||||
root.destroy()
|
root.destroy()
|
||||||
if not file_path:
|
if not file_path:
|
||||||
print("No project file selected. Exiting.")
|
print("No se seleccionó ningún archivo de proyecto. Saliendo.")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
return file_path
|
return file_path
|
||||||
|
|
||||||
|
|
||||||
def export_plc_cross_references(plc, export_base_dir):
|
def export_plc_cross_references(plc, export_base_dir):
|
||||||
"""Exports cross-references for various elements from a given PLC."""
|
"""Exports cross-references for various elements from a given PLC."""
|
||||||
plc_name = plc.get_name()
|
plc_name = plc.get_name()
|
||||||
print(f"\n--- Processing PLC: {plc_name} ---")
|
print(f"\n--- Procesando PLC: {plc_name} ---")
|
||||||
|
|
||||||
# Define base export path for this PLC's cross-references
|
# Define base export path for this PLC's cross-references
|
||||||
plc_export_dir = export_base_dir / plc_name
|
plc_export_dir = export_base_dir / plc_name
|
||||||
plc_export_dir.mkdir(parents=True, exist_ok=True) # Use pathlib's mkdir
|
plc_export_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
# --- Export Program Block Cross-References ---
|
# --- Export Program Block Cross-References ---
|
||||||
blocks_cr_exported = 0
|
blocks_cr_exported = 0
|
||||||
blocks_cr_skipped = 0
|
blocks_cr_skipped = 0
|
||||||
print(f"\n[PLC: {plc_name}] Exporting Program Block Cross-References...")
|
print(f"\n[PLC: {plc_name}] Exportando referencias cruzadas de bloques de programa...")
|
||||||
blocks_cr_path = plc_export_dir / "ProgramBlocks_CR"
|
blocks_cr_path = plc_export_dir / "ProgramBlocks_CR"
|
||||||
blocks_cr_path.mkdir(exist_ok=True)
|
blocks_cr_path.mkdir(exist_ok=True)
|
||||||
print(f" Target: {blocks_cr_path}")
|
print(f" Destino: {blocks_cr_path}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Assuming get_program_blocks() doesn't need folder_path to get all blocks
|
|
||||||
program_blocks = plc.get_program_blocks()
|
program_blocks = plc.get_program_blocks()
|
||||||
print(f" Found {len(program_blocks)} program blocks.")
|
print(f" Se encontraron {len(program_blocks)} bloques de programa.")
|
||||||
for block in program_blocks:
|
for block in program_blocks:
|
||||||
block_name = block.get_name()
|
block_name = block.get_name()
|
||||||
print(f" Processing block: {block_name}...")
|
print(f" Procesando bloque: {block_name}...")
|
||||||
try:
|
try:
|
||||||
# Note: Consistency check might not be needed/available before cross-ref export
|
print(f" Exportando referencias cruzadas para {block_name}...")
|
||||||
print(f" Exporting cross-references for {block_name}...")
|
|
||||||
block.export_cross_references(
|
block.export_cross_references(
|
||||||
target_directorypath=str(
|
target_directorypath=str(blocks_cr_path),
|
||||||
blocks_cr_path
|
|
||||||
), # API likely needs string path
|
|
||||||
filter=CROSS_REF_FILTER,
|
filter=CROSS_REF_FILTER,
|
||||||
)
|
)
|
||||||
blocks_cr_exported += 1
|
blocks_cr_exported += 1
|
||||||
except RuntimeError as block_ex:
|
except RuntimeError as block_ex:
|
||||||
print(
|
print(
|
||||||
f" TIA ERROR exporting cross-references for block {block_name}: {block_ex}"
|
f" ERROR TIA al exportar referencias cruzadas para el bloque {block_name}: {block_ex}"
|
||||||
)
|
)
|
||||||
blocks_cr_skipped += 1
|
blocks_cr_skipped += 1
|
||||||
except Exception as block_ex:
|
except Exception as block_ex:
|
||||||
print(
|
print(
|
||||||
f" GENERAL ERROR exporting cross-references for block {block_name}: {block_ex}"
|
f" ERROR GENERAL al exportar referencias cruzadas para el bloque {block_name}: {block_ex}"
|
||||||
)
|
)
|
||||||
traceback.print_exc() # Print stack trace for general errors
|
traceback.print_exc()
|
||||||
blocks_cr_skipped += 1
|
blocks_cr_skipped += 1
|
||||||
print(
|
print(
|
||||||
f" Program Block CR Export Summary: Exported={blocks_cr_exported}, Skipped/Errors={blocks_cr_skipped}"
|
f" Resumen de exportación de referencias cruzadas de bloques: Exportados={blocks_cr_exported}, Omitidos/Errores={blocks_cr_skipped}"
|
||||||
)
|
)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
print(
|
print(
|
||||||
" AttributeError: Could not find 'get_program_blocks' on PLC object. Skipping Program Blocks."
|
" Error de atributo: No se pudo encontrar 'get_program_blocks' en el objeto PLC. Omitiendo bloques de programa."
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f" ERROR accessing Program Blocks for cross-reference export: {e}")
|
print(f" ERROR al acceder a los bloques de programa para exportar referencias cruzadas: {e}")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
# --- Export PLC Tag Table Cross-References ---
|
# --- Export PLC Tag Table Cross-References ---
|
||||||
tags_cr_exported = 0
|
tags_cr_exported = 0
|
||||||
tags_cr_skipped = 0
|
tags_cr_skipped = 0
|
||||||
print(f"\n[PLC: {plc_name}] Exporting PLC Tag Table Cross-References...")
|
print(f"\n[PLC: {plc_name}] Exportando referencias cruzadas de tablas de variables...")
|
||||||
tags_cr_path = plc_export_dir / "PlcTags_CR"
|
tags_cr_path = plc_export_dir / "PlcTags_CR"
|
||||||
tags_cr_path.mkdir(exist_ok=True)
|
tags_cr_path.mkdir(exist_ok=True)
|
||||||
print(f" Target: {tags_cr_path}")
|
print(f" Destino: {tags_cr_path}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Assuming get_plc_tag_tables() doesn't need folder_path to get all tables
|
|
||||||
tag_tables = plc.get_plc_tag_tables()
|
tag_tables = plc.get_plc_tag_tables()
|
||||||
print(f" Found {len(tag_tables)} Tag Tables.")
|
print(f" Se encontraron {len(tag_tables)} tablas de variables.")
|
||||||
for table in tag_tables:
|
for table in tag_tables:
|
||||||
table_name = table.get_name()
|
table_name = table.get_name()
|
||||||
print(f" Processing Tag Table: {table_name}...")
|
print(f" Procesando tabla de variables: {table_name}...")
|
||||||
try:
|
try:
|
||||||
print(f" Exporting cross-references for {table_name}...")
|
print(f" Exportando referencias cruzadas para {table_name}...")
|
||||||
table.export_cross_references(
|
table.export_cross_references(
|
||||||
target_directorypath=str(tags_cr_path), filter=CROSS_REF_FILTER
|
target_directorypath=str(tags_cr_path),
|
||||||
|
filter=CROSS_REF_FILTER
|
||||||
)
|
)
|
||||||
tags_cr_exported += 1
|
tags_cr_exported += 1
|
||||||
except RuntimeError as table_ex:
|
except RuntimeError as table_ex:
|
||||||
print(
|
print(
|
||||||
f" TIA ERROR exporting cross-references for Tag Table {table_name}: {table_ex}"
|
f" ERROR TIA al exportar referencias cruzadas para la tabla {table_name}: {table_ex}"
|
||||||
)
|
)
|
||||||
tags_cr_skipped += 1
|
tags_cr_skipped += 1
|
||||||
except Exception as table_ex:
|
except Exception as table_ex:
|
||||||
print(
|
print(
|
||||||
f" GENERAL ERROR exporting cross-references for Tag Table {table_name}: {table_ex}"
|
f" ERROR GENERAL al exportar referencias cruzadas para la tabla {table_name}: {table_ex}"
|
||||||
)
|
)
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
tags_cr_skipped += 1
|
tags_cr_skipped += 1
|
||||||
print(
|
print(
|
||||||
f" Tag Table CR Export Summary: Exported={tags_cr_exported}, Skipped/Errors={tags_cr_skipped}"
|
f" Resumen de exportación de referencias cruzadas de tablas: Exportados={tags_cr_exported}, Omitidos/Errores={tags_cr_skipped}"
|
||||||
)
|
)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
print(
|
print(
|
||||||
" AttributeError: Could not find 'get_plc_tag_tables' on PLC object. Skipping Tag Tables."
|
" Error de atributo: No se pudo encontrar 'get_plc_tag_tables' en el objeto PLC. Omitiendo tablas de variables."
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f" ERROR accessing Tag Tables for cross-reference export: {e}")
|
print(f" ERROR al acceder a las tablas de variables para exportar referencias cruzadas: {e}")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
# --- Export PLC Data Type (UDT) Cross-References ---
|
# --- Export PLC Data Type (UDT) Cross-References ---
|
||||||
udts_cr_exported = 0
|
udts_cr_exported = 0
|
||||||
udts_cr_skipped = 0
|
udts_cr_skipped = 0
|
||||||
print(f"\n[PLC: {plc_name}] Exporting PLC Data Type (UDT) Cross-References...")
|
print(f"\n[PLC: {plc_name}] Exportando referencias cruzadas de tipos de datos PLC (UDTs)...")
|
||||||
udts_cr_path = plc_export_dir / "PlcDataTypes_CR"
|
udts_cr_path = plc_export_dir / "PlcDataTypes_CR"
|
||||||
udts_cr_path.mkdir(exist_ok=True)
|
udts_cr_path.mkdir(exist_ok=True)
|
||||||
print(f" Target: {udts_cr_path}")
|
print(f" Destino: {udts_cr_path}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Assuming get_user_data_types() doesn't need folder_path to get all UDTs
|
|
||||||
udts = plc.get_user_data_types()
|
udts = plc.get_user_data_types()
|
||||||
print(f" Found {len(udts)} UDTs.")
|
print(f" Se encontraron {len(udts)} UDTs.")
|
||||||
for udt in udts:
|
for udt in udts:
|
||||||
udt_name = udt.get_name()
|
udt_name = udt.get_name()
|
||||||
print(f" Processing UDT: {udt_name}...")
|
print(f" Procesando UDT: {udt_name}...")
|
||||||
try:
|
try:
|
||||||
print(f" Exporting cross-references for {udt_name}...")
|
print(f" Exportando referencias cruzadas para {udt_name}...")
|
||||||
udt.export_cross_references(
|
udt.export_cross_references(
|
||||||
target_directorypath=str(udts_cr_path), filter=CROSS_REF_FILTER
|
target_directorypath=str(udts_cr_path),
|
||||||
|
filter=CROSS_REF_FILTER
|
||||||
)
|
)
|
||||||
udts_cr_exported += 1
|
udts_cr_exported += 1
|
||||||
except RuntimeError as udt_ex:
|
except RuntimeError as udt_ex:
|
||||||
print(
|
print(
|
||||||
f" TIA ERROR exporting cross-references for UDT {udt_name}: {udt_ex}"
|
f" ERROR TIA al exportar referencias cruzadas para el UDT {udt_name}: {udt_ex}"
|
||||||
)
|
)
|
||||||
udts_cr_skipped += 1
|
udts_cr_skipped += 1
|
||||||
except Exception as udt_ex:
|
except Exception as udt_ex:
|
||||||
print(
|
print(
|
||||||
f" GENERAL ERROR exporting cross-references for UDT {udt_name}: {udt_ex}"
|
f" ERROR GENERAL al exportar referencias cruzadas para el UDT {udt_name}: {udt_ex}"
|
||||||
)
|
)
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
udts_cr_skipped += 1
|
udts_cr_skipped += 1
|
||||||
print(
|
print(
|
||||||
f" UDT CR Export Summary: Exported={udts_cr_exported}, Skipped/Errors={udts_cr_skipped}"
|
f" Resumen de exportación de referencias cruzadas de UDTs: Exportados={udts_cr_exported}, Omitidos/Errores={udts_cr_skipped}"
|
||||||
)
|
)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
print(
|
print(
|
||||||
" AttributeError: Could not find 'get_user_data_types' on PLC object. Skipping UDTs."
|
" Error de atributo: No se pudo encontrar 'get_user_data_types' en el objeto PLC. Omitiendo UDTs."
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f" ERROR accessing UDTs for cross-reference export: {e}")
|
print(f" ERROR al acceder a los UDTs para exportar referencias cruzadas: {e}")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
# --- Export System Block Cross-References ---
|
# --- Export System Block Cross-References ---
|
||||||
sys_blocks_cr_exported = 0
|
sys_blocks_cr_exported = 0
|
||||||
sys_blocks_cr_skipped = 0
|
sys_blocks_cr_skipped = 0
|
||||||
print(f"\n[PLC: {plc_name}] Attempting to Export System Block Cross-References...")
|
print(f"\n[PLC: {plc_name}] Intentando exportar referencias cruzadas de bloques de sistema...")
|
||||||
sys_blocks_cr_path = plc_export_dir / "SystemBlocks_CR"
|
sys_blocks_cr_path = plc_export_dir / "SystemBlocks_CR"
|
||||||
sys_blocks_cr_path.mkdir(exist_ok=True)
|
sys_blocks_cr_path.mkdir(exist_ok=True)
|
||||||
print(f" Target: {sys_blocks_cr_path}")
|
print(f" Destino: {sys_blocks_cr_path}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Check if method exists before calling
|
|
||||||
if hasattr(plc, "get_system_blocks"):
|
if hasattr(plc, "get_system_blocks"):
|
||||||
system_blocks = plc.get_system_blocks()
|
system_blocks = plc.get_system_blocks()
|
||||||
print(
|
print(
|
||||||
f" Found {len(system_blocks)} system blocks (using get_system_blocks)."
|
f" Se encontraron {len(system_blocks)} bloques de sistema."
|
||||||
)
|
)
|
||||||
for sys_block in system_blocks:
|
for sys_block in system_blocks:
|
||||||
sys_block_name = sys_block.get_name()
|
sys_block_name = sys_block.get_name()
|
||||||
print(f" Processing System Block: {sys_block_name}...")
|
print(f" Procesando bloque de sistema: {sys_block_name}...")
|
||||||
try:
|
try:
|
||||||
print(f" Exporting cross-references for {sys_block_name}...")
|
print(f" Exportando referencias cruzadas para {sys_block_name}...")
|
||||||
sys_block.export_cross_references(
|
sys_block.export_cross_references(
|
||||||
target_directorypath=str(sys_blocks_cr_path),
|
target_directorypath=str(sys_blocks_cr_path),
|
||||||
filter=CROSS_REF_FILTER,
|
filter=CROSS_REF_FILTER,
|
||||||
|
@ -243,53 +264,51 @@ def export_plc_cross_references(plc, export_base_dir):
|
||||||
sys_blocks_cr_exported += 1
|
sys_blocks_cr_exported += 1
|
||||||
except RuntimeError as sys_ex:
|
except RuntimeError as sys_ex:
|
||||||
print(
|
print(
|
||||||
f" TIA ERROR exporting cross-references for System Block {sys_block_name}: {sys_ex}"
|
f" ERROR TIA al exportar referencias cruzadas para el bloque de sistema {sys_block_name}: {sys_ex}"
|
||||||
)
|
)
|
||||||
sys_blocks_cr_skipped += 1
|
sys_blocks_cr_skipped += 1
|
||||||
except Exception as sys_ex:
|
except Exception as sys_ex:
|
||||||
print(
|
print(
|
||||||
f" GENERAL ERROR exporting cross-references for System Block {sys_block_name}: {sys_ex}"
|
f" ERROR GENERAL al exportar referencias cruzadas para el bloque de sistema {sys_block_name}: {sys_ex}"
|
||||||
)
|
)
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
sys_blocks_cr_skipped += 1
|
sys_blocks_cr_skipped += 1
|
||||||
else:
|
else:
|
||||||
print(
|
print(
|
||||||
" Method 'get_system_blocks' not found on PLC object. Skipping System Blocks."
|
" Método 'get_system_blocks' no encontrado en el objeto PLC. Omitiendo bloques de sistema."
|
||||||
)
|
)
|
||||||
# Alternative: Try navigating DeviceItems if needed, but that's more complex.
|
|
||||||
|
|
||||||
print(
|
print(
|
||||||
f" System Block CR Export Summary: Exported={sys_blocks_cr_exported}, Skipped/Errors={sys_blocks_cr_skipped}"
|
f" Resumen de exportación de referencias cruzadas de bloques de sistema: Exportados={sys_blocks_cr_exported}, Omitidos/Errores={sys_blocks_cr_skipped}"
|
||||||
)
|
)
|
||||||
except AttributeError: # Catch if get_name() or other methods fail on sys_block
|
except AttributeError:
|
||||||
print(
|
print(
|
||||||
" AttributeError during System Block processing. Skipping remaining System Blocks."
|
" Error de atributo durante el procesamiento de bloques de sistema. Omitiendo bloques de sistema restantes."
|
||||||
)
|
)
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(
|
print(
|
||||||
f" ERROR accessing/processing System Blocks for cross-reference export: {e}"
|
f" ERROR al acceder/procesar bloques de sistema para exportar referencias cruzadas: {e}"
|
||||||
)
|
)
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
# --- Export Software Unit Cross-References ---
|
# --- Export Software Unit Cross-References ---
|
||||||
sw_units_cr_exported = 0
|
sw_units_cr_exported = 0
|
||||||
sw_units_cr_skipped = 0
|
sw_units_cr_skipped = 0
|
||||||
print(f"\n[PLC: {plc_name}] Attempting to Export Software Unit Cross-References...")
|
print(f"\n[PLC: {plc_name}] Intentando exportar referencias cruzadas de unidades de software...")
|
||||||
sw_units_cr_path = plc_export_dir / "SoftwareUnits_CR"
|
sw_units_cr_path = plc_export_dir / "SoftwareUnits_CR"
|
||||||
sw_units_cr_path.mkdir(exist_ok=True)
|
sw_units_cr_path.mkdir(exist_ok=True)
|
||||||
print(f" Target: {sw_units_cr_path}")
|
print(f" Destino: {sw_units_cr_path}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Check if method exists before calling
|
|
||||||
if hasattr(plc, "get_software_units"):
|
if hasattr(plc, "get_software_units"):
|
||||||
software_units = plc.get_software_units()
|
software_units = plc.get_software_units()
|
||||||
print(f" Found {len(software_units)} Software Units.")
|
print(f" Se encontraron {len(software_units)} unidades de software.")
|
||||||
for unit in software_units:
|
for unit in software_units:
|
||||||
unit_name = unit.get_name()
|
unit_name = unit.get_name()
|
||||||
print(f" Processing Software Unit: {unit_name}...")
|
print(f" Procesando unidad de software: {unit_name}...")
|
||||||
try:
|
try:
|
||||||
print(f" Exporting cross-references for {unit_name}...")
|
print(f" Exportando referencias cruzadas para {unit_name}...")
|
||||||
unit.export_cross_references(
|
unit.export_cross_references(
|
||||||
target_directorypath=str(sw_units_cr_path),
|
target_directorypath=str(sw_units_cr_path),
|
||||||
filter=CROSS_REF_FILTER,
|
filter=CROSS_REF_FILTER,
|
||||||
|
@ -297,35 +316,34 @@ def export_plc_cross_references(plc, export_base_dir):
|
||||||
sw_units_cr_exported += 1
|
sw_units_cr_exported += 1
|
||||||
except RuntimeError as unit_ex:
|
except RuntimeError as unit_ex:
|
||||||
print(
|
print(
|
||||||
f" TIA ERROR exporting cross-references for Software Unit {unit_name}: {unit_ex}"
|
f" ERROR TIA al exportar referencias cruzadas para la unidad de software {unit_name}: {unit_ex}"
|
||||||
)
|
)
|
||||||
sw_units_cr_skipped += 1
|
sw_units_cr_skipped += 1
|
||||||
except Exception as unit_ex:
|
except Exception as unit_ex:
|
||||||
print(
|
print(
|
||||||
f" GENERAL ERROR exporting cross-references for Software Unit {unit_name}: {unit_ex}"
|
f" ERROR GENERAL al exportar referencias cruzadas para la unidad de software {unit_name}: {unit_ex}"
|
||||||
)
|
)
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
sw_units_cr_skipped += 1
|
sw_units_cr_skipped += 1
|
||||||
print(
|
print(
|
||||||
f" Software Unit CR Export Summary: Exported={sw_units_cr_exported}, Skipped/Errors={sw_units_cr_skipped}"
|
f" Resumen de exportación de referencias cruzadas de unidades de software: Exportados={sw_units_cr_exported}, Omitidos/Errores={sw_units_cr_skipped}"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
print(
|
print(
|
||||||
" Method 'get_software_units' not found on PLC object. Skipping Software Units."
|
" Método 'get_software_units' no encontrado en el objeto PLC. Omitiendo unidades de software."
|
||||||
)
|
)
|
||||||
except AttributeError: # Catch if get_name() or other methods fail on unit
|
except AttributeError:
|
||||||
print(
|
print(
|
||||||
" AttributeError during Software Unit processing. Skipping remaining Software Units."
|
" Error de atributo durante el procesamiento de unidades de software. Omitiendo unidades restantes."
|
||||||
)
|
)
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(
|
print(
|
||||||
f" ERROR accessing/processing Software Units for cross-reference export: {e}"
|
f" ERROR al acceder/procesar unidades de software para exportar referencias cruzadas: {e}"
|
||||||
)
|
)
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
print(f"\n--- Finished processing PLC: {plc_name} ---")
|
print(f"\n--- Finalizado el procesamiento del PLC: {plc_name} ---")
|
||||||
|
|
||||||
|
|
||||||
# --- Main Script ---
|
# --- Main Script ---
|
||||||
|
|
||||||
|
@ -333,90 +351,90 @@ if __name__ == "__main__":
|
||||||
configs = load_configuration()
|
configs = load_configuration()
|
||||||
working_directory = configs.get("working_directory")
|
working_directory = configs.get("working_directory")
|
||||||
|
|
||||||
print("--- TIA Portal Cross-Reference Exporter ---")
|
print("--- Exportador de Referencias Cruzadas de TIA Portal ---")
|
||||||
|
|
||||||
# Validate working directory
|
# Validate working directory
|
||||||
if not working_directory or not os.path.isdir(working_directory):
|
if not working_directory or not os.path.isdir(working_directory):
|
||||||
print("ERROR: Working directory not set or invalid in configuration.")
|
print("ERROR: Directorio de trabajo no configurado o inválido.")
|
||||||
print("Please configure the working directory using the main application.")
|
print("Por favor configure el directorio de trabajo usando la aplicación principal.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# 1. Select Project File
|
# 1. Select Project File
|
||||||
project_file = select_project_file()
|
project_file = select_project_file()
|
||||||
|
|
||||||
# 2. Define Export Directory using working_directory and subfolder
|
# 2. Detect TIA Portal version from project file
|
||||||
# The export base directory is the working directory. PLC-specific folders will be created inside.
|
tia_version = detect_tia_version(project_file)
|
||||||
|
|
||||||
|
# 3. Define Export Directory using working_directory and subfolder
|
||||||
export_base_dir = Path(working_directory)
|
export_base_dir = Path(working_directory)
|
||||||
try:
|
try:
|
||||||
# Ensure the base working directory exists (it should, but check doesn't hurt)
|
|
||||||
export_base_dir.mkdir(parents=True, exist_ok=True)
|
export_base_dir.mkdir(parents=True, exist_ok=True)
|
||||||
print(f"\nSelected Project: {project_file}")
|
print(f"\nProyecto seleccionado: {project_file}")
|
||||||
print(f"Using Base Export Directory: {export_base_dir.resolve()}")
|
print(f"Usando directorio base de exportación: {export_base_dir.resolve()}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"ERROR: Could not create export directory '{export_dir}'. Error: {e}")
|
print(f"ERROR: No se pudo crear el directorio de exportación '{export_base_dir}'. Error: {e}")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
portal_instance = None
|
portal_instance = None
|
||||||
project_object = None
|
project_object = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 3. Connect to TIA Portal
|
# 4. Connect to TIA Portal with detected version
|
||||||
print(f"\nConnecting to TIA Portal V{TIA_PORTAL_VERSION}...")
|
print(f"\nConectando a TIA Portal V{tia_version}...")
|
||||||
# Connect using WithGraphicalUserInterface mode for visibility
|
|
||||||
portal_instance = ts.open_portal(
|
portal_instance = ts.open_portal(
|
||||||
version=TIA_PORTAL_VERSION,
|
version=tia_version,
|
||||||
portal_mode=ts.Enums.PortalMode.WithGraphicalUserInterface,
|
portal_mode=ts.Enums.PortalMode.WithGraphicalUserInterface,
|
||||||
)
|
)
|
||||||
print("Connected to TIA Portal.")
|
print("Conectado a TIA Portal.")
|
||||||
print(f"Portal Process ID: {portal_instance.get_process_id()}")
|
print(f"ID del proceso del Portal: {portal_instance.get_process_id()}")
|
||||||
|
|
||||||
# 4. Open Project
|
# 5. Open Project
|
||||||
print(f"Opening project: {os.path.basename(project_file)}...")
|
print(f"Abriendo proyecto: {os.path.basename(project_file)}...")
|
||||||
project_path_obj = Path(project_file) # Use Path object
|
project_path_obj = Path(project_file)
|
||||||
project_object = portal_instance.open_project(
|
project_object = portal_instance.open_project(
|
||||||
project_file_path=str(project_path_obj)
|
project_file_path=str(project_path_obj)
|
||||||
)
|
)
|
||||||
if project_object is None:
|
if project_object is None:
|
||||||
print("Project might already be open, attempting to get handle...")
|
print("El proyecto podría estar ya abierto, intentando obtener el manejador...")
|
||||||
project_object = portal_instance.get_project()
|
project_object = portal_instance.get_project()
|
||||||
if project_object is None:
|
if project_object is None:
|
||||||
raise Exception("Failed to open or get the specified project.")
|
raise Exception("No se pudo abrir u obtener el proyecto especificado.")
|
||||||
print("Project opened successfully.")
|
print("Proyecto abierto exitosamente.")
|
||||||
|
|
||||||
# 5. Get PLCs
|
# 6. Get PLCs
|
||||||
plcs = project_object.get_plcs()
|
plcs = project_object.get_plcs()
|
||||||
if not plcs:
|
if not plcs:
|
||||||
print("No PLC devices found in the project.")
|
print("No se encontraron dispositivos PLC en el proyecto.")
|
||||||
else:
|
else:
|
||||||
print(
|
print(
|
||||||
f"Found {len(plcs)} PLC(s). Starting cross-reference export process..."
|
f"Se encontraron {len(plcs)} PLC(s). Iniciando proceso de exportación de referencias cruzadas..."
|
||||||
)
|
)
|
||||||
|
|
||||||
# 6. Iterate and Export Cross-References for each PLC
|
# 7. Iterate and Export Cross-References for each PLC
|
||||||
for plc_device in plcs:
|
for plc_device in plcs:
|
||||||
export_plc_cross_references(
|
export_plc_cross_references(
|
||||||
plc=plc_device,
|
plc=plc_device,
|
||||||
export_base_dir=export_base_dir, # Pass the base directory
|
export_base_dir=export_base_dir,
|
||||||
)
|
)
|
||||||
|
|
||||||
print("\nCross-reference export process completed.")
|
print("\nProceso de exportación de referencias cruzadas completado.")
|
||||||
|
|
||||||
except RuntimeError as tia_ex:
|
except RuntimeError as tia_ex:
|
||||||
print(f"\nTIA Portal Openness Error: {tia_ex}")
|
print(f"\nError de TIA Portal Openness: {tia_ex}")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
print(f"\nERROR: Project file not found at {project_file}")
|
print(f"\nERROR: Archivo de proyecto no encontrado en {project_file}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"\nAn unexpected error occurred: {e}")
|
print(f"\nOcurrió un error inesperado: {e}")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
finally:
|
finally:
|
||||||
# 7. Cleanup
|
# 8. Cleanup
|
||||||
if portal_instance:
|
if portal_instance:
|
||||||
try:
|
try:
|
||||||
print("\nClosing TIA Portal...")
|
print("\nCerrando TIA Portal...")
|
||||||
portal_instance.close_portal()
|
portal_instance.close_portal()
|
||||||
print("TIA Portal closed.")
|
print("TIA Portal cerrado.")
|
||||||
except Exception as close_ex:
|
except Exception as close_ex:
|
||||||
print(f"Error during TIA Portal cleanup: {close_ex}")
|
print(f"Error durante la limpieza de TIA Portal: {close_ex}")
|
||||||
|
|
||||||
print("\nScript finished.")
|
print("\nScript finalizado.")
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
{
|
||||||
|
"block_name": "FC General Lamp",
|
||||||
|
"block_number": 172,
|
||||||
|
"language": "LAD",
|
||||||
|
"block_type": "FC",
|
||||||
|
"block_comment": "",
|
||||||
|
"interface": {
|
||||||
|
"Return": [
|
||||||
|
{
|
||||||
|
"name": "Ret_Val",
|
||||||
|
"datatype": "Void",
|
||||||
|
"remanence": "NonRetain",
|
||||||
|
"accessibility": "Public",
|
||||||
|
"start_value": null,
|
||||||
|
"comment": null,
|
||||||
|
"children": [],
|
||||||
|
"array_elements": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"networks": [
|
||||||
|
{
|
||||||
|
"id": "4",
|
||||||
|
"title": "Lamp Alarm - Q.E. - Light Green",
|
||||||
|
"comment": "",
|
||||||
|
"language": "LAD",
|
||||||
|
"logic": [],
|
||||||
|
"error": "FlgNet not found inside NetworkSource or CompileUnit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "B",
|
||||||
|
"title": "Lamp Alarm - Q.E. - Light Red",
|
||||||
|
"comment": "",
|
||||||
|
"language": "LAD",
|
||||||
|
"logic": [],
|
||||||
|
"error": "FlgNet not found inside NetworkSource or CompileUnit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "12",
|
||||||
|
"title": "Lamp Alarm - Q.E. - Buzzer",
|
||||||
|
"comment": "",
|
||||||
|
"language": "LAD",
|
||||||
|
"logic": [],
|
||||||
|
"error": "FlgNet not found inside NetworkSource or CompileUnit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "19",
|
||||||
|
"title": "Lamp Alarm - Q.E. - Light Blue",
|
||||||
|
"comment": "",
|
||||||
|
"language": "LAD",
|
||||||
|
"logic": [],
|
||||||
|
"error": "FlgNet not found inside NetworkSource or CompileUnit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "20",
|
||||||
|
"title": "Lamp - Alarm Presence",
|
||||||
|
"comment": "",
|
||||||
|
"language": "LAD",
|
||||||
|
"logic": [],
|
||||||
|
"error": "FlgNet not found inside NetworkSource or CompileUnit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "27",
|
||||||
|
"title": "Light Signal Phased Stop Machine",
|
||||||
|
"comment": "",
|
||||||
|
"language": "LAD",
|
||||||
|
"logic": [],
|
||||||
|
"error": "FlgNet not found inside NetworkSource or CompileUnit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "2E",
|
||||||
|
"title": "",
|
||||||
|
"comment": "",
|
||||||
|
"language": "LAD",
|
||||||
|
"logic": [],
|
||||||
|
"error": "FlgNet not found inside NetworkSource or CompileUnit"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source_xml_mod_time": 1749751920.2702959,
|
||||||
|
"source_xml_size": 39346
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,81 @@
|
||||||
|
{
|
||||||
|
"block_name": "FC General Lamp",
|
||||||
|
"block_number": 172,
|
||||||
|
"language": "LAD",
|
||||||
|
"block_type": "FC",
|
||||||
|
"block_comment": "",
|
||||||
|
"interface": {
|
||||||
|
"Return": [
|
||||||
|
{
|
||||||
|
"name": "Ret_Val",
|
||||||
|
"datatype": "Void",
|
||||||
|
"remanence": "NonRetain",
|
||||||
|
"accessibility": "Public",
|
||||||
|
"start_value": null,
|
||||||
|
"comment": null,
|
||||||
|
"children": [],
|
||||||
|
"array_elements": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"networks": [
|
||||||
|
{
|
||||||
|
"id": "4",
|
||||||
|
"title": "Lamp Alarm - Q.E. - Light Green",
|
||||||
|
"comment": "",
|
||||||
|
"language": "LAD",
|
||||||
|
"logic": [],
|
||||||
|
"error": "FlgNet not found inside NetworkSource or CompileUnit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "B",
|
||||||
|
"title": "Lamp Alarm - Q.E. - Light Red",
|
||||||
|
"comment": "",
|
||||||
|
"language": "LAD",
|
||||||
|
"logic": [],
|
||||||
|
"error": "FlgNet not found inside NetworkSource or CompileUnit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "12",
|
||||||
|
"title": "Lamp Alarm - Q.E. - Buzzer",
|
||||||
|
"comment": "",
|
||||||
|
"language": "LAD",
|
||||||
|
"logic": [],
|
||||||
|
"error": "FlgNet not found inside NetworkSource or CompileUnit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "19",
|
||||||
|
"title": "Lamp Alarm - Q.E. - Light Blue",
|
||||||
|
"comment": "",
|
||||||
|
"language": "LAD",
|
||||||
|
"logic": [],
|
||||||
|
"error": "FlgNet not found inside NetworkSource or CompileUnit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "20",
|
||||||
|
"title": "Lamp - Alarm Presence",
|
||||||
|
"comment": "",
|
||||||
|
"language": "LAD",
|
||||||
|
"logic": [],
|
||||||
|
"error": "FlgNet not found inside NetworkSource or CompileUnit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "27",
|
||||||
|
"title": "Light Signal Phased Stop Machine",
|
||||||
|
"comment": "",
|
||||||
|
"language": "LAD",
|
||||||
|
"logic": [],
|
||||||
|
"error": "FlgNet not found inside NetworkSource or CompileUnit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "2E",
|
||||||
|
"title": "",
|
||||||
|
"comment": "",
|
||||||
|
"language": "LAD",
|
||||||
|
"logic": [],
|
||||||
|
"error": "FlgNet not found inside NetworkSource or CompileUnit"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source_xml_mod_time": 1749751920.2702959,
|
||||||
|
"source_xml_size": 39346
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,455 @@
|
||||||
|
// Block Type: FC
|
||||||
|
// Block Name (Original): FC Ttop Motor M31010
|
||||||
|
// Block Number: 327
|
||||||
|
// Original Network Languages: LAD, SCL
|
||||||
|
|
||||||
|
FUNCTION "FC_Ttop_Motor_M31010" : Void
|
||||||
|
{ S7_Optimized_Access := 'TRUE' }
|
||||||
|
VERSION : 0.1
|
||||||
|
|
||||||
|
VAR_INOUT
|
||||||
|
Motor : STRUCT
|
||||||
|
RCP_Speed_Fix_01 : Int;
|
||||||
|
RCP_Speed_Fix_02 : Int;
|
||||||
|
RCP_Speed_Fix_03 : Int;
|
||||||
|
RCP_Speed_Fix_04 : Int;
|
||||||
|
RCP_Speed_Fix_05 : Int;
|
||||||
|
RCP_Speed_Sync_01 : Int;
|
||||||
|
RCP_Speed_Sync_02 : Int;
|
||||||
|
RCP_Speed_Sync_03 : Int;
|
||||||
|
RCP_Speed_Sync_04 : Int;
|
||||||
|
RCP_Speed_Sync_05 : Int;
|
||||||
|
RCP_Timer_01 : Int;
|
||||||
|
RCP_Timer_02 : Int;
|
||||||
|
RCP_Timer_03 : Int;
|
||||||
|
RCP_Timer_04 : Int;
|
||||||
|
RCP_Timer_05 : Int;
|
||||||
|
RCP_Speed_Fix_01_mBar : Int;
|
||||||
|
RCP_Speed_Fix_02_mBar : Int;
|
||||||
|
RCP_Speed_Fix_03_mBar : Int;
|
||||||
|
RCP_Speed_Fix_04_mBar : Int;
|
||||||
|
RCP_Speed_Fix_05_mBar : Int;
|
||||||
|
RCP_ACC_Ramp : Int;
|
||||||
|
RCP_DEC_Ramp : Int;
|
||||||
|
RCP_W044 : Int;
|
||||||
|
RCP_W046 : Int;
|
||||||
|
RCP_W048 : Int;
|
||||||
|
CFG_VFD : Bool;
|
||||||
|
CFG_DP : Bool;
|
||||||
|
CFG_Analog_Speed : Bool;
|
||||||
|
CFG_EN_BWD : Bool;
|
||||||
|
CFG_Reverse : Bool;
|
||||||
|
CFG_Motor_N_Sel : Bool;
|
||||||
|
CFG_PN : Bool;
|
||||||
|
CFG_X050_7 : Bool;
|
||||||
|
CFG_TH_CTR_Single : Bool;
|
||||||
|
CFG_SW_CTR_Single : Bool;
|
||||||
|
CFG_TRIP_CTR_Single : Bool;
|
||||||
|
CFG_Speed_User : Bool;
|
||||||
|
CFG_mBar : Bool;
|
||||||
|
CFG_SW_CTR_OnOff : Bool;
|
||||||
|
CFG_Plug_CTR_Single : Bool;
|
||||||
|
CFG_X051_7 : Bool;
|
||||||
|
CFG_Min_Speed_Hz : Int;
|
||||||
|
CFG_Max_Speed_Hz : Int;
|
||||||
|
CFG_mBar_Type : Byte;
|
||||||
|
CFG_B57 : Byte;
|
||||||
|
CFG_Max_mBar : Int;
|
||||||
|
CFG_EOLO_Zone : Bool;
|
||||||
|
CFG_TableTop_Zone : Bool;
|
||||||
|
CFG_Pack_Zone : Bool;
|
||||||
|
CFG_VIS_Sp_User_Step200 : Bool;
|
||||||
|
CFG_X060_4 : Bool;
|
||||||
|
CFG_X060_5 : Bool;
|
||||||
|
CFG_X060_6 : Bool;
|
||||||
|
CFG_X060_7 : Bool;
|
||||||
|
CFG_MPrew : Int;
|
||||||
|
CFG_MNext : Int;
|
||||||
|
CFG_DBExternal1 : Int;
|
||||||
|
CFG_DBExternal2 : Int;
|
||||||
|
CFG_Vis_Fix_00 : Bool;
|
||||||
|
CFG_VIS_Fix_01 : Bool;
|
||||||
|
CFG_VIS_Fix_02 : Bool;
|
||||||
|
CFG_VIS_Fix_03 : Bool;
|
||||||
|
CFG_VIS_Fix_04 : Bool;
|
||||||
|
CFG_VIS_Fix_05 : Bool;
|
||||||
|
CFG_VIS_Fix_06 : Bool;
|
||||||
|
CFG_VIS_Fix_07 : Bool;
|
||||||
|
CFG_VIS_Sync_00 : Bool;
|
||||||
|
CFG_VIS_Sync_01 : Bool;
|
||||||
|
CFG_VIS_Sync_02 : Bool;
|
||||||
|
CFG_VIS_Sync_03 : Bool;
|
||||||
|
CFG_VIS_Sync_04 : Bool;
|
||||||
|
CFG_VIS_Sync_05 : Bool;
|
||||||
|
CFG_VIS_Sync_06 : Bool;
|
||||||
|
CFG_VIS_Sync_07 : Bool;
|
||||||
|
CFG_VIS_Timer_00 : Bool;
|
||||||
|
CFG_VIS_Timer_01 : Bool;
|
||||||
|
CFG_VIS_Timer_02 : Bool;
|
||||||
|
CFG_VIS_Timer_03 : Bool;
|
||||||
|
CFG_VIS_Timer_04 : Bool;
|
||||||
|
CFG_VIS_Timer_05 : Bool;
|
||||||
|
CFG_VIS_Timer_06 : Bool;
|
||||||
|
CFG_VIS_Timer_07 : Bool;
|
||||||
|
CFG_VIS_SA : Bool;
|
||||||
|
CFG_VIS_SB : Bool;
|
||||||
|
CFG_VIS_SC : Bool;
|
||||||
|
CFG_VIS_SD : Bool;
|
||||||
|
CFG_VIS_BA : Bool;
|
||||||
|
CFG_VIS_BB : Bool;
|
||||||
|
CFG_VIS_EXTA : Bool;
|
||||||
|
CFG_VIS_EXTB : Bool;
|
||||||
|
CFG_VIS_SW : Bool;
|
||||||
|
CFG_VIS_TH : Bool;
|
||||||
|
CFG_VIS_TRIP : Bool;
|
||||||
|
CFG_VIS_PAW : Bool;
|
||||||
|
CFG_VIS_RUN_FWD : Bool;
|
||||||
|
CFG_VIS_RUN_BWD : Bool;
|
||||||
|
CFG_VIS_Kspeed : Bool;
|
||||||
|
CFG_VIS_PLUG : Bool;
|
||||||
|
CFG_VIS_PB_Auto : Bool;
|
||||||
|
CFG_VIS_PB_Man : Bool;
|
||||||
|
CFG_VIS_PB_Jog : Bool;
|
||||||
|
CFG_VIS_PB_Stop : Bool;
|
||||||
|
CFG_VIS_PB_Reverse : Bool;
|
||||||
|
CFG_VIS_PB_sp_05 : Bool;
|
||||||
|
CFG_VIS_PB_sp_06 : Bool;
|
||||||
|
CFG_VIS_ManSpeed : Bool;
|
||||||
|
CFG_VIS_ACT_Torque : Bool;
|
||||||
|
CFG_VIS_ACC_Ramp : Bool;
|
||||||
|
CFG_VIS_DEC_Ramp : Bool;
|
||||||
|
CFG_VIS_X76_3 : Bool;
|
||||||
|
CFG_VIS_X76_4 : Bool;
|
||||||
|
CFG_VIS_X76_5 : Bool;
|
||||||
|
CFG_VIS_X76_6 : Bool;
|
||||||
|
CFG_VIS_X76 : Bool;
|
||||||
|
CFG_B77 : Byte;
|
||||||
|
CFG_W078 : Int;
|
||||||
|
CFG_Add_Signal_SA : UInt;
|
||||||
|
CFG_Add_Signal_SB : UInt;
|
||||||
|
CFG_Add_Signal_SC : UInt;
|
||||||
|
CFG_Add_Signal_SD : UInt;
|
||||||
|
CFG_Add_Signal_BA : UInt;
|
||||||
|
CFG_Add_Signal_BB : UInt;
|
||||||
|
CFG_Add_Signal_EXTA : UInt;
|
||||||
|
CFG_Add_Signal_EXTB : UInt;
|
||||||
|
CFG_Add_Signal_SW : UInt;
|
||||||
|
CFG_Add_Signal_TH : UInt;
|
||||||
|
CFG_Add_Signal_TRIP : UInt;
|
||||||
|
CFG_Add_Signal_PAW : Int;
|
||||||
|
CFG_Add_Signal_RUN_FWD : UInt;
|
||||||
|
CFG_Add_Signal_RUN_BWD : UInt;
|
||||||
|
CFG_Add_Signal_mBar : Int;
|
||||||
|
CFG_Add_Signal_PLUG : Int;
|
||||||
|
CFG_Add_Signal_SP02 : Int;
|
||||||
|
CFG_DB_Machine : Int;
|
||||||
|
CFG_DB_NextMotor : Int;
|
||||||
|
CFG_W118 : Int;
|
||||||
|
CFG_Stop_Empty : Bool;
|
||||||
|
CFG_Stop_Full : Bool;
|
||||||
|
CFG_Stop_STBY : Bool;
|
||||||
|
CFG_Pressurization : Bool;
|
||||||
|
CFG_EOLO_Press_Speed : Int;
|
||||||
|
Spare_124 : Array[124..145] of Byte;
|
||||||
|
CFG_Motor_N : DInt;
|
||||||
|
CFG_Phylosopy_N : Int;
|
||||||
|
CFG_Motor_HW_IO : "HW_IO";
|
||||||
|
CFG_Node_N : Int;
|
||||||
|
CFG_Inverter_Type : Int;
|
||||||
|
CFG_W158 : Int;
|
||||||
|
CFG_Kspeed_User50Hz : Int;
|
||||||
|
CFG_Min_Speed_User : Int;
|
||||||
|
CFG_Max_Speed_User : Int;
|
||||||
|
CFG_W166 : Int;
|
||||||
|
CFG_W168 : Int;
|
||||||
|
CFG_EN_mBar_FCT : Bool;
|
||||||
|
CFG_EN_mBar_FilterALM : Bool;
|
||||||
|
CFG_Isteresi_mBar : Int;
|
||||||
|
CFG_Gain_Mbar : Int;
|
||||||
|
CFG_Max_Speed_FilterALM : Int;
|
||||||
|
CFG_W178 : Int;
|
||||||
|
CFG_T_Gain : STRUCT
|
||||||
|
S : Bool;
|
||||||
|
Q : Bool;
|
||||||
|
TW : Int;
|
||||||
|
ST : Int;
|
||||||
|
ACT : Int;
|
||||||
|
W008 : Int;
|
||||||
|
END_STRUCT;
|
||||||
|
|
||||||
|
CFG_T_FilterALM : STRUCT
|
||||||
|
S : Bool;
|
||||||
|
Q : Bool;
|
||||||
|
TW : Int;
|
||||||
|
ST : Int;
|
||||||
|
ACT : Int;
|
||||||
|
W008 : Int;
|
||||||
|
END_STRUCT;
|
||||||
|
|
||||||
|
IN_PB_Start : Bool;
|
||||||
|
IN_PB_Stop : Bool;
|
||||||
|
IN_PB_Reset : Bool;
|
||||||
|
IN_PB_Silence : Bool;
|
||||||
|
IN_X200_4 : Bool;
|
||||||
|
IN_X200_5 : Bool;
|
||||||
|
IN_X200_6 : Bool;
|
||||||
|
IN_X200_7 : Bool;
|
||||||
|
IN_KG_PowerON : Bool;
|
||||||
|
IN_SW_ManAuto : Bool;
|
||||||
|
IN_Cycle_ON : Bool;
|
||||||
|
IN_X201_3 : Bool;
|
||||||
|
IN_X201_4 : Bool;
|
||||||
|
IN_X201_5 : Bool;
|
||||||
|
IN_X201_6 : Bool;
|
||||||
|
IN_X201_7 : Bool;
|
||||||
|
IN_SW_HMI_Auto : Bool;
|
||||||
|
IN_SW_HMI_Man : Bool;
|
||||||
|
IN_SW_HMI_Jog : Bool;
|
||||||
|
IN_SW_HMI_Stop : Bool;
|
||||||
|
IN_SW_HMI_Reverse : Bool;
|
||||||
|
IN_SW_HMI_sp_05 : Bool;
|
||||||
|
IN_SW_HMI_sp_06 : Bool;
|
||||||
|
IN_SW_HMI_ManSpeed : Bool;
|
||||||
|
IN_SW_HMI_sp_08 : Bool;
|
||||||
|
IN_SW_HMI_VVFix1 : Bool;
|
||||||
|
IN_SW_HMI_VVFix2 : Bool;
|
||||||
|
IN_SW_HMI_VVFix3 : Bool;
|
||||||
|
IN_SW_HMI_VVFix4 : Bool;
|
||||||
|
IN_SW_HMI_VVFix5 : Bool;
|
||||||
|
IN_SW_HMI_sp_14 : Bool;
|
||||||
|
IN_SW_HMI_sp_15 : Bool;
|
||||||
|
IN_HMI_ManSpeed : Int;
|
||||||
|
IN_Signal_SA : Bool;
|
||||||
|
IN_Signal_SB : Bool;
|
||||||
|
IN_Signal_SC : Bool;
|
||||||
|
IN_Signal_SD : Bool;
|
||||||
|
IN_Signal_BA : Bool;
|
||||||
|
IN_Signal_BB : Bool;
|
||||||
|
IN_Signal_EXTA : Bool;
|
||||||
|
IN_Signal_EXTB : Bool;
|
||||||
|
IN_Signal_SW : Bool;
|
||||||
|
IN_Signal_TH : Bool;
|
||||||
|
IN_Signal_TRIP : Bool;
|
||||||
|
IN_Signal_RUN_FWD : Bool;
|
||||||
|
IN_Signal_RUN_BWD : Bool;
|
||||||
|
IN_Signal_sp_05 : Bool;
|
||||||
|
IN_Signal_sp_06 : Bool;
|
||||||
|
IN_Signal_PLUG : Bool;
|
||||||
|
IN_Signal_sp_08 : Int;
|
||||||
|
IN_Signal_PEW_mBar : Int;
|
||||||
|
IN_Signal_mBar : Int;
|
||||||
|
IN_Motor_DI : "Struct";
|
||||||
|
IN_W216 : Int;
|
||||||
|
IN_W218 : Int;
|
||||||
|
IN_Line_Empty : Bool;
|
||||||
|
IN_Line_Full : Bool;
|
||||||
|
IN_Line_StandBy : Bool;
|
||||||
|
Spare_222 : Array[222..249] of Byte;
|
||||||
|
OUT_VFD_Run_FWD : Bool;
|
||||||
|
OUT_VFD_Run_BWD : Bool;
|
||||||
|
OUT_VFD_Reverse : Bool;
|
||||||
|
OUT_VFD_Qstop : Bool;
|
||||||
|
OUT_VFD_Reset : Bool;
|
||||||
|
OUT_X250_5 : Bool;
|
||||||
|
OUT_X250_6 : Bool;
|
||||||
|
OUT_EnergySavingON : Bool;
|
||||||
|
OUT_VFD_REQ_Speed_Hz : Int;
|
||||||
|
OUT_VFD_REQ_Speed_User : Int;
|
||||||
|
OUT_VFD_ACT_Sync_Speed : Int;
|
||||||
|
OUT_VFD_REQ_Speed_mBar : Int;
|
||||||
|
OUT_Motor_DO : "Struct";
|
||||||
|
OUT_W262 : Int;
|
||||||
|
OUT_W264 : Int;
|
||||||
|
OUT_W266 : Int;
|
||||||
|
OUT_W268 : Int;
|
||||||
|
STATUS_VFD_Run_FWD : Bool;
|
||||||
|
STATUS_VFD_Run_BWD : Bool;
|
||||||
|
STATUS_VFD_Trip : Bool;
|
||||||
|
STATUS_VFD_Warning : Bool;
|
||||||
|
STATUS_Ready : Bool;
|
||||||
|
STATUS_VFD_Ready : Bool;
|
||||||
|
STATUS_VFD_Coasting : Bool;
|
||||||
|
STATUS_X270_7 : Bool;
|
||||||
|
STATUS_VFD_ACT_Speed_Hz : Int;
|
||||||
|
STATUS_VFD_ACT_Speed_Use : Int;
|
||||||
|
STATUS_VFD_ACT_Torque : Int;
|
||||||
|
STATUS_MainFault_MovigearADV : Byte;
|
||||||
|
STATUS_Subfault_MovigearADV : Byte;
|
||||||
|
STATUS_W280 : Int;
|
||||||
|
STATUS_W282 : Int;
|
||||||
|
STATUS_PWR_OFF : Bool;
|
||||||
|
STATUS_CYCLE_OFF : Bool;
|
||||||
|
STATUS_ALARM : Bool;
|
||||||
|
STATUS_AUTO : Bool;
|
||||||
|
STATUS_MAN : Bool;
|
||||||
|
STATUS_JOG : Bool;
|
||||||
|
STATUS_STOP : Bool;
|
||||||
|
STATUS_X284_7 : Bool;
|
||||||
|
STATUS_X285_0 : Bool;
|
||||||
|
STATUS_X285_1 : Bool;
|
||||||
|
STATUS_X285_2 : Bool;
|
||||||
|
STATUS_X285_3 : Bool;
|
||||||
|
STATUS_X285_4 : Bool;
|
||||||
|
STATUS_X285_5 : Bool;
|
||||||
|
STATUS_X285_6 : Bool;
|
||||||
|
STATUS_X285_7 : Bool;
|
||||||
|
STATUS_NOTRUN : Bool;
|
||||||
|
STATUS_RUN : Bool;
|
||||||
|
STATUS_X286_2 : Bool;
|
||||||
|
STATUS_X286_3 : Bool;
|
||||||
|
STATUS_X286_4 : Bool;
|
||||||
|
STATUS_X286_5 : Bool;
|
||||||
|
STATUS_X286_6 : Bool;
|
||||||
|
STATUS_X286_7 : Bool;
|
||||||
|
Spare_288 : Array[288..289] of Byte;
|
||||||
|
Alarm_09 : Bool;
|
||||||
|
Alarm_10 : Bool;
|
||||||
|
Alarm_11 : Bool;
|
||||||
|
Alarm_12 : Bool;
|
||||||
|
Alarm_13 : Bool;
|
||||||
|
Alarm_14 : Bool;
|
||||||
|
Alarm_15 : Bool;
|
||||||
|
Alarm_16 : Bool;
|
||||||
|
Alarm_01 : Bool;
|
||||||
|
Alarm_02 : Bool;
|
||||||
|
Alarm_03 : Bool;
|
||||||
|
Alarm_04 : Bool;
|
||||||
|
Alarm_05 : Bool;
|
||||||
|
Alarm_06 : Bool;
|
||||||
|
Alarm_07 : Bool;
|
||||||
|
Alarm_08 : Bool;
|
||||||
|
Spare_292 : Array[292..299] of Byte;
|
||||||
|
M_Power_ON : Bool;
|
||||||
|
M_Cycle_ON_AUTO : Bool;
|
||||||
|
M_Cycle_ON_MAN : Bool;
|
||||||
|
M_W302 : Int;
|
||||||
|
M_W304 : Int;
|
||||||
|
M_W306 : Int;
|
||||||
|
M_W308 : Int;
|
||||||
|
M_Delay_Cycle_ON_Auto : STRUCT
|
||||||
|
S : Bool;
|
||||||
|
Q : Bool;
|
||||||
|
TW : Int;
|
||||||
|
ST : Int;
|
||||||
|
ACT : Int;
|
||||||
|
W008 : Int;
|
||||||
|
END_STRUCT;
|
||||||
|
|
||||||
|
Spare_320 : Array[320..349] of Byte;
|
||||||
|
REQ_EN_Run : Bool;
|
||||||
|
REQ_Start_FWD : Bool;
|
||||||
|
REQ_Start_BWD : Bool;
|
||||||
|
REQ_QStop : Bool;
|
||||||
|
REQ_X350_4 : Bool;
|
||||||
|
REQ_X350_5 : Bool;
|
||||||
|
REQ_X350_6 : Bool;
|
||||||
|
REQ_X350_7 : Bool;
|
||||||
|
REQ_X351_0 : Bool;
|
||||||
|
REQ_X351_1 : Bool;
|
||||||
|
REQ_X351_2 : Bool;
|
||||||
|
REQ_X351_3 : Bool;
|
||||||
|
REQ_X351_4 : Bool;
|
||||||
|
REQ_X351_5 : Bool;
|
||||||
|
REQ_X351_6 : Bool;
|
||||||
|
REQ_X351_7 : Bool;
|
||||||
|
REQ_W352 : Int;
|
||||||
|
REQ_Master_Speed_Sync : Int;
|
||||||
|
REQ_W356 : Int;
|
||||||
|
REQ_Speed_Fix_00_NU : Bool;
|
||||||
|
REQ_Speed_Fix_01 : Bool;
|
||||||
|
REQ_Speed_Fix_02 : Bool;
|
||||||
|
REQ_Speed_Fix_03 : Bool;
|
||||||
|
REQ_Speed_Fix_04 : Bool;
|
||||||
|
REQ_Speed_Fix_05 : Bool;
|
||||||
|
REQ_Speed_Fix_06_NU : Bool;
|
||||||
|
REQ_Speed_Fix_07_NU : Bool;
|
||||||
|
REQ_Speed_Sync_00_NU : Bool;
|
||||||
|
REQ_Speed_Sync_01 : Bool;
|
||||||
|
REQ_Speed_Sync_02 : Bool;
|
||||||
|
REQ_Speed_Sync_03 : Bool;
|
||||||
|
REQ_Speed_Sync_04 : Bool;
|
||||||
|
REQ_Speed_Sync_05 : Bool;
|
||||||
|
REQ_Speed_Sync_06_NU : Bool;
|
||||||
|
REQ_Speed_Sync_07_NU : Bool;
|
||||||
|
REQ_T01 : STRUCT
|
||||||
|
S : Bool;
|
||||||
|
Q : Bool;
|
||||||
|
TW : Int;
|
||||||
|
ST : Int;
|
||||||
|
ACT : Int;
|
||||||
|
W008 : Int;
|
||||||
|
END_STRUCT;
|
||||||
|
|
||||||
|
REQ_T02 : STRUCT
|
||||||
|
S : Bool;
|
||||||
|
Q : Bool;
|
||||||
|
TW : Int;
|
||||||
|
ST : Int;
|
||||||
|
ACT : Int;
|
||||||
|
W008 : Int;
|
||||||
|
END_STRUCT;
|
||||||
|
|
||||||
|
REQ_T03 : STRUCT
|
||||||
|
S : Bool;
|
||||||
|
Q : Bool;
|
||||||
|
TW : Int;
|
||||||
|
ST : Int;
|
||||||
|
ACT : Int;
|
||||||
|
W008 : Int;
|
||||||
|
END_STRUCT;
|
||||||
|
|
||||||
|
REQ_T04 : STRUCT
|
||||||
|
S : Bool;
|
||||||
|
Q : Bool;
|
||||||
|
TW : Int;
|
||||||
|
ST : Int;
|
||||||
|
ACT : Int;
|
||||||
|
W008 : Int;
|
||||||
|
END_STRUCT;
|
||||||
|
|
||||||
|
REQ_T05 : STRUCT
|
||||||
|
S : Bool;
|
||||||
|
Q : Bool;
|
||||||
|
TW : Int;
|
||||||
|
ST : Int;
|
||||||
|
ACT : Int;
|
||||||
|
W008 : Int;
|
||||||
|
END_STRUCT;
|
||||||
|
|
||||||
|
END_STRUCT;
|
||||||
|
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
VAR_TEMP
|
||||||
|
RetVal : Int;
|
||||||
|
MotorNumber : Int;
|
||||||
|
DBNumber : Int;
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
BEGIN
|
||||||
|
|
||||||
|
// Network 1: INIT Configuration (Original Language: SCL)
|
||||||
|
|
||||||
|
// SCL extraction failed: StructuredText node not found.
|
||||||
|
|
||||||
|
// Network 2: (Original Language: LAD)
|
||||||
|
|
||||||
|
// Network 2 has no logic elements.
|
||||||
|
|
||||||
|
// Network 3: EN run (Original Language: LAD)
|
||||||
|
|
||||||
|
"Motor"."REQ_EN_Run" := "M0.1";
|
||||||
|
|
||||||
|
// Network 4: REQ Auto RUN (Original Language: LAD)
|
||||||
|
|
||||||
|
"Motor"."REQ_Start_FWD" := TRUE;
|
||||||
|
|
||||||
|
// Network 5: Request Speed Fix 01 (Original Language: LAD)
|
||||||
|
|
||||||
|
"Motor"."REQ_Speed_Fix_01" := "M0.1";
|
||||||
|
|
||||||
|
// Network 6: INIT Configuration (Original Language: SCL)
|
||||||
|
|
||||||
|
// SCL extraction failed: StructuredText node not found.
|
||||||
|
|
||||||
|
END_FUNCTION
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,93 @@
|
||||||
|
--- Log de Ejecución: x7_clear.py ---
|
||||||
|
Grupo: XML Parser to SCL
|
||||||
|
Directorio de Trabajo: D:\Trabajo\VM\44 - 98050 - Fiera\Reporte\ExportsTia\Source
|
||||||
|
Inicio: 2025-06-13 01:01:10
|
||||||
|
Fin: 2025-06-13 01:01:11
|
||||||
|
Duración: 0:00:00.701052
|
||||||
|
Estado: SUCCESS (Código de Salida: 0)
|
||||||
|
|
||||||
|
--- SALIDA ESTÁNDAR (STDOUT) ---
|
||||||
|
INFO: format_variable_name importado desde generators.generator_utils
|
||||||
|
|
||||||
|
=== Limpiando PLC: 98050_PLC ===
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\PlcDataTypes\CONVEYORS\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\PlcDataTypes\CONVEYORS\MiniMotor\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\PlcDataTypes\CONVEYORS\MiniMotor\DBS55_PN_Extend-A\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\PlcDataTypes\CONVEYORS\SICK AG\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\PlcDataTypes\CONVEYORS\TRANSFER\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\PlcDataTypes\ConveyorsBase\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\PlcDataTypes\Library\Motion\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\PlcDataTypes\Library\Motion\Siemens\LCamHdl_Types\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\PlcDataTypes\Library\Motion\Technology\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\PlcDataTypes\Library\SeamlessDivider\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\PlcDataTypes\Library\SeamlessDivider\Technology\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\PlcDataTypes\Machine\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\PlcDataTypes\Machine\Cycle\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\PlcTags\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\PlcTags\Library\Motion\Siemens\LCamHdl_Tags\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\!!! SYS !!!\DB\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\!!! SYS !!!\FB\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\!!! SYS !!!\FC\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\!!! SYS !!!\FC\1-AIR Philosophy\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\!!! SYS !!!\FC\2-TTOP Philosophy\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\!!! SYS !!!\FC\3-Motors Manage\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\!!! SYS !!!\FC\3-Motors Manage\MiniMotor_PN\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\!!! SYS !!!\FC\3-Motors Manage\MiniMotor_PN\MiniMotor_PN\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\!!! SYS !!!\FC\HMI\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\!!! SYS !!!\FC\MACHINE SIGNALS\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\!!! SYS !!!\OB\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\!!!TRANSFER\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\0 - MAIN\DB\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\0 - MAIN\FC\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\0 - MAIN\OB\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\1 - CONVEYORS\2 - TTOP\Device\DB\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\1 - CONVEYORS\2 - TTOP\Device\FB\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\1 - CONVEYORS\2 - TTOP\Device\FC\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\1 - CONVEYORS\2 - TTOP\General\DB\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\1 - CONVEYORS\2 - TTOP\General\FC\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\1 - CONVEYORS\2 - TTOP\Motor\DB\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\1 - CONVEYORS\2 - TTOP\Motor\DB\Minimotor\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\1 - CONVEYORS\2 - TTOP\Motor\FC\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\1 - CONVEYORS\2 - TTOP\Motor\FC\Minimotor\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\1 - CONVEYORS\4 - LUBE\DB\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\1 - CONVEYORS\4 - LUBE\FB\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\1 - CONVEYORS\4 - LUBE\FB\OLD\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\2 - MACHINE\DB\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\2 - MACHINE\FB\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\Divider\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\Divider\! ConveyorsSTD\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\Divider\! ConveyorsSTD\Hmi\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\Divider\! ConveyorsSTD\System\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\Divider\! ConveyorsSTD\TimeZone\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\Divider\AAA_Debug\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\Divider\AAA_VirtualMaster\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\Divider\ExchangeSignals\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\Divider\ExchangeSignals\Loop\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\Divider\HMI\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\Divider\Instances\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\Divider\Libraries\Generic\Alarms\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\Divider\Libraries\Motion\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\Divider\Libraries\Motion\Siemens\LCamHdl_Blocks\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\Divider\Libraries\Motion\Technology\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\Divider\Libraries\Motion\Utilities\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\Divider\Libraries\SeamlessDivider\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\Divider\Libraries\SeamlessDivider\Technology\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\Divider\Machine\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\Divider\Machine\Instances\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\Divider\Setup\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\Divider\TimingBelt (downstream divider)\parsing
|
||||||
|
- Eliminado directorio de parsing: 98050_PLC\ProgramBlocks_XML\Divider\TimingBelt (downstream divider)\Instances\parsing
|
||||||
|
- Eliminado directorio 'scl_output': 98050_PLC\scl_output
|
||||||
|
- Eliminado directorio 'xref_output': 98050_PLC\xref_output
|
||||||
|
- Eliminado archivo agregado: 98050_PLC\full_project_representation.md
|
||||||
|
- Eliminado log: log_98050_PLC.txt
|
||||||
|
|
||||||
|
--- Resumen de limpieza ---
|
||||||
|
Directorios eliminados: 70
|
||||||
|
Archivos eliminados: 2
|
||||||
|
Limpieza completada.
|
||||||
|
|
||||||
|
--- ERRORES (STDERR) ---
|
||||||
|
Ninguno
|
||||||
|
--- FIN DEL LOG ---
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -61,15 +61,19 @@ def parse_lad_fbd_network(network_element):
|
||||||
network_lang = lang_node_net[0].strip()
|
network_lang = lang_node_net[0].strip()
|
||||||
|
|
||||||
# --- Buscar FlgNet ---
|
# --- Buscar FlgNet ---
|
||||||
# Buscar NetworkSource y luego FlgNet (ambos usan namespace flg)
|
# Paso 1: localizar el nodo <NetworkSource> (sin importar namespace)
|
||||||
network_source_node = network_element.xpath(".//flg:NetworkSource", namespaces=ns)
|
network_source_node = network_element.xpath(".//*[local-name()='NetworkSource']")
|
||||||
|
|
||||||
flgnet = None
|
flgnet = None
|
||||||
if network_source_node:
|
if network_source_node:
|
||||||
flgnet_list = network_source_node[0].xpath("./flg:FlgNet", namespaces=ns)
|
# Buscar FlgNet dentro del NetworkSource
|
||||||
|
flgnet_list = network_source_node[0].xpath(".//*[local-name()='FlgNet']")
|
||||||
if flgnet_list:
|
if flgnet_list:
|
||||||
flgnet = flgnet_list[0]
|
flgnet = flgnet_list[0]
|
||||||
else: # Intentar buscar FlgNet directamente si no hay NetworkSource
|
|
||||||
flgnet_list = network_element.xpath(".//flg:FlgNet", namespaces=ns)
|
# Paso 2: si no se encontró, intentar buscar FlgNet directamente en el CompileUnit
|
||||||
|
if flgnet is None:
|
||||||
|
flgnet_list = network_element.xpath(".//*[local-name()='FlgNet']")
|
||||||
if flgnet_list:
|
if flgnet_list:
|
||||||
flgnet = flgnet_list[0]
|
flgnet = flgnet_list[0]
|
||||||
|
|
||||||
|
|
|
@ -215,32 +215,43 @@ def parse_scl_network(network_element):
|
||||||
Devuelve un diccionario representando la red para el JSON.
|
Devuelve un diccionario representando la red para el JSON.
|
||||||
"""
|
"""
|
||||||
network_id = network_element.get("ID", "UnknownSCL_ID")
|
network_id = network_element.get("ID", "UnknownSCL_ID")
|
||||||
network_lang = "SCL" # Sabemos que es SCL
|
network_lang = "SCL" # Sabemos que es SCL
|
||||||
|
|
||||||
# Buscar NetworkSource y luego StructuredText
|
# --- Obtener título y comentario para coherencia con otros parsers ---
|
||||||
network_source_node = network_element.xpath(".//flg:NetworkSource", namespaces=ns)
|
title_elem = network_element.xpath(
|
||||||
|
"./ObjectList/MultilingualText[@CompositionName='Title']", namespaces=ns
|
||||||
|
)
|
||||||
|
network_title = get_multilingual_text(title_elem[0]) if title_elem else f"Network {network_id}"
|
||||||
|
|
||||||
|
comment_elem = network_element.xpath(
|
||||||
|
"./ObjectList/MultilingualText[@CompositionName='Comment']", namespaces=ns
|
||||||
|
)
|
||||||
|
network_comment = get_multilingual_text(comment_elem[0]) if comment_elem else ""
|
||||||
|
|
||||||
|
# --- Buscar NetworkSource y StructuredText sin depender del namespace ---
|
||||||
|
network_source_node = network_element.xpath(".//*[local-name()='NetworkSource']")
|
||||||
structured_text_node = None
|
structured_text_node = None
|
||||||
if network_source_node:
|
if network_source_node:
|
||||||
structured_text_node_list = network_source_node[0].xpath("./st:StructuredText", namespaces=ns)
|
st_nodes = network_source_node[0].xpath(".//*[local-name()='StructuredText']")
|
||||||
if structured_text_node_list:
|
if st_nodes:
|
||||||
structured_text_node = structured_text_node_list[0]
|
structured_text_node = st_nodes[0]
|
||||||
|
|
||||||
reconstructed_scl = "// SCL extraction failed: StructuredText node not found.\n"
|
reconstructed_scl = "// SCL extraction failed: StructuredText node not found.\n"
|
||||||
if structured_text_node is not None:
|
if structured_text_node is not None:
|
||||||
reconstructed_scl = reconstruct_scl_from_tokens(structured_text_node)
|
reconstructed_scl = reconstruct_scl_from_tokens(structured_text_node)
|
||||||
|
|
||||||
# Crear la estructura de datos para la red
|
|
||||||
parsed_network_data = {
|
parsed_network_data = {
|
||||||
"id": network_id,
|
"id": network_id,
|
||||||
|
"title": network_title,
|
||||||
|
"comment": network_comment,
|
||||||
"language": network_lang,
|
"language": network_lang,
|
||||||
"logic": [ # SCL se guarda como un único bloque lógico
|
"logic": [
|
||||||
{
|
{
|
||||||
"instruction_uid": f"SCL_{network_id}", # UID sintético
|
"instruction_uid": f"SCL_{network_id}",
|
||||||
"type": "RAW_SCL_CHUNK", # Tipo especial para SCL crudo
|
"type": "RAW_SCL_CHUNK",
|
||||||
"scl": reconstructed_scl, # El código SCL reconstruido
|
"scl": reconstructed_scl,
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
# No añadimos error aquí, reconstruct_scl_from_tokens ya incluye comentarios de error
|
|
||||||
}
|
}
|
||||||
return parsed_network_data
|
return parsed_network_data
|
||||||
|
|
||||||
|
|
|
@ -478,3 +478,74 @@ def parse_interface_members(member_elements):
|
||||||
} # Guardar como dict simple si no hay comment
|
} # Guardar como dict simple si no hay comment
|
||||||
members_data.append(member_info)
|
members_data.append(member_info)
|
||||||
return members_data
|
return members_data
|
||||||
|
|
||||||
|
# --- NUEVA FUNCIÓN: Adaptación dinámica de namespaces ---
|
||||||
|
|
||||||
|
def adapt_namespaces(root):
|
||||||
|
"""Actualiza dinámicamente los valores en el diccionario global `ns` para que
|
||||||
|
coincidan con los namespaces reales presentes en el XML exportado por TIA.
|
||||||
|
|
||||||
|
Debe llamarse después de obtener la raíz (`root = tree.getroot()`). Si en el
|
||||||
|
XML aparecen nuevas versiones (p.ej. v6) de los URIs, esta función las
|
||||||
|
detectará y sobreescribirá las entradas correspondientes en `ns`.
|
||||||
|
"""
|
||||||
|
if root is None:
|
||||||
|
return # nada que hacer
|
||||||
|
|
||||||
|
detected = {}
|
||||||
|
|
||||||
|
# 1) Examinar los namespaces declarados en la raíz (cuando existan)
|
||||||
|
if hasattr(root, "nsmap") and root.nsmap:
|
||||||
|
for uri in root.nsmap.values():
|
||||||
|
if not uri or "siemens.com/automation" not in str(uri):
|
||||||
|
continue
|
||||||
|
_assign_uri_to_prefix(str(uri), detected)
|
||||||
|
|
||||||
|
# 2) Escaneo rápido por elementos clave si aún no hemos encontrado URIs
|
||||||
|
# Utilizamos búsquedas sin namespace (local-name) para localizar el primer
|
||||||
|
# elemento relevante y extraer su URI real.
|
||||||
|
|
||||||
|
# helper interno
|
||||||
|
|
||||||
|
def find_uri_by_localname(tag_local):
|
||||||
|
elem = root.xpath(f'//*[local-name()="{tag_local}"]')
|
||||||
|
if elem:
|
||||||
|
return etree.QName(elem[0]).namespace
|
||||||
|
return None
|
||||||
|
|
||||||
|
if "flg" not in detected or not detected.get("flg"):
|
||||||
|
flg_uri = find_uri_by_localname("FlgNet")
|
||||||
|
if flg_uri:
|
||||||
|
detected["flg"] = flg_uri
|
||||||
|
|
||||||
|
if "st" not in detected or not detected.get("st"):
|
||||||
|
st_uri = find_uri_by_localname("StructuredText")
|
||||||
|
if st_uri:
|
||||||
|
detected["st"] = st_uri
|
||||||
|
|
||||||
|
if "stl" not in detected or not detected.get("stl"):
|
||||||
|
stl_uri = find_uri_by_localname("StatementList")
|
||||||
|
if stl_uri:
|
||||||
|
detected["stl"] = stl_uri
|
||||||
|
|
||||||
|
if "iface" not in detected or not detected.get("iface"):
|
||||||
|
iface_uri = find_uri_by_localname("Sections")
|
||||||
|
if iface_uri and "/Interface/" in iface_uri:
|
||||||
|
detected["iface"] = iface_uri
|
||||||
|
|
||||||
|
if detected:
|
||||||
|
ns.update(detected)
|
||||||
|
|
||||||
|
|
||||||
|
# --- función auxiliar privada para adapt_namespaces ---
|
||||||
|
|
||||||
|
def _assign_uri_to_prefix(uri_str: str, out_dict: dict):
|
||||||
|
"""Asigna un URI concreto al prefijo adecuado en `out_dict`."""
|
||||||
|
if "/Interface/" in uri_str:
|
||||||
|
out_dict["iface"] = uri_str
|
||||||
|
elif "/NetworkSource/FlgNet/" in uri_str:
|
||||||
|
out_dict["flg"] = uri_str
|
||||||
|
elif "/NetworkSource/StructuredText/" in uri_str:
|
||||||
|
out_dict["st"] = uri_str
|
||||||
|
elif "/NetworkSource/StatementList/" in uri_str:
|
||||||
|
out_dict["stl"] = uri_str
|
||||||
|
|
|
@ -15,5 +15,5 @@
|
||||||
"xref_source_subdir": "source"
|
"xref_source_subdir": "source"
|
||||||
},
|
},
|
||||||
"level3": {},
|
"level3": {},
|
||||||
"working_directory": "D:\\Trabajo\\VM\\44 - 98050 - Fiera\\Reporte\\ExportsTia\\Source"
|
"working_directory": "D:\\Trabajo\\VM\\22 - 93841 - Sidel - Tilting\\Reporte\\TiaExports"
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"x0_main.py": {
|
"x0_main.py": {
|
||||||
"display_name": "1: Procesar Exportación XML",
|
"display_name": "1: Procesar Exportación XML de un proyecto a SCL",
|
||||||
"short_description": "LadderToSCL - Conversor de Siemens LAD/FUP XML a SCL",
|
"short_description": "LadderToSCL - Conversor de Siemens LAD/FUP XML a SCL",
|
||||||
"long_description": "Este script es el punto de entrada y orquestador principal para el proceso de conversión de archivos XML de Siemens TIA Portal (LAD/FUP) a código SCL y la generación de documentación relacionada.\n\n**Lógica Principal:**\n\n1. **Configuración:** Carga parámetros desde `ParamManagerScripts` (directorio de trabajo, nombres de carpetas de salida, etc.).\n2. **Logging:** Inicia un archivo `log.txt` para registrar detalladamente el progreso y los errores.\n3. **Descubrimiento:** Busca recursivamente todos los archivos `.xml` dentro del subdirectorio `PLC` del directorio de trabajo configurado.\n4. **Procesamiento Individual (Pasos x1-x3):**\n * Itera sobre cada archivo XML encontrado.\n * Implementa lógica para **saltar** pasos si el XML no ha cambiado y las salidas ya existen y están actualizadas.\n * Llama a funciones de `x1_to_json.py`, `x2_process.py`, y `x3_generate_scl.py` para convertir XML -> JSON intermedio -> JSON procesado -> archivo SCL/Markdown final.\n5. **Referencias Cruzadas (Paso x4):** Llama a una función de `x4_cross_reference.py` para generar análisis de llamadas, uso de DBs, etc., basándose en los archivos procesados.\n6. **Agregación (Paso x5):** Llama a una función de `x5_aggregate.py` para combinar las salidas SCL/Markdown y las referencias cruzadas en un único archivo Markdown resumen.\n7. **Resumen y Salida:** Registra un resumen final del proceso (éxitos, saltos, fallos) y finaliza con un código de estado (0 para éxito, 1 si hubo errores).\n",
|
"long_description": "Este script es el punto de entrada y orquestador principal para el proceso de conversión de archivos XML de Siemens TIA Portal (LAD/FUP) a código SCL y la generación de documentación relacionada.\n\n**Lógica Principal:**\n\n1. **Configuración:** Carga parámetros desde `ParamManagerScripts` (directorio de trabajo, nombres de carpetas de salida, etc.).\n2. **Logging:** Inicia un archivo `log.txt` para registrar detalladamente el progreso y los errores.\n3. **Descubrimiento:** Busca recursivamente todos los archivos `.xml` dentro del subdirectorio `PLC` del directorio de trabajo configurado.\n4. **Procesamiento Individual (Pasos x1-x3):**\n * Itera sobre cada archivo XML encontrado.\n * Implementa lógica para **saltar** pasos si el XML no ha cambiado y las salidas ya existen y están actualizadas.\n * Llama a funciones de `x1_to_json.py`, `x2_process.py`, y `x3_generate_scl.py` para convertir XML -> JSON intermedio -> JSON procesado -> archivo SCL/Markdown final.\n5. **Referencias Cruzadas (Paso x4):** Llama a una función de `x4_cross_reference.py` para generar análisis de llamadas, uso de DBs, etc., basándose en los archivos procesados.\n6. **Agregación (Paso x5):** Llama a una función de `x5_aggregate.py` para combinar las salidas SCL/Markdown y las referencias cruzadas en un único archivo Markdown resumen.\n7. **Resumen y Salida:** Registra un resumen final del proceso (éxitos, saltos, fallos) y finaliza con un código de estado (0 para éxito, 1 si hubo errores).\n",
|
||||||
"hidden": false
|
"hidden": false
|
||||||
|
@ -34,5 +34,11 @@
|
||||||
"short_description": "LadderToSCL - Conversor de Siemens LAD/FUP XML a SCL",
|
"short_description": "LadderToSCL - Conversor de Siemens LAD/FUP XML a SCL",
|
||||||
"long_description": "",
|
"long_description": "",
|
||||||
"hidden": true
|
"hidden": true
|
||||||
|
},
|
||||||
|
"x7_clear.py": {
|
||||||
|
"display_name": "3: Limpiar archivos json y md",
|
||||||
|
"short_description": "3: Limpiar archivos json y md generados por (1)",
|
||||||
|
"long_description": "",
|
||||||
|
"hidden": false
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"path": "D:\\Trabajo\\VM\\44 - 98050 - Fiera\\Reporte\\ExportsTia\\Source",
|
"path": "D:\\Trabajo\\VM\\22 - 93841 - Sidel - Tilting\\Reporte\\TiaExports",
|
||||||
"history": [
|
"history": [
|
||||||
|
"D:\\Trabajo\\VM\\22 - 93841 - Sidel - Tilting\\Reporte\\TiaExports",
|
||||||
"D:\\Trabajo\\VM\\44 - 98050 - Fiera\\Reporte\\ExportsTia\\Source",
|
"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"
|
||||||
|
|
|
@ -158,76 +158,225 @@ def check_skip_status(
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
|
||||||
|
# --- FUNCIÓN DE LIMPIEZA (x7) ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def clear_generated_outputs(plc_dir: str = None) -> bool:
|
||||||
|
"""Elimina todos los artefactos (JSON, SCL, MD, logs) generados por este script.
|
||||||
|
|
||||||
|
Si *plc_dir* es None, se comporta de forma análoga al modo orquestador,
|
||||||
|
localizando todos los PLCs bajo el *working_directory* configurado y
|
||||||
|
limpiándolos uno a uno. Devuelve *True* si la operación terminó sin
|
||||||
|
errores críticos, *False* en caso contrario.
|
||||||
|
"""
|
||||||
|
errors_found = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
configs = load_configuration()
|
||||||
|
working_directory = configs.get("working_directory")
|
||||||
|
if not working_directory or not os.path.isdir(working_directory):
|
||||||
|
print("Error: 'working_directory' inválido en la configuración.", file=sys.stderr)
|
||||||
|
return False
|
||||||
|
|
||||||
|
xml_parser_config = configs.get("level2", {})
|
||||||
|
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_aggregated_filename = xml_parser_config.get("aggregated_filename", "full_project_representation.md")
|
||||||
|
|
||||||
|
# Determinar la lista de PLCs a limpiar
|
||||||
|
if plc_dir is not None:
|
||||||
|
plc_dirs = [os.path.abspath(plc_dir)]
|
||||||
|
if not os.path.isdir(plc_dirs[0]):
|
||||||
|
print(f"Advertencia: El directorio PLC especificado no existe: {plc_dirs[0]}")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
plc_dirs = []
|
||||||
|
for entry in os.listdir(working_directory):
|
||||||
|
cand_path = os.path.join(working_directory, entry)
|
||||||
|
if os.path.isdir(cand_path) and glob.glob(os.path.join(cand_path, "**", "*.xml"), recursive=True):
|
||||||
|
plc_dirs.append(cand_path)
|
||||||
|
if not plc_dirs:
|
||||||
|
plc_dirs = [working_directory]
|
||||||
|
|
||||||
|
total_dirs_removed = 0
|
||||||
|
total_files_removed = 0
|
||||||
|
|
||||||
|
for plc_path in plc_dirs:
|
||||||
|
plc_path = os.path.abspath(plc_path)
|
||||||
|
plc_name_safe = os.path.basename(plc_path.strip(os.sep))
|
||||||
|
print(f"\n=== Limpiando PLC: {plc_name_safe} ===")
|
||||||
|
|
||||||
|
# 1) Eliminar carpetas 'parsing' (y su contenido JSON)
|
||||||
|
for parsing_dir in glob.glob(os.path.join(plc_path, "**", "parsing"), recursive=True):
|
||||||
|
if os.path.isdir(parsing_dir):
|
||||||
|
try:
|
||||||
|
shutil.rmtree(parsing_dir)
|
||||||
|
print(f" - Eliminado directorio de parsing: {os.path.relpath(parsing_dir, working_directory)}")
|
||||||
|
total_dirs_removed += 1
|
||||||
|
except Exception as e:
|
||||||
|
print(f" - ERROR al eliminar {parsing_dir}: {e}")
|
||||||
|
errors_found = True
|
||||||
|
|
||||||
|
# 2) Eliminar directorios de salida SCL y XRef
|
||||||
|
for dirname in [cfg_scl_output_dirname, cfg_xref_output_dirname]:
|
||||||
|
target_dir = os.path.join(plc_path, dirname)
|
||||||
|
if os.path.isdir(target_dir):
|
||||||
|
try:
|
||||||
|
shutil.rmtree(target_dir)
|
||||||
|
print(f" - Eliminado directorio '{dirname}': {os.path.relpath(target_dir, working_directory)}")
|
||||||
|
total_dirs_removed += 1
|
||||||
|
except Exception as e:
|
||||||
|
print(f" - ERROR al eliminar {target_dir}: {e}")
|
||||||
|
errors_found = True
|
||||||
|
|
||||||
|
# 3) Eliminar archivo agregado principal
|
||||||
|
agg_file = os.path.join(plc_path, cfg_aggregated_filename)
|
||||||
|
if os.path.isfile(agg_file):
|
||||||
|
try:
|
||||||
|
os.remove(agg_file)
|
||||||
|
print(f" - Eliminado archivo agregado: {os.path.relpath(agg_file, working_directory)}")
|
||||||
|
total_files_removed += 1
|
||||||
|
except Exception as e:
|
||||||
|
print(f" - ERROR al eliminar {agg_file}: {e}")
|
||||||
|
errors_found = True
|
||||||
|
|
||||||
|
# 4) Eliminar logs específicos del PLC
|
||||||
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
log_path = os.path.join(script_dir, f"log_{plc_name_safe}.txt")
|
||||||
|
if os.path.isfile(log_path):
|
||||||
|
try:
|
||||||
|
os.remove(log_path)
|
||||||
|
print(f" - Eliminado log: {os.path.basename(log_path)}")
|
||||||
|
total_files_removed += 1
|
||||||
|
except Exception as e:
|
||||||
|
print(f" - ERROR al eliminar {log_path}: {e}")
|
||||||
|
errors_found = True
|
||||||
|
|
||||||
|
print("\n--- Resumen de limpieza ---")
|
||||||
|
print(f" Directorios eliminados: {total_dirs_removed}")
|
||||||
|
print(f" Archivos eliminados: {total_files_removed}")
|
||||||
|
print(" Limpieza completada." if not errors_found else " Limpieza completada con errores.")
|
||||||
|
|
||||||
|
return not errors_found
|
||||||
|
except Exception as e:
|
||||||
|
print(f"ERROR inesperado durante la limpieza: {e}", file=sys.stderr)
|
||||||
|
traceback.print_exc()
|
||||||
|
return False
|
||||||
|
|
||||||
|
# --- FIN FUNCIÓN DE LIMPIEZA -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
# --- Bloque Principal ---
|
# --- Bloque Principal ---
|
||||||
if __name__ == "__main__":
|
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()
|
configs = load_configuration()
|
||||||
working_directory = configs.get("working_directory")
|
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", {})
|
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_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_output_dirname = xml_parser_config.get("xref_output_dir", "xref_output")
|
||||||
cfg_xref_source_subdir = xml_parser_config.get("xref_source_subdir", "source")
|
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_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_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")
|
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:
|
try:
|
||||||
cfg_max_call_depth = int(xml_parser_config.get("max_call_depth", 5))
|
cfg_max_call_depth = int(xml_parser_config.get("max_call_depth", 5))
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
print("Advertencia: Valor inválido para 'max_call_depth' en la configuración. Usando valor por defecto 5.", file=sys.stderr)
|
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
|
cfg_max_call_depth = 5
|
||||||
|
|
||||||
# Ensure max_users_list is an integer
|
|
||||||
try:
|
try:
|
||||||
cfg_max_users_list = int(xml_parser_config.get("max_users_list", 20))
|
cfg_max_users_list = int(xml_parser_config.get("max_users_list", 20))
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
print("Advertencia: Valor inválido para 'max_users_list' en la configuración. Usando valor por defecto 20.", file=sys.stderr)
|
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_max_users_list = 20
|
||||||
|
|
||||||
cfg_aggregated_filename = xml_parser_config.get("aggregated_filename", "full_project_representation.md")
|
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)
|
# Directorio donde se encuentra este script (x0_main.py)
|
||||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
# <-- MODIFICADO: Abrir archivo log -->
|
# <-- MODIFICADO: Abrir archivo log -->
|
||||||
log_filepath = os.path.join(
|
|
||||||
os.path.dirname(os.path.abspath(__file__)), LOG_FILENAME
|
|
||||||
)
|
|
||||||
with open(
|
with open(
|
||||||
log_filepath, "w", encoding="utf-8"
|
log_filepath, "w", encoding="utf-8"
|
||||||
) as log_f: # Usar 'a' para añadir al log
|
) as log_f: # Usar 'a' para añadir al log
|
||||||
log_message("=" * 40 + " LOG START " + "=" * 40, log_f)
|
log_message("=" * 40 + " LOG START " + "=" * 40, log_f)
|
||||||
|
|
||||||
# --- PARTE 1: BUSCAR ARCHIVOS ---
|
# --- PARTE 1: BUSCAR ARCHIVOS ---
|
||||||
# <-- MODIFICADO: Apuntar al subdirectorio 'PLC' dentro del working_directory -->
|
# Se trabaja exclusivamente dentro del PLC indicado.
|
||||||
plc_subdir_name = "PLC" # Nombre estándar del subdirectorio de TIA Portal
|
|
||||||
xml_project_dir = os.path.join(working_directory, plc_subdir_name)
|
|
||||||
|
|
||||||
log_message(
|
log_message(
|
||||||
f"Directorio de trabajo base configurado: '{working_directory}'", log_f
|
f"Directorio de trabajo base configurado: '{working_directory}'", log_f
|
||||||
)
|
)
|
||||||
log_message(
|
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
|
# Patrón de búsqueda global para todos los PLC
|
||||||
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)
|
|
||||||
search_pattern = os.path.join(xml_project_dir, "**", "*.xml")
|
search_pattern = os.path.join(xml_project_dir, "**", "*.xml")
|
||||||
xml_files_found = glob.glob(search_pattern, recursive=True)
|
xml_files_found = glob.glob(search_pattern, recursive=True)
|
||||||
if not xml_files_found:
|
if not xml_files_found:
|
||||||
|
@ -423,7 +572,7 @@ if __name__ == "__main__":
|
||||||
log_message(f"Se encontraron {len(filtered_scl_files)} archivos .scl existentes para copiar:", log_f)
|
log_message(f"Se encontraron {len(filtered_scl_files)} archivos .scl existentes para copiar:", log_f)
|
||||||
for src_scl_path in filtered_scl_files:
|
for src_scl_path in filtered_scl_files:
|
||||||
relative_scl_path = os.path.relpath(src_scl_path, xml_project_dir)
|
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
|
# Check if a file with the same name was already generated from XML
|
||||||
if os.path.exists(dest_scl_path):
|
if os.path.exists(dest_scl_path):
|
||||||
|
@ -513,7 +662,8 @@ if __name__ == "__main__":
|
||||||
run_x5 = False
|
run_x5 = False
|
||||||
|
|
||||||
if run_x5:
|
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(
|
log_message(
|
||||||
f"Ejecutando x5 (aggregate_outputs) sobre: {xml_project_dir}, salida agregada en: {output_agg_file}",
|
f"Ejecutando x5 (aggregate_outputs) sobre: {xml_project_dir}, salida agregada en: {output_agg_file}",
|
||||||
log_f
|
log_f
|
||||||
|
@ -590,7 +740,7 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
log_message(final_console_message, log_f) # Loguear mensaje final
|
log_message(final_console_message, log_f) # Loguear mensaje final
|
||||||
print(
|
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
|
) # Mostrar mensaje en consola
|
||||||
log_message("="*41 + " LOG END " + "="*42, log_f)
|
log_message("="*41 + " LOG END " + "="*42, log_f)
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ from backend.script_utils import load_configuration
|
||||||
|
|
||||||
# Importar funciones comunes y namespaces desde el nuevo módulo de utils
|
# Importar funciones comunes y namespaces desde el nuevo módulo de utils
|
||||||
try:
|
try:
|
||||||
from parsers.parser_utils import ns, get_multilingual_text, parse_interface_members
|
from parsers.parser_utils import ns, get_multilingual_text, parse_interface_members, adapt_namespaces
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
print(
|
print(
|
||||||
f"Error crítico: No se pudieron importar funciones desde parsers.parser_utils: {e}"
|
f"Error crítico: No se pudieron importar funciones desde parsers.parser_utils: {e}"
|
||||||
|
@ -253,6 +253,11 @@ def convert_xml_to_json(xml_filepath, json_filepath):
|
||||||
parser = etree.XMLParser(remove_blank_text=True, recover=True)
|
parser = etree.XMLParser(remove_blank_text=True, recover=True)
|
||||||
tree = etree.parse(xml_filepath, parser)
|
tree = etree.parse(xml_filepath, parser)
|
||||||
root = tree.getroot()
|
root = tree.getroot()
|
||||||
|
# Ajustar namespaces dinámicamente para soportar distintas versiones de TIA
|
||||||
|
try:
|
||||||
|
adapt_namespaces(root)
|
||||||
|
except Exception as e_ns:
|
||||||
|
print(f"Advertencia: No se pudo adaptar namespaces dinámicamente: {e_ns}")
|
||||||
print("Paso 1: Parseo XML completado.")
|
print("Paso 1: Parseo XML completado.")
|
||||||
|
|
||||||
result = None
|
result = None
|
||||||
|
|
|
@ -366,6 +366,18 @@ def generate_call_tree_output(call_graph, block_data, base_xref_dir, max_call_de
|
||||||
"""
|
"""
|
||||||
output_lines = ["# Árbol de Referencias Cruzadas de Llamadas\n"]
|
output_lines = ["# Árbol de Referencias Cruzadas de Llamadas\n"]
|
||||||
output_lines.append(f"(Profundidad máxima: {max_call_depth})\n") # <-- Usar el parámetro
|
output_lines.append(f"(Profundidad máxima: {max_call_depth})\n") # <-- Usar el parámetro
|
||||||
|
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
# Aviso cuando NO se han detectado llamadas entre bloques
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
has_any_call = any(len(callees) > 0 for callees in call_graph.values())
|
||||||
|
if not has_any_call:
|
||||||
|
output_lines.append(
|
||||||
|
"\n> ⚠️ Nota: No se detectaron referencias cruzadas de llamadas. "
|
||||||
|
"Es posible que no existan los archivos '*_XRef.xml' o que aún no "
|
||||||
|
"se haya ejecutado el análisis de fallback sobre los bloques SCL.\n"
|
||||||
|
)
|
||||||
|
|
||||||
root_nodes = sorted( # Encontrar OBs
|
root_nodes = sorted( # Encontrar OBs
|
||||||
[
|
[
|
||||||
name
|
name
|
||||||
|
@ -646,7 +658,8 @@ def generate_cross_references(
|
||||||
# 2. Construir Grafo de Llamadas desde XML XRef
|
# 2. Construir Grafo de Llamadas desde XML XRef
|
||||||
print("Construyendo grafo de llamadas desde archivos XML XRef...")
|
print("Construyendo grafo de llamadas desde archivos XML XRef...")
|
||||||
call_graph = defaultdict(list) # Usamos lista, no necesitamos contar llamadas múltiples aquí
|
call_graph = defaultdict(list) # Usamos lista, no necesitamos contar llamadas múltiples aquí
|
||||||
xref_xml_files = glob.glob(os.path.join(xref_xml_dir, "*_XRef.xml"))
|
# Buscar recursivamente en todas las subcarpetas (algunos proyectos guardan los XML en estructuras anidadas)
|
||||||
|
xref_xml_files = glob.glob(os.path.join(xref_xml_dir, "**", "*_XRef.xml"), recursive=True)
|
||||||
if not xref_xml_files:
|
if not xref_xml_files:
|
||||||
print(f"ADVERTENCIA: No se encontraron archivos '*_XRef.xml' en {xref_xml_dir}. El árbol de llamadas estará vacío.", file=sys.stderr)
|
print(f"ADVERTENCIA: No se encontraron archivos '*_XRef.xml' en {xref_xml_dir}. El árbol de llamadas estará vacío.", file=sys.stderr)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
"""x7_clear.py
|
||||||
|
Script de limpieza para eliminar todos los artefactos generados por x0_main.py.
|
||||||
|
|
||||||
|
Este script actúa como envoltorio del método `clear_generated_outputs` definido
|
||||||
|
en `x0_main.py`. De esta forma, la lógica de eliminación se mantiene en un solo
|
||||||
|
lugar y se adapta automáticamente a futuros cambios en la estructura de
|
||||||
|
salidas de x0.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# Importar la función de limpieza desde x0_main.py
|
||||||
|
from x0_main import clear_generated_outputs # noqa: E402 – import absoluto intencional
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Elimina los archivos generados por x0_main.py (JSON, SCL, MD, logs)."
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--plc-dir",
|
||||||
|
dest="plc_dir",
|
||||||
|
default=None,
|
||||||
|
help=(
|
||||||
|
"Ruta de un PLC específico a limpiar. Si se omite, se limpiarán "
|
||||||
|
"todos los PLCs detectados bajo el working_directory definido en la configuración."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
success = clear_generated_outputs(args.plc_dir)
|
||||||
|
# Salir con 0 si todo fue bien, 1 en caso de errores
|
||||||
|
sys.exit(0 if success else 1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
|
@ -1,5 +1,18 @@
|
||||||
{
|
{
|
||||||
"history": [
|
"history": [
|
||||||
|
{
|
||||||
|
"id": "15176a5f",
|
||||||
|
"group_id": "1",
|
||||||
|
"script_name": "calc.py",
|
||||||
|
"executed_date": "2025-06-13T10:53:37.648203Z",
|
||||||
|
"arguments": [],
|
||||||
|
"working_directory": "D:/Proyectos/Scripts/Calcv2",
|
||||||
|
"python_env": "tia_scripting",
|
||||||
|
"executable_type": "pythonw.exe",
|
||||||
|
"status": "running",
|
||||||
|
"pid": 21072,
|
||||||
|
"execution_time": null
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "a599effd",
|
"id": "a599effd",
|
||||||
"group_id": "4",
|
"group_id": "4",
|
||||||
|
|
134
data/log.txt
134
data/log.txt
|
@ -1,5 +1,129 @@
|
||||||
[20:03:36] Iniciando ejecución de x1.py en D:\Trabajo\VM\44 - 98050 - Fiera\Reporte\ExportsTia\Source...
|
[11:14:30] Iniciando ejecución de x4.py en D:\Trabajo\VM\22 - 93841 - Sidel - Tilting\Reporte\TiaExports...
|
||||||
[20:03:37] --- TIA Portal Data Exporter (Blocks, UDTs, Tags) ---
|
[11:14:30] --- Exportador de Referencias Cruzadas de TIA Portal ---
|
||||||
[20:03:47] No project file selected. Exiting.
|
[11:14:34] Versión de TIA Portal detectada: 19.0 (de la extensión .ap19)
|
||||||
[20:03:47] Ejecución de x1.py finalizada (success). Duración: 0:00:10.497365.
|
[11:14:34] Proyecto seleccionado: D:/Trabajo/VM/22 - 93841 - Sidel - Tilting/InLavoro/PLC/93841_PLC_28/93841_PLC_28.ap19
|
||||||
[20:03:47] Log completo guardado en: D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\ObtainIOFromProjectTia\log_x1.txt
|
[11:14:34] Usando directorio base de exportación: D:\Trabajo\VM\22 - 93841 - Sidel - Tilting\Reporte\TiaExports
|
||||||
|
[11:14:34] Conectando a TIA Portal V19.0...
|
||||||
|
[11:14:34] 2025-06-13 11:14:34,713 [1] INFO Siemens.TiaPortal.OpennessApi19.Implementations.Global OpenPortal - Start TIA Portal, please acknowledge the security dialog.
|
||||||
|
[11:14:34] 2025-06-13 11:14:34,731 [1] INFO Siemens.TiaPortal.OpennessApi19.Implementations.Global OpenPortal - With user interface
|
||||||
|
[11:14:58] Conectado a TIA Portal.
|
||||||
|
[11:14:58] 2025-06-13 11:14:58,165 [1] INFO Siemens.TiaPortal.OpennessApi19.Implementations.Portal GetProcessId - Process id: 30140
|
||||||
|
[11:14:58] ID del proceso del Portal: 30140
|
||||||
|
[11:14:58] Abriendo proyecto: 93841_PLC_28.ap19...
|
||||||
|
[11:14:58] 2025-06-13 11:14:58,500 [1] INFO Siemens.TiaPortal.OpennessApi19.Implementations.Portal OpenProject - Open project... D:\Trabajo\VM\22 - 93841 - Sidel - Tilting\InLavoro\PLC\93841_PLC_28\93841_PLC_28.ap19
|
||||||
|
[11:15:25] Proyecto abierto exitosamente.
|
||||||
|
[11:15:29] 2025-06-13 11:15:29,701 [1] INFO Siemens.TiaPortal.OpennessApi19.Implementations.Project GetPlcs - Found plc VM 1512 with parent name ET 200SP station_1
|
||||||
|
[11:15:30] 2025-06-13 11:15:30,551 [1] INFO Siemens.TiaPortal.OpennessApi19.Implementations.Project GetPlcs - Found plc SIDEL Transport Example with parent name S71500/ET200MP station_1
|
||||||
|
[11:15:34] Se encontraron 2 PLC(s). Iniciando proceso de exportación de referencias cruzadas...
|
||||||
|
[11:15:34] --- Procesando PLC: VM 1512 ---
|
||||||
|
[11:15:34] [PLC: VM 1512] Exportando referencias cruzadas de bloques de programa...
|
||||||
|
[11:15:34] Destino: D:\Trabajo\VM\22 - 93841 - Sidel - Tilting\Reporte\TiaExports\VM 1512\ProgramBlocks_CR
|
||||||
|
[11:15:34] Se encontraron 201 bloques de programa.
|
||||||
|
[11:15:34] Procesando bloque: FC General COM...
|
||||||
|
[11:15:34] Exportando referencias cruzadas para FC General COM...
|
||||||
|
[11:15:38] Procesando bloque: From_SIDEL...
|
||||||
|
[11:15:38] Exportando referencias cruzadas para From_SIDEL...
|
||||||
|
[11:15:38] Procesando bloque: To_SIDEL...
|
||||||
|
[11:15:38] Exportando referencias cruzadas para To_SIDEL...
|
||||||
|
[11:15:38] Procesando bloque: DB Early Restart Blower...
|
||||||
|
[11:15:38] Exportando referencias cruzadas para DB Early Restart Blower...
|
||||||
|
[11:15:39] Procesando bloque: DB Early Restart Filler...
|
||||||
|
[11:15:39] Exportando referencias cruzadas para DB Early Restart Filler...
|
||||||
|
[11:15:39] Procesando bloque: DB Early Restart SynchroBlock...
|
||||||
|
[11:15:39] Exportando referencias cruzadas para DB Early Restart SynchroBlock...
|
||||||
|
[11:15:40] Procesando bloque: FB Early Restart...
|
||||||
|
[11:15:40] Exportando referencias cruzadas para FB Early Restart...
|
||||||
|
[11:15:40] Procesando bloque: DB Signal Transport...
|
||||||
|
[11:15:40] Exportando referencias cruzadas para DB Signal Transport...
|
||||||
|
[11:15:42] Procesando bloque: FC Signal Transport...
|
||||||
|
[11:15:42] Exportando referencias cruzadas para FC Signal Transport...
|
||||||
|
[11:15:43] Procesando bloque: DB Lube - Dry Ecolab...
|
||||||
|
[11:15:43] Exportando referencias cruzadas para DB Lube - Dry Ecolab...
|
||||||
|
[11:15:46] Procesando bloque: FB Lube - Water/Dry...
|
||||||
|
[11:15:46] Exportando referencias cruzadas para FB Lube - Water/Dry...
|
||||||
|
[11:15:46] Procesando bloque: FB Lube - Dry Ecolab...
|
||||||
|
[11:15:46] Exportando referencias cruzadas para FB Lube - Dry Ecolab...
|
||||||
|
[11:15:47] Procesando bloque: FB Lube - EcoLab VM...
|
||||||
|
[11:15:47] Exportando referencias cruzadas para FB Lube - EcoLab VM...
|
||||||
|
[11:15:48] Procesando bloque: FB Lube - Ecolab...
|
||||||
|
[11:15:48] Exportando referencias cruzadas para FB Lube - Ecolab...
|
||||||
|
[11:15:49] Procesando bloque: DB LUBE - Ecolab...
|
||||||
|
[11:15:49] Exportando referencias cruzadas para DB LUBE - Ecolab...
|
||||||
|
[11:15:57] Procesando bloque: FC Ttop Configuration...
|
||||||
|
[11:15:57] Exportando referencias cruzadas para FC Ttop Configuration...
|
||||||
|
[11:15:57] Procesando bloque: FC Ttop Run...
|
||||||
|
[11:15:57] Exportando referencias cruzadas para FC Ttop Run...
|
||||||
|
[11:15:58] Procesando bloque: FC Ttop Alarms...
|
||||||
|
[11:15:58] Exportando referencias cruzadas para FC Ttop Alarms...
|
||||||
|
[11:15:58] Procesando bloque: DB Ttop Run...
|
||||||
|
[11:15:58] Exportando referencias cruzadas para DB Ttop Run...
|
||||||
|
[11:15:59] Procesando bloque: DB Ttop Motor CFG...
|
||||||
|
[11:15:59] Exportando referencias cruzadas para DB Ttop Motor CFG...
|
||||||
|
[11:16:02] Procesando bloque: DB Ttop Alarm...
|
||||||
|
[11:16:02] Exportando referencias cruzadas para DB Ttop Alarm...
|
||||||
|
[11:16:07] Procesando bloque: FC Ttop Motor 31...
|
||||||
|
[11:16:07] Exportando referencias cruzadas para FC Ttop Motor 31...
|
||||||
|
[11:16:07] Procesando bloque: FC Ttop Motor 32...
|
||||||
|
[11:16:07] Exportando referencias cruzadas para FC Ttop Motor 32...
|
||||||
|
[11:16:07] Procesando bloque: FC Ttop Motor 34...
|
||||||
|
[11:16:07] Exportando referencias cruzadas para FC Ttop Motor 34...
|
||||||
|
[11:16:08] Procesando bloque: FC Ttop Motor 35...
|
||||||
|
[11:16:08] Exportando referencias cruzadas para FC Ttop Motor 35...
|
||||||
|
[11:16:08] Procesando bloque: FC Ttop Motor 36...
|
||||||
|
[11:16:08] Exportando referencias cruzadas para FC Ttop Motor 36...
|
||||||
|
[11:16:08] Procesando bloque: DB Ttop Motor 31...
|
||||||
|
[11:16:08] Exportando referencias cruzadas para DB Ttop Motor 31...
|
||||||
|
[11:16:13] Procesando bloque: DB Ttop Motor 32...
|
||||||
|
[11:16:13] Exportando referencias cruzadas para DB Ttop Motor 32...
|
||||||
|
[11:16:18] Procesando bloque: DB Ttop Motor 34...
|
||||||
|
[11:16:18] Exportando referencias cruzadas para DB Ttop Motor 34...
|
||||||
|
[11:16:23] Procesando bloque: DB Ttop Motor 35...
|
||||||
|
[11:16:23] Exportando referencias cruzadas para DB Ttop Motor 35...
|
||||||
|
[11:16:27] Procesando bloque: DB Ttop Minimotor Cfg 32...
|
||||||
|
[11:16:27] Exportando referencias cruzadas para DB Ttop Minimotor Cfg 32...
|
||||||
|
[11:16:29] Procesando bloque: DB Ttop Minimotor Data 32...
|
||||||
|
[11:16:29] Exportando referencias cruzadas para DB Ttop Minimotor Data 32...
|
||||||
|
[11:16:31] Procesando bloque: DB Ttop Motor 36...
|
||||||
|
[11:16:31] Exportando referencias cruzadas para DB Ttop Motor 36...
|
||||||
|
[11:16:35] Procesando bloque: FB Ttop Dryer...
|
||||||
|
[11:16:35] Exportando referencias cruzadas para FB Ttop Dryer...
|
||||||
|
[11:16:36] Procesando bloque: FB Ttop Energy Saving...
|
||||||
|
[11:16:36] Exportando referencias cruzadas para FB Ttop Energy Saving...
|
||||||
|
[11:16:36] Procesando bloque: FB SKID...
|
||||||
|
[11:16:36] Exportando referencias cruzadas para FB SKID...
|
||||||
|
[11:16:36] Procesando bloque: FC Analog Sensor Process...
|
||||||
|
[11:16:36] Exportando referencias cruzadas para FC Analog Sensor Process...
|
||||||
|
[11:16:37] Procesando bloque: FC Valve...
|
||||||
|
[11:16:37] Exportando referencias cruzadas para FC Valve...
|
||||||
|
[11:16:37] Procesando bloque: FB SpeedRegulation...
|
||||||
|
[11:16:37] Exportando referencias cruzadas para FB SpeedRegulation...
|
||||||
|
[11:16:37] Procesando bloque: FC Simple PID...
|
||||||
|
[11:16:37] Exportando referencias cruzadas para FC Simple PID...
|
||||||
|
[11:16:38] Procesando bloque: FC Scale Real...
|
||||||
|
[11:16:38] Exportando referencias cruzadas para FC Scale Real...
|
||||||
|
[11:16:38] Procesando bloque: FB Correct Speed F/Pulses...
|
||||||
|
[11:16:38] Exportando referencias cruzadas para FB Correct Speed F/Pulses...
|
||||||
|
[11:16:43] ERROR GENERAL al exportar referencias cruzadas para el bloque FB Correct Speed F/Pulses: OpennessAccessException: Unexpected exception - no exception message available.
|
||||||
|
[11:16:43] ERROR al acceder a los bloques de programa para exportar referencias cruzadas: OpennessAccessException: Access to a disposed object of type 'Siemens.Engineering.SW.Blocks.FB' is not possible.
|
||||||
|
[11:16:43] TIA Portal has either been disposed or stopped running.
|
||||||
|
[11:16:43] [PLC: VM 1512] Exportando referencias cruzadas de tablas de variables...
|
||||||
|
[11:16:43] Destino: D:\Trabajo\VM\22 - 93841 - Sidel - Tilting\Reporte\TiaExports\VM 1512\PlcTags_CR
|
||||||
|
[11:16:43] ERROR al acceder a las tablas de variables para exportar referencias cruzadas: SerializationException: No se puede encontrar el ensamblado 'Siemens.Engineering, Version=19.0.0.0, Culture=neutral, PublicKeyToken=d29ec89bac048f84'.
|
||||||
|
[11:16:43] [PLC: VM 1512] Exportando referencias cruzadas de tipos de datos PLC (UDTs)...
|
||||||
|
[11:16:43] Destino: D:\Trabajo\VM\22 - 93841 - Sidel - Tilting\Reporte\TiaExports\VM 1512\PlcDataTypes_CR
|
||||||
|
[11:16:43] ERROR al acceder a los UDTs para exportar referencias cruzadas: SerializationException: No se puede encontrar el ensamblado 'Siemens.Engineering, Version=19.0.0.0, Culture=neutral, PublicKeyToken=d29ec89bac048f84'.
|
||||||
|
[11:16:43] [PLC: VM 1512] Intentando exportar referencias cruzadas de bloques de sistema...
|
||||||
|
[11:16:43] Destino: D:\Trabajo\VM\22 - 93841 - Sidel - Tilting\Reporte\TiaExports\VM 1512\SystemBlocks_CR
|
||||||
|
[11:16:43] ERROR al acceder/procesar bloques de sistema para exportar referencias cruzadas: SerializationException: No se puede encontrar el ensamblado 'Siemens.Engineering, Version=19.0.0.0, Culture=neutral, PublicKeyToken=d29ec89bac048f84'.
|
||||||
|
[11:16:43] [PLC: VM 1512] Intentando exportar referencias cruzadas de unidades de software...
|
||||||
|
[11:16:43] Destino: D:\Trabajo\VM\22 - 93841 - Sidel - Tilting\Reporte\TiaExports\VM 1512\SoftwareUnits_CR
|
||||||
|
[11:16:43] ERROR al acceder/procesar unidades de software para exportar referencias cruzadas: SerializationException: No se puede encontrar el ensamblado 'Siemens.Engineering, Version=19.0.0.0, Culture=neutral, PublicKeyToken=d29ec89bac048f84'.
|
||||||
|
[11:16:43] --- Finalizado el procesamiento del PLC: VM 1512 ---
|
||||||
|
[11:16:43] Ocurrió un error inesperado: OpennessAccessException: Access to a disposed object of type 'Siemens.Engineering.HW.DeviceItemImpl' is not possible.
|
||||||
|
[11:16:43] TIA Portal has either been disposed or stopped running.
|
||||||
|
[11:16:43] Cerrando TIA Portal...
|
||||||
|
[11:16:43] 2025-06-13 11:16:43,486 [1] INFO Siemens.TiaPortal.OpennessApi19.Implementations.Portal ClosePortal - Close TIA Portal
|
||||||
|
[11:16:43] TIA Portal cerrado.
|
||||||
|
[11:16:43] Script finalizado.
|
||||||
|
[11:16:43] Ejecución de x4.py finalizada (success). Duración: 0:02:13.165274. Se detectaron errores (ver log).
|
||||||
|
[11:16:43] Log completo guardado en: D:\Proyectos\Scripts\ParamManagerScripts\backend\script_groups\ObtainIOFromProjectTia\log_x4.txt
|
||||||
|
|
|
@ -181,17 +181,17 @@
|
||||||
<div class="flex-1 flex gap-2">
|
<div class="flex-1 flex gap-2">
|
||||||
<input type="text" id="working-directory" class="flex-1 p-2 border rounded bg-green-50">
|
<input type="text" id="working-directory" class="flex-1 p-2 border rounded bg-green-50">
|
||||||
<button class="bg-gray-500 text-white px-4 py-2 rounded" onclick="browseDirectory()">
|
<button class="bg-gray-500 text-white px-4 py-2 rounded" onclick="browseDirectory()">
|
||||||
Explorar
|
Buscar
|
||||||
</button>
|
</button>
|
||||||
<button id="open-in-explorer-btn"
|
<button id="open-in-explorer-btn"
|
||||||
class="bg-indigo-500 hover:bg-indigo-600 text-white px-4 py-2 rounded"
|
class="bg-indigo-500 hover:bg-indigo-600 text-white px-4 py-2 rounded"
|
||||||
title="Abrir directorio actual en el explorador de archivos">
|
title="Abrir directorio actual en el explorador de archivos">
|
||||||
Abrir Carpeta
|
Abrir Carpeta
|
||||||
</button>
|
</button>
|
||||||
</div>
|
<button class="bg-blue-500 text-white px-4 py-2 rounded" onclick="setWorkingDirectory()">
|
||||||
<button class="bg-blue-500 text-white px-4 py-2 rounded" onclick="setWorkingDirectory()">
|
Salvar
|
||||||
Confirmar
|
</button>
|
||||||
</button>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Add directory history dropdown -->
|
<!-- Add directory history dropdown -->
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
|
|
Loading…
Reference in New Issue