Se eliminó el archivo `README_x8_manual_gui.md` y se simplificó el script `x8_manual_gui.py`, transformándolo en un wrapper simple que utiliza cuadros de diálogo nativos de Windows para seleccionar archivos XML y directorios de destino. Se eliminaron ejemplos de archivos SCL y XML obsoletos, así como mejoras en la gestión de comentarios en el parser SCL. Se optimizó el manejo de errores y se actualizaron los logs para reflejar los cambios realizados.

This commit is contained in:
Miguel 2025-07-31 21:55:38 +02:00
parent 9e7e310384
commit b67851e615
13 changed files with 18936 additions and 21545 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,178 @@
// Block Type: FC
// Block Name (Original): FC TT Devices
// Block Number: 380
// Original Network Languages: SCL, LAD, STL
FUNCTION "FC_TT_Devices" : Void
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_TEMP
YLBR1 : Bool;
YLBR2 : Bool;
YLBR3 : Bool;
YLBR4 : Bool;
YLBR5 : Bool;
SystemReady : Bool;
ConveyorsRunning : Bool;
Filler_Run : Bool;
Labeller_Run : Bool;
Line_Empty : Bool;
Reset_Push_Button : Bool;
Line_Empty : Bool;
DUMMY : Bool;
LEVEL_OK : Bool;
Temp : Bool;
Ap_HighLim : Real;
Ap_LowLim : Real;
Apoyo_Rechazo : Bool;
END_VAR
#_0 : Bool; // Auto-generated temporary
#_1500ms : Bool; // Auto-generated temporary
BEGIN
// Network 1: EMD - Body Guide (Original Language: LAD)
"DB TTOP - Body Guide EMD"(Number_Zone := 4, Pressure_Control_Zone_1 := "P1-M37" AND NOT "DB TT Alarm"."A371_04_0", Pressure_Control_Zone_2 := "P1-M39" AND NOT "DB TT Alarm"."A371_04_1", Pressure_Control_Zone_3 := "P1-M41" AND NOT "DB TT Alarm"."A371_04_2", Pressure_Control_Zone_4 := "P1-M42" AND NOT "DB TT Alarm"."A371_04_3", Pressure_Control_Zone_5 := FALSE);
// Network 2: Elevator Door Management - UpStair (Original Language: LAD)
"DB Door Control - Lifter - UpStair"(BUTTON_REQUEST := "E7.2", CLK_FAST := "M1.3", CLK_SLOW := "M1.5", DOOR_OPEN := "E7.6" OR "E7.7" OR NOT "KS165-1C", FBK_MACHINE_OFF := Eq("DB TT Motor 35"."Manage"."STATUS_VFD_ACT_Speed_Hz", 0));
// Network 3: Elevator Door Management - DownStair (Original Language: LAD)
"DB Door Control - Lifter - DownStair"(BUTTON_REQUEST := "E7.0", CLK_FAST := "M1.3", CLK_SLOW := "M1.5", DOOR_OPEN := "E7.4" OR "E7.5" OR NOT "KS165-1C", FBK_MACHINE_OFF := Eq("DB TT Motor 35"."Manage"."STATUS_VFD_ACT_Speed_Hz", 0));
// Network 4: Elevator - Right/ Left Control breaking chains (Original Language: LAD)
"Timer_Chain_Right"(IN := NOT "S1-M35", PT := S5T#1500ms); // TODO: Declarar "Timer_Chain_Right" : TON;
"Timer_Chain_Left"(IN := NOT "S2-M35", PT := S5T#1500ms); // TODO: Declarar "Timer_Chain_Left" : TON;
// Network 5: Energy Saving - Line Empty (Original Language: STL)
// --- BEGIN STL Network 5 ---
```stl
A "B1-M31"
A "B1-M32"
A "B2-M32"
A "B1-M34"
A "B2-M34"
A "B1-M35"
A "B2-M35"
A "B4-M35"
A "B5-M35"
A "B1-M36"
A "B1-M37"
A "B2-M37"
A "B1-M38"
A "B2-M38"
A "B1-M39"
A "B2-M39"
A "B1-M40"
A "B2-M40"
A "B1-M41"
A "B2-M41"
A "B1-M42"
A "B2-M42"
= "Line Empty"
```
// --- END STL Network 5 ---
// Network 6: Energy Saving (Original Language: LAD)
"DB TTOP - Energy Saving"(DownStream_Mac_Req := "M0.1" OR ("DB Signal DownStream Machine - TL25_Q2"."IN_DIG_Signal_01" AND "M0.0"), Sensor_on_the_line := "Line Empty", UpStream_Mac_Empty := "DB TT Run"."TT_Run"."OUT_Cycle_ON" AND (("ComSV"."TL25_ReadFromSv"."FromSV"."STW"."X00" AND "ComSV"."TL25_ReadFromSv"."FromSV"."Data From TL28"."Run") OR (NOT "ComSV"."TL25_ReadFromSv"."FromSV"."STW"."X00" AND NOT "ComSV"."TL25_ReadFromSv"."FromSV"."STW"."X13" AND NOT "ComSV"."TL25_ReadFromSv"."FromSV"."STW"."X14")));
// Network 7: Bottle Counter M153_154 (Original Language: LAD)
"DB Bottle Counter M153_154"(Conveyor_Running := "DB TT Motor 41"."Manage"."STATUS_VFD_Run_FWD" AND "DB TT Motor 42"."Manage"."STATUS_VFD_Run_FWD", PH_Inlet := "Count 1 M42", PH_Outlet := "Count 2 M42", Reset_Button_Allarm := "SH331-1B", Reset_Counter_Henkel := "ComSV"."TL25_WriteToSv"."FromHenkel"."STW"."di0.x");
// Network 8: Bottle Counter M37 (Original Language: LAD)
"DB Bottle Counter_M37"(Conveyor_Running := "DB TT Motor 37"."Manage"."STATUS_VFD_Run_FWD", PH_Inlet := "Count 1 M35", PH_Outlet := "Count 2 M35", Reset_Button_Allarm := "SH331-1B", Reset_Counter_Henkel := "ComSV"."TL25_WriteToSv"."FromHenkel"."STW"."di0.x");
IF "M0.1" THEN
"DB TT Alarm"."A371_03_3" := FALSE;
END_IF;
// Network 9: (Original Language: LAD)
IF "Tag_27" > 5 THEN
"Tag_27" := 0;
END_IF;
"Apoyo_Rechazo" := "B5-M35" OR ("M0.0" AND Eq("Tag_27", 5));
// Network 10: Ejector Bottle (Original Language: STL)
// --- BEGIN STL Network 10 ---
```stl
CALL "DB Ejector Bottle"
```
// --- END STL Network 10 ---
// Network 11: Photocell Teach (Original Language: LAD)
"Delay Photocell Teach"(IN := "DB General"."X203_0", PT := S5T#0.8s); // TODO: Declarar "Delay Photocell Teach" : TP;
"A8.0" := "Delay Photocell Teach".Q;
"DB General"."X203_1" := "Delay Photocell Teach".Q;
IF "Delay Photocell Teach".Q THEN
"DB General"."X203_0" := FALSE;
END_IF;
// Network 12: Elevator - Guide (Original Language: STL)
// --- BEGIN STL Network 12 ---
```stl
CALL "DB Guide Lifter - Lowerator"
```
// --- END STL Network 12 ---
// Network 13: Elevator - Lube (Original Language: STL)
// --- BEGIN STL Network 13 ---
```stl
CALL "DB lube M35"
```
// --- END STL Network 13 ---
// Network 14: Camera Ejector Bottle (Original Language: STL)
// "E38.1"
// --- BEGIN STL Network 14 ---
```stl
CALL "DB Camera Ejector Bottle"
```
// --- END STL Network 14 ---
// Network 15: (Original Language: LAD)
// Network 15 did not produce printable SCL code.
// Network 16: Elevator - SV Reject Y1-M35 (Original Language: LAD)
"Y1-M35" := "Ejector_Tower" OR "Ejector_Camera";
// Network 17: Signal for changeover done (Original Language: LAD)
"Ap_EMD_InPsosition" := Eq("DB TTOP - Body Guide EMD"."Counter_Position", "DB TTOP - Body Guide EMD"."Position_Selection");
"Ap_HighLim" := ("DB Guide Lifter - Lowerator"."Position Selection") + ("DB Guide Lifter - Lowerator"."Range Position");
"Ap_LowLim" := ("DB Guide Lifter - Lowerator"."Position Selection") - ("DB Guide Lifter - Lowerator"."Range Position");
"Ap_LifterGuideInPositon" := "DB Guide Lifter - Lowerator"."Actual Position" >= "Ap_LowLim";
// Network 18: INTERLOCK EMD CHANGEOVER (Original Language: SCL)
"ComSV".TL25_WriteToSv.ToSV.STW.QE1.X13 := "ComSV".TL25_ReadFromSv.FromSV.STW.X06;
"ComSV".TL25_WriteToSv.ToSV.STW.QE1.X14 := "ComSV".TL25_ReadFromSv.FromSV.STW.X07;
"ComSV".TL25_WriteToSv.ToSV.STW.QE1.X15 := "ComSV".TL25_ReadFromSv.FromSV.STW.X08;
"ComSV".TL25_WriteToSv.ToSV.STW.QE1.X16 := "ComSV".TL25_ReadFromSv.FromSV.STW.X09;
END_FUNCTION

View File

@ -0,0 +1,178 @@
// Block Type: FC
// Block Name (Original): FC TT Devices
// Block Number: 380
// Original Network Languages: SCL, STL, LAD
FUNCTION "FC_TT_Devices" : Void
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_TEMP
YLBR1 : Bool;
YLBR2 : Bool;
YLBR3 : Bool;
YLBR4 : Bool;
YLBR5 : Bool;
SystemReady : Bool;
ConveyorsRunning : Bool;
Filler_Run : Bool;
Labeller_Run : Bool;
Line_Empty : Bool;
Reset_Push_Button : Bool;
Line_Empty : Bool;
DUMMY : Bool;
LEVEL_OK : Bool;
Temp : Bool;
Ap_HighLim : Real;
Ap_LowLim : Real;
Apoyo_Rechazo : Bool;
END_VAR
#_0 : Bool; // Auto-generated temporary
#_1500ms : Bool; // Auto-generated temporary
BEGIN
// Network 1: EMD - Body Guide (Original Language: LAD)
"DB TTOP - Body Guide EMD"(Number_Zone := 4, Pressure_Control_Zone_1 := "P1-M37" AND NOT "DB TT Alarm"."A371_04_0", Pressure_Control_Zone_2 := "P1-M39" AND NOT "DB TT Alarm"."A371_04_1", Pressure_Control_Zone_3 := "P1-M41" AND NOT "DB TT Alarm"."A371_04_2", Pressure_Control_Zone_4 := "P1-M42" AND NOT "DB TT Alarm"."A371_04_3", Pressure_Control_Zone_5 := FALSE);
// Network 2: Elevator Door Management - UpStair (Original Language: LAD)
"DB Door Control - Lifter - UpStair"(BUTTON_REQUEST := "E7.2", CLK_FAST := "M1.3", CLK_SLOW := "M1.5", DOOR_OPEN := "E7.6" OR "E7.7" OR NOT "KS165-1C", FBK_MACHINE_OFF := Eq("DB TT Motor 35"."Manage"."STATUS_VFD_ACT_Speed_Hz", 0));
// Network 3: Elevator Door Management - DownStair (Original Language: LAD)
"DB Door Control - Lifter - DownStair"(BUTTON_REQUEST := "E7.0", CLK_FAST := "M1.3", CLK_SLOW := "M1.5", DOOR_OPEN := "E7.4" OR "E7.5" OR NOT "KS165-1C", FBK_MACHINE_OFF := Eq("DB TT Motor 35"."Manage"."STATUS_VFD_ACT_Speed_Hz", 0));
// Network 4: Elevator - Right/ Left Control breaking chains (Original Language: LAD)
"Timer_Chain_Right"(IN := NOT "S1-M35", PT := S5T#1500ms); // TODO: Declarar "Timer_Chain_Right" : TON;
"Timer_Chain_Left"(IN := NOT "S2-M35", PT := S5T#1500ms); // TODO: Declarar "Timer_Chain_Left" : TON;
// Network 5: Energy Saving - Line Empty (Original Language: STL)
// --- BEGIN STL Network 5 ---
```stl
A "B1-M31"
A "B1-M32"
A "B2-M32"
A "B1-M34"
A "B2-M34"
A "B1-M35"
A "B2-M35"
A "B4-M35"
A "B5-M35"
A "B1-M36"
A "B1-M37"
A "B2-M37"
A "B1-M38"
A "B2-M38"
A "B1-M39"
A "B2-M39"
A "B1-M40"
A "B2-M40"
A "B1-M41"
A "B2-M41"
A "B1-M42"
A "B2-M42"
= "Line Empty"
```
// --- END STL Network 5 ---
// Network 6: Energy Saving (Original Language: LAD)
"DB TTOP - Energy Saving"(DownStream_Mac_Req := "M0.1" OR ("DB Signal DownStream Machine - TL25_Q2"."IN_DIG_Signal_01" AND "M0.0"), Sensor_on_the_line := "Line Empty", UpStream_Mac_Empty := "DB TT Run"."TT_Run"."OUT_Cycle_ON" AND (("ComSV"."TL25_ReadFromSv"."FromSV"."STW"."X00" AND "ComSV"."TL25_ReadFromSv"."FromSV"."Data From TL28"."Run") OR (NOT "ComSV"."TL25_ReadFromSv"."FromSV"."STW"."X00" AND NOT "ComSV"."TL25_ReadFromSv"."FromSV"."STW"."X13" AND NOT "ComSV"."TL25_ReadFromSv"."FromSV"."STW"."X14")));
// Network 7: Bottle Counter M153_154 (Original Language: LAD)
"DB Bottle Counter M153_154"(Conveyor_Running := "DB TT Motor 41"."Manage"."STATUS_VFD_Run_FWD" AND "DB TT Motor 42"."Manage"."STATUS_VFD_Run_FWD", PH_Inlet := "Count 1 M42", PH_Outlet := "Count 2 M42", Reset_Button_Allarm := "SH331-1B", Reset_Counter_Henkel := "ComSV"."TL25_WriteToSv"."FromHenkel"."STW"."di0.x"[1]);
// Network 8: Bottle Counter M37 (Original Language: LAD)
"DB Bottle Counter_M37"(Conveyor_Running := "DB TT Motor 37"."Manage"."STATUS_VFD_Run_FWD", PH_Inlet := "Count 1 M35", PH_Outlet := "Count 2 M35", Reset_Button_Allarm := "SH331-1B", Reset_Counter_Henkel := "ComSV"."TL25_WriteToSv"."FromHenkel"."STW"."di0.x"[1]);
IF "M0.1" THEN
"DB TT Alarm"."A371_03_3" := FALSE;
END_IF;
// Network 9: (Original Language: LAD)
IF "Tag_27" > 5 THEN
"Tag_27" := 0;
END_IF;
"Apoyo_Rechazo" := "B5-M35" OR ("M0.0" AND Eq("Tag_27", 5));
// Network 10: Ejector Bottle (Original Language: STL)
// --- BEGIN STL Network 10 ---
```stl
CALL "DB Ejector Bottle"
```
// --- END STL Network 10 ---
// Network 11: Photocell Teach (Original Language: LAD)
"Delay Photocell Teach"(IN := "DB General"."X203_0", PT := S5T#0.8s); // TODO: Declarar "Delay Photocell Teach" : TP;
"A8.0" := "Delay Photocell Teach".Q;
"DB General"."X203_1" := "Delay Photocell Teach".Q;
IF "Delay Photocell Teach".Q THEN
"DB General"."X203_0" := FALSE;
END_IF;
// Network 12: Elevator - Guide (Original Language: STL)
// --- BEGIN STL Network 12 ---
```stl
CALL "DB Guide Lifter - Lowerator"
```
// --- END STL Network 12 ---
// Network 13: Elevator - Lube (Original Language: STL)
// --- BEGIN STL Network 13 ---
```stl
CALL "DB lube M35"
```
// --- END STL Network 13 ---
// Network 14: Camera Ejector Bottle (Original Language: STL)
// "E38.1"
// --- BEGIN STL Network 14 ---
```stl
CALL "DB Camera Ejector Bottle"
```
// --- END STL Network 14 ---
// Network 15: (Original Language: LAD)
// Network 15 did not produce printable SCL code.
// Network 16: Elevator - SV Reject Y1-M35 (Original Language: LAD)
"Y1-M35" := "Ejector_Tower" OR "Ejector_Camera";
// Network 17: Signal for changeover done (Original Language: LAD)
"Ap_EMD_InPsosition" := Eq("DB TTOP - Body Guide EMD"."Counter_Position", "DB TTOP - Body Guide EMD"."Position_Selection");
"Ap_HighLim" := ("DB Guide Lifter - Lowerator"."Position Selection") + ("DB Guide Lifter - Lowerator"."Range Position");
"Ap_LowLim" := ("DB Guide Lifter - Lowerator"."Position Selection") - ("DB Guide Lifter - Lowerator"."Range Position");
"Ap_LifterGuideInPositon" := "DB Guide Lifter - Lowerator"."Actual Position" >= "Ap_LowLim";
// Network 18: INTERLOCK EMD CHANGEOVER (Original Language: SCL)
"ComSV".TL25_WriteToSv.ToSV.STW.QE1.X13 := "ComSV".TL25_ReadFromSv.FromSV.STW.X06;
"ComSV".TL25_WriteToSv.ToSV.STW.QE1.X14 := "ComSV".TL25_ReadFromSv.FromSV.STW.X07;
"ComSV".TL25_WriteToSv.ToSV.STW.QE1.X15 := "ComSV".TL25_ReadFromSv.FromSV.STW.X08;
"ComSV".TL25_WriteToSv.ToSV.STW.QE1.X16 := "ComSV".TL25_ReadFromSv.FromSV.STW.X09;
END_FUNCTION

View File

@ -1,287 +0,0 @@
// Block Type: FC
// Block Number: 800
// Original Network Languages: SCL, LAD
FUNCTION "FormatManagementQE1_G" : Void
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_TEMP
CalculatedBottlesRemainigToFill : DInt;
END_VAR
CONSTANT
FormatChange_Disabled : Int := 0;
FormatChange_Enabled : Int := 1;
FormatChange_Emptying : Int := 2;
FormatChange_InProgress : Int := 3;
FormatChange_Done : Int := 4;
FormatChange_NotNecessary : Int := 5;
FormatChange_Error : Int := 6;
PopUp_LineReady : Int := 2000;
PopUp_EmptyStart : Int := 2001;
PopUp_EmptyEnd : Int := 2002;
END_CONSTANT
#_3s : Bool; // Auto-generated temporary
#TON_INSTANCE_31 : Bool; // Auto-generated temporary
BEGIN
// Network 1: HMI Selector for "Local Format Change" or "Remote Format Change" (Original Language: SCL)
"Rt_Enable_RemoteFormatChange"/*_ERR_NO_CALLINFO_*/;
IF NOT "FormatManagementQE1_D".RemoteSelector THEN
"FormatManagementQE1_D".FormatChangeCycle := /*_ERR_NO_SYMBOL_IN_LocalConstant_*/;
ELSIF "Rt_Enable_RemoteFormatChange".Q THEN
"FormatManagementQE1_D".FormatChangeCycle := /*_ERR_NO_SYMBOL_IN_LocalConstant_*/;
END_IF;
// Network 2: For test (Original Language: SCL)
"CalculatedBottlesRemainigToFill" := "ComSV".TL25_WriteToSv.FromHenkel.SignalExchange.Filler.CalculatedBottlesRemainingToFill;
// Network 3: STATE MACHINE - REMOTE FORMAT CHANGE MANAGEMENT (Original Language: SCL)
//
//
IF "FormatManagementQE1_D".RemoteSelector THEN
"FormatManagementQE1_D".RemoteSelector := FALSE;
"FormatManagementQE1_D".FormatChangeCycle := /*_ERR_NO_SYMBOL_IN_LocalConstant_*/;
END_IF;
CASE "FormatManagementQE1_D".FormatChangeCycle OF
/*_ERR_NO_SYMBOL_IN_LocalConstant_*/: //
IF "FormatManagementQE1_D".RemoteSelector THEN
/*_ERR_Scope_Address_*/ := 0;
/*_ERR_Scope_Address_*/ := 0;
"FormatManagementQE1_D".FormatChangeCycle := /*_ERR_NO_SYMBOL_IN_LocalConstant_*/;
END_IF;
/*_ERR_NO_SYMBOL_IN_LocalConstant_*/: //
IF ("CalculatedBottlesRemainigToFill" = 0) THEN //
//
"ComSV".TL25_WriteToSv.ToAutefa.dw0.x[1] := TRUE;
IF ("DB HMI Recipe Bottle".number_set_data = "FormatManagementQE1_D".NextSku.ProdFamily) AND ("FormatManagementQE1_D".NextSku.ProdFamily <> 0) AND
("FormatManagementQE1_D".AB_IDH_BTL = "FormatManagementQE1_D".NB_IDH_BTL) AND ("DB COM Signal Merger".Input.ActualBottleType = "DB HMI Recipe Bottle".number_set_data) AND
("DB COM Signal Guides".From_Guides.ActualBottleType = "DB HMI Recipe Bottle".number_set_data) THEN
"FormatManagementQE1_D".HMI_PopUp.ShowPopUp := TRUE;
"FormatManagementQE1_D".HMI_PopUp.PageNumber := /*_ERR_NO_SYMBOL_IN_LocalConstant_*/;
"FormatManagementQE1_D".FormatChangeCycle := /*_ERR_NO_SYMBOL_IN_LocalConstant_*/;
ELSIF
(("DB HMI Recipe Bottle".number_set_data <> "FormatManagementQE1_D".NextSku.ProdFamily)OR("FormatManagementQE1_D".AB_IDH_BTL <> "FormatManagementQE1_D".NB_IDH_BTL)) AND
("FormatManagementQE1_D".NextSku.ProdFamily <> 0) THEN
"FormatManagementQE1_D".HMI_PopUp.ShowPopUp := TRUE;
"FormatManagementQE1_D".HMI_PopUp.PageNumber := /*_ERR_NO_SYMBOL_IN_LocalConstant_*/;
"FormatManagementQE1_D".FormatChangeCycle := /*_ERR_NO_SYMBOL_IN_LocalConstant_*/;
END_IF;
END_IF;
IF ("CalculatedBottlesRemainigToFill" > 0) AND //
("DB HMI Recipe Bottle".number_set_data = "ComSV".TL25_ReadFromSv.FromAlpla.ActualSku.ProdFamily) AND NOT "ComSV".TL25_WriteToSv.FromHenkel.STW.di0.x[0] THEN
"FormatManagementQE1_D".FormatChangeCycle := /*_ERR_NO_SYMBOL_IN_LocalConstant_*/;
END_IF;
/*_ERR_NO_SYMBOL_IN_LocalConstant_*/: //
IF "FormatManagementQE1_D".HMI_PopUp.Yes AND ("DB HMI".DBW_2 = /*_ERR_NO_SYMBOL_IN_LocalConstant_*/) THEN
"FormatManagementQE1_D".EmptyingStart := TRUE;
"FormatManagementQE1_D".HMI_PopUp.ShowPopUp := TRUE;
"FormatManagementQE1_D".HMI_PopUp.PageNumber := /*_ERR_NO_SYMBOL_IN_LocalConstant_*/;
ELSIF
"FormatManagementQE1_D".HMI_PopUp.No AND ("DB HMI".DBW_2 = /*_ERR_NO_SYMBOL_IN_LocalConstant_*/) THEN
"FormatManagementQE1_D".FormatChangeCycle := /*_ERR_NO_SYMBOL_IN_LocalConstant_*/;
END_IF;
IF "ComSV".TL25_WriteToSv.ToSV.STW.QE1.MachineEmpty AND
"ComSV".TL25_WriteToSv.ToSV.STW.Merger.MachineEmpty THEN //
"FormatManagementQE1_D".EmptyingStart := FALSE;
END_IF;
IF NOT "FormatManagementQE1_D".EmptyingStart THEN
IF "FormatManagementQE1_D".HMI_PopUp.Yes AND ("DB HMI".DBW_2 = /*_ERR_NO_SYMBOL_IN_LocalConstant_*/) AND
"ComSV".TL25_WriteToSv.FromHenkel.STW.di0.x[0] THEN
"FormatManagementQE1_D".IN_EndFormatManagement := FALSE;
"FormatManagementQE1_D".FormatChangeQE := FALSE;
IF ("DB HMI Recipe Bottle".number_set_data = "FormatManagementQE1_D".NextSku.ProdFamily) THEN
"FormatManagementQE1_D".HMI_PopUp.ShowPopUp := TRUE;
"FormatManagementQE1_D".HMI_PopUp.PageNumber := /*_ERR_NO_SYMBOL_IN_LocalConstant_*/;
"FormatManagementQE1_D".FormatChangeCycle := /*_ERR_NO_SYMBOL_IN_LocalConstant_*/;
ELSE
"FormatManagementQE1_D".FormatChangeCycle := /*_ERR_NO_SYMBOL_IN_LocalConstant_*/;
END_IF;
ELSIF
"FormatManagementQE1_D".HMI_PopUp.No AND ("DB HMI".DBW_2 = /*_ERR_NO_SYMBOL_IN_LocalConstant_*/) THEN
"FormatManagementQE1_D".EmptyingStart := TRUE;
END_IF;
END_IF;
/*_ERR_NO_SYMBOL_IN_LocalConstant_*/: //
IF NOT "FormatManagementQE1_D".EndFormatManagement.Q THEN
"FormatManagementQE1_D".IN_EndFormatManagement := TRUE;
END_IF;
IF ("DB HMI".DBW_36 = 4) THEN
"FormatManagementQE1_D".FormatChangeQE := TRUE;
ELSIF
("DB HMI".DBW_36 = 12) THEN
"FormatManagementQE1_D".LoadRecipeError := TRUE;
"FormatManagementQE1_D".FormatChangeCycle := /*_ERR_NO_SYMBOL_IN_LocalConstant_*/;
END_IF;
IF "FormatManagementQE1_D".EndFormatManagement.Q AND "FormatManagementQE1_D".FormatChangeQE THEN
IF ("DB COM Signal Merger".Input.ActualBottleType = "DB HMI Recipe Bottle".number_set_data) AND
"Ap_LifterGuideInPositon" THEN //
"FormatManagementQE1_D".HMI_PopUp.ShowPopUp := TRUE;
"FormatManagementQE1_D".FormatChangeQE := FALSE;
"FormatManagementQE1_D".HMI_PopUp.PageNumber := /*_ERR_NO_SYMBOL_IN_LocalConstant_*/;
ELSIF
NOT "DB COM Signal Merger".Input.StatusWord.X5 OR NOT "DB COM Signal Guides".From_Guides.StatusWord.Bit_1 ChangeOverInProgress THEN
"FormatManagementQE1_D".LoadRecipeErrorMachine := TRUE;
"FormatManagementQE1_D".FormatChangeCycle := /*_ERR_NO_SYMBOL_IN_LocalConstant_*/;
END_IF;
END_IF;
IF "FormatManagementQE1_D".HMI_PopUp.Yes AND NOT "FormatManagementQE1_D".HMI_PopUp.ShowPopUp AND
("DB HMI".DBW_2 = /*_ERR_NO_SYMBOL_IN_LocalConstant_*/) THEN
"FormatManagementQE1_D".FormatChangeCycle := /*_ERR_NO_SYMBOL_IN_LocalConstant_*/;
"ComSV".TL25_WriteToSv.ToAlpla.BatchLast := "FormatManagementQE1_D".BatchLast;
//
"FormatManagementQE1_D".IN_EndFormatManagement := FALSE;
ELSIF
"FormatManagementQE1_D".HMI_PopUp.No AND NOT "FormatManagementQE1_D".HMI_PopUp.ShowPopUp AND
("DB HMI".DBW_2 = /*_ERR_NO_SYMBOL_IN_LocalConstant_*/) THEN
"FormatManagementQE1_D".IN_EndFormatManagement := FALSE;
END_IF;
/*_ERR_NO_SYMBOL_IN_LocalConstant_*/: //
"Rt_RestartRemoteFormatChange"/*_ERR_NO_CALLINFO_*/;
IF ("CalculatedBottlesRemainigToFill" > 0) AND "Rt_RestartRemoteFormatChange".Q AND
"ComSV".TL25_WriteToSv.FromHenkel.STW.di0.x[2] THEN //
"FormatManagementQE1_D".FormatChangeCycle := /*_ERR_NO_SYMBOL_IN_LocalConstant_*/;
END_IF;
/*_ERR_NO_SYMBOL_IN_LocalConstant_*/: //
IF "FormatManagementQE1_D".HMI_PopUp.Yes AND ("DB HMI".DBW_2 = /*_ERR_NO_SYMBOL_IN_LocalConstant_*/) THEN
"ComSV".TL25_WriteToSv.ToAlpla.BatchLast := "FormatManagementQE1_D".BatchLast;
//
"FormatManagementQE1_D".FormatChangeCycle := /*_ERR_NO_SYMBOL_IN_LocalConstant_*/;
ELSIF
"FormatManagementQE1_D".HMI_PopUp.No AND ("DB HMI".DBW_2 = /*_ERR_NO_SYMBOL_IN_LocalConstant_*/) THEN
"FormatManagementQE1_D".RemoteSelector := FALSE;
END_IF;
/*_ERR_NO_SYMBOL_IN_LocalConstant_*/: //
IF "DB TT Run".TT_Run.IN_PB_Reset THEN
IF "FormatManagementQE1_D".LoadRecipeError THEN
"FormatManagementQE1_D".LoadRecipeError := FALSE;
"FormatManagementQE1_D".FormatChangeCycle := /*_ERR_NO_SYMBOL_IN_LocalConstant_*/;
ELSIF "FormatManagementQE1_D".LoadRecipeErrorMachine AND ("DB COM Signal Merger".Input.ActualBottleType = "DB HMI Recipe Bottle".number_set_data) AND
("DB COM Signal Guides".From_Guides.ActualBottleType = "DB HMI Recipe Bottle".number_set_data) THEN
"FormatManagementQE1_D".LoadRecipeErrorMachine := FALSE;
"FormatManagementQE1_D".FormatChangeCycle := /*_ERR_NO_SYMBOL_IN_LocalConstant_*/;
ELSIF "FormatManagementQE1_D".LoadRecipeErrorMachine AND ("DB COM Signal Merger".Input.ActualBottleType <> "DB HMI Recipe Bottle".number_set_data) OR
("DB COM Signal Guides".From_Guides.ActualBottleType <> "DB HMI Recipe Bottle".number_set_data) THEN
"FormatManagementQE1_D".FormatChangeCycle := /*_ERR_NO_SYMBOL_IN_LocalConstant_*/;
END_IF;
END_IF;
END_CASE;
"FormatManagementQE1_D".EndFormatManagement./*_ERR_NO_CALLINFO_*/;
//
"DB TT Alarm".A371_23_0 := "FormatManagementQE1_D".LoadRecipeError;
"DB TT Alarm".A371_23_1 := "FormatManagementQE1_D".LoadRecipeErrorMachine;
// Network 4: Format Management Information / Batch Last (Original Language: SCL)
IF ("CalculatedBottlesRemainigToFill" > 0) AND
("FormatManagementQE1_D".FormatChangeCycle = /*_ERR_NO_SYMBOL_IN_LocalConstant_*/) AND NOT "ComSV".TL25_WriteToSv.FromHenkel.STW.di0.x[0] THEN
"FormatManagementQE1_D".ABBottlesNumber := "ComSV".TL25_WriteToSv.FromHenkel.ABBottlesNumber;
"FormatManagementQE1_D".NBBottlesNumber := "ComSV".TL25_WriteToSv.FromHenkel.NBBottlesNumber;
"FormatManagementQE1_D".AB_IDH_BTL := "ComSV".TL25_WriteToSv.FromHenkel.AB_IDH_BTL;
"FormatManagementQE1_D".NB_IDH_BTL := "ComSV".TL25_WriteToSv.FromHenkel.NB_IDH_BTL;
"FormatManagementQE1_D".PO_NUMBER := "ComSV".TL25_WriteToSv.FromHenkel.PO_NUMBER;
"FormatManagementQE1_D".PO_NUMBER_NEXT := "ComSV".TL25_WriteToSv.FromHenkel.PO_NUMBER_NEXT;
"FormatManagementQE1_D".NextSku := "ComSV".TL25_ReadFromSv.FromAlpla.NextSku;
"FormatManagementQE1_D".ActualSku := "ComSV".TL25_ReadFromSv.FromAlpla.ActualSku;
//
"FormatManagementQE1_D".BatchLast.CustomArticleNum := "ComSV".TL25_ReadFromSv.FromAlpla.ActualSku.CustomArticleNum;
"FormatManagementQE1_D".BatchLast.BottlesNumber := "ComSV".TL25_WriteToSv.FromHenkel.ABBottlesNumber;
/*_ERR_NO_CALLINFO_*/;
"FormatManagementQE1_D".BatchLast.CounterSideGripDosingBelt := "ComSV".TL25_WriteToSv.ToHenkel.Counter.SideGripDosingBelt;
"FormatManagementQE1_D".BatchLast.CounterInfeedFiller := "ComSV".TL25_WriteToSv.ToHenkel.Counter.InfeedFiller;
ELSIF
("FormatManagementQE1_D".FormatChangeCycle = /*_ERR_NO_SYMBOL_IN_LocalConstant_*/) AND ("CalculatedBottlesRemainigToFill" > 0) THEN
"FormatManagementQE1_D".ABBottlesNumber := "ComSV".TL25_WriteToSv.FromHenkel.ABBottlesNumber;
"FormatManagementQE1_D".NBBottlesNumber := "ComSV".TL25_WriteToSv.FromHenkel.NBBottlesNumber;
"FormatManagementQE1_D".AB_IDH_BTL := "ComSV".TL25_WriteToSv.FromHenkel.AB_IDH_BTL;
"FormatManagementQE1_D".NB_IDH_BTL := "ComSV".TL25_WriteToSv.FromHenkel.NB_IDH_BTL;
"FormatManagementQE1_D".PO_NUMBER := "ComSV".TL25_WriteToSv.FromHenkel.PO_NUMBER;
"FormatManagementQE1_D".PO_NUMBER_NEXT := "ComSV".TL25_WriteToSv.FromHenkel.PO_NUMBER_NEXT;
"FormatManagementQE1_D".NextSku := "ComSV".TL25_ReadFromSv.FromAlpla.NextSku;
"FormatManagementQE1_D".ActualSku := "ComSV".TL25_ReadFromSv.FromAlpla.ActualSku;
//
"FormatManagementQE1_D".BatchLast.CustomArticleNum := "ComSV".TL25_ReadFromSv.FromAlpla.ActualSku.CustomArticleNum;
"FormatManagementQE1_D".BatchLast.BottlesNumber := "ComSV".TL25_WriteToSv.FromHenkel.ABBottlesNumber;
/*_ERR_NO_CALLINFO_*/;
"FormatManagementQE1_D".BatchLast.CounterSideGripDosingBelt := "ComSV".TL25_WriteToSv.ToHenkel.Counter.SideGripDosingBelt;
"FormatManagementQE1_D".BatchLast.CounterInfeedFiller := "ComSV".TL25_WriteToSv.ToHenkel.Counter.InfeedFiller;
END_IF;
// Network 5: EndFormatChangeLine (Original Language: LAD)
#TON_INSTANCE_31(IN := "ComSV"."TL25_WriteToSv"."ToSV"."STW"."QE1"."ChangeoverDone" AND "ComSV"."TL25_WriteToSv"."ToSV"."STW"."QE2"."ChangeoverDone" AND Eq("DB COM Signal Guides"."From_Guides"."ActualBottleType", "DB HMI Recipe Bottle"."number_set_data"), PT := T#3s); // TODO: Declarar #TON_INSTANCE_31 : TON;
// Network 6: Format Management Line (Original Language: SCL)
//
//
//
"FormatManagementQE1_D".OnsR_EndFormatChangeLine := "FormatManagementQE1_D".EndFormatChangeLine.Q;
IF ("ComSV".TL25_WriteToSv.ToSV.STW.QE1.ChangeoverInProgress OR "ComSV".TL25_WriteToSv.ToSV.STW.QE2.ChangeoverInProgress) AND "ComSV".TL25_ReadFromSv.FromAutefa.dw0.x[24] THEN
"ComSV".TL25_WriteToSv.ToHenkel.LineStatus.di0.x[0] := TRUE;
ELSE
"ComSV".TL25_WriteToSv.ToHenkel.LineStatus.di0.x[0] := FALSE;
END_IF;
IF ("FormatManagementQE1_D".OnsR_EndFormatChangeLine AND "ComSV".TL25_ReadFromSv.FromAutefa.dw0.x[25] AND NOT "ComSV".TL25_WriteToSv.FromHenkel.STW.di0.x[2]) THEN
"ComSV".TL25_WriteToSv.ToHenkel.LineStatus.di0.x[1] := TRUE;
"ComSV".TL25_WriteToSv.ToAutefa.dw0.x[1] := FALSE;
ELSE
"ComSV".TL25_WriteToSv.ToHenkel.LineStatus.di0.x[1] := FALSE;
END_IF;
//
IF "ComSV".TL25_WriteToSv.ToAutefa.dw0.x[1] AND NOT "ComSV".TL25_ReadFromSv.FromAutefa.dw0.x[24] THEN
"DB Warnings".W173_03_0 := TRUE;
ELSIF
"ComSV".TL25_WriteToSv.ToAutefa.dw0.x[1] AND "ComSV".TL25_ReadFromSv.FromAutefa.dw0.x[24] THEN
"DB Warnings".W173_03_0 := FALSE;
"DB Warnings".W173_03_1 := TRUE;
ELSIF
"ComSV".TL25_ReadFromSv.FromAutefa.dw0.x[24] THEN
"DB Warnings".W173_03_1 := FALSE;
END_IF;
// Network 7: Load Remote Recipe (Original Language: SCL)
"Rt_LoadRemoteRecipe"/*_ERR_NO_CALLINFO_*/;
IF "Rt_LoadRemoteRecipe".Q THEN
"DB HMI".DBW_36 := 0;
"DB HMI".DBW_12 := 2;
"DB HMI".DBW_14 := /*_ERR_NO_CALLINFO_*/;
"DB HMI".DBW_16 := 0;
"DB HMI".DBW_10 := 70;
END_IF;
IF ("DB HMI".DBW_36 = 4) OR ("DB HMI".DBW_36 = 12) AND
("DB HMI".DBW_10 = 70) THEN
"DB HMI".DBW_10 := 0;
"DB HMI".DBW_12 := 0;
"DB HMI".DBW_14 := 0;
"DB HMI".DBW_16 := 0;
END_IF;
// Network 8: PopUp Remote HMI (Original Language: SCL)
"Rt_PopUp_RemoteFormatChange"/*_ERR_NO_CALLINFO_*/;
IF "Rt_PopUp_RemoteFormatChange".Q THEN
"DB HMI".DBW_12 := "FormatManagementQE1_D".HMI_PopUp.PageNumber;
"DB HMI".DBW_14 := 0;
"DB HMI".DBW_16 := 0;
"DB HMI".DBW_10 := 51;
"FormatManagementQE1_D".HMI_PopUp.PageNumber := 0;
"FormatManagementQE1_D".HMI_PopUp.ShowPopUp := FALSE;
"FormatManagementQE1_D".HMI_PopUp.Yes := FALSE;
"FormatManagementQE1_D".HMI_PopUp.No := FALSE;
END_IF;
IF ("DB HMI".DBW_2 = "FormatManagementQE1_D".HMI_PopUp.PageNumber) AND
("DB HMI".DBW_10 = 51) THEN
"DB HMI".DBW_10 := 0;
"DB HMI".DBW_12 := 0;
"DB HMI".DBW_14 := 0;
"DB HMI".DBW_16 := 0;
END_IF;
END_FUNCTION

View File

@ -1,297 +0,0 @@
// Block Type: FC
// Block Number: 800
// Original Network Languages: LAD, SCL
FUNCTION "FormatManagementQE1_G" : Void
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_TEMP
CalculatedBottlesRemainigToFill : DInt;
END_VAR
CONSTANT
FormatChange_Disabled : Int := 0;
FormatChange_Enabled : Int := 1;
FormatChange_Emptying : Int := 2;
FormatChange_InProgress : Int := 3;
FormatChange_Done : Int := 4;
FormatChange_NotNecessary : Int := 5;
FormatChange_Error : Int := 6;
PopUp_LineReady : Int := 2000;
PopUp_EmptyStart : Int := 2001;
PopUp_EmptyEnd : Int := 2002;
END_CONSTANT
#_3s : Bool; // Auto-generated temporary
#FormatChange_Disabled : Bool; // Auto-generated temporary
#FormatChange_Done : Bool; // Auto-generated temporary
#FormatChange_Emptying : Bool; // Auto-generated temporary
#FormatChange_Enabled : Bool; // Auto-generated temporary
#FormatChange_Error : Bool; // Auto-generated temporary
#FormatChange_InProgress : Bool; // Auto-generated temporary
#FormatChange_NotNecessary : Bool; // Auto-generated temporary
#PopUp_EmptyEnd : Bool; // Auto-generated temporary
#PopUp_EmptyStart : Bool; // Auto-generated temporary
#PopUp_LineReady : Bool; // Auto-generated temporary
#TON_INSTANCE_31 : Bool; // Auto-generated temporary
BEGIN
// Network 1: HMI Selector for "Local Format Change" or "Remote Format Change" (Original Language: SCL)
"Rt_Enable_RemoteFormatChange"/*_ERR_NO_CALLINFO_*/;
IF NOT "FormatManagementQE1_D".RemoteSelector THEN
"FormatManagementQE1_D".FormatChangeCycle := #FormatChange_Disabled;
ELSIF "Rt_Enable_RemoteFormatChange".Q THEN
"FormatManagementQE1_D".FormatChangeCycle := #FormatChange_Enabled;
END_IF;
// Network 2: For test (Original Language: SCL)
"CalculatedBottlesRemainigToFill" := "ComSV".TL25_WriteToSv.FromHenkel.SignalExchange.Filler.CalculatedBottlesRemainingToFill;
// Network 3: STATE MACHINE - REMOTE FORMAT CHANGE MANAGEMENT (Original Language: SCL)
//
//
IF "FormatManagementQE1_D".RemoteSelector THEN
"FormatManagementQE1_D".RemoteSelector := FALSE;
"FormatManagementQE1_D".FormatChangeCycle := #FormatChange_Disabled;
END_IF;
CASE "FormatManagementQE1_D".FormatChangeCycle OF
#FormatChange_Disabled: //
IF "FormatManagementQE1_D".RemoteSelector THEN
/*_ERR_Scope_Address_*/ := 0;
/*_ERR_Scope_Address_*/ := 0;
"FormatManagementQE1_D".FormatChangeCycle := #FormatChange_Enabled;
END_IF;
#FormatChange_Enabled: //
IF ("CalculatedBottlesRemainigToFill" = 0) THEN //
//
"ComSV".TL25_WriteToSv.ToAutefa.dw0.x[1] := TRUE;
IF ("DB HMI Recipe Bottle".number_set_data = "FormatManagementQE1_D".NextSku.ProdFamily) AND ("FormatManagementQE1_D".NextSku.ProdFamily <> 0) AND
("FormatManagementQE1_D".AB_IDH_BTL = "FormatManagementQE1_D".NB_IDH_BTL) AND ("DB COM Signal Merger".Input.ActualBottleType = "DB HMI Recipe Bottle".number_set_data) AND
("DB COM Signal Guides".From_Guides.ActualBottleType = "DB HMI Recipe Bottle".number_set_data) THEN
"FormatManagementQE1_D".HMI_PopUp.ShowPopUp := TRUE;
"FormatManagementQE1_D".HMI_PopUp.PageNumber := #PopUp_LineReady;
"FormatManagementQE1_D".FormatChangeCycle := #FormatChange_NotNecessary;
ELSIF
(("DB HMI Recipe Bottle".number_set_data <> "FormatManagementQE1_D".NextSku.ProdFamily)OR("FormatManagementQE1_D".AB_IDH_BTL <> "FormatManagementQE1_D".NB_IDH_BTL)) AND
("FormatManagementQE1_D".NextSku.ProdFamily <> 0) THEN
"FormatManagementQE1_D".HMI_PopUp.ShowPopUp := TRUE;
"FormatManagementQE1_D".HMI_PopUp.PageNumber := #PopUp_EmptyStart;
"FormatManagementQE1_D".FormatChangeCycle := #FormatChange_Emptying;
END_IF;
END_IF;
IF ("CalculatedBottlesRemainigToFill" > 0) AND //
("DB HMI Recipe Bottle".number_set_data = "ComSV".TL25_ReadFromSv.FromAlpla.ActualSku.ProdFamily) AND NOT "ComSV".TL25_WriteToSv.FromHenkel.STW.di0.x[0] THEN
"FormatManagementQE1_D".FormatChangeCycle := #FormatChange_Done;
END_IF;
#FormatChange_Emptying: //
IF "FormatManagementQE1_D".HMI_PopUp.Yes AND ("DB HMI".DBW_2 = #PopUp_EmptyStart) THEN
"FormatManagementQE1_D".EmptyingStart := TRUE;
"FormatManagementQE1_D".HMI_PopUp.ShowPopUp := TRUE;
"FormatManagementQE1_D".HMI_PopUp.PageNumber := #PopUp_EmptyEnd;
ELSIF
"FormatManagementQE1_D".HMI_PopUp.No AND ("DB HMI".DBW_2 = #PopUp_EmptyStart) THEN
"FormatManagementQE1_D".FormatChangeCycle := #FormatChange_Enabled;
END_IF;
IF "ComSV".TL25_WriteToSv.ToSV.STW.QE1.MachineEmpty AND
"ComSV".TL25_WriteToSv.ToSV.STW.Merger.MachineEmpty THEN //
"FormatManagementQE1_D".EmptyingStart := FALSE;
END_IF;
IF NOT "FormatManagementQE1_D".EmptyingStart THEN
IF "FormatManagementQE1_D".HMI_PopUp.Yes AND ("DB HMI".DBW_2 = #PopUp_EmptyEnd) AND
"ComSV".TL25_WriteToSv.FromHenkel.STW.di0.x[0] THEN
"FormatManagementQE1_D".IN_EndFormatManagement := FALSE;
"FormatManagementQE1_D".FormatChangeQE := FALSE;
IF ("DB HMI Recipe Bottle".number_set_data = "FormatManagementQE1_D".NextSku.ProdFamily) THEN
"FormatManagementQE1_D".HMI_PopUp.ShowPopUp := TRUE;
"FormatManagementQE1_D".HMI_PopUp.PageNumber := #PopUp_LineReady;
"FormatManagementQE1_D".FormatChangeCycle := #FormatChange_NotNecessary;
ELSE
"FormatManagementQE1_D".FormatChangeCycle := #FormatChange_InProgress;
END_IF;
ELSIF
"FormatManagementQE1_D".HMI_PopUp.No AND ("DB HMI".DBW_2 = #PopUp_EmptyEnd) THEN
"FormatManagementQE1_D".EmptyingStart := TRUE;
END_IF;
END_IF;
#FormatChange_InProgress: //
IF NOT "FormatManagementQE1_D".EndFormatManagement.Q THEN
"FormatManagementQE1_D".IN_EndFormatManagement := TRUE;
END_IF;
IF ("DB HMI".DBW_36 = 4) THEN
"FormatManagementQE1_D".FormatChangeQE := TRUE;
ELSIF
("DB HMI".DBW_36 = 12) THEN
"FormatManagementQE1_D".LoadRecipeError := TRUE;
"FormatManagementQE1_D".FormatChangeCycle := #FormatChange_Error;
END_IF;
IF "FormatManagementQE1_D".EndFormatManagement.Q AND "FormatManagementQE1_D".FormatChangeQE THEN
IF ("DB COM Signal Merger".Input.ActualBottleType = "DB HMI Recipe Bottle".number_set_data) AND
"Ap_LifterGuideInPositon" THEN //
"FormatManagementQE1_D".HMI_PopUp.ShowPopUp := TRUE;
"FormatManagementQE1_D".FormatChangeQE := FALSE;
"FormatManagementQE1_D".HMI_PopUp.PageNumber := #PopUp_LineReady;
ELSIF
NOT "DB COM Signal Merger".Input.StatusWord.X5 OR NOT "DB COM Signal Guides".From_Guides.StatusWord.Bit_1 ChangeOverInProgress THEN
"FormatManagementQE1_D".LoadRecipeErrorMachine := TRUE;
"FormatManagementQE1_D".FormatChangeCycle := #FormatChange_Error;
END_IF;
END_IF;
IF "FormatManagementQE1_D".HMI_PopUp.Yes AND NOT "FormatManagementQE1_D".HMI_PopUp.ShowPopUp AND
("DB HMI".DBW_2 = #PopUp_LineReady) THEN
"FormatManagementQE1_D".FormatChangeCycle := #FormatChange_Done;
"ComSV".TL25_WriteToSv.ToAlpla.BatchLast := "FormatManagementQE1_D".BatchLast;
//
"FormatManagementQE1_D".IN_EndFormatManagement := FALSE;
ELSIF
"FormatManagementQE1_D".HMI_PopUp.No AND NOT "FormatManagementQE1_D".HMI_PopUp.ShowPopUp AND
("DB HMI".DBW_2 = #PopUp_LineReady) THEN
"FormatManagementQE1_D".IN_EndFormatManagement := FALSE;
END_IF;
#FormatChange_Done: //
"Rt_RestartRemoteFormatChange"/*_ERR_NO_CALLINFO_*/;
IF ("CalculatedBottlesRemainigToFill" > 0) AND "Rt_RestartRemoteFormatChange".Q AND
"ComSV".TL25_WriteToSv.FromHenkel.STW.di0.x[2] THEN //
"FormatManagementQE1_D".FormatChangeCycle := #FormatChange_Enabled;
END_IF;
#FormatChange_NotNecessary: //
IF "FormatManagementQE1_D".HMI_PopUp.Yes AND ("DB HMI".DBW_2 = #PopUp_LineReady) THEN
"ComSV".TL25_WriteToSv.ToAlpla.BatchLast := "FormatManagementQE1_D".BatchLast;
//
"FormatManagementQE1_D".FormatChangeCycle := #FormatChange_Done;
ELSIF
"FormatManagementQE1_D".HMI_PopUp.No AND ("DB HMI".DBW_2 = #PopUp_LineReady) THEN
"FormatManagementQE1_D".RemoteSelector := FALSE;
END_IF;
#FormatChange_Error: //
IF "DB TT Run".TT_Run.IN_PB_Reset THEN
IF "FormatManagementQE1_D".LoadRecipeError THEN
"FormatManagementQE1_D".LoadRecipeError := FALSE;
"FormatManagementQE1_D".FormatChangeCycle := #FormatChange_Enabled;
ELSIF "FormatManagementQE1_D".LoadRecipeErrorMachine AND ("DB COM Signal Merger".Input.ActualBottleType = "DB HMI Recipe Bottle".number_set_data) AND
("DB COM Signal Guides".From_Guides.ActualBottleType = "DB HMI Recipe Bottle".number_set_data) THEN
"FormatManagementQE1_D".LoadRecipeErrorMachine := FALSE;
"FormatManagementQE1_D".FormatChangeCycle := #FormatChange_Done;
ELSIF "FormatManagementQE1_D".LoadRecipeErrorMachine AND ("DB COM Signal Merger".Input.ActualBottleType <> "DB HMI Recipe Bottle".number_set_data) OR
("DB COM Signal Guides".From_Guides.ActualBottleType <> "DB HMI Recipe Bottle".number_set_data) THEN
"FormatManagementQE1_D".FormatChangeCycle := #FormatChange_Enabled;
END_IF;
END_IF;
END_CASE;
"FormatManagementQE1_D".EndFormatManagement./*_ERR_NO_CALLINFO_*/;
//
"DB TT Alarm".A371_23_0 := "FormatManagementQE1_D".LoadRecipeError;
"DB TT Alarm".A371_23_1 := "FormatManagementQE1_D".LoadRecipeErrorMachine;
// Network 4: Format Management Information / Batch Last (Original Language: SCL)
IF ("CalculatedBottlesRemainigToFill" > 0) AND
("FormatManagementQE1_D".FormatChangeCycle = #FormatChange_Done) AND NOT "ComSV".TL25_WriteToSv.FromHenkel.STW.di0.x[0] THEN
"FormatManagementQE1_D".ABBottlesNumber := "ComSV".TL25_WriteToSv.FromHenkel.ABBottlesNumber;
"FormatManagementQE1_D".NBBottlesNumber := "ComSV".TL25_WriteToSv.FromHenkel.NBBottlesNumber;
"FormatManagementQE1_D".AB_IDH_BTL := "ComSV".TL25_WriteToSv.FromHenkel.AB_IDH_BTL;
"FormatManagementQE1_D".NB_IDH_BTL := "ComSV".TL25_WriteToSv.FromHenkel.NB_IDH_BTL;
"FormatManagementQE1_D".PO_NUMBER := "ComSV".TL25_WriteToSv.FromHenkel.PO_NUMBER;
"FormatManagementQE1_D".PO_NUMBER_NEXT := "ComSV".TL25_WriteToSv.FromHenkel.PO_NUMBER_NEXT;
"FormatManagementQE1_D".NextSku := "ComSV".TL25_ReadFromSv.FromAlpla.NextSku;
"FormatManagementQE1_D".ActualSku := "ComSV".TL25_ReadFromSv.FromAlpla.ActualSku;
//
"FormatManagementQE1_D".BatchLast.CustomArticleNum := "ComSV".TL25_ReadFromSv.FromAlpla.ActualSku.CustomArticleNum;
"FormatManagementQE1_D".BatchLast.BottlesNumber := "ComSV".TL25_WriteToSv.FromHenkel.ABBottlesNumber;
/*_ERR_NO_CALLINFO_*/;
"FormatManagementQE1_D".BatchLast.CounterSideGripDosingBelt := "ComSV".TL25_WriteToSv.ToHenkel.Counter.SideGripDosingBelt;
"FormatManagementQE1_D".BatchLast.CounterInfeedFiller := "ComSV".TL25_WriteToSv.ToHenkel.Counter.InfeedFiller;
ELSIF
("FormatManagementQE1_D".FormatChangeCycle = #FormatChange_Disabled) AND ("CalculatedBottlesRemainigToFill" > 0) THEN
"FormatManagementQE1_D".ABBottlesNumber := "ComSV".TL25_WriteToSv.FromHenkel.ABBottlesNumber;
"FormatManagementQE1_D".NBBottlesNumber := "ComSV".TL25_WriteToSv.FromHenkel.NBBottlesNumber;
"FormatManagementQE1_D".AB_IDH_BTL := "ComSV".TL25_WriteToSv.FromHenkel.AB_IDH_BTL;
"FormatManagementQE1_D".NB_IDH_BTL := "ComSV".TL25_WriteToSv.FromHenkel.NB_IDH_BTL;
"FormatManagementQE1_D".PO_NUMBER := "ComSV".TL25_WriteToSv.FromHenkel.PO_NUMBER;
"FormatManagementQE1_D".PO_NUMBER_NEXT := "ComSV".TL25_WriteToSv.FromHenkel.PO_NUMBER_NEXT;
"FormatManagementQE1_D".NextSku := "ComSV".TL25_ReadFromSv.FromAlpla.NextSku;
"FormatManagementQE1_D".ActualSku := "ComSV".TL25_ReadFromSv.FromAlpla.ActualSku;
//
"FormatManagementQE1_D".BatchLast.CustomArticleNum := "ComSV".TL25_ReadFromSv.FromAlpla.ActualSku.CustomArticleNum;
"FormatManagementQE1_D".BatchLast.BottlesNumber := "ComSV".TL25_WriteToSv.FromHenkel.ABBottlesNumber;
/*_ERR_NO_CALLINFO_*/;
"FormatManagementQE1_D".BatchLast.CounterSideGripDosingBelt := "ComSV".TL25_WriteToSv.ToHenkel.Counter.SideGripDosingBelt;
"FormatManagementQE1_D".BatchLast.CounterInfeedFiller := "ComSV".TL25_WriteToSv.ToHenkel.Counter.InfeedFiller;
END_IF;
// Network 5: EndFormatChangeLine (Original Language: LAD)
#TON_INSTANCE_31(IN := "ComSV"."TL25_WriteToSv"."ToSV"."STW"."QE1"."ChangeoverDone" AND "ComSV"."TL25_WriteToSv"."ToSV"."STW"."QE2"."ChangeoverDone" AND Eq("DB COM Signal Guides"."From_Guides"."ActualBottleType", "DB HMI Recipe Bottle"."number_set_data"), PT := T#3s); // TODO: Declarar #TON_INSTANCE_31 : TON;
// Network 6: Format Management Line (Original Language: SCL)
//
//
//
"FormatManagementQE1_D".OnsR_EndFormatChangeLine := "FormatManagementQE1_D".EndFormatChangeLine.Q;
IF ("ComSV".TL25_WriteToSv.ToSV.STW.QE1.ChangeoverInProgress OR "ComSV".TL25_WriteToSv.ToSV.STW.QE2.ChangeoverInProgress) AND "ComSV".TL25_ReadFromSv.FromAutefa.dw0.x[24] THEN
"ComSV".TL25_WriteToSv.ToHenkel.LineStatus.di0.x[0] := TRUE;
ELSE
"ComSV".TL25_WriteToSv.ToHenkel.LineStatus.di0.x[0] := FALSE;
END_IF;
IF ("FormatManagementQE1_D".OnsR_EndFormatChangeLine AND "ComSV".TL25_ReadFromSv.FromAutefa.dw0.x[25] AND NOT "ComSV".TL25_WriteToSv.FromHenkel.STW.di0.x[2]) THEN
"ComSV".TL25_WriteToSv.ToHenkel.LineStatus.di0.x[1] := TRUE;
"ComSV".TL25_WriteToSv.ToAutefa.dw0.x[1] := FALSE;
ELSE
"ComSV".TL25_WriteToSv.ToHenkel.LineStatus.di0.x[1] := FALSE;
END_IF;
//
IF "ComSV".TL25_WriteToSv.ToAutefa.dw0.x[1] AND NOT "ComSV".TL25_ReadFromSv.FromAutefa.dw0.x[24] THEN
"DB Warnings".W173_03_0 := TRUE;
ELSIF
"ComSV".TL25_WriteToSv.ToAutefa.dw0.x[1] AND "ComSV".TL25_ReadFromSv.FromAutefa.dw0.x[24] THEN
"DB Warnings".W173_03_0 := FALSE;
"DB Warnings".W173_03_1 := TRUE;
ELSIF
"ComSV".TL25_ReadFromSv.FromAutefa.dw0.x[24] THEN
"DB Warnings".W173_03_1 := FALSE;
END_IF;
// Network 7: Load Remote Recipe (Original Language: SCL)
"Rt_LoadRemoteRecipe"/*_ERR_NO_CALLINFO_*/;
IF "Rt_LoadRemoteRecipe".Q THEN
"DB HMI".DBW_36 := 0;
"DB HMI".DBW_12 := 2;
"DB HMI".DBW_14 := /*_ERR_NO_CALLINFO_*/;
"DB HMI".DBW_16 := 0;
"DB HMI".DBW_10 := 70;
END_IF;
IF ("DB HMI".DBW_36 = 4) OR ("DB HMI".DBW_36 = 12) AND
("DB HMI".DBW_10 = 70) THEN
"DB HMI".DBW_10 := 0;
"DB HMI".DBW_12 := 0;
"DB HMI".DBW_14 := 0;
"DB HMI".DBW_16 := 0;
END_IF;
// Network 8: PopUp Remote HMI (Original Language: SCL)
"Rt_PopUp_RemoteFormatChange"/*_ERR_NO_CALLINFO_*/;
IF "Rt_PopUp_RemoteFormatChange".Q THEN
"DB HMI".DBW_12 := "FormatManagementQE1_D".HMI_PopUp.PageNumber;
"DB HMI".DBW_14 := 0;
"DB HMI".DBW_16 := 0;
"DB HMI".DBW_10 := 51;
"FormatManagementQE1_D".HMI_PopUp.PageNumber := 0;
"FormatManagementQE1_D".HMI_PopUp.ShowPopUp := FALSE;
"FormatManagementQE1_D".HMI_PopUp.Yes := FALSE;
"FormatManagementQE1_D".HMI_PopUp.No := FALSE;
END_IF;
IF ("DB HMI".DBW_2 = "FormatManagementQE1_D".HMI_PopUp.PageNumber) AND
("DB HMI".DBW_10 = 51) THEN
"DB HMI".DBW_10 := 0;
"DB HMI".DBW_12 := 0;
"DB HMI".DBW_14 := 0;
"DB HMI".DBW_16 := 0;
END_IF;
END_FUNCTION

View File

@ -1,117 +0,0 @@
# 🔄 XML→SCL Converter - Modo Manual con GUI
## 📋 Descripción
`x8_manual_gui.py` es una interfaz gráfica de usuario (GUI) que facilita la conversión de archivos XML de Siemens TIA Portal a código SCL de manera manual e interactiva.
## 🚀 Características Principales
- **🖥️ Interfaz gráfica amigable** - Cuadros de diálogo de Windows nativos
- **📄 Selección de archivo XML** - Navegador de archivos integrado
- **📂 Selección de directorio destino** - Explorador de carpetas
- **📝 Generación automática de nombres** - El nombre del archivo SCL se genera automáticamente
- **📊 Progreso en tiempo real** - Visualización del proceso de conversión
- **✅ Verificación de resultados** - Confirmación de éxito y opción para abrir directorio
- **🔧 Manejo de errores** - Mensajes claros de error y advertencias
## 🎯 Modo de Uso
### 1. Ejecutar el Script
```bash
python x8_manual_gui.py
```
### 2. Pasos en la Interfaz
1. **📄 Seleccionar Archivo XML**
- Haz clic en "📁 Examinar..." en la sección "Archivo XML de Origen"
- Navega y selecciona tu archivo `.xml` de Siemens TIA Portal
- El nombre del archivo SCL se generará automáticamente
2. **📂 Seleccionar Directorio de Destino**
- Haz clic en "📁 Examinar..." en la sección "Directorio de Destino"
- Selecciona la carpeta donde quieres guardar el archivo SCL
3. **🚀 Iniciar Conversión**
- El botón "🚀 Convertir XML → SCL" se habilitará automáticamente
- Haz clic para iniciar el proceso de conversión
4. **📊 Monitorear Progreso**
- Observa los mensajes de progreso en tiempo real
- La barra de progreso indica que el proceso está en ejecución
5. **✅ Verificar Resultados**
- Al completarse, verás un mensaje de éxito
- Opción para abrir automáticamente el directorio de destino
## 🔧 Funcionamiento Interno
El script GUI internamente:
1. **Valida** las selecciones del usuario
2. **Ejecuta** `x0_main.py` en modo simple con los parámetros:
```bash
python x0_main.py --source-xml "archivo.xml" --dest-scl "destino/archivo.scl"
```
3. **Captura** la salida del proceso en tiempo real
4. **Muestra** los resultados de manera amigable
## 📋 Requisitos
- **Python 3.x** con tkinter (incluido en la mayoría de instalaciones)
- **x0_main.py** funcional con modo simple implementado
- **Sistema operativo Windows** (para cuadros de diálogo nativos)
## 🆚 Comparación con Otros Modos
| Modo | Comando | Uso Recomendado |
|------|---------|-----------------|
| **GUI (x8)** | `python x8_manual_gui.py` | 🎯 **Usuario final, conversiones manuales** |
| **Simple** | `python x0_main.py --source-xml file.xml --dest-scl file.scl` | 🔧 **Testing, desarrollo, scripts** |
| **PLC** | `python x0_main.py --plc-dir /path/to/plc` | 🏭 **Procesamiento de proyecto completo** |
| **Orquestador** | `python x0_main.py` | 🌐 **Procesamiento masivo multi-PLC** |
## 🎨 Capturas de Funcionalidad
### Interfaz Principal
- Sección clara para selección de archivo XML
- Área dedicada para directorio de destino
- Nombre de archivo auto-generado
- Botón prominente de conversión
### Área de Progreso
- Barra de progreso animada
- Log en tiempo real con timestamps
- Colores distintivos para diferentes tipos de mensajes
- Scroll automático para seguir el progreso
### Diálogos de Resultado
- **Éxito**: Confirmación con opción de abrir directorio
- **Error**: Detalles claros del problema encontrado
## 🚨 Solución de Problemas
### El script no inicia
- Verificar que Python tenga tkinter instalado
- Ejecutar desde el directorio correcto
### Error "x0_main.py no encontrado"
- Asegurarse de que `x0_main.py` esté en el mismo directorio
- Verificar permisos de archivo
### La conversión falla
- Revisar los mensajes en el área de log
- Verificar que el archivo XML sea válido
- Comprobar permisos de escritura en el directorio destino
## 💡 Consejos de Uso
1. **📁 Organización**: Mantén los archivos XML organizados en carpetas por proyecto
2. **🔄 Nombres**: Los nombres de archivo SCL se generan automáticamente basados en el XML
3. **📋 Log**: Revisa siempre el área de log para detalles del proceso
4. **💾 Backup**: Mantén copias de seguridad de tus archivos XML originales
5. **🔍 Verificación**: Siempre verifica el archivo SCL generado antes de usarlo en producción
---
*Creado para facilitar la conversión manual de archivos XML de Siemens TIA Portal a código SCL* 🎯

View File

@ -453,12 +453,28 @@ def reconstruct_scl_from_tokens(st_node):
scl_parts.append(access_str) scl_parts.append(access_str)
elif tag == "Comment" or tag == "LineComment": elif tag == "Comment" or tag == "LineComment":
# Usar get_multilingual_text del parser_utils # Manejar diferentes estructuras de comentarios
comment_text = get_multilingual_text(elem) if tag == "LineComment":
if tag == "Comment": # LineComment tiene estructura <Text> directa, no MultilingualText
scl_parts.append(f"(* {comment_text} *)") text_elem = elem.xpath("./st:Text", namespaces=ns)
if not text_elem:
text_elem = elem.xpath("./Text")
if text_elem and text_elem[0].text:
comment_text = text_elem[0].text.strip()
# Preservar comentarios de bloque multilinea
if "\n" in comment_text:
# Comentario multilinea: usar formato (* ... *)
scl_parts.append(f"(* {comment_text} *)")
else:
# Comentario de línea simple
scl_parts.append(f"// {comment_text}")
else:
scl_parts.append("// [Comentario vacío]")
else: else:
scl_parts.append(f"// {comment_text}") # Comment tradicional: usar get_multilingual_text
comment_text = get_multilingual_text(elem)
scl_parts.append(f"(* {comment_text} *)")
# Ignorar otros tipos de nodos si no son relevantes para el SCL # Ignorar otros tipos de nodos si no son relevantes para el SCL
full_scl = "".join(scl_parts) full_scl = "".join(scl_parts)
@ -467,6 +483,8 @@ def reconstruct_scl_from_tokens(st_node):
output_lines = [] output_lines = []
indent_level = 0 indent_level = 0
indent_str = " " # Dos espacios indent_str = " " # Dos espacios
case_indent_level = 0 # Nivel especial para manejar CASE statements
for line in full_scl.splitlines(): for line in full_scl.splitlines():
trimmed_line = line.strip() trimmed_line = line.strip()
if not trimmed_line: if not trimmed_line:
@ -474,28 +492,58 @@ def reconstruct_scl_from_tokens(st_node):
# output_lines.append("") # output_lines.append("")
continue continue
# Reducir indentación ANTES de imprimir para END, ELSE, etc.
if trimmed_line.upper().startswith(
("END_", "UNTIL", "}")
) or trimmed_line.upper() in ["ELSE", "ELSIF"]:
indent_level = max(0, indent_level - 1)
output_lines.append(indent_str * indent_level + trimmed_line)
# Aumentar indentación DESPUÉS de imprimir para IF, FOR, etc.
# Ser más específico con las palabras clave que aumentan indentación
# Usar .upper() para ignorar mayúsculas/minúsculas
line_upper = trimmed_line.upper() line_upper = trimmed_line.upper()
if (
line_upper.endswith(("THEN", "DO", "OF", "{")) # Detectar labels de CASE (pattern: #SomeName: o SomeName:)
or line_upper.startswith( is_case_label = (
("IF ", "FOR ", "WHILE ", "CASE ", "REPEAT", "STRUCT") ":" in trimmed_line
and (
trimmed_line.startswith("#")
or not any(
keyword in line_upper for keyword in ["IF", "ELSIF", "ELSE", "THEN"]
)
) )
or line_upper == "ELSE" and line_upper not in ["ELSE:", "ELSIF:"]
): and "//" not in trimmed_line.split(":")[0] # Evitar comentarios
)
# Reducir indentación ANTES de imprimir para ciertas palabras clave
if line_upper.startswith(("END_", "UNTIL", "}")):
indent_level = max(0, indent_level - 1)
if line_upper.startswith("END_CASE"):
case_indent_level = 0
elif line_upper in ["ELSE", "ELSIF"] and not is_case_label:
indent_level = max(0, indent_level - 1)
elif is_case_label and case_indent_level > 0:
# Los labels de case van un nivel menos indentados que el contenido del case
indent_level = max(0, case_indent_level)
# Aplicar indentación
current_indent = indent_level
if is_case_label and case_indent_level > 0:
# Los labels de case van un nivel menos que el contenido normal
current_indent = case_indent_level
output_lines.append(indent_str * current_indent + trimmed_line)
# Aumentar indentación DESPUÉS de imprimir para ciertas palabras clave
if line_upper.endswith(("THEN", "DO", "{")) or line_upper == "ELSE":
# Excepción: No indentar después de ELSE IF # Excepción: No indentar después de ELSE IF
if not (line_upper == "ELSE" and "IF" in output_lines[-1].upper()): if not (
line_upper == "ELSE"
and len(output_lines) > 0
and "IF" in output_lines[-1].upper()
):
indent_level += 1 indent_level += 1
elif line_upper.startswith(("IF ", "FOR ", "WHILE ", "REPEAT", "STRUCT")):
indent_level += 1
elif line_upper.startswith("CASE ") and line_upper.endswith(" OF"):
# Manejar CASE especialmente
case_indent_level = indent_level + 1
indent_level += 1
elif is_case_label and case_indent_level > 0:
# Después de un label de case, el contenido va un nivel más indentado
indent_level = case_indent_level + 1
return "\n".join(output_lines) return "\n".join(output_lines)

View File

@ -19,20 +19,25 @@ def get_multilingual_text(element, default_lang="en-US-it-IT", fallback_lang=Non
Extrae texto multilingüe de un elemento XML. (v5.2 - DEBUG + XPath ObjectList) Extrae texto multilingüe de un elemento XML. (v5.2 - DEBUG + XPath ObjectList)
""" """
# print(f"--- DEBUG get_multilingual_text v5.2: Iniciando para elemento {element.tag if element is not None else 'None'}, default='{default_lang}' ---") # print(f"--- DEBUG get_multilingual_text v5.2: Iniciando para elemento {element.tag if element is not None else 'None'}, default='{default_lang}' ---")
if element is None: return "" if element is None:
return ""
combined_texts = [] combined_texts = []
languages_to_try = [] languages_to_try = []
# --- Lógica Combinada --- # --- Lógica Combinada ---
is_combined_mode = default_lang and '-' in default_lang and len(default_lang.split('-')) >= 2 is_combined_mode = (
default_lang and "-" in default_lang and len(default_lang.split("-")) >= 2
)
if is_combined_mode: if is_combined_mode:
# print(f"--- DEBUG v5.2: Detectado modo combinado: '{default_lang}' ---") # print(f"--- DEBUG v5.2: Detectado modo combinado: '{default_lang}' ---")
parts = default_lang.split('-') parts = default_lang.split("-")
target_langs = [] target_langs = []
if len(parts) % 2 == 0: if len(parts) % 2 == 0:
for i in range(0, len(parts), 2): target_langs.append(f"{parts[i]}-{parts[i+1]}") for i in range(0, len(parts), 2):
else: target_langs = [] target_langs.append(f"{parts[i]}-{parts[i+1]}")
else:
target_langs = []
if target_langs: if target_langs:
# print(f"--- DEBUG v5.2: Culturas combinadas a buscar: {target_langs} ---") # print(f"--- DEBUG v5.2: Culturas combinadas a buscar: {target_langs} ---")
@ -50,7 +55,8 @@ def get_multilingual_text(element, default_lang="en-US-it-IT", fallback_lang=Non
if text_nodes: if text_nodes:
text_content = text_nodes[0].strip() text_content = text_nodes[0].strip()
# print(f" DEBUG Combinado v5.2: Texto encontrado para '{lang}': '{text_content[:50]}...'") # print(f" DEBUG Combinado v5.2: Texto encontrado para '{lang}': '{text_content[:50]}...'")
if text_content: combined_texts.append(text_content) if text_content:
combined_texts.append(text_content)
# --- FIN CORRECCIÓN XPath v5.2 --- # --- FIN CORRECCIÓN XPath v5.2 ---
if combined_texts: if combined_texts:
# print(f"--- DEBUG v5.2: Modo combinado retornando: '{' - '.join(combined_texts)}' ---") # print(f"--- DEBUG v5.2: Modo combinado retornando: '{' - '.join(combined_texts)}' ---")
@ -59,22 +65,29 @@ def get_multilingual_text(element, default_lang="en-US-it-IT", fallback_lang=Non
# print(f"--- DEBUG v5.2: Modo combinado no encontró textos. Intentando fallback... ---") # print(f"--- DEBUG v5.2: Modo combinado no encontró textos. Intentando fallback... ---")
default_lang = None default_lang = None
except Exception as e_comb: except Exception as e_comb:
print(f" Advertencia: Error procesando modo combinado '{default_lang}': {e_comb}") print(
f" Advertencia: Error procesando modo combinado '{default_lang}': {e_comb}"
)
default_lang = None default_lang = None
else: default_lang = None else:
default_lang = None
# --- Fin Lógica Combinada --- # --- Fin Lógica Combinada ---
# --- Lógica Normal / Fallback --- # --- Lógica Normal / Fallback ---
# print("--- DEBUG v5.2: Iniciando lógica Normal/Fallback ---") # print("--- DEBUG v5.2: Iniciando lógica Normal/Fallback ---")
if default_lang: languages_to_try.append(default_lang) if default_lang:
if fallback_lang: languages_to_try.append(fallback_lang) languages_to_try.append(default_lang)
if fallback_lang:
languages_to_try.append(fallback_lang)
# print(f" DEBUG v5.2: Idiomas específicos a probar: {languages_to_try}") # print(f" DEBUG v5.2: Idiomas específicos a probar: {languages_to_try}")
try: try:
if languages_to_try: if languages_to_try:
for lang in languages_to_try: for lang in languages_to_try:
# --- CORRECCIÓN XPath v5.2: Añadir ObjectList --- # --- CORRECCIÓN XPath v5.2: Añadir ObjectList ---
xpath_find_item = f"./ObjectList/MultilingualTextItem[AttributeList/Culture='{lang}']" xpath_find_item = (
f"./ObjectList/MultilingualTextItem[AttributeList/Culture='{lang}']"
)
found_items = element.xpath(xpath_find_item, namespaces=ns) found_items = element.xpath(xpath_find_item, namespaces=ns)
# print(f" DEBUG Fallback v5.2: Items encontrados para '{lang}': {len(found_items)}") # print(f" DEBUG Fallback v5.2: Items encontrados para '{lang}': {len(found_items)}")
if found_items: if found_items:
@ -91,14 +104,14 @@ def get_multilingual_text(element, default_lang="en-US-it-IT", fallback_lang=Non
# Fallback final: buscar cualquier texto no vacío # Fallback final: buscar cualquier texto no vacío
# print(" DEBUG v5.2: Probando cualquier idioma con texto no vacío...") # print(" DEBUG v5.2: Probando cualquier idioma con texto no vacío...")
xpath_any_text = "./ObjectList/MultilingualTextItem/AttributeList/Text/text()" # .// busca en cualquier nivel xpath_any_text = "./ObjectList/MultilingualTextItem/AttributeList/Text/text()" # .// busca en cualquier nivel
all_text_nodes = element.xpath(xpath_any_text, namespaces=ns) all_text_nodes = element.xpath(xpath_any_text, namespaces=ns)
# print(f" DEBUG Fallback Any v5.2: Nodos de texto encontrados: {len(all_text_nodes)}") # print(f" DEBUG Fallback Any v5.2: Nodos de texto encontrados: {len(all_text_nodes)}")
for text_content_raw in all_text_nodes: for text_content_raw in all_text_nodes:
text_content = text_content_raw.strip() text_content = text_content_raw.strip()
if text_content: if text_content:
# print(f"--- DEBUG v5.2: Fallback 'Any' retornando texto: '{text_content}' ---") # print(f"--- DEBUG v5.2: Fallback 'Any' retornando texto: '{text_content}' ---")
return text_content return text_content
# print("--- DEBUG v5.2: No se encontró ningún texto no vacío. Retornando '' ---") # print("--- DEBUG v5.2: No se encontró ningún texto no vacío. Retornando '' ---")
return "" return ""
@ -110,19 +123,76 @@ def get_multilingual_text(element, default_lang="en-US-it-IT", fallback_lang=Non
def get_symbol_name(symbol_element): def get_symbol_name(symbol_element):
"""Obtiene el nombre completo de un símbolo desde un elemento <flg:Symbol>.""" """Obtiene el nombre completo de un símbolo desde un elemento <flg:Symbol>, incluyendo índices de arrays."""
if symbol_element is None: if symbol_element is None:
return None return None
try: try:
components = symbol_element.xpath("./flg:Component/@Name", namespaces=ns) # Obtener todos los elementos Component
return ( component_elements = symbol_element.xpath("./flg:Component", namespaces=ns)
".".join(
f'"{c}"' if not c.startswith("#") and '"' not in c else c if not component_elements:
for c in components # Fallback al método anterior si no se encuentran elementos Component
components = symbol_element.xpath("./flg:Component/@Name", namespaces=ns)
return (
".".join(
f'"{c}"' if not c.startswith("#") and '"' not in c else c
for c in components
)
if components
else None
) )
if components
else None symbol_parts = []
)
for i, comp in enumerate(component_elements):
comp_name = comp.get("Name", "_ERR_COMP_NAME_")
# Añadir separador de punto si no es el primer componente
if i > 0:
symbol_parts.append(".")
# Formatear el nombre del componente
if not comp_name.startswith("#") and '"' not in comp_name:
symbol_parts.append(f'"{comp_name}"')
else:
symbol_parts.append(comp_name)
# Buscar accesos de array dentro del componente
# Buscar tanto con namespace flg: como sin namespace
access_elements = comp.xpath("./flg:Access", namespaces=ns)
if not access_elements:
access_elements = comp.xpath("./Access")
if access_elements:
indices_parts = []
for access_elem in access_elements:
access_scope = access_elem.get("Scope")
if access_scope == "LiteralConstant":
# Buscar el valor de la constante
const_elem = access_elem.xpath("./flg:Constant", namespaces=ns)
if not const_elem:
const_elem = access_elem.xpath("./Constant")
if const_elem:
val_elem = const_elem[0].xpath(
"./flg:ConstantValue", namespaces=ns
)
if not val_elem:
val_elem = const_elem[0].xpath("./ConstantValue")
if val_elem and val_elem[0].text:
indices_parts.append(val_elem[0].text.strip())
else:
# Para otros tipos de acceso, podríamos implementar lógica adicional
# Por ahora, añadir un marcador de error
indices_parts.append(f"/*_ERR_COMPLEX_INDEX_{access_scope}_*/")
if indices_parts:
symbol_parts.append(f"[{','.join(indices_parts)}]")
return "".join(symbol_parts) if symbol_parts else None
except Exception as e: except Exception as e:
print(f"Advertencia: Excepción en get_symbol_name: {e}") print(f"Advertencia: Excepción en get_symbol_name: {e}")
return None return None
@ -142,7 +212,9 @@ def parse_access(access_element):
if address_elem: if address_elem:
addr = address_elem[0] addr = address_elem[0]
# Extraer toda la información disponible sobre la dirección # Extraer toda la información disponible sobre la dirección
info["type"] = "unknown_structure" # Mantener compatible con el código existente info["type"] = (
"unknown_structure" # Mantener compatible con el código existente
)
info["Area"] = addr.get("Area", "DB") info["Area"] = addr.get("Area", "DB")
info["BitOffset"] = addr.get("BitOffset", "0") info["BitOffset"] = addr.get("BitOffset", "0")
info["BlockNumber"] = addr.get("BlockNumber", "") info["BlockNumber"] = addr.get("BlockNumber", "")
@ -262,6 +334,7 @@ def parse_access(access_element):
info["type"] = "error_no_name" info["type"] = "error_no_name"
return info return info
def parse_part(part_element): def parse_part(part_element):
"""Parsea un nodo <flg:Part> de LAD/FBD.""" """Parsea un nodo <flg:Part> de LAD/FBD."""
if part_element is None: if part_element is None:
@ -279,7 +352,9 @@ def parse_part(part_element):
for tv in part_element.xpath("./flg:TemplateValue", namespaces=ns): for tv in part_element.xpath("./flg:TemplateValue", namespaces=ns):
tv_name = tv.get("Name") tv_name = tv.get("Name")
tv_type = tv.get("Type") tv_type = tv.get("Type")
tv_value = tv.text.strip() if tv.text else tv_type # Obtener valor real del elemento tv_value = (
tv.text.strip() if tv.text else tv_type
) # Obtener valor real del elemento
if tv_name: if tv_name:
template_values[tv_name] = tv_value template_values[tv_name] = tv_value
except Exception as e: except Exception as e:
@ -480,8 +555,10 @@ def parse_interface_members(member_elements):
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 --- # --- NUEVA FUNCIÓN: Adaptación dinámica de namespaces ---
def adapt_namespaces(root): def adapt_namespaces(root):
"""Actualiza dinámicamente los valores en el diccionario global `ns` para que """Actualiza dinámicamente los valores en el diccionario global `ns` para que
coincidan con los namespaces reales presentes en el XML exportado por TIA. coincidan con los namespaces reales presentes en el XML exportado por TIA.
@ -540,6 +617,7 @@ def adapt_namespaces(root):
# --- función auxiliar privada para adapt_namespaces --- # --- función auxiliar privada para adapt_namespaces ---
def _assign_uri_to_prefix(uri_str: str, out_dict: dict): def _assign_uri_to_prefix(uri_str: str, out_dict: dict):
"""Asigna un URI concreto al prefijo adecuado en `out_dict`.""" """Asigna un URI concreto al prefijo adecuado en `out_dict`."""
if "/Interface/" in uri_str: if "/Interface/" in uri_str:

View File

@ -0,0 +1,47 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Script de prueba para verificar que los índices de arrays se capturen correctamente en LAD/FBD."""
import os
import sys
# Añadir el directorio padre al path para los imports
sys.path.insert(0, os.path.dirname(__file__))
from x1_to_json import convert_xml_to_json
if __name__ == "__main__":
xml_file = ".example/FC TT Devices.xml"
json_file = ".example/FC_TT_Devices_test.json"
print(f"Probando conversión de {xml_file} a {json_file}...")
try:
success = convert_xml_to_json(xml_file, json_file)
if success:
print("Conversión exitosa!")
# Buscar patrones de arrays en el JSON generado
with open(json_file, "r", encoding="utf-8") as f:
content = f.read()
# Buscar di0.x con índices
if '"di0.x"[1]' in content:
print(
"✅ ÉXITO: Se encontró di0.x[1] - los índices de arrays se están capturando correctamente!"
)
elif '"di0.x"[]' in content:
print("❌ PROBLEMA: Se encontró di0.x[] - los índices están vacíos")
elif '"di0.x"' in content:
print(
"❌ PROBLEMA: Se encontró di0.x sin índices - el fix no está funcionando"
)
else:
print("⚠️ No se encontró di0.x en el contenido")
else:
print("Error en la conversión")
except Exception as e:
print(f"Error: {e}")
import traceback
traceback.print_exc()

View File

@ -1,435 +1,145 @@
""" """
x8_manual_gui.py - Interfaz Manual con GUI para XMLSCL x8_manual_gui.py - Wrapper Simple para XMLSCL
Este script proporciona una interfaz gráfica simple para convertir archivos XML Este script es un wrapper simple que:
de Siemens TIA Portal a código SCL usando cuadros de diálogo de Windows. 1. Abre un cuadro de diálogo para seleccionar archivo XML
2. Abre un cuadro de diálogo para seleccionar directorio de destino
3. Ejecuta automáticamente x0_main.py en modo simple
Funcionalidad: No requiere GUI compleja, solo usa los cuadros de diálogo nativos de Windows.
- Cuadro de diálogo para seleccionar archivo XML de origen
- Cuadro de diálogo para seleccionar directorio de destino
- Ejecuta automáticamente x0_main.py en modo simple
- Interfaz amigable con mensajes de progreso
""" """
import tkinter as tk import tkinter as tk
from tkinter import filedialog, messagebox, ttk from tkinter import filedialog, messagebox
import os import os
import sys import sys
import subprocess import subprocess
import threading
import time
class XMLtoSCLConverter:
def __init__(self):
self.root = tk.Tk()
self.root.title("XML→SCL Converter - Modo Manual")
self.root.geometry("600x500")
self.root.resizable(False, False)
# Variables
self.source_xml_path = tk.StringVar()
self.dest_directory = tk.StringVar()
self.dest_filename = tk.StringVar()
# Configurar el directorio de script
self.script_dir = os.path.dirname(os.path.abspath(__file__))
self.x0_main_path = os.path.join(self.script_dir, "x0_main.py")
self.setup_ui()
def setup_ui(self):
"""Configurar la interfaz de usuario"""
# Título principal
title_frame = tk.Frame(self.root, bg="#2c3e50")
title_frame.pack(fill="x", pady=(0, 20))
title_label = tk.Label(
title_frame,
text="🔄 XML → SCL Converter",
font=("Arial", 16, "bold"),
fg="white",
bg="#2c3e50",
pady=15,
)
title_label.pack()
subtitle_label = tk.Label(
title_frame,
text="Convierte archivos XML de Siemens TIA Portal a código SCL",
font=("Arial", 10),
fg="#ecf0f1",
bg="#2c3e50",
pady=(0, 10),
)
subtitle_label.pack()
# Frame principal
main_frame = tk.Frame(self.root)
main_frame.pack(fill="both", expand=True, padx=20)
# Sección 1: Selección de archivo XML
xml_frame = tk.LabelFrame(
main_frame,
text=" 📄 Archivo XML de Origen ",
font=("Arial", 11, "bold"),
pady=10,
)
xml_frame.pack(fill="x", pady=(0, 15))
xml_info_label = tk.Label(
xml_frame,
text="Selecciona el archivo XML de Siemens TIA Portal que deseas convertir:",
font=("Arial", 9),
fg="#34495e",
)
xml_info_label.pack(anchor="w", padx=10, pady=(0, 5))
xml_entry_frame = tk.Frame(xml_frame)
xml_entry_frame.pack(fill="x", padx=10, pady=(0, 10))
self.xml_entry = tk.Entry(
xml_entry_frame,
textvariable=self.source_xml_path,
font=("Arial", 9),
state="readonly",
bg="#ecf0f1",
)
self.xml_entry.pack(side="left", fill="x", expand=True, padx=(0, 10))
xml_browse_btn = tk.Button(
xml_entry_frame,
text="📁 Examinar...",
command=self.browse_xml_file,
bg="#3498db",
fg="white",
font=("Arial", 9, "bold"),
relief="flat",
padx=15,
)
xml_browse_btn.pack(side="right")
# Sección 2: Selección de directorio de salida
dest_frame = tk.LabelFrame(
main_frame,
text=" 📂 Directorio de Destino ",
font=("Arial", 11, "bold"),
pady=10,
)
dest_frame.pack(fill="x", pady=(0, 15))
dest_info_label = tk.Label(
dest_frame,
text="Selecciona el directorio donde se guardará el archivo SCL generado:",
font=("Arial", 9),
fg="#34495e",
)
dest_info_label.pack(anchor="w", padx=10, pady=(0, 5))
dest_entry_frame = tk.Frame(dest_frame)
dest_entry_frame.pack(fill="x", padx=10, pady=(0, 10))
self.dest_entry = tk.Entry(
dest_entry_frame,
textvariable=self.dest_directory,
font=("Arial", 9),
state="readonly",
bg="#ecf0f1",
)
self.dest_entry.pack(side="left", fill="x", expand=True, padx=(0, 10))
dest_browse_btn = tk.Button(
dest_entry_frame,
text="📁 Examinar...",
command=self.browse_dest_directory,
bg="#e67e22",
fg="white",
font=("Arial", 9, "bold"),
relief="flat",
padx=15,
)
dest_browse_btn.pack(side="right")
# Sección 3: Nombre del archivo de salida
filename_frame = tk.LabelFrame(
main_frame,
text=" 📝 Nombre del Archivo SCL ",
font=("Arial", 11, "bold"),
pady=10,
)
filename_frame.pack(fill="x", pady=(0, 15))
filename_info_label = tk.Label(
filename_frame,
text="Nombre del archivo SCL de salida (se generará automáticamente):",
font=("Arial", 9),
fg="#34495e",
)
filename_info_label.pack(anchor="w", padx=10, pady=(0, 5))
self.filename_entry = tk.Entry(
filename_frame,
textvariable=self.dest_filename,
font=("Arial", 9),
state="readonly",
bg="#f8f9fa",
)
self.filename_entry.pack(fill="x", padx=10, pady=(0, 10))
# Botón de conversión
convert_btn = tk.Button(
main_frame,
text="🚀 Convertir XML → SCL",
command=self.start_conversion,
bg="#27ae60",
fg="white",
font=("Arial", 12, "bold"),
relief="flat",
pady=10,
state="disabled",
)
convert_btn.pack(fill="x", pady=20)
self.convert_btn = convert_btn
# Área de progreso y resultados
progress_frame = tk.LabelFrame(
main_frame, text=" 📊 Progreso ", font=("Arial", 11, "bold")
)
progress_frame.pack(fill="both", expand=True, pady=(0, 20))
# Barra de progreso
self.progress_bar = ttk.Progressbar(
progress_frame, mode="indeterminate", length=300
)
self.progress_bar.pack(pady=10)
# Área de mensajes
self.log_text = tk.Text(
progress_frame,
height=8,
font=("Consolas", 9),
bg="#2c3e50",
fg="#ecf0f1",
state="disabled",
wrap="word",
)
self.log_text.pack(fill="both", expand=True, padx=10, pady=(0, 10))
# Scrollbar para el área de mensajes
scrollbar = tk.Scrollbar(self.log_text)
scrollbar.pack(side="right", fill="y")
self.log_text.config(yscrollcommand=scrollbar.set)
scrollbar.config(command=self.log_text.yview)
# Vincular eventos para actualizar botón de conversión
self.source_xml_path.trace("w", self.update_convert_button)
self.dest_directory.trace("w", self.update_convert_button)
def log_message(self, message, color="#ecf0f1"):
"""Agregar mensaje al área de log"""
self.log_text.config(state="normal")
timestamp = time.strftime("%H:%M:%S")
self.log_text.insert("end", f"[{timestamp}] {message}\n")
self.log_text.config(state="disabled")
self.log_text.see("end") # Scroll automático
self.root.update()
def browse_xml_file(self):
"""Abrir cuadro de diálogo para seleccionar archivo XML"""
filename = filedialog.askopenfilename(
title="Seleccionar archivo XML de Siemens TIA Portal",
filetypes=[("Archivos XML", "*.xml"), ("Todos los archivos", "*.*")],
initialdir=self.script_dir,
)
if filename:
self.source_xml_path.set(filename)
# Generar nombre de archivo de salida automáticamente
base_name = os.path.splitext(os.path.basename(filename))[0]
self.dest_filename.set(f"{base_name}.scl")
self.log_message(
f"✓ Archivo XML seleccionado: {os.path.basename(filename)}"
)
def browse_dest_directory(self):
"""Abrir cuadro de diálogo para seleccionar directorio de destino"""
directory = filedialog.askdirectory(
title="Seleccionar directorio de destino", initialdir=self.script_dir
)
if directory:
self.dest_directory.set(directory)
self.log_message(f"✓ Directorio de destino seleccionado: {directory}")
def update_convert_button(self, *args):
"""Actualizar estado del botón de conversión"""
if self.source_xml_path.get() and self.dest_directory.get():
self.convert_btn.config(state="normal")
else:
self.convert_btn.config(state="disabled")
def start_conversion(self):
"""Iniciar proceso de conversión en un hilo separado"""
# Deshabilitar botón durante conversión
self.convert_btn.config(state="disabled", text="🔄 Convirtiendo...")
self.progress_bar.start()
# Ejecutar conversión en hilo separado para no bloquear UI
conversion_thread = threading.Thread(target=self.run_conversion)
conversion_thread.daemon = True
conversion_thread.start()
def run_conversion(self):
"""Ejecutar el proceso de conversión"""
try:
# Preparar rutas
source_xml = self.source_xml_path.get()
dest_dir = self.dest_directory.get()
dest_filename = self.dest_filename.get()
dest_scl = os.path.join(dest_dir, dest_filename)
self.log_message("=" * 50)
self.log_message("🚀 INICIANDO CONVERSIÓN XML → SCL")
self.log_message("=" * 50)
self.log_message(f"📄 Archivo origen: {os.path.basename(source_xml)}")
self.log_message(f"📂 Destino: {dest_scl}")
self.log_message("")
# Verificar que x0_main.py existe
if not os.path.exists(self.x0_main_path):
raise FileNotFoundError(
f"No se encontró x0_main.py en: {self.x0_main_path}"
)
# Ejecutar x0_main.py en modo simple
self.log_message("🔧 Ejecutando convertidor...")
cmd = [
sys.executable,
self.x0_main_path,
"--source-xml",
source_xml,
"--dest-scl",
dest_scl,
]
# Ejecutar proceso
process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
encoding="utf-8",
cwd=self.script_dir,
)
# Leer salida línea por línea
while True:
output = process.stdout.readline()
if output == "" and process.poll() is not None:
break
if output:
self.log_message(output.strip())
# Obtener código de salida
return_code = process.poll()
# Leer errores si los hay
stderr_output = process.stderr.read()
if stderr_output:
self.log_message("⚠️ ADVERTENCIAS/ERRORES:")
for line in stderr_output.strip().split("\n"):
if line.strip():
self.log_message(f" {line.strip()}")
# Verificar resultado
if return_code == 0 and os.path.exists(dest_scl):
self.log_message("")
self.log_message("=" * 50)
self.log_message("✅ CONVERSIÓN COMPLETADA EXITOSAMENTE")
self.log_message("=" * 50)
self.log_message(f"📁 Archivo generado: {dest_scl}")
# Preguntar si abrir el directorio
self.root.after(0, self.show_success_dialog, dest_scl)
else:
self.log_message("")
self.log_message("=" * 50)
self.log_message("❌ ERROR EN LA CONVERSIÓN")
self.log_message("=" * 50)
self.root.after(
0,
self.show_error_dialog,
"La conversión falló. Revisa los mensajes de error arriba.",
)
except Exception as e:
self.log_message(f"❌ ERROR INESPERADO: {str(e)}")
self.root.after(0, self.show_error_dialog, f"Error inesperado: {str(e)}")
finally:
# Restaurar UI
self.root.after(0, self.restore_ui)
def restore_ui(self):
"""Restaurar estado de la UI después de conversión"""
self.progress_bar.stop()
self.convert_btn.config(state="normal", text="🚀 Convertir XML → SCL")
def show_success_dialog(self, dest_scl):
"""Mostrar diálogo de éxito"""
result = messagebox.askyesno(
"Conversión Exitosa",
f"✅ La conversión se completó exitosamente.\n\n"
f"Archivo generado:\n{dest_scl}\n\n"
f"¿Deseas abrir el directorio de destino?",
icon="question",
)
if result:
# Abrir directorio en el explorador de Windows
dest_dir = os.path.dirname(dest_scl)
os.startfile(dest_dir)
def show_error_dialog(self, error_message):
"""Mostrar diálogo de error"""
messagebox.showerror(
"Error en Conversión",
f"❌ Error durante la conversión:\n\n{error_message}\n\n"
f"Revisa los mensajes de log para más detalles.",
)
def run(self):
"""Ejecutar la aplicación"""
# Mensaje inicial
self.log_message("🎯 XML→SCL Converter iniciado")
self.log_message(
"👆 Selecciona un archivo XML y directorio de destino para comenzar"
)
# Centrar ventana
self.root.eval("tk::PlaceWindow . center")
# Iniciar loop principal
self.root.mainloop()
def main(): def main():
"""Función principal""" """Función principal - Solo cuadros de diálogo y ejecución"""
# Configurar el directorio de script
script_dir = os.path.dirname(os.path.abspath(__file__))
x0_main_path = os.path.join(script_dir, "x0_main.py")
# Verificar que x0_main.py existe
if not os.path.exists(x0_main_path):
print(f"Error: No se encontró x0_main.py en: {x0_main_path}", file=sys.stderr)
sys.exit(1)
print("=== XML -> SCL Converter ===")
print("Selecciona el archivo XML y directorio de destino...")
print()
# Crear ventana oculta para los cuadros de diálogo
root = tk.Tk()
root.withdraw() # Ocultar la ventana principal
try: try:
# Verificar que tkinter esté disponible # 1. Seleccionar archivo XML
app = XMLtoSCLConverter() print("1. Seleccionando archivo XML...")
app.run() source_xml = filedialog.askopenfilename(
except ImportError: title="Seleccionar archivo XML de Siemens TIA Portal",
print( filetypes=[("Archivos XML", "*.xml"), ("Todos los archivos", "*.*")],
"Error: tkinter no está disponible. Este script requiere una instalación de Python con tkinter.", initialdir=script_dir,
file=sys.stderr, )
if not source_xml:
print("Operación cancelada por el usuario.")
sys.exit(0)
print(f" Archivo seleccionado: {os.path.basename(source_xml)}")
# 2. Seleccionar directorio de destino
print("2. Seleccionando directorio de destino...")
dest_dir = filedialog.askdirectory(
title="Seleccionar directorio de destino", initialdir=script_dir
)
if not dest_dir:
print("Operación cancelada por el usuario.")
sys.exit(0)
print(f" Directorio seleccionado: {dest_dir}")
# 3. Generar nombre de archivo de salida
base_name = os.path.splitext(os.path.basename(source_xml))[0]
dest_filename = f"{base_name}.scl"
dest_scl = os.path.join(dest_dir, dest_filename)
print(f"3. Archivo de salida: {dest_filename}")
print()
# 4. Confirmar operación
confirm = messagebox.askyesno(
"Confirmar Conversión",
f"¿Convertir el archivo?\n\n"
f"Origen: {os.path.basename(source_xml)}\n"
f"Destino: {dest_scl}\n\n"
f"¿Continuar?",
)
if not confirm:
print("Operación cancelada por el usuario.")
sys.exit(0)
# 5. Ejecutar conversión
print("4. Ejecutando conversión...")
print("=" * 50)
cmd = [
sys.executable,
x0_main_path,
"--source-xml",
source_xml,
"--dest-scl",
dest_scl,
]
# Ejecutar proceso
result = subprocess.run(
cmd,
cwd=script_dir,
capture_output=False, # Mostrar salida en tiempo real
text=True,
)
# 6. Verificar resultado
print("=" * 50)
if result.returncode == 0 and os.path.exists(dest_scl):
print("✅ CONVERSIÓN COMPLETADA EXITOSAMENTE")
print(f"📁 Archivo generado: {dest_scl}")
# Preguntar si abrir el directorio
open_dir = messagebox.askyesno(
"Conversión Exitosa",
f"La conversión se completó exitosamente.\n\n"
f"Archivo generado:\n{dest_scl}\n\n"
f"¿Deseas abrir el directorio de destino?",
)
if open_dir:
os.startfile(dest_dir)
else:
print("❌ ERROR EN LA CONVERSIÓN")
print("Revisa los mensajes de error arriba.")
messagebox.showerror(
"Error en Conversión",
"La conversión falló. Revisa los mensajes de error en la consola.",
)
except Exception as e:
print(f"❌ ERROR INESPERADO: {e}")
messagebox.showerror(
"Error Inesperado", f"Error inesperado durante la conversión:\n{e}"
) )
sys.exit(1) sys.exit(1)
except Exception as e:
print(f"Error inesperado: {e}", file=sys.stderr) finally:
sys.exit(1) # Cerrar la ventana oculta
root.destroy()
if __name__ == "__main__": if __name__ == "__main__":

29959
data/log.txt

File diff suppressed because it is too large Load Diff