Cambio a busqueda de XML bajo el directorio XML Project

This commit is contained in:
Miguel 2025-04-20 02:52:26 +02:00
parent 4e3aba9a2a
commit 5213d09bcf
31 changed files with 854 additions and 29273 deletions

2
.gitignore vendored
View File

@ -8,6 +8,8 @@ __pycache__/
# Distribution / packaging
.Python
XML Project/
XML Proyect/
build/
develop-eggs/
dist/

View File

@ -1,105 +0,0 @@
FUNCTION "BlenderCtrl_MFM Command" : Void
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : 'Author'
FAMILY : TASK2
NAME : 'Name'
VERSION : 1.0
VAR_INPUT
mResetWaterTot : Bool;
mResetSyrupTot : Bool;
mResetCO2Tot : Bool;
mResetProductTot : Bool;
END_VAR
VAR_TEMP
mWaterVFMCtrl : Int;
mSyrupMFMCtrl : Int;
mCO2MFMCtrl : Int;
mProductMFMCtrl : Int;
END_VAR
BEGIN
IF #mResetWaterTot THEN
#mWaterVFMCtrl := 1 ;
ELSE
#mWaterVFMCtrl := 0 ;
END_IF;
IF #mResetSyrupTot THEN
#mSyrupMFMCtrl := 1 ;
ELSE
#mSyrupMFMCtrl := 0 ;
END_IF;
IF #mResetCO2Tot THEN
#mCO2MFMCtrl := 1 ;
ELSE
#mCO2MFMCtrl := 0 ;
END_IF;
IF #mResetProductTot THEN
#mProductMFMCtrl := 1 ;
ELSE
#mProductMFMCtrl := 0 ;
END_IF;
CASE #mWaterVFMCtrl OF
1: "P_FTN301_Tot_Ctrl" := 01; // Reset Totalizer
2: "P_FTN301_Tot_Ctrl" := 02 ; // Preset Totalizer
ELSE:
"P_FTN301_Tot_Ctrl" := 00;
END_CASE;
IF "gSyrupRoomEn" THEN
CASE #mSyrupMFMCtrl OF
1: "P_FTP302_Tot_Ctrl" := 01; (* Reset Totalizer 1*)
2: "P_FTP302_Tot_Ctrl" := 02; (* Reset Totalizer 2*)
3: "P_FTP302_Tot_Ctrl" := 03; (* Reset Totalizer 1 & 2*)
4: "P_FTP302_Tot_Ctrl" := 04; (* Zeropoint Adjust *)
5: "P_FTP302_Tot_Ctrl" := 05; (* Positive Zero Return *)
6: "P_FTP302_Tot_Ctrl" := 06; (* Negative Zero Return *)
ELSE:
"P_FTP302_Tot_Ctrl" := 00;
END_CASE;
END_IF;
CASE #mCO2MFMCtrl OF
1: "P_FTM303_Tot_Ctrl" := 01; (* Reset Totalizer 1*)
2: "P_FTM303_Tot_Ctrl" := 02; (* Reset Totalizer 2 *)
3: "P_FTM303_Tot_Ctrl" := 03; (* Reset Totalizer 1 & 2*)
4: "P_FTM303_Tot_Ctrl" := 04; (* Zeropoint Adjust *)
5: "P_FTM303_Tot_Ctrl" := 05; (* Positive Zero Return *)
6: "P_FTM303_Tot_Ctrl" := 06; (* Negative Zero Return *)
ELSE:
"P_FTM303_Tot_Ctrl" := 00;
END_CASE;
(*CASE mProductMFMCtrl OF
1: gProductTotCtrl_Node17 := 01; (* Reset Totalizer 1*)
2: gProductTotCtrl_Node17 := 02 ; (* Preset Totalizer1 *)
ELSE
gProductTotCtrl_Node17 := 00;
END_CASE;*)
END_FUNCTION

View File

@ -1,477 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Document>
<Engineering version="V18" />
<SW.Blocks.FC ID="0">
<AttributeList>
<AutoNumber>false</AutoNumber>
<HeaderFamily>TASK2</HeaderFamily>
<Interface><Sections xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v5">
<Section Name="Input" />
<Section Name="Output" />
<Section Name="InOut" />
<Section Name="Temp" />
<Section Name="Constant" />
<Section Name="Return">
<Member Name="Ret_Val" Datatype="Void" />
</Section>
</Sections></Interface>
<MemoryLayout>Standard</MemoryLayout>
<Name>BlenderCtrl_ProdModeInit</Name>
<Namespace />
<Number>2012</Number>
<ProgrammingLanguage>LAD</ProgrammingLanguage>
<SetENOAutomatically>false</SetENOAutomatically>
</AttributeList>
<ObjectList>
<MultilingualText ID="1" CompositionName="Comment">
<ObjectList>
<MultilingualTextItem ID="2" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="3" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="4" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="5" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="6" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="7" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="8" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
<SW.Blocks.CompileUnit ID="9" CompositionName="CompileUnits">
<AttributeList>
<NetworkSource><FlgNet xmlns="http://www.siemens.com/automation/Openness/SW/NetworkSource/FlgNet/v4">
<Parts>
<Call UId="21">
<CallInfo Name="BlenderPID_PIDResInteg" BlockType="FC" />
</Call>
</Parts>
<Wires>
<Wire UId="22">
<Powerrail />
<NameCon UId="21" Name="en" />
</Wire>
</Wires>
</FlgNet></NetworkSource>
<ProgrammingLanguage>LAD</ProgrammingLanguage>
</AttributeList>
<ObjectList>
<MultilingualText ID="A" CompositionName="Comment">
<ObjectList>
<MultilingualTextItem ID="B" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="C" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="D" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="E" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="F" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="10" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="11" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
<MultilingualText ID="12" CompositionName="Title">
<ObjectList>
<MultilingualTextItem ID="13" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text>PID Reset Integral</Text>
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="14" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="15" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="16" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="17" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="18" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="19" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
</ObjectList>
</SW.Blocks.CompileUnit>
<SW.Blocks.CompileUnit ID="1A" CompositionName="CompileUnits">
<AttributeList>
<NetworkSource><FlgNet xmlns="http://www.siemens.com/automation/Openness/SW/NetworkSource/FlgNet/v4">
<Parts>
<Call UId="21">
<CallInfo Name="BlenderCtrl_InitErrors" BlockType="FC" />
</Call>
</Parts>
<Wires>
<Wire UId="22">
<Powerrail />
<NameCon UId="21" Name="en" />
</Wire>
</Wires>
</FlgNet></NetworkSource>
<ProgrammingLanguage>LAD</ProgrammingLanguage>
</AttributeList>
<ObjectList>
<MultilingualText ID="1B" CompositionName="Comment">
<ObjectList>
<MultilingualTextItem ID="1C" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="1D" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="1E" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="1F" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="20" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="21" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="22" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
<MultilingualText ID="23" CompositionName="Title">
<ObjectList>
<MultilingualTextItem ID="24" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text>Ctrl Init Errors</Text>
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="25" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="26" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="27" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="28" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="29" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="2A" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
</ObjectList>
</SW.Blocks.CompileUnit>
<SW.Blocks.CompileUnit ID="2B" CompositionName="CompileUnits">
<AttributeList>
<NetworkSource><FlgNet xmlns="http://www.siemens.com/automation/Openness/SW/NetworkSource/FlgNet/v4">
<Parts>
<Access Scope="LiteralConstant" UId="21">
<Constant>
<ConstantType>Real</ConstantType>
<ConstantValue>0.0</ConstantValue>
</Constant>
</Access>
<Access Scope="GlobalVariable" UId="22">
<Symbol>
<Component Name="HMI_Variables_Status" />
<Component Name="Analog_Values" />
<Component Name="TP301RunOutCount" />
</Symbol>
</Access>
<Part Name="Move" UId="23" DisabledENO="false">
<TemplateValue Name="Card" Type="Cardinality">1</TemplateValue>
</Part>
</Parts>
<Wires>
<Wire UId="24">
<IdentCon UId="21" />
<NameCon UId="23" Name="in" />
</Wire>
<Wire UId="25">
<NameCon UId="23" Name="out1" />
<IdentCon UId="22" />
</Wire>
<Wire UId="26">
<Powerrail />
<NameCon UId="23" Name="en" />
</Wire>
</Wires>
</FlgNet></NetworkSource>
<ProgrammingLanguage>LAD</ProgrammingLanguage>
</AttributeList>
<ObjectList>
<MultilingualText ID="2C" CompositionName="Comment">
<ObjectList>
<MultilingualTextItem ID="2D" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="2E" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="2F" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="30" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="31" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="32" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="33" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
<MultilingualText ID="34" CompositionName="Title">
<ObjectList>
<MultilingualTextItem ID="35" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text>RunOut Counter</Text>
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="36" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="37" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="38" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="39" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="3A" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="3B" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
</ObjectList>
</SW.Blocks.CompileUnit>
<MultilingualText ID="3C" CompositionName="Title">
<ObjectList>
<MultilingualTextItem ID="3D" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text>Prode Mode Init</Text>
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="3E" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="3F" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="40" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="41" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="42" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="43" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
</ObjectList>
</SW.Blocks.FC>
</Document>

View File

@ -1,97 +0,0 @@
{
"block_name": "BlenderCtrl_ProdModeInit",
"block_number": 2012,
"language": "LAD",
"block_comment": "",
"interface": {
"Return": [
{
"name": "Ret_Val",
"datatype": "Void"
}
]
},
"networks": [
{
"id": "9",
"title": "PID Reset Integral",
"comment": "",
"logic": [
{
"instruction_uid": "21",
"uid": "21",
"type": "Call",
"block_name": "BlenderPID_PIDResInteg",
"block_type": "FC",
"inputs": {
"en": {
"type": "powerrail"
}
},
"outputs": {}
}
],
"language": "LAD"
},
{
"id": "1A",
"title": "Ctrl Init Errors",
"comment": "",
"logic": [
{
"instruction_uid": "21",
"uid": "21",
"type": "Call",
"block_name": "BlenderCtrl_InitErrors",
"block_type": "FC",
"inputs": {
"en": {
"type": "powerrail"
}
},
"outputs": {}
}
],
"language": "LAD"
},
{
"id": "2B",
"title": "RunOut Counter",
"comment": "",
"logic": [
{
"instruction_uid": "23",
"uid": "23",
"type": "Move",
"template_values": {
"Card": "Cardinality"
},
"negated_pins": {},
"inputs": {
"en": {
"type": "powerrail"
},
"in": {
"uid": "21",
"scope": "LiteralConstant",
"type": "constant",
"datatype": "Real",
"value": 0.0
}
},
"outputs": {
"out1": [
{
"uid": "22",
"scope": "GlobalVariable",
"type": "variable",
"name": "\"HMI_Variables_Status\".\"Analog_Values\".\"TP301RunOutCount\""
}
]
}
}
],
"language": "LAD"
}
]
}

View File

@ -1,100 +0,0 @@
{
"block_name": "BlenderCtrl_ProdModeInit",
"block_number": 2012,
"language": "LAD",
"block_comment": "",
"interface": {
"Return": [
{
"name": "Ret_Val",
"datatype": "Void"
}
]
},
"networks": [
{
"id": "9",
"title": "PID Reset Integral",
"comment": "",
"logic": [
{
"instruction_uid": "21",
"uid": "21",
"type": "Call_FC_sympy_processed",
"block_name": "BlenderPID_PIDResInteg",
"block_type": "FC",
"inputs": {
"en": {
"type": "powerrail"
}
},
"outputs": {},
"scl": "BlenderPID_PIDResInteg();"
}
],
"language": "LAD"
},
{
"id": "1A",
"title": "Ctrl Init Errors",
"comment": "",
"logic": [
{
"instruction_uid": "21",
"uid": "21",
"type": "Call_FC_sympy_processed",
"block_name": "BlenderCtrl_InitErrors",
"block_type": "FC",
"inputs": {
"en": {
"type": "powerrail"
}
},
"outputs": {},
"scl": "BlenderCtrl_InitErrors();"
}
],
"language": "LAD"
},
{
"id": "2B",
"title": "RunOut Counter",
"comment": "",
"logic": [
{
"instruction_uid": "23",
"uid": "23",
"type": "Move_sympy_processed",
"template_values": {
"Card": "Cardinality"
},
"negated_pins": {},
"inputs": {
"en": {
"type": "powerrail"
},
"in": {
"uid": "21",
"scope": "LiteralConstant",
"type": "constant",
"datatype": "Real",
"value": 0.0
}
},
"outputs": {
"out1": [
{
"uid": "22",
"scope": "GlobalVariable",
"type": "variable",
"name": "\"HMI_Variables_Status\".\"Analog_Values\".\"TP301RunOutCount\""
}
]
},
"scl": "\"HMI_Variables_Status\".\"Analog_Values\".\"TP301RunOutCount\" := 0.0;"
}
],
"language": "LAD"
}
]
}

View File

@ -1,30 +0,0 @@
// Block Name (Original): BlenderCtrl_ProdModeInit
// Block Number: 2012
// Original Language: LAD
FUNCTION_BLOCK "BlenderCtrl_ProdModeInit"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_RETURN
Ret_Val : Void;
END_VAR
VAR_TEMP
END_VAR
BEGIN
// Network 1: PID Reset Integral (Original Language: LAD)
BlenderPID_PIDResInteg();
// Network 2: Ctrl Init Errors (Original Language: LAD)
BlenderCtrl_InitErrors();
// Network 3: RunOut Counter (Original Language: LAD)
"HMI_Variables_Status"."Analog_Values"."TP301RunOutCount" := 0.0;
END_FUNCTION_BLOCK

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

View File

@ -1,365 +0,0 @@
// Block Name (Original): BlenderCtrl__Main
// Block Number: 2000
// Original Language: LAD
FUNCTION_BLOCK "BlenderCtrl__Main"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_RETURN
Ret_Val : Void;
END_VAR
VAR_TEMP
All_Auto_RETVAL : Int;
Reset_SP_Word_RETVAL : Int;
mResetWaterTot : Bool;
mResetSyrupTot : Bool;
mResetCO2Tot : Bool;
mResetProductTot : Bool;
Block_Move_Err : Int;
END_VAR
BEGIN
// Network 1: Clock Generation (Original Language: LAD)
Clock_Signal();
// Network 2: Machine Init (Original Language: LAD)
BlenderCtrl_MachineInit();
// Network 3: Filler Head (Original Language: LAD)
IF "AUX FALSE" THEN
"Block_Move_Err" := BLKMOV(SRCBLK := "HMI_PID"."PPM303", DSTBLK => "Filler_Head_Variables"."FillerHead"); // ADVERTENCIA: BLKMOV usado directamente, probablemente no compile!
END_IF;
// Network 4: Emergency Pressed (Original Language: LAD)
"gEmergencyPressed" := "M19000" AND NOT "gIN_VoltageOk";
"M19000" := "gIN_VoltageOk"; // N_TRIG("gIN_VoltageOk") - Mem: "M19000"
// Network 5: Air and CO2 pressure ok and auxiliary ok (Original Language: LAD)
"gBlenderSuppliesOk" := ("gIN_VoltageOk" AND "gIN_LinePressCO2Ok" AND "HMI_Digital"."_PAL_S11"."Filtered") OR ("gIN_VoltageOk" AND "gIN_LinePressCO2Ok" AND NOT "Disable_Bit") OR ("gIN_VoltageOk" AND "gWorkshopTest" AND "HMI_Digital"."_PAL_S11"."Filtered" AND NOT "gWorkshop_Co2_Presence" AND NOT "gWorkshop_CIP_Signals") OR ("gIN_VoltageOk" AND "gWorkshopTest" AND NOT "gWorkshop_Co2_Presence" AND NOT "gWorkshop_CIP_Signals" AND NOT "Disable_Bit");
// Network 6: Blender State Num (Original Language: LAD)
"HMI_Variables_Status"."Procedures"."BlenderStateNum" := 0;
// Network 7: Delay Power On (Original Language: LAD)
"mDelayPowerOnTmr"(IN := "FirstScan", PT := S5T#2S); // TODO: Declarar "mDelayPowerOnTmr" : TP;
// Network 8: Production Mode (Original Language: LAD)
"gBlenderProdMode" := "HMI_Variables_Status"."System"."Blender_Prod_CIP";
// Network 9: CIp Mode (Original Language: LAD)
"gBlenderCIPMode" := NOT "HMI_Variables_Status"."System"."Blender_Prod_CIP";
IF NOT "HMI_Variables_Status"."System"."Blender_Prod_CIP" THEN
"HMI_Variables_Status"."Procedures"."BlenderStateNum" := 19;
END_IF;
// Network 10: Error Faults (Original Language: LAD)
IF NOT "AUX FALSE" THEN
"HMI_Variables_Status"."Meters"."QTM3012_PRD_Fault" := FALSE;
END_IF;
IF NOT "AUX FALSE" THEN
"gmPDS2000_Error_Fault" := FALSE;
END_IF;
IF NOT "AUX FALSE" THEN
"HMI_Variables_Status"."Meters"."QTM3012_PRD_Run" := FALSE;
END_IF;
IF NOT "AUX FALSE" THEN
"gNoFreezeProductMeter" := FALSE;
END_IF;
// Network 11: Filler Bottle Count Used to push Product (Original Language: LAD)
"System_RunOut_Variables"."ProdPipeRunOutFillerBott" := NOT "System_RunOut_Variables"."ProdPipeRunOutWaterCount";
// Network 12: Water Bypass Enable (Original Language: LAD)
"gStillWaterByPassEn" := ("HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_StillWaterByPass" AND "Blender_Variables_Pers"."gWaterRecipe" AND NOT "Blender_Variables_Pers"."gCarboStillRecipe") OR ("HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_ByPassDeair" AND "Blender_Variables_Pers"."gWaterRecipe" AND NOT "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_Deaireation" AND NOT "Blender_Variables_Pers"."gCarboStillRecipe");
// Network 13: Still Water Bypass (Original Language: LAD)
"gBlendFiStillWaterByPass" := "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_StillWaterByPass" AND "Blender_Variables_Pers"."gWaterRecipe" AND "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_BlendFillSystem" AND NOT "Blender_Variables_Pers"."gCarboStillRecipe";
// Network 14: Manual Syrup Drain Valve Open - Operator Alarm (Original Language: LAD)
"gHVP301_Open" := ("gSyrupRoomEn" AND "gBlenderCIPMode" AND "gIN_CIP_CIPRunning" AND "Procedure_Variables"."Blender_Run"."Running" AND NOT "gIN_HVP301_Aux") OR ("gSyrupRoomEn" AND "Procedure_Variables"."FTP302Line_Preparation"."Done" AND NOT "gIN_HVP301_Aux" AND NOT "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_FastChangeOverEnabled" AND NOT "Procedure_Variables"."Syr_RunOut"."Done");
// Network 15: Manual Syrup Drain Valve Open - Operator Alarm (Original Language: LAD)
"mHVM302_Dly"(IN := "gIN_HVM302_Aux", PT := S5T#1S); // TODO: Declarar "mHVM302_Dly" : TON;
"gHVM302_Open" := "mHVM302_Dly".Q;
// Network 16: Maselli Control (Original Language: LAD)
IF Eq("HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_MeterType", 6) THEN
Maselli_PA_Control();
END_IF;
// Network 17: mPDS Control (Original Language: LAD)
IF Eq("HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_MeterType", 5) THEN
mPDS_PA_Control();
END_IF;
// Network 18: mPDS Syrup Control (Original Language: LAD)
IF "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_SyrBrixMeter" THEN
mPDS_SYR_PA_Control();
END_IF;
// Network 19: Co2 Analog Input (Original Language: LAD)
// GetProdBrixCO2_FromAnalogIn
// CALL "GetProdBrixCO2_FromAn"
// NOP 0
IF Eq("HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_MeterType", 3) THEN
GetProdBrixCO2_Anal_Inpt();
END_IF;
// Network 20: Quality (Original Language: LAD)
ProductQuality();
// Network 21: Input Data (Original Language: LAD)
"Input_Data"();
// Network 22: Sel Brix Source Check (Original Language: LAD)
SelCheckBrixSource();
// Network 23: Check Water Cooling System Temperature (Original Language: LAD)
IF "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_InverterRecirPumpPPM306" THEN
CTRLCoolingSystem();
END_IF;
// Network 24: Tank Level (Original Language: LAD)
TankLevel();
// Network 25: Production ONS (Original Language: LAD)
"gProductionONS" := "gBlenderProdMode" AND NOT "mDelayPowerOnTmr" AND NOT "M19001";
// Network 26: Blender Prod Mode Init (Original Language: LAD)
IF ("gProductionONS" AND NOT "Blender_Variables_Pers"."gBlenderStarted") OR ("Procedure_Variables"."Blender_Rinse"."ONS_Done" AND NOT "Blender_Variables_Pers"."gBlenderStarted") THEN
BlenderCtrl_ProdModeInit();
END_IF;
// Network 27: Rinse ONS (Original Language: LAD)
"gRinseONS" := "HMI_Variables_Status"."System"."Blender_Prod_CIP" AND NOT "mDelayPowerOnTmr" AND NOT "M19002";
// Network 28: CIP ONS (Original Language: LAD)
"gCIPONS" := "gBlenderCIPMode" AND NOT "mDelayPowerOnTmr" AND NOT "M19003";
// Network 29: CIp Mode Init (Original Language: LAD)
IF "gCIPONS" THEN
BlenderCtrl_CIPModeInit();
END_IF;
// Network 30: Reset SPWords (Original Language: LAD)
BlenderCtrl_ResetSPWord();
// Network 31: Blender Run Control (Original Language: LAD)
BlenderRun__Control();
// Network 32: Tank Pressure Control (Original Language: LAD)
Prod_Tank_PressCtrl();
// Network 33: Balaiage (Original Language: LAD)
Baialage();
// Network 34: First Production (Original Language: LAD)
"FirstProduction_Data"();
// Network 35: CIP MAIN Calling (Original Language: LAD)
CIPMain();
// Network 36: Blender Rinse (Original Language: LAD)
BlenderRinse();
// Network 37: Safeties (Original Language: LAD)
Safeties();
// Network 38: Instrument Scanner (Original Language: LAD)
Instrument_Scanner();
// Network 39: Vacuum Control (Original Language: LAD)
VacuumCtrl();
// Network 40: Syrup Room Control (Original Language: LAD)
SyrupRoomCtrl();
// Network 41: Blend Procedure Data (Original Language: LAD)
IF NOT "mDelayPowerOnTmr" THEN
"Blender_Procedure Data"();
END_IF;
// Network 42: Pneumatic Valve Control (Original Language: LAD)
Pneumatic_Valve_Ctrl();
// Network 43: Pumps Control (Original Language: LAD)
PumpsControl();
// Network 44: Prod Report Manager (Original Language: LAD)
IF "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_Report" THEN
ProdReportManager();
END_IF;
// Network 45: Outputs (Original Language: LAD)
Output();
// Network 46: SLIM BLOCK (Original Language: LAD)
SLIM_Block();
// Network 47: Interlocking Panel 1 (Original Language: LAD)
Interlocking_Panel_1();
// Network 48: Filler Control (Original Language: LAD)
FillerControl();
// Network 49: Blender Ctrl Update PWORD (Original Language: LAD)
BlenderCtrl_UpdatePWord();
// Network 50: ResetTotalizer (Original Language: LAD)
"mResetTotalizerTmr"(IN := "gBlendResetTotalizer", PT := S5T#2S); // TODO: Declarar "mResetTotalizerTmr" : TP;
// Network 51: ResetWaterTot (Original Language: LAD)
"mResetFTN301TotTmr"(IN := "gFTN301_ResetTot" OR "mResetTotalizerTmr", PT := S5T#2S); // TODO: Declarar "mResetFTN301TotTmr" : TP;
"mResetWaterTot" := "mResetFTN301TotTmr".Q;
// Network 52: Water VFM Reset Totalizer (Original Language: LAD)
IF "gFTN301_ResetTot" THEN
"gFTN301_ResetTot" := FALSE;
END_IF;
// Network 53: ResetCO2Tot (Original Language: LAD)
"mResetFTP302TotTmr"(IN := "mResetTotalizerTmr" OR "gFTP302_ResetTot", PT := S5T#2S); // TODO: Declarar "mResetFTP302TotTmr" : TP;
"mResetSyrupTot" := "gSyrupRoomEn" AND "mResetFTP302TotTmr".Q;
// Network 54: Syrup MFM Reset Totalizer (Original Language: LAD)
IF "gFTP302_ResetTot" THEN
"gFTP302_ResetTot" := FALSE;
END_IF;
// Network 55: ResetProductTot (Original Language: LAD)
"mResetFTM303TotTmr"(IN := "mResetTotalizerTmr" OR "gFTM303_ResetTot", PT := S5T#2S); // TODO: Declarar "mResetFTM303TotTmr" : TP;
"mResetCO2Tot" := "mResetFTM303TotTmr".Q;
// Network 56: CO2 MFM Reset Tot (Original Language: LAD)
IF "gFTM303_ResetTot" THEN
"gFTM303_ResetTot" := FALSE;
END_IF;
// Network 57: ResetCO2Tot (Original Language: LAD)
"mResetProductTotTmr"(IN := "mResetTotalizerTmr" OR "gProductMFMResetTot", PT := S5T#2S); // TODO: Declarar "mResetProductTotTmr" : TP;
"mResetProductTot" := "mResetProductTotTmr".Q;
// Network 58: Reset Totalizer (Original Language: LAD)
IF "gProductMFMResetTot" THEN
"gProductMFMResetTot" := FALSE;
END_IF;
// Network 59: Reset Totalizer (Original Language: LAD)
IF "gBlendResetTotalizer" THEN
"gBlendResetTotalizer" := FALSE;
END_IF;
// Network 60: Blender Ctrl Command (Original Language: LAD)
IF NOT "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_Simulation" THEN
BlenderCtrl_MFM_Command();
END_IF;
// Network 61: DP Global Diag (Original Language: LAD)
CPU_DP_Global_Diag();
// Network 62: Profibus (Original Language: LAD)
Profibus_Network();
// Network 63: Valve Fault (Original Language: LAD)
ModValveFault();
// Network 64: All Auto (Original Language: LAD)
IF ("M19011" AND NOT "HMI_Variables_Cmd"."Commands_From_HMI"."F7_DeviceControl"."Command") OR ("M19011" AND NOT "HMI_Variables_Cmd"."Commands_From_HMI"."F7_DeviceControl"."Enable") THEN
BlenderCtrl_All_Auto();
END_IF;
"HMI_Variables_Cmd"."Commands_From_HMI"."F7_DeviceControl"."Light" := "HMI_Variables_Cmd"."Commands_From_HMI"."F7_DeviceControl"."Command" AND "HMI_Variables_Cmd"."Commands_From_HMI"."F7_DeviceControl"."Enable";
// Network 65: Ctrl HMI Manual Active (Original Language: LAD)
BlenderCtrl_ManualActive();
// Network 66: Mod Copy Recipe (Original Language: LAD)
"mAux_FP_M700_1" := "HMI_Variables_Cmd"."Recipe"."Main_Page" AND NOT "mFP_Recip_Main_Page";
"mFP_Recip_Main_Page" := "HMI_Variables_Cmd"."Recipe"."Main_Page";
"T_Pulse_Recipe_Edit"(IN := "HMI_Variables_Cmd"."Recipe"."Main_Page" AND "HMI_Variables_Cmd"."Recipe"."Edit", PT := S5T#500ms); // TODO: Declarar "T_Pulse_Recipe_Edit" : TP;
IF "T_Pulse_Recipe_Edit" AND "T_Pulse_Recipe_Edit".Q THEN
"HMI_Variables_Cmd"."Recipe"."Edit" := FALSE;
END_IF;
IF "mAux_FP_M700_1" THEN
"HMI_Variables_Cmd"."Recipe"."Edit" := TRUE;
END_IF;
// Network 67: to HMI - Recipe Management (Original Language: LAD)
IF "AUX TRUE" THEN
"RecipeManagement_Data"();
END_IF;
// Network 68: Recipe Calculation (Original Language: LAD)
RecipeCalculation();
END_FUNCTION_BLOCK

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

View File

@ -1,107 +0,0 @@
// Block Name (Original): BlenderPIDCtrl__Loop
// Block Number: 1729
// Original Language: LAD
// Block Comment: TASK1 PID
FUNCTION_BLOCK "BlenderPIDCtrl__Loop"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_STAT_STATIC
PID_1_300ms : Bool;
PID_2_300ms : Bool;
PID_3_300ms : Bool;
PID_4_300ms : Bool;
PID_5_300ms : Bool;
PID_6_300ms : Bool;
Flow_Meter_Error_RETVAL : Real;
PID_FF_Calc : "BlenderPID_PIDFFCalc";
PID_Blending_Fault : "BlenderPID_BlendingFault";
PID_Save_Integral : "BlenderPIDCtrl_SaveInteg";
PID_Monitor : "BlenderPIDCtrl_Monitor";
Read_AnalogInput : "BlenderPIDCtrl_ReadAnIn";
END_VAR
VAR_TEMP
END_VAR
BEGIN
// Network 1: Read Analoc Inputs (Original Language: LAD)
"Read_AnalogInput"();
// Network 2: MIX - OB35 scan counter (Original Language: LAD)
// PID Control Time Bit (300ms)
"PID_1_300ms" := Eq("MW1968", 1);
"PID_2_300ms" := Eq("MW1968", 2);
"PID_3_300ms" := Eq("MW1968", 3);
"PID_4_300ms" := Eq("MW1968", 4);
"PID_5_300ms" := Eq("MW1968", 5);
"PID_6_300ms" := Eq("MW1968", 6);
// Network 3: PID Call (Original Language: LAD)
// Water PID
// Syrup PID
// CO2 PID
IF "PID_1_300ms" THEN
"PID_FF_Calc"();
"PID_Blending_Fault"();
BlenderPID_FlowMeterErro();
"PID_Monitor"();
"PID_Save_Integral"();
BlenderPIDCtrl_SaveValve();
END_IF;
IF "PID_1_300ms" AND "HMI_PID"."RMM301"."Config" THEN
"PID_RMM301_Data"();
END_IF;
IF "PID_1_300ms" AND "HMI_PID"."RMP302"."Config" THEN
"PID_RMP302_Data"();
END_IF;
IF "PID_1_300ms" AND "HMI_PID"."RMM303"."Config" THEN
"PID_RMM303_Data"();
END_IF;
IF "PID_1_300ms" AND "HMI_PID"."RMM304"."Config" THEN
"PID_RMM304_Data"();
END_IF;
// Network 4: PID Product Tank Pressure (Original Language: LAD)
IF "PID_2_300ms" AND "HMI_PID"."RVM301"."Config" THEN
"PID_RVM301_Data"();
BlenderPIDCtrl_PresRelea();
END_IF;
// Network 5: Pid Call (Original Language: LAD)
IF "PID_4_300ms" AND "HMI_PID"."RVM319_PRD"."Config" THEN
"PID_RVM319_Data"();
END_IF;
IF "HMI_PID"."RVP303"."Config" AND "PID_4_300ms" THEN
"PID_RVP303_Data"();
END_IF;
IF "HMI_PID"."RVN302"."Config" AND "PID_4_300ms" AND NOT "HMI_PID"."RVN302"."ConfigPID" THEN
"PID_RVN302_Data"();
END_IF;
// Network 6: Filling Head (Original Language: LAD)
IF "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_BlendFillSystem" AND "PID_5_300ms" AND "HMI_PID"."PPM303"."Config" THEN
"PID_Filling_Head_Data"();
END_IF;
// Network 7: CIp Heating PID (Original Language: LAD)
IF "PID_6_300ms" AND "HMI_PID"."RVS318"."Config" THEN
"PID_RVS318_Data"();
END_IF;
// Network 8: Write Analog Outputs (Original Language: LAD)
IF "AUX TRUE" THEN
BlenderPIDCtrl_WriteAnOu();
END_IF;
END_FUNCTION_BLOCK

File diff suppressed because it is too large Load Diff

View File

@ -1,995 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Document>
<Engineering version="V18" />
<SW.Blocks.FC ID="0">
<AttributeList>
<Interface><Sections xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v5">
<Section Name="Input" />
<Section Name="Output" />
<Section Name="InOut" />
<Section Name="Temp">
<Member Name="mWaterMaxFlow" Datatype="Real" />
<Member Name="mWaterMinFlow" Datatype="Real" />
<Member Name="mSyrupMaxFlow" Datatype="Real" />
<Member Name="mSyrupMinFlow" Datatype="Real" />
<Member Name="mMinRatio" Datatype="Real" />
<Member Name="mMaxRatio" Datatype="Real" />
<Member Name="mBevBrixMax" Datatype="Real" />
<Member Name="mBevBrixMin" Datatype="Real" />
</Section>
<Section Name="Constant" />
<Section Name="Return">
<Member Name="Ret_Val" Datatype="Real" />
</Section>
</Sections></Interface>
<MemoryLayout>Optimized</MemoryLayout>
<Name>TestLAD</Name>
<Namespace />
<Number>2</Number>
<ProgrammingLanguage>LAD</ProgrammingLanguage>
<SetENOAutomatically>false</SetENOAutomatically>
</AttributeList>
<ObjectList>
<MultilingualText ID="1" CompositionName="Comment">
<ObjectList>
<MultilingualTextItem ID="2" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="3" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="4" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="5" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="6" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="7" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="8" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
<SW.Blocks.CompileUnit ID="9" CompositionName="CompileUnits">
<AttributeList>
<NetworkSource><StructuredText xmlns="http://www.siemens.com/automation/Openness/SW/NetworkSource/StructuredText/v3">
<NewLine UId="21" />
<Token Text="IF" UId="22" />
<Blank UId="23" />
<Access Scope="GlobalVariable" UId="24">
<Symbol UId="25">
<Component Name="Blender_Variables" UId="26">
<BooleanAttribute Name="HasQuotes" UId="27">true</BooleanAttribute>
</Component>
<Token Text="." UId="28" />
<Component Name="gSP_H2O" UId="29" />
</Symbol>
</Access>
<Blank UId="30" />
<Token Text="&lt;&gt;" UId="31" />
<Blank UId="32" />
<Access Scope="LiteralConstant" UId="33">
<Constant UId="34">
<ConstantValue UId="36">0</ConstantValue>
</Constant>
</Access>
<Blank UId="37" />
<Token Text="THEN" UId="38" />
<NewLine UId="39" />
<Blank Num="4" UId="40" />
<Access Scope="GlobalVariable" UId="41">
<Symbol UId="42">
<Component Name="Blender_Variables" UId="43">
<BooleanAttribute Name="HasQuotes" UId="44">true</BooleanAttribute>
</Component>
<Token Text="." UId="45" />
<Component Name="gWaterVFMCalcError" UId="46" />
</Symbol>
</Access>
<Blank UId="47" />
<Token Text=":=" UId="48" />
<Blank UId="49" />
<Access Scope="GlobalVariable" UId="50">
<Symbol UId="51">
<Component Name="Blender_Variables" UId="52">
<BooleanAttribute Name="HasQuotes" UId="53">true</BooleanAttribute>
</Component>
<Token Text="." UId="54" />
<Component Name="gWaterVFMMeasError" UId="55" />
</Symbol>
</Access>
<Blank UId="56" />
<Token Text="/" UId="57" />
<Blank UId="58" />
<Access Scope="LiteralConstant" UId="59">
<Constant UId="60">
<ConstantValue UId="62">100</ConstantValue>
</Constant>
</Access>
<Blank UId="63" />
<Token Text="*" UId="64" />
<Blank UId="65" />
<Access Scope="GlobalVariable" UId="66">
<Symbol UId="67">
<Component Name="Blender_Variables" UId="68">
<BooleanAttribute Name="HasQuotes" UId="69">true</BooleanAttribute>
</Component>
<Token Text="." UId="70" />
<Component Name="gSP_H2O" UId="71" />
</Symbol>
</Access>
<Token Text=";" UId="72" />
<NewLine UId="73" />
<Token Text="END_IF" UId="74" />
<Token Text=";" UId="75" />
<NewLine UId="76" />
<Token Text="IF" UId="77" />
<Blank UId="78" />
<Access Scope="GlobalVariable" UId="79">
<Symbol UId="80">
<Component Name="Blender_Variables" UId="81">
<BooleanAttribute Name="HasQuotes" UId="82">true</BooleanAttribute>
</Component>
<Token Text="." UId="83" />
<Component Name="gSP_SYR" UId="84" />
</Symbol>
</Access>
<Blank UId="85" />
<Token Text="&lt;&gt;" UId="86" />
<Blank UId="87" />
<Access Scope="LiteralConstant" UId="88">
<Constant UId="89">
<ConstantValue UId="91">0</ConstantValue>
</Constant>
</Access>
<Blank UId="92" />
<Token Text="THEN" UId="93" />
<NewLine UId="94" />
<Blank Num="4" UId="95" />
<Access Scope="GlobalVariable" UId="96">
<Symbol UId="97">
<Component Name="Blender_Variables" UId="98">
<BooleanAttribute Name="HasQuotes" UId="99">true</BooleanAttribute>
</Component>
<Token Text="." UId="100" />
<Component Name="gSyrupMFMCalcError" UId="101" />
</Symbol>
</Access>
<Blank UId="102" />
<Token Text=":=" UId="103" />
<Blank UId="104" />
<Token Text="(" UId="105" />
<Access Scope="GlobalVariable" UId="106">
<Symbol UId="107">
<Component Name="Blender_Variables" UId="108">
<BooleanAttribute Name="HasQuotes" UId="109">true</BooleanAttribute>
</Component>
<Token Text="." UId="110" />
<Component Name="gSyrupMFMMeasError" UId="111" />
</Symbol>
</Access>
<Blank UId="112" />
<Token Text="/" UId="113" />
<Blank UId="114" />
<Access Scope="LiteralConstant" UId="115">
<Constant UId="116">
<ConstantValue UId="118">100</ConstantValue>
</Constant>
</Access>
<Blank UId="119" />
<Token Text="+" UId="120" />
<Blank UId="121" />
<Token Text="(" UId="122" />
<Access Scope="GlobalVariable" UId="123">
<Symbol UId="124">
<Component Name="Blender_Variables" UId="125">
<BooleanAttribute Name="HasQuotes" UId="126">true</BooleanAttribute>
</Component>
<Token Text="." UId="127" />
<Component Name="gSyrupMFMZeroStab" UId="128" />
</Symbol>
</Access>
<Blank UId="129" />
<Token Text="/" UId="130" />
<Blank UId="131" />
<Token Text="(" UId="132" />
<Access Scope="GlobalVariable" UId="133">
<Symbol UId="134">
<Component Name="Blender_Variables" UId="135">
<BooleanAttribute Name="HasQuotes" UId="136">true</BooleanAttribute>
</Component>
<Token Text="." UId="137" />
<Component Name="gSP_SYR" UId="138" />
</Symbol>
</Access>
<Blank UId="139" />
<Token Text="*" UId="140" />
<Blank UId="141" />
<Access Scope="LiteralConstant" UId="142">
<Constant UId="143">
<ConstantValue UId="145">60</ConstantValue>
</Constant>
</Access>
<Token Text=")" UId="146" />
<Token Text=")" UId="147" />
<Blank UId="148" />
<Token Text="/" UId="149" />
<Blank UId="150" />
<Access Scope="LiteralConstant" UId="151">
<Constant UId="152">
<ConstantValue UId="154">100</ConstantValue>
</Constant>
</Access>
<Token Text=")" UId="155" />
<Blank UId="156" />
<Token Text="*" UId="157" />
<Blank UId="158" />
<Access Scope="GlobalVariable" UId="159">
<Symbol UId="160">
<Component Name="Blender_Variables" UId="161">
<BooleanAttribute Name="HasQuotes" UId="162">true</BooleanAttribute>
</Component>
<Token Text="." UId="163" />
<Component Name="gSP_SYR" UId="164" />
</Symbol>
</Access>
<Token Text=";" UId="165" />
<NewLine UId="166" />
<Token Text="END_IF" UId="167" />
<Token Text=";" UId="168" />
<NewLine UId="169" />
<Token Text="IF" UId="170" />
<Blank UId="171" />
<Access Scope="GlobalVariable" UId="172">
<Symbol UId="173">
<Component Name="Blender_Variables" UId="174">
<BooleanAttribute Name="HasQuotes" UId="175">true</BooleanAttribute>
</Component>
<Token Text="." UId="176" />
<Component Name="gSP_CO2" UId="177" />
</Symbol>
</Access>
<Blank UId="178" />
<Token Text="&lt;&gt;" UId="179" />
<Blank UId="180" />
<Access Scope="LiteralConstant" UId="181">
<Constant UId="182">
<ConstantValue UId="184">0</ConstantValue>
</Constant>
</Access>
<Blank UId="185" />
<Token Text="THEN" UId="186" />
<NewLine UId="187" />
<Blank Num="4" UId="188" />
<Access Scope="GlobalVariable" UId="189">
<Symbol UId="190">
<Component Name="Blender_Variables" UId="191">
<BooleanAttribute Name="HasQuotes" UId="192">true</BooleanAttribute>
</Component>
<Token Text="." UId="193" />
<Component Name="gCO2MFMCalcError" UId="194" />
</Symbol>
</Access>
<Blank UId="195" />
<Token Text=":=" UId="196" />
<Blank UId="197" />
<Token Text="(" UId="198" />
<Access Scope="GlobalVariable" UId="199">
<Symbol UId="200">
<Component Name="Blender_Variables" UId="201">
<BooleanAttribute Name="HasQuotes" UId="202">true</BooleanAttribute>
</Component>
<Token Text="." UId="203" />
<Component Name="gCO2MFMMeasError" UId="204" />
</Symbol>
</Access>
<Blank UId="205" />
<Token Text="/" UId="206" />
<Blank UId="207" />
<Access Scope="LiteralConstant" UId="208">
<Constant UId="209">
<ConstantValue UId="211">100</ConstantValue>
</Constant>
</Access>
<Blank UId="212" />
<Token Text="+" UId="213" />
<Blank UId="214" />
<Token Text="(" UId="215" />
<Access Scope="GlobalVariable" UId="216">
<Symbol UId="217">
<Component Name="Blender_Variables" UId="218">
<BooleanAttribute Name="HasQuotes" UId="219">true</BooleanAttribute>
</Component>
<Token Text="." UId="220" />
<Component Name="gCO2MFMZeroStab" UId="221" />
</Symbol>
</Access>
<Blank UId="222" />
<Token Text="/" UId="223" />
<Blank UId="224" />
<Token Text="(" UId="225" />
<Access Scope="GlobalVariable" UId="226">
<Symbol UId="227">
<Component Name="Blender_Variables" UId="228">
<BooleanAttribute Name="HasQuotes" UId="229">true</BooleanAttribute>
</Component>
<Token Text="." UId="230" />
<Component Name="gSP_CO2" UId="231" />
</Symbol>
</Access>
<Blank UId="232" />
<Token Text="*" UId="233" />
<Blank UId="234" />
<Access Scope="LiteralConstant" UId="235">
<Constant UId="236">
<ConstantValue UId="238">60</ConstantValue>
</Constant>
</Access>
<Blank UId="239" />
<Token Text="/" UId="240" />
<Blank UId="241" />
<Access Scope="LiteralConstant" UId="242">
<Constant UId="243">
<ConstantValue UId="245">1000</ConstantValue>
</Constant>
</Access>
<Token Text=")" UId="246" />
<Token Text=")" UId="247" />
<Blank UId="248" />
<Token Text="/" UId="249" />
<Blank UId="250" />
<Access Scope="LiteralConstant" UId="251">
<Constant UId="252">
<ConstantValue UId="254">100</ConstantValue>
</Constant>
</Access>
<Token Text=")" UId="255" />
<Blank UId="256" />
<Token Text="*" UId="257" />
<Blank UId="258" />
<Access Scope="GlobalVariable" UId="259">
<Symbol UId="260">
<Component Name="Blender_Variables" UId="261">
<BooleanAttribute Name="HasQuotes" UId="262">true</BooleanAttribute>
</Component>
<Token Text="." UId="263" />
<Component Name="gSP_CO2" UId="264" />
</Symbol>
</Access>
<Token Text=";" UId="265" />
<NewLine UId="266" />
<Token Text="END_IF" UId="267" />
<Token Text=";" UId="268" />
<NewLine UId="269" />
<Access Scope="LocalVariable" UId="270">
<Symbol UId="271">
<Component Name="mWaterMaxFlow" UId="272" />
</Symbol>
</Access>
<Blank UId="273" />
<Token Text=":=" UId="274" />
<Blank UId="275" />
<Access Scope="GlobalVariable" UId="276">
<Symbol UId="277">
<Component Name="Blender_Variables" UId="278">
<BooleanAttribute Name="HasQuotes" UId="279">true</BooleanAttribute>
</Component>
<Token Text="." UId="280" />
<Component Name="gSP_H2O" UId="281" />
</Symbol>
</Access>
<Blank UId="282" />
<Token Text="+" UId="283" />
<Blank UId="284" />
<Access Scope="GlobalVariable" UId="285">
<Symbol UId="286">
<Component Name="Blender_Variables" UId="287">
<BooleanAttribute Name="HasQuotes" UId="288">true</BooleanAttribute>
</Component>
<Token Text="." UId="289" />
<Component Name="gWaterVFMCalcError" UId="290" />
</Symbol>
</Access>
<Token Text=";" UId="291" />
<NewLine UId="292" />
<Access Scope="LocalVariable" UId="293">
<Symbol UId="294">
<Component Name="mWaterMinFlow" UId="295" />
</Symbol>
</Access>
<Blank UId="296" />
<Token Text=":=" UId="297" />
<Blank UId="298" />
<Access Scope="GlobalVariable" UId="299">
<Symbol UId="300">
<Component Name="Blender_Variables" UId="301">
<BooleanAttribute Name="HasQuotes" UId="302">true</BooleanAttribute>
</Component>
<Token Text="." UId="303" />
<Component Name="gSP_H2O" UId="304" />
</Symbol>
</Access>
<Blank UId="305" />
<Token Text="-" UId="306" />
<Blank UId="307" />
<Access Scope="GlobalVariable" UId="308">
<Symbol UId="309">
<Component Name="Blender_Variables" UId="310">
<BooleanAttribute Name="HasQuotes" UId="311">true</BooleanAttribute>
</Component>
<Token Text="." UId="312" />
<Component Name="gWaterVFMCalcError" UId="313" />
</Symbol>
</Access>
<Token Text=";" UId="314" />
<NewLine UId="315" />
<Token Text="IF" UId="316" />
<Blank UId="317" />
<Access Scope="GlobalVariable" UId="318">
<Symbol UId="319">
<Component Name="HMI_Blender_Parameters" UId="320">
<BooleanAttribute Name="HasQuotes" UId="321">true</BooleanAttribute>
</Component>
<Token Text="." UId="322" />
<Component Name="Actual_Recipe_Parameters" UId="323" />
<Token Text="." UId="324" />
<Component Name="_SyrupDensity" UId="325" />
</Symbol>
</Access>
<Blank UId="326" />
<Token Text="&lt;&gt;" UId="327" />
<Blank UId="328" />
<Access Scope="LiteralConstant" UId="329">
<Constant UId="330">
<ConstantValue UId="332">0</ConstantValue>
</Constant>
</Access>
<Blank UId="333" />
<Token Text="THEN" UId="334" />
<NewLine UId="335" />
<Blank Num="4" UId="336" />
<Access Scope="LocalVariable" UId="337">
<Symbol UId="338">
<Component Name="mSyrupMaxFlow" UId="339" />
</Symbol>
</Access>
<Blank UId="340" />
<Token Text=":=" UId="341" />
<Blank UId="342" />
<Token Text="(" UId="343" />
<Access Scope="GlobalVariable" UId="344">
<Symbol UId="345">
<Component Name="Blender_Variables" UId="346">
<BooleanAttribute Name="HasQuotes" UId="347">true</BooleanAttribute>
</Component>
<Token Text="." UId="348" />
<Component Name="gSP_SYR" UId="349" />
</Symbol>
</Access>
<Blank UId="350" />
<Token Text="+" UId="351" />
<Blank UId="352" />
<Access Scope="GlobalVariable" UId="353">
<Symbol UId="354">
<Component Name="Blender_Variables" UId="355">
<BooleanAttribute Name="HasQuotes" UId="356">true</BooleanAttribute>
</Component>
<Token Text="." UId="357" />
<Component Name="gSyrupMFMCalcError" UId="358" />
</Symbol>
</Access>
<Token Text=")" UId="359" />
<Blank UId="360" />
<Token Text="/" UId="361" />
<Blank UId="362" />
<Access Scope="GlobalVariable" UId="363">
<Symbol UId="364">
<Component Name="HMI_Blender_Parameters" UId="365">
<BooleanAttribute Name="HasQuotes" UId="366">true</BooleanAttribute>
</Component>
<Token Text="." UId="367" />
<Component Name="Actual_Recipe_Parameters" UId="368" />
<Token Text="." UId="369" />
<Component Name="_SyrupDensity" UId="370" />
</Symbol>
</Access>
<Token Text=";" UId="371" />
<NewLine UId="372" />
<Blank Num="4" UId="373" />
<Access Scope="LocalVariable" UId="374">
<Symbol UId="375">
<Component Name="mSyrupMinFlow" UId="376" />
</Symbol>
</Access>
<Blank UId="377" />
<Token Text=":=" UId="378" />
<Blank UId="379" />
<Token Text="(" UId="380" />
<Access Scope="GlobalVariable" UId="381">
<Symbol UId="382">
<Component Name="Blender_Variables" UId="383">
<BooleanAttribute Name="HasQuotes" UId="384">true</BooleanAttribute>
</Component>
<Token Text="." UId="385" />
<Component Name="gSP_SYR" UId="386" />
</Symbol>
</Access>
<Blank UId="387" />
<Token Text="-" UId="388" />
<Blank UId="389" />
<Access Scope="GlobalVariable" UId="390">
<Symbol UId="391">
<Component Name="Blender_Variables" UId="392">
<BooleanAttribute Name="HasQuotes" UId="393">true</BooleanAttribute>
</Component>
<Token Text="." UId="394" />
<Component Name="gSyrupMFMCalcError" UId="395" />
</Symbol>
</Access>
<Token Text=")" UId="396" />
<Blank UId="397" />
<Token Text="/" UId="398" />
<Blank UId="399" />
<Access Scope="GlobalVariable" UId="400">
<Symbol UId="401">
<Component Name="HMI_Blender_Parameters" UId="402">
<BooleanAttribute Name="HasQuotes" UId="403">true</BooleanAttribute>
</Component>
<Token Text="." UId="404" />
<Component Name="Actual_Recipe_Parameters" UId="405" />
<Token Text="." UId="406" />
<Component Name="_SyrupDensity" UId="407" />
</Symbol>
</Access>
<Token Text=";" UId="408" />
<NewLine UId="409" />
<Token Text="END_IF" UId="410" />
<Token Text=";" UId="411" />
<NewLine UId="412" />
<Token Text="IF" UId="413" />
<Blank UId="414" />
<Access Scope="LocalVariable" UId="415">
<Symbol UId="416">
<Component Name="mSyrupMaxFlow" UId="417" />
</Symbol>
</Access>
<Blank UId="418" />
<Token Text="&lt;&gt;" UId="419" />
<Blank UId="420" />
<Access Scope="LiteralConstant" UId="421">
<Constant UId="422">
<ConstantValue UId="424">0</ConstantValue>
</Constant>
</Access>
<Blank UId="425" />
<Token Text="THEN" UId="426" />
<NewLine UId="427" />
<Blank Num="4" UId="428" />
<Access Scope="LocalVariable" UId="429">
<Symbol UId="430">
<Component Name="mMinRatio" UId="431" />
</Symbol>
</Access>
<Blank UId="432" />
<Token Text=":=" UId="433" />
<Blank UId="434" />
<Access Scope="LocalVariable" UId="435">
<Symbol UId="436">
<Component Name="mWaterMinFlow" UId="437" />
</Symbol>
</Access>
<Blank UId="438" />
<Token Text="/" UId="439" />
<Blank UId="440" />
<Access Scope="LocalVariable" UId="441">
<Symbol UId="442">
<Component Name="mSyrupMaxFlow" UId="443" />
</Symbol>
</Access>
<Token Text=";" UId="444" />
<NewLine UId="445" />
<Token Text="END_IF" UId="446" />
<Token Text=";" UId="447" />
<NewLine UId="448" />
<Token Text="IF" UId="449" />
<Blank UId="450" />
<Access Scope="LocalVariable" UId="451">
<Symbol UId="452">
<Component Name="mSyrupMinFlow" UId="453" />
</Symbol>
</Access>
<Blank UId="454" />
<Token Text="&lt;&gt;" UId="455" />
<Blank UId="456" />
<Access Scope="LiteralConstant" UId="457">
<Constant UId="458">
<ConstantValue UId="460">0</ConstantValue>
</Constant>
</Access>
<Blank UId="461" />
<Token Text="THEN" UId="462" />
<NewLine UId="463" />
<Blank Num="4" UId="464" />
<Access Scope="LocalVariable" UId="465">
<Symbol UId="466">
<Component Name="mMaxRatio" UId="467" />
</Symbol>
</Access>
<Blank UId="468" />
<Token Text=":=" UId="469" />
<Blank UId="470" />
<Access Scope="LocalVariable" UId="471">
<Symbol UId="472">
<Component Name="mWaterMaxFlow" UId="473" />
</Symbol>
</Access>
<Blank UId="474" />
<Token Text="/" UId="475" />
<Blank UId="476" />
<Access Scope="LocalVariable" UId="477">
<Symbol UId="478">
<Component Name="mSyrupMinFlow" UId="479" />
</Symbol>
</Access>
<Token Text=";" UId="480" />
<NewLine UId="481" />
<Token Text="END_IF" UId="482" />
<Token Text=";" UId="483" />
<NewLine UId="484" />
<Token Text="IF" UId="485" />
<Blank UId="486" />
<Access Scope="GlobalVariable" UId="487">
<Symbol UId="488">
<Component Name="HMI_Blender_Parameters" UId="489">
<BooleanAttribute Name="HasQuotes" UId="490">true</BooleanAttribute>
</Component>
<Token Text="." UId="491" />
<Component Name="Actual_Recipe_Parameters" UId="492" />
<Token Text="." UId="493" />
<Component Name="_SyrupDensity" UId="494" />
</Symbol>
</Access>
<Blank UId="495" />
<Token Text="&lt;&gt;" UId="496" />
<Blank UId="497" />
<Access Scope="LiteralConstant" UId="498">
<Constant UId="499">
<ConstantValue UId="501">0</ConstantValue>
</Constant>
</Access>
<Blank UId="502" />
<Token Text="THEN" UId="503" />
<NewLine UId="504" />
<Blank Num="4" UId="505" />
<Access Scope="LocalVariable" UId="506">
<Symbol UId="507">
<Component Name="mBevBrixMax" UId="508" />
</Symbol>
</Access>
<Blank UId="509" />
<Token Text=":=" UId="510" />
<Blank UId="511" />
<Access Scope="GlobalVariable" UId="512">
<Symbol UId="513">
<Component Name="HMI_Blender_Parameters" UId="514">
<BooleanAttribute Name="HasQuotes" UId="515">true</BooleanAttribute>
</Component>
<Token Text="." UId="516" />
<Component Name="Actual_Recipe_Parameters" UId="517" />
<Token Text="." UId="518" />
<Component Name="_SyrupBrix" UId="519" />
</Symbol>
</Access>
<Blank UId="520" />
<Token Text="/" UId="521" />
<Blank UId="522" />
<Token Text="(" UId="523" />
<Token Text="(" UId="524" />
<Access Scope="LocalVariable" UId="525">
<Symbol UId="526">
<Component Name="mMinRatio" UId="527" />
</Symbol>
</Access>
<Blank UId="528" />
<Token Text="/" UId="529" />
<Blank UId="530" />
<Access Scope="GlobalVariable" UId="531">
<Symbol UId="532">
<Component Name="HMI_Blender_Parameters" UId="533">
<BooleanAttribute Name="HasQuotes" UId="534">true</BooleanAttribute>
</Component>
<Token Text="." UId="535" />
<Component Name="Actual_Recipe_Parameters" UId="536" />
<Token Text="." UId="537" />
<Component Name="_SyrupDensity" UId="538" />
</Symbol>
</Access>
<Token Text=")" UId="539" />
<Blank UId="540" />
<Token Text="+" UId="541" />
<Blank UId="542" />
<Access Scope="LiteralConstant" UId="543">
<Constant UId="544">
<ConstantValue UId="546">1</ConstantValue>
</Constant>
</Access>
<Token Text=")" UId="547" />
<Token Text=";" UId="548" />
<NewLine UId="549" />
<Blank Num="4" UId="550" />
<Access Scope="LocalVariable" UId="551">
<Symbol UId="552">
<Component Name="mBevBrixMin" UId="553" />
</Symbol>
</Access>
<Blank UId="554" />
<Token Text=":=" UId="555" />
<Blank UId="556" />
<Access Scope="GlobalVariable" UId="557">
<Symbol UId="558">
<Component Name="HMI_Blender_Parameters" UId="559">
<BooleanAttribute Name="HasQuotes" UId="560">true</BooleanAttribute>
</Component>
<Token Text="." UId="561" />
<Component Name="Actual_Recipe_Parameters" UId="562" />
<Token Text="." UId="563" />
<Component Name="_SyrupBrix" UId="564" />
</Symbol>
</Access>
<Blank UId="565" />
<Token Text="/" UId="566" />
<Blank UId="567" />
<Token Text="(" UId="568" />
<Token Text="(" UId="569" />
<Access Scope="LocalVariable" UId="570">
<Symbol UId="571">
<Component Name="mMaxRatio" UId="572" />
</Symbol>
</Access>
<Blank UId="573" />
<Token Text="/" UId="574" />
<Blank UId="575" />
<Access Scope="GlobalVariable" UId="576">
<Symbol UId="577">
<Component Name="HMI_Blender_Parameters" UId="578">
<BooleanAttribute Name="HasQuotes" UId="579">true</BooleanAttribute>
</Component>
<Token Text="." UId="580" />
<Component Name="Actual_Recipe_Parameters" UId="581" />
<Token Text="." UId="582" />
<Component Name="_SyrupDensity" UId="583" />
</Symbol>
</Access>
<Token Text=")" UId="584" />
<Blank UId="585" />
<Token Text="+" UId="586" />
<Blank UId="587" />
<Access Scope="LiteralConstant" UId="588">
<Constant UId="589">
<ConstantValue UId="591">1</ConstantValue>
</Constant>
</Access>
<Token Text=")" UId="592" />
<Token Text=";" UId="593" />
<NewLine UId="594" />
<Token Text="END_IF" UId="595" />
<Token Text=";" UId="596" />
<NewLine UId="597" />
<Access Scope="GlobalVariable" UId="598">
<Symbol UId="599">
<Component Name="Blender_Variables" UId="600">
<BooleanAttribute Name="HasQuotes" UId="601">true</BooleanAttribute>
</Component>
<Token Text="." UId="602" />
<Component Name="gBlenderBlendMaxError" UId="603" />
</Symbol>
</Access>
<Blank UId="604" />
<Token Text=":=" UId="605" />
<Blank UId="606" />
<Access Scope="LocalVariable" UId="607">
<Symbol UId="608">
<Component Name="mBevBrixMax" UId="609" />
</Symbol>
</Access>
<Blank UId="610" />
<Token Text="-" UId="611" />
<Blank UId="612" />
<Access Scope="LocalVariable" UId="613">
<Symbol UId="614">
<Component Name="mBevBrixMin" UId="615" />
</Symbol>
</Access>
<Token Text=";" UId="616" />
<NewLine Num="2" UId="617" />
<Access Scope="LocalVariable" UId="618">
<Symbol UId="619">
<Component Name="TestLAD" UId="620" />
</Symbol>
</Access>
<Blank UId="621" />
<Token Text=":=" UId="622" />
<Blank UId="623" />
<Access Scope="GlobalVariable" UId="624">
<Symbol UId="625">
<Component Name="Blender_Variables" UId="626">
<BooleanAttribute Name="HasQuotes" UId="627">true</BooleanAttribute>
</Component>
<Token Text="." UId="628" />
<Component Name="gBlenderBlendMaxError" UId="629" />
</Symbol>
</Access>
<Token Text=";" UId="630" />
</StructuredText></NetworkSource>
<ProgrammingLanguage>SCL</ProgrammingLanguage>
</AttributeList>
<ObjectList>
<MultilingualText ID="A" CompositionName="Comment">
<ObjectList>
<MultilingualTextItem ID="B" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="C" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="D" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="E" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="F" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="10" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="11" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
<MultilingualText ID="12" CompositionName="Title">
<ObjectList>
<MultilingualTextItem ID="13" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="14" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="15" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="16" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="17" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="18" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="19" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
</ObjectList>
</SW.Blocks.CompileUnit>
<MultilingualText ID="1A" CompositionName="Title">
<ObjectList>
<MultilingualTextItem ID="1B" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="1C" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="1D" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="1E" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="1F" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="20" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="21" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
</ObjectList>
</SW.Blocks.FC>
</Document>

View File

@ -1,63 +0,0 @@
{
"block_name": "TestLAD",
"block_number": 2,
"language": "LAD",
"block_comment": "",
"interface": {
"Temp": [
{
"name": "mWaterMaxFlow",
"datatype": "Real"
},
{
"name": "mWaterMinFlow",
"datatype": "Real"
},
{
"name": "mSyrupMaxFlow",
"datatype": "Real"
},
{
"name": "mSyrupMinFlow",
"datatype": "Real"
},
{
"name": "mMinRatio",
"datatype": "Real"
},
{
"name": "mMaxRatio",
"datatype": "Real"
},
{
"name": "mBevBrixMax",
"datatype": "Real"
},
{
"name": "mBevBrixMin",
"datatype": "Real"
}
],
"Return": [
{
"name": "Ret_Val",
"datatype": "Real"
}
]
},
"networks": [
{
"id": "9",
"title": "",
"comment": "",
"language": "SCL",
"logic": [
{
"instruction_uid": "SCL_9",
"type": "RAW_SCL_CHUNK",
"scl": "IF \"Blender_Variables\".gSP_H2O <> 0 THEN\n \"Blender_Variables\".gWaterVFMCalcError := \"Blender_Variables\".gWaterVFMMeasError / 100 * \"Blender_Variables\".gSP_H2O;\nEND_IF;\nIF \"Blender_Variables\".gSP_SYR <> 0 THEN\n \"Blender_Variables\".gSyrupMFMCalcError := (\"Blender_Variables\".gSyrupMFMMeasError / 100 + (\"Blender_Variables\".gSyrupMFMZeroStab / (\"Blender_Variables\".gSP_SYR * 60)) / 100) * \"Blender_Variables\".gSP_SYR;\nEND_IF;\nIF \"Blender_Variables\".gSP_CO2 <> 0 THEN\n \"Blender_Variables\".gCO2MFMCalcError := (\"Blender_Variables\".gCO2MFMMeasError / 100 + (\"Blender_Variables\".gCO2MFMZeroStab / (\"Blender_Variables\".gSP_CO2 * 60 / 1000)) / 100) * \"Blender_Variables\".gSP_CO2;\nEND_IF;\n\"mWaterMaxFlow\" := \"Blender_Variables\".gSP_H2O + \"Blender_Variables\".gWaterVFMCalcError;\n\"mWaterMinFlow\" := \"Blender_Variables\".gSP_H2O - \"Blender_Variables\".gWaterVFMCalcError;\nIF \"HMI_Blender_Parameters\".Actual_Recipe_Parameters._SyrupDensity <> 0 THEN\n \"mSyrupMaxFlow\" := (\"Blender_Variables\".gSP_SYR + \"Blender_Variables\".gSyrupMFMCalcError) / \"HMI_Blender_Parameters\".Actual_Recipe_Parameters._SyrupDensity;\n \"mSyrupMinFlow\" := (\"Blender_Variables\".gSP_SYR - \"Blender_Variables\".gSyrupMFMCalcError) / \"HMI_Blender_Parameters\".Actual_Recipe_Parameters._SyrupDensity;\nEND_IF;\nIF \"mSyrupMaxFlow\" <> 0 THEN\n \"mMinRatio\" := \"mWaterMinFlow\" / \"mSyrupMaxFlow\";\nEND_IF;\nIF \"mSyrupMinFlow\" <> 0 THEN\n \"mMaxRatio\" := \"mWaterMaxFlow\" / \"mSyrupMinFlow\";\nEND_IF;\nIF \"HMI_Blender_Parameters\".Actual_Recipe_Parameters._SyrupDensity <> 0 THEN\n \"mBevBrixMax\" := \"HMI_Blender_Parameters\".Actual_Recipe_Parameters._SyrupBrix / ((\"mMinRatio\" / \"HMI_Blender_Parameters\".Actual_Recipe_Parameters._SyrupDensity) + 1);\n \"mBevBrixMin\" := \"HMI_Blender_Parameters\".Actual_Recipe_Parameters._SyrupBrix / ((\"mMaxRatio\" / \"HMI_Blender_Parameters\".Actual_Recipe_Parameters._SyrupDensity) + 1);\nEND_IF;\n\"Blender_Variables\".gBlenderBlendMaxError := \"mBevBrixMax\" - \"mBevBrixMin\";\n\"TestLAD\" := \"Blender_Variables\".gBlenderBlendMaxError;"
}
]
}
]
}

View File

@ -1,63 +0,0 @@
{
"block_name": "TestLAD",
"block_number": 2,
"language": "LAD",
"block_comment": "",
"interface": {
"Temp": [
{
"name": "mWaterMaxFlow",
"datatype": "Real"
},
{
"name": "mWaterMinFlow",
"datatype": "Real"
},
{
"name": "mSyrupMaxFlow",
"datatype": "Real"
},
{
"name": "mSyrupMinFlow",
"datatype": "Real"
},
{
"name": "mMinRatio",
"datatype": "Real"
},
{
"name": "mMaxRatio",
"datatype": "Real"
},
{
"name": "mBevBrixMax",
"datatype": "Real"
},
{
"name": "mBevBrixMin",
"datatype": "Real"
}
],
"Return": [
{
"name": "Ret_Val",
"datatype": "Real"
}
]
},
"networks": [
{
"id": "9",
"title": "",
"comment": "",
"language": "SCL",
"logic": [
{
"instruction_uid": "SCL_9",
"type": "RAW_SCL_CHUNK",
"scl": "IF \"Blender_Variables\".gSP_H2O <> 0 THEN\n \"Blender_Variables\".gWaterVFMCalcError := \"Blender_Variables\".gWaterVFMMeasError / 100 * \"Blender_Variables\".gSP_H2O;\nEND_IF;\nIF \"Blender_Variables\".gSP_SYR <> 0 THEN\n \"Blender_Variables\".gSyrupMFMCalcError := (\"Blender_Variables\".gSyrupMFMMeasError / 100 + (\"Blender_Variables\".gSyrupMFMZeroStab / (\"Blender_Variables\".gSP_SYR * 60)) / 100) * \"Blender_Variables\".gSP_SYR;\nEND_IF;\nIF \"Blender_Variables\".gSP_CO2 <> 0 THEN\n \"Blender_Variables\".gCO2MFMCalcError := (\"Blender_Variables\".gCO2MFMMeasError / 100 + (\"Blender_Variables\".gCO2MFMZeroStab / (\"Blender_Variables\".gSP_CO2 * 60 / 1000)) / 100) * \"Blender_Variables\".gSP_CO2;\nEND_IF;\n\"mWaterMaxFlow\" := \"Blender_Variables\".gSP_H2O + \"Blender_Variables\".gWaterVFMCalcError;\n\"mWaterMinFlow\" := \"Blender_Variables\".gSP_H2O - \"Blender_Variables\".gWaterVFMCalcError;\nIF \"HMI_Blender_Parameters\".Actual_Recipe_Parameters._SyrupDensity <> 0 THEN\n \"mSyrupMaxFlow\" := (\"Blender_Variables\".gSP_SYR + \"Blender_Variables\".gSyrupMFMCalcError) / \"HMI_Blender_Parameters\".Actual_Recipe_Parameters._SyrupDensity;\n \"mSyrupMinFlow\" := (\"Blender_Variables\".gSP_SYR - \"Blender_Variables\".gSyrupMFMCalcError) / \"HMI_Blender_Parameters\".Actual_Recipe_Parameters._SyrupDensity;\nEND_IF;\nIF \"mSyrupMaxFlow\" <> 0 THEN\n \"mMinRatio\" := \"mWaterMinFlow\" / \"mSyrupMaxFlow\";\nEND_IF;\nIF \"mSyrupMinFlow\" <> 0 THEN\n \"mMaxRatio\" := \"mWaterMaxFlow\" / \"mSyrupMinFlow\";\nEND_IF;\nIF \"HMI_Blender_Parameters\".Actual_Recipe_Parameters._SyrupDensity <> 0 THEN\n \"mBevBrixMax\" := \"HMI_Blender_Parameters\".Actual_Recipe_Parameters._SyrupBrix / ((\"mMinRatio\" / \"HMI_Blender_Parameters\".Actual_Recipe_Parameters._SyrupDensity) + 1);\n \"mBevBrixMin\" := \"HMI_Blender_Parameters\".Actual_Recipe_Parameters._SyrupBrix / ((\"mMaxRatio\" / \"HMI_Blender_Parameters\".Actual_Recipe_Parameters._SyrupDensity) + 1);\nEND_IF;\n\"Blender_Variables\".gBlenderBlendMaxError := \"mBevBrixMax\" - \"mBevBrixMin\";\n\"TestLAD\" := \"Blender_Variables\".gBlenderBlendMaxError;"
}
]
}
]
}

View File

@ -1,56 +0,0 @@
// Block Name (Original): TestLAD
// Block Number: 2
// Original Language: LAD
FUNCTION_BLOCK "TestLAD"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_RETURN
Ret_Val : Real;
END_VAR
VAR_TEMP
mWaterMaxFlow : Real;
mWaterMinFlow : Real;
mSyrupMaxFlow : Real;
mSyrupMinFlow : Real;
mMinRatio : Real;
mMaxRatio : Real;
mBevBrixMax : Real;
mBevBrixMin : Real;
END_VAR
BEGIN
// Network 1: (Original Language: SCL)
IF "Blender_Variables".gSP_H2O <> 0 THEN
"Blender_Variables".gWaterVFMCalcError := "Blender_Variables".gWaterVFMMeasError / 100 * "Blender_Variables".gSP_H2O;
END_IF;
IF "Blender_Variables".gSP_SYR <> 0 THEN
"Blender_Variables".gSyrupMFMCalcError := ("Blender_Variables".gSyrupMFMMeasError / 100 + ("Blender_Variables".gSyrupMFMZeroStab / ("Blender_Variables".gSP_SYR * 60)) / 100) * "Blender_Variables".gSP_SYR;
END_IF;
IF "Blender_Variables".gSP_CO2 <> 0 THEN
"Blender_Variables".gCO2MFMCalcError := ("Blender_Variables".gCO2MFMMeasError / 100 + ("Blender_Variables".gCO2MFMZeroStab / ("Blender_Variables".gSP_CO2 * 60 / 1000)) / 100) * "Blender_Variables".gSP_CO2;
END_IF;
"mWaterMaxFlow" := "Blender_Variables".gSP_H2O + "Blender_Variables".gWaterVFMCalcError;
"mWaterMinFlow" := "Blender_Variables".gSP_H2O - "Blender_Variables".gWaterVFMCalcError;
IF "HMI_Blender_Parameters".Actual_Recipe_Parameters._SyrupDensity <> 0 THEN
"mSyrupMaxFlow" := ("Blender_Variables".gSP_SYR + "Blender_Variables".gSyrupMFMCalcError) / "HMI_Blender_Parameters".Actual_Recipe_Parameters._SyrupDensity;
"mSyrupMinFlow" := ("Blender_Variables".gSP_SYR - "Blender_Variables".gSyrupMFMCalcError) / "HMI_Blender_Parameters".Actual_Recipe_Parameters._SyrupDensity;
END_IF;
IF "mSyrupMaxFlow" <> 0 THEN
"mMinRatio" := "mWaterMinFlow" / "mSyrupMaxFlow";
END_IF;
IF "mSyrupMinFlow" <> 0 THEN
"mMaxRatio" := "mWaterMaxFlow" / "mSyrupMinFlow";
END_IF;
IF "HMI_Blender_Parameters".Actual_Recipe_Parameters._SyrupDensity <> 0 THEN
"mBevBrixMax" := "HMI_Blender_Parameters".Actual_Recipe_Parameters._SyrupBrix / (("mMinRatio" / "HMI_Blender_Parameters".Actual_Recipe_Parameters._SyrupDensity) + 1);
"mBevBrixMin" := "HMI_Blender_Parameters".Actual_Recipe_Parameters._SyrupBrix / (("mMaxRatio" / "HMI_Blender_Parameters".Actual_Recipe_Parameters._SyrupDensity) + 1);
END_IF;
"Blender_Variables".gBlenderBlendMaxError := "mBevBrixMax" - "mBevBrixMin";
"TestLAD" := "Blender_Variables".gBlenderBlendMaxError;
END_FUNCTION_BLOCK

View File

@ -1,763 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Document>
<Engineering version="V18" />
<SW.Blocks.FC ID="0">
<AttributeList>
<Interface><Sections xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v5">
<Section Name="Input" />
<Section Name="Output" />
<Section Name="InOut" />
<Section Name="Temp">
<Member Name="All_Auto_RETVAL" Datatype="Int" />
<Member Name="Reset_SP_Word_RETVAL" Datatype="Int" />
<Member Name="mResetWaterTot" Datatype="Bool" />
<Member Name="mResetSyrupTot" Datatype="Bool" />
<Member Name="mResetCO2Tot" Datatype="Bool" />
<Member Name="mResetProductTot" Datatype="Bool" />
<Member Name="Block_Move_Err" Datatype="Int" />
<Member Name="Dim_HMI_Device" Datatype="Int" />
<Member Name="PDim_HMI_Device" Datatype="DWord" />
<Member Name="Dim_HMI_PID" Datatype="Int" />
<Member Name="PDim_HMI_PID" Datatype="DWord" />
</Section>
<Section Name="Constant" />
<Section Name="Return">
<Member Name="Ret_Val" Datatype="Void" />
</Section>
</Sections></Interface>
<MemoryLayout>Optimized</MemoryLayout>
<Name>TestLAD</Name>
<Namespace />
<Number>2</Number>
<ProgrammingLanguage>LAD</ProgrammingLanguage>
<SetENOAutomatically>false</SetENOAutomatically>
</AttributeList>
<ObjectList>
<MultilingualText ID="1" CompositionName="Comment">
<ObjectList>
<MultilingualTextItem ID="2" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="3" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="4" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="5" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="6" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="7" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="8" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
<SW.Blocks.CompileUnit ID="9" CompositionName="CompileUnits">
<AttributeList>
<NetworkSource><StatementList xmlns="http://www.siemens.com/automation/Openness/SW/NetworkSource/StatementList/v4">
<StlStatement UId="24">
<StlToken Text="SET" />
</StlStatement>
<StlStatement UId="25">
<StlToken Text="R" />
<Access Scope="GlobalVariable">
<Symbol>
<Component Name="HMI_Alarms" />
<Component Name="gH_Message" AccessModifier="Array">
<Access Scope="LiteralConstant">
<Constant>
<ConstantType>DInt</ConstantType>
<ConstantValue>3</ConstantValue>
</Constant>
</Access>
</Component>
</Symbol>
</Access>
</StlStatement>
</StatementList></NetworkSource>
<ProgrammingLanguage>STL</ProgrammingLanguage>
</AttributeList>
<ObjectList>
<MultilingualText ID="A" CompositionName="Comment">
<ObjectList>
<MultilingualTextItem ID="B" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text> DEVICE</Text>
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="C" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="D" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="E" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="F" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="10" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="11" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
<MultilingualText ID="12" CompositionName="Title">
<ObjectList>
<MultilingualTextItem ID="13" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text>Set manual active</Text>
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="14" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="15" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="16" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="17" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="18" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="19" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
</ObjectList>
</SW.Blocks.CompileUnit>
<SW.Blocks.CompileUnit ID="1A" CompositionName="CompileUnits">
<AttributeList>
<NetworkSource><StatementList xmlns="http://www.siemens.com/automation/Openness/SW/NetworkSource/StatementList/v4">
<StlStatement UId="24">
<StlToken Text="OPEN_DB" />
<Access Scope="GlobalVariable">
<Symbol>
<Component Name="HMI_Device" />
</Symbol>
</Access>
</StlStatement>
<StlStatement UId="26">
<StlToken Text="L_DBLG" />
</StlStatement>
<StlStatement UId="27">
<StlToken Text="T" />
<Access Scope="LocalVariable">
<Symbol>
<Component Name="Dim_HMI_Device" />
</Symbol>
</Access>
</StlStatement>
<StlStatement UId="29">
<StlToken Text="L" />
<Access Scope="LiteralConstant">
<Constant>
<ConstantType>ARef</ConstantType>
<ConstantValue>P#0.0</ConstantValue>
</Constant>
</Access>
</StlStatement>
<StlStatement UId="31">
<StlToken Text="L" />
<Access Scope="LocalVariable">
<Symbol>
<Component Name="Dim_HMI_Device" />
</Symbol>
</Access>
</StlStatement>
<StlStatement UId="33">
<StlToken Text="SLD" />
<Access Scope="LiteralConstant">
<Constant>
<ConstantType>Int</ConstantType>
<ConstantValue>3</ConstantValue>
</Constant>
</Access>
</StlStatement>
<StlStatement UId="35">
<StlToken Text="ADD_D" />
</StlStatement>
<StlStatement UId="36">
<StlToken Text="T" />
<Access Scope="LocalVariable">
<Symbol>
<Component Name="PDim_HMI_Device" />
</Symbol>
</Access>
</StlStatement>
<StlStatement UId="38">
<StlToken Text="L" />
<Access Scope="LiteralConstant">
<Constant>
<ConstantType>ARef</ConstantType>
<ConstantValue>P#0.0</ConstantValue>
</Constant>
</Access>
</StlStatement>
<StlStatement UId="40">
<StlToken Text="LAR1_ACCU1" />
</StlStatement>
<StlStatement UId="41">
<LabelDeclaration>
<Label Name="M100" />
</LabelDeclaration>
<StlToken Text="NOP_0" />
</StlStatement>
<StlStatement UId="43">
<StlToken Text="OPEN_DB" />
<Access Scope="GlobalVariable">
<Symbol>
<Component Name="HMI_Device" />
</Symbol>
</Access>
</StlStatement>
<StlStatement UId="45">
<StlToken Text="A" />
<Access Scope="Address">
<Indirect Width="Bit" Area="DB" Register="AR1" BitOffset="7" />
<LineComment>
<Text> config</Text>
</LineComment>
</Access>
</StlStatement>
<StlStatement UId="48">
<StlToken Text="AN" />
<Access Scope="Address">
<Indirect Width="Bit" Area="DB" Register="AR1" BitOffset="0" />
<LineComment>
<Text> auto</Text>
</LineComment>
</Access>
</StlStatement>
<StlStatement UId="51">
<StlToken Text="S" />
<Access Scope="GlobalVariable">
<Symbol>
<Component Name="HMI_Alarms" />
<Component Name="gH_Message" AccessModifier="Array">
<Access Scope="LiteralConstant">
<Constant>
<ConstantType>DInt</ConstantType>
<ConstantValue>3</ConstantValue>
</Constant>
</Access>
</Component>
</Symbol>
</Access>
</StlStatement>
<StlStatement UId="53">
<StlToken Text="ADDAR1" />
<Access Scope="LiteralConstant">
<Constant>
<ConstantType>ARef</ConstantType>
<ConstantValue>P#2.0</ConstantValue>
</Constant>
</Access>
</StlStatement>
<StlStatement UId="55">
<StlToken Text="TAR1_ACCU1" />
</StlStatement>
<StlStatement UId="56">
<StlToken Text="L" />
<Access Scope="LocalVariable">
<Symbol>
<Component Name="PDim_HMI_Device" />
</Symbol>
</Access>
</StlStatement>
<StlStatement UId="58">
<StlToken Text="LT_D" />
</StlStatement>
<StlStatement UId="59">
<StlToken Text="JC" />
<Access Scope="Label">
<Label Name="M100" />
</Access>
</StlStatement>
</StatementList></NetworkSource>
<ProgrammingLanguage>STL</ProgrammingLanguage>
</AttributeList>
<ObjectList>
<MultilingualText ID="1B" CompositionName="Comment">
<ObjectList>
<MultilingualTextItem ID="1C" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="1D" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="1E" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="1F" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="20" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="21" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="22" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
<MultilingualText ID="23" CompositionName="Title">
<ObjectList>
<MultilingualTextItem ID="24" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="25" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="26" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="27" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="28" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="29" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="2A" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
</ObjectList>
</SW.Blocks.CompileUnit>
<SW.Blocks.CompileUnit ID="2B" CompositionName="CompileUnits">
<AttributeList>
<NetworkSource><StatementList xmlns="http://www.siemens.com/automation/Openness/SW/NetworkSource/StatementList/v4">
<StlStatement UId="24">
<LineComment>
<Text> PID</Text>
</LineComment>
<StlToken Text="COMMENT" />
</StlStatement>
<StlStatement UId="26">
<StlToken Text="OPEN_DB" />
<Access Scope="GlobalVariable">
<Symbol>
<Component Name="HMI_PID" />
</Symbol>
</Access>
</StlStatement>
<StlStatement UId="28">
<StlToken Text="L_DBLG" />
</StlStatement>
<StlStatement UId="29">
<StlToken Text="T" />
<Access Scope="LocalVariable">
<Symbol>
<Component Name="Dim_HMI_PID" />
</Symbol>
</Access>
</StlStatement>
<StlStatement UId="31">
<StlToken Text="L" />
<Access Scope="LiteralConstant">
<Constant>
<ConstantType>ARef</ConstantType>
<ConstantValue>P#0.0</ConstantValue>
</Constant>
</Access>
</StlStatement>
<StlStatement UId="33">
<StlToken Text="L" />
<Access Scope="LocalVariable">
<Symbol>
<Component Name="Dim_HMI_PID" />
</Symbol>
</Access>
</StlStatement>
<StlStatement UId="35">
<StlToken Text="SLD" />
<Access Scope="LiteralConstant">
<Constant>
<ConstantType>Int</ConstantType>
<ConstantValue>3</ConstantValue>
</Constant>
</Access>
</StlStatement>
<StlStatement UId="37">
<StlToken Text="ADD_D" />
</StlStatement>
<StlStatement UId="38">
<StlToken Text="T" />
<Access Scope="LocalVariable">
<Symbol>
<Component Name="PDim_HMI_PID" />
</Symbol>
</Access>
</StlStatement>
<StlStatement UId="40">
<StlToken Text="L" />
<Access Scope="LiteralConstant">
<Constant>
<ConstantType>ARef</ConstantType>
<ConstantValue>P#0.0</ConstantValue>
</Constant>
</Access>
</StlStatement>
<StlStatement UId="42">
<StlToken Text="LAR1_ACCU1" />
</StlStatement>
<StlStatement UId="43">
<LabelDeclaration>
<Label Name="M101" />
</LabelDeclaration>
<StlToken Text="NOP_0" />
</StlStatement>
<StlStatement UId="45">
<StlToken Text="OPEN_DB" />
<Access Scope="GlobalVariable">
<Symbol>
<Component Name="HMI_PID" />
</Symbol>
</Access>
</StlStatement>
<StlStatement UId="47">
<StlToken Text="A" />
<Access Scope="Address">
<Indirect Width="Bit" Area="DB" Register="AR1" BitOffset="7" />
<LineComment>
<Text> config</Text>
</LineComment>
</Access>
</StlStatement>
<StlStatement UId="50">
<StlToken Text="A_BRACK" />
</StlStatement>
<StlStatement UId="51">
<StlToken Text="A" />
<Access Scope="Address">
<Indirect Width="Bit" Area="DB" Register="AR1" BitOffset="16" />
<LineComment>
<Text> ManOut</Text>
</LineComment>
</Access>
</StlStatement>
<StlStatement UId="54">
<StlToken Text="O" />
<Access Scope="Address">
<Indirect Width="Bit" Area="DB" Register="AR1" BitOffset="24" />
<LineComment>
<Text> LocalSP</Text>
</LineComment>
</Access>
</StlStatement>
<StlStatement UId="57">
<StlToken Text="BRACKET" />
</StlStatement>
<StlStatement UId="58">
<StlToken Text="S" />
<Access Scope="GlobalVariable">
<Symbol>
<Component Name="HMI_Alarms" />
<Component Name="gH_Message" AccessModifier="Array">
<Access Scope="LiteralConstant">
<Constant>
<ConstantType>DInt</ConstantType>
<ConstantValue>3</ConstantValue>
</Constant>
</Access>
</Component>
</Symbol>
</Access>
</StlStatement>
<StlStatement UId="60">
<StlToken Text="ADDAR1" />
<Access Scope="LiteralConstant">
<Constant>
<ConstantType>ARef</ConstantType>
<ConstantValue>P#76.0</ConstantValue>
</Constant>
</Access>
</StlStatement>
<StlStatement UId="62">
<StlToken Text="TAR1_ACCU1" />
</StlStatement>
<StlStatement UId="63">
<StlToken Text="L" />
<Access Scope="LocalVariable">
<Symbol>
<Component Name="PDim_HMI_PID" />
</Symbol>
</Access>
</StlStatement>
<StlStatement UId="65">
<StlToken Text="LT_D" />
</StlStatement>
<StlStatement UId="66">
<StlToken Text="JC" />
<Access Scope="Label">
<Label Name="M101" />
</Access>
</StlStatement>
</StatementList></NetworkSource>
<ProgrammingLanguage>STL</ProgrammingLanguage>
</AttributeList>
<ObjectList>
<MultilingualText ID="2C" CompositionName="Comment">
<ObjectList>
<MultilingualTextItem ID="2D" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="2E" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="2F" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="30" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="31" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="32" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="33" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
<MultilingualText ID="34" CompositionName="Title">
<ObjectList>
<MultilingualTextItem ID="35" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="36" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="37" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="38" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="39" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="3A" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="3B" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
</ObjectList>
</SW.Blocks.CompileUnit>
<MultilingualText ID="3C" CompositionName="Title">
<ObjectList>
<MultilingualTextItem ID="3D" CompositionName="Items">
<AttributeList>
<Culture>it-IT</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="3E" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="3F" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="40" CompositionName="Items">
<AttributeList>
<Culture>es-ES</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="41" CompositionName="Items">
<AttributeList>
<Culture>fr-FR</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="42" CompositionName="Items">
<AttributeList>
<Culture>zh-CN</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="43" CompositionName="Items">
<AttributeList>
<Culture>ja-JP</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
</ObjectList>
</SW.Blocks.FC>
</Document>

View File

@ -1,101 +0,0 @@
{
"block_name": "TestLAD",
"block_number": 2,
"language": "LAD",
"block_comment": "",
"interface": {
"Temp": [
{
"name": "All_Auto_RETVAL",
"datatype": "Int"
},
{
"name": "Reset_SP_Word_RETVAL",
"datatype": "Int"
},
{
"name": "mResetWaterTot",
"datatype": "Bool"
},
{
"name": "mResetSyrupTot",
"datatype": "Bool"
},
{
"name": "mResetCO2Tot",
"datatype": "Bool"
},
{
"name": "mResetProductTot",
"datatype": "Bool"
},
{
"name": "Block_Move_Err",
"datatype": "Int"
},
{
"name": "Dim_HMI_Device",
"datatype": "Int"
},
{
"name": "PDim_HMI_Device",
"datatype": "DWord"
},
{
"name": "Dim_HMI_PID",
"datatype": "Int"
},
{
"name": "PDim_HMI_PID",
"datatype": "DWord"
}
],
"Return": [
{
"name": "Ret_Val",
"datatype": "Void"
}
]
},
"networks": [
{
"id": "9",
"title": "Set manual active",
"comment": "DEVICE",
"language": "STL",
"logic": [
{
"instruction_uid": "UNS_9",
"type": "UNSUPPORTED_LANG",
"scl": "// Network 9 uses unsupported language: STL\n"
}
]
},
{
"id": "1A",
"title": "",
"comment": "",
"language": "STL",
"logic": [
{
"instruction_uid": "UNS_1A",
"type": "UNSUPPORTED_LANG",
"scl": "// Network 1A uses unsupported language: STL\n"
}
]
},
{
"id": "2B",
"title": "",
"comment": "",
"language": "STL",
"logic": [
{
"instruction_uid": "UNS_2B",
"type": "UNSUPPORTED_LANG",
"scl": "// Network 2B uses unsupported language: STL\n"
}
]
}
]
}

View File

@ -1,101 +0,0 @@
{
"block_name": "TestLAD",
"block_number": 2,
"language": "LAD",
"block_comment": "",
"interface": {
"Temp": [
{
"name": "All_Auto_RETVAL",
"datatype": "Int"
},
{
"name": "Reset_SP_Word_RETVAL",
"datatype": "Int"
},
{
"name": "mResetWaterTot",
"datatype": "Bool"
},
{
"name": "mResetSyrupTot",
"datatype": "Bool"
},
{
"name": "mResetCO2Tot",
"datatype": "Bool"
},
{
"name": "mResetProductTot",
"datatype": "Bool"
},
{
"name": "Block_Move_Err",
"datatype": "Int"
},
{
"name": "Dim_HMI_Device",
"datatype": "Int"
},
{
"name": "PDim_HMI_Device",
"datatype": "DWord"
},
{
"name": "Dim_HMI_PID",
"datatype": "Int"
},
{
"name": "PDim_HMI_PID",
"datatype": "DWord"
}
],
"Return": [
{
"name": "Ret_Val",
"datatype": "Void"
}
]
},
"networks": [
{
"id": "9",
"title": "Set manual active",
"comment": "DEVICE",
"language": "STL",
"logic": [
{
"instruction_uid": "UNS_9",
"type": "UNSUPPORTED_LANG",
"scl": "// Network 9 uses unsupported language: STL\n"
}
]
},
{
"id": "1A",
"title": "",
"comment": "",
"language": "STL",
"logic": [
{
"instruction_uid": "UNS_1A",
"type": "UNSUPPORTED_LANG",
"scl": "// Network 1A uses unsupported language: STL\n"
}
]
},
{
"id": "2B",
"title": "",
"comment": "",
"language": "STL",
"logic": [
{
"instruction_uid": "UNS_2B",
"type": "UNSUPPORTED_LANG",
"scl": "// Network 2B uses unsupported language: STL\n"
}
]
}
]
}

View File

@ -1,42 +0,0 @@
// Block Name (Original): TestLAD
// Block Number: 2
// Original Language: LAD
FUNCTION_BLOCK "TestLAD"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_RETURN
Ret_Val : Void;
END_VAR
VAR_TEMP
All_Auto_RETVAL : Int;
Reset_SP_Word_RETVAL : Int;
mResetWaterTot : Bool;
mResetSyrupTot : Bool;
mResetCO2Tot : Bool;
mResetProductTot : Bool;
Block_Move_Err : Int;
Dim_HMI_Device : Int;
PDim_HMI_Device : DWord;
Dim_HMI_PID : Int;
PDim_HMI_PID : DWord;
END_VAR
BEGIN
// Network 1: Set manual active (Original Language: STL)
// DEVICE
// Network 9 uses unsupported language: STL
// Network 2: (Original Language: STL)
// Network 1A uses unsupported language: STL
// Network 3: (Original Language: STL)
// Network 2B uses unsupported language: STL
END_FUNCTION_BLOCK

View File

@ -97,6 +97,81 @@ def select_xml_file():
if __name__ == "__main__":
# Imports necesarios para esta sección
import os
import sys
import glob # Asegúrate de que glob esté importado al principio del archivo
# Directorio base donde buscar los archivos XML (relativo al script)
base_search_dir = "XML Project"
script_dir = os.path.dirname(__file__) # Directorio donde está x0_main.py
xml_project_dir = os.path.join(script_dir, base_search_dir)
print(f"Buscando archivos XML recursivamente en: '{xml_project_dir}'")
# Verificar si el directorio 'XML Project' existe
if not os.path.isdir(xml_project_dir):
print(f"Error: El directorio '{xml_project_dir}' no existe o no es un directorio.")
print("Por favor, crea el directorio 'XML Project' en la misma carpeta que este script y coloca tus archivos XML dentro.")
sys.exit(1)
# Buscar todos los archivos .xml recursivamente dentro de xml_project_dir
# Usamos os.path.join para construir la ruta de búsqueda correctamente
# y '**/*.xml' para la recursividad con glob
search_pattern = os.path.join(xml_project_dir, '**', '*.xml')
xml_files_found = glob.glob(search_pattern, recursive=True)
if not xml_files_found:
print(f"No se encontraron archivos XML en '{xml_project_dir}' o sus subdirectorios.")
sys.exit(0) # Salir limpiamente si no hay archivos
print(f"Se encontraron {len(xml_files_found)} archivos XML para procesar:")
# Ordenar para un procesamiento predecible (opcional)
xml_files_found.sort()
for xml_file in xml_files_found:
# Imprimir la ruta relativa desde el directorio del script para claridad
print(f" - {os.path.relpath(xml_file, script_dir)}")
# Scripts a ejecutar en secuencia (asegúrate que los nombres son correctos)
script1 = "x1_to_json.py"
script2 = "x2_process.py"
script3 = "x3_generate_scl.py"
# Procesar cada archivo encontrado
processed_count = 0
failed_count = 0
for xml_filepath in xml_files_found:
print(f"\n--- Iniciando pipeline para: {os.path.relpath(xml_filepath, script_dir)} ---")
# Usar la ruta absoluta para evitar problemas si los scripts cambian de directorio
absolute_xml_filepath = os.path.abspath(xml_filepath)
# Ejecutar los scripts en secuencia para el archivo actual
# La función run_script ya está definida en tu script x0_main.py
success = True
if not run_script(script1, absolute_xml_filepath):
print(f"\nPipeline falló en el script '{script1}' para el archivo: {os.path.relpath(xml_filepath, script_dir)}")
success = False
elif not run_script(script2, absolute_xml_filepath):
print(f"\nPipeline falló en el script '{script2}' para el archivo: {os.path.relpath(xml_filepath, script_dir)}")
success = False
elif not run_script(script3, absolute_xml_filepath):
print(f"\nPipeline falló en el script '{script3}' para el archivo: {os.path.relpath(xml_filepath, script_dir)}")
success = False
if success:
print(f"--- Pipeline completado exitosamente para: {os.path.relpath(xml_filepath, script_dir)} ---")
processed_count += 1
else:
failed_count += 1
print(f"--- Pipeline falló para: {os.path.relpath(xml_filepath, script_dir)} ---")
print("\n--- Resumen Final del Procesamiento ---")
print(f"Total de archivos XML encontrados: {len(xml_files_found)}")
print(f"Archivos procesados exitosamente por el pipeline completo: {processed_count}")
print(f"Archivos que fallaron en algún punto del pipeline: {failed_count}")
print("---------------------------------------")
xml_filename = None
# Comprobar si se pasó un argumento de línea de comandos

View File

@ -2,6 +2,7 @@
import json
import argparse
import os
import re
from lxml import etree
import traceback
from collections import defaultdict
@ -11,7 +12,8 @@ from collections import defaultdict
ns = {
"iface": "http://www.siemens.com/automation/Openness/SW/Interface/v5",
"flg": "http://www.siemens.com/automation/Openness/SW/NetworkSource/FlgNet/v4",
"st": "http://www.siemens.com/automation/Openness/SW/NetworkSource/StructuredText/v3", # <--- Added SCL namespace
"st": "http://www.siemens.com/automation/Openness/SW/NetworkSource/StructuredText/v3",
"stl": "http://www.siemens.com/automation/Openness/SW/NetworkSource/StatementList/v4",
}
@ -44,7 +46,6 @@ def get_multilingual_text(element, default_lang="en-US", fallback_lang="it-IT"):
print(f"Advertencia: Error extrayendo MultilingualText: {e}")
return ""
def get_symbol_name(symbol_element):
# (Sin cambios respecto a la versión anterior)
if symbol_element is None:
@ -56,7 +57,6 @@ def get_symbol_name(symbol_element):
print(f"Advertencia: Excepción en get_symbol_name: {e}")
return None
def parse_access(access_element):
# (Sin cambios respecto a la versión anterior)
if access_element is None:
@ -149,7 +149,6 @@ def parse_access(access_element):
return info
return info
def parse_part(part_element):
# (Sin cambios respecto a la versión anterior)
if part_element is None:
@ -185,7 +184,6 @@ def parse_part(part_element):
"negated_pins": negated_pins,
}
def parse_call(call_element):
# (Mantiene la corrección para DB de instancia)
if call_element is None:
@ -245,20 +243,17 @@ def parse_call(call_element):
call_data["instance_scope"] = instance_scope
return call_data
# EN x1_to_json.py, junto a otras funciones auxiliares
# SCL (Structured Text) Parser
def reconstruct_scl_from_tokens(st_node):
"""
Intenta reconstruir una cadena SCL a partir de los elementos hijos
de un nodo <StructuredText>. Es una aproximación y puede no ser perfecta.
Reconstruye SCL desde <StructuredText>, mejorando el manejo de
variables, constantes literales, tokens básicos, espacios y saltos de línea.
"""
if st_node is None:
return "// Error: StructuredText node not found.\n"
scl_parts = []
# Obtener todos los elementos hijos directos en orden
children = st_node.xpath("./st:*", namespaces=ns)
for elem in children:
@ -267,86 +262,335 @@ def reconstruct_scl_from_tokens(st_node):
if tag == "Token":
scl_parts.append(elem.get("Text", ""))
elif tag == "Blank":
scl_parts.append(" " * int(elem.get("Num", 1)))
# Añadir espacios simples, evitar múltiples si ya hay uno antes/después
if not scl_parts or not scl_parts[-1].endswith(' '):
scl_parts.append(" " * int(elem.get("Num", 1)))
elif int(elem.get("Num", 1)) > 1: # Añadir extras si son más de 1
scl_parts.append(" " * (int(elem.get("Num", 1))-1))
elif tag == "NewLine":
# Añadir un salto de línea real. strip() al final de la línea actual
# para evitar espacios extra antes del salto.
# Limpiar espacios antes del salto de línea real
if scl_parts:
scl_parts[-1] = scl_parts[-1].rstrip()
scl_parts.append("\n")
elif tag == "Access":
# Reconstruir acceso (simplificado)
symbol_parts = []
# Buscar componentes y puntos dentro del símbolo de este acceso
symbol_children = elem.xpath(
".//st:Component | .//st:Token[@Text='.']", namespaces=ns
)
for sym_child in symbol_children:
sym_tag = etree.QName(sym_child.tag).localname
if sym_tag == "Component":
comp_name = sym_child.get("Name", "_ERR_")
# Comprobar si necesita comillas (podríamos necesitar parsear BooleanAttribute)
# Simplificación: Añadir comillas si el nombre original parece tenerlas (o siempre para DBs?)
# Aquí usamos el nombre tal cual viene en el XML por ahora
# Si el XML tiene <BooleanAttribute Name="HasQuotes">true</BooleanAttribute> podríamos usarlo
has_quotes_elem = sym_child.xpath(
"../st:BooleanAttribute[@Name='HasQuotes']/text()",
namespaces=ns,
)
has_quotes = (
has_quotes_elem and has_quotes_elem[0].lower() == "true"
)
scope = elem.get("Scope")
access_str = f"/*_ERR_Scope_{scope}_*/" # Fallback más informativo
# Reconstrucción básica: poner comillas si HasQuotes es true o si es el primer componente (posible DB)
# Esto es heurístico y puede fallar.
# if has_quotes or (len(symbol_parts) == 0 and '.' not in comp_name): # Asumir primer componente es DB
# symbol_parts.append(f'"{comp_name}"')
# else:
# symbol_parts.append(comp_name)
if scope in ["GlobalVariable", "LocalVariable", "TempVariable", "InOutVariable", "InputVariable", "OutputVariable", "ConstantVariable"]: # Tipos comunes de variables
symbol_elem = elem.xpath("./st:Symbol", namespaces=ns)
if symbol_elem:
components = symbol_elem[0].xpath("./st:Component", namespaces=ns)
symbol_text_parts = []
for i, comp in enumerate(components):
name = comp.get("Name", "_ERR_COMP_")
# Añadir punto si no es el primer componente
if i > 0:
symbol_text_parts.append(".")
# Versión más simple: usar nombre tal cual del XML
symbol_parts.append(comp_name)
# Reconstrucción de comillas (heurística)
has_quotes_elem = comp.xpath("../st:BooleanAttribute[@Name='HasQuotes']/text()", namespaces=ns)
has_quotes = has_quotes_elem and has_quotes_elem[0].lower() == "true"
is_temp = name.startswith('#')
elif sym_tag == "Token": # Solo nos interesa el punto aquí
symbol_parts.append(".")
access_str = "".join(symbol_parts)
if has_quotes or (i == 0 and not is_temp): # Comillas si HasQuotes o primer componente (no temp)
symbol_text_parts.append(f'"{name}"')
else:
symbol_text_parts.append(name)
# Manejar llamadas a funciones/FB dentro de Access Scope="Call"
if elem.get("Scope") == "Call":
instruction_elem = elem.xpath("./st:Instruction", namespaces=ns)
if instruction_elem:
instr_name = instruction_elem[0].get("Name", "_UNKNOWN_CALL_")
# Reconstrucción básica de parámetros (muy simplificada)
# Necesitaría parsear Parameters, Tokens '(', ')', ':=', '=>', etc.
# Por ahora, solo añadimos el nombre y paréntesis vacíos
access_str = f"{instr_name}()" # Placeholder muy básico
# Manejar índices de array (RECURSIVO)
index_access = comp.xpath("./st:Access", namespaces=ns)
if index_access:
# Llama recursivamente para obtener el texto de cada índice
indices_text = [reconstruct_scl_from_tokens(idx_node) for idx_node in index_access]
symbol_text_parts.append(f"[{','.join(indices_text)}]")
access_str = "".join(symbol_text_parts)
elif scope == "LiteralConstant":
constant_elem = elem.xpath("./st:Constant", namespaces=ns)
if constant_elem:
val_elem = constant_elem[0].xpath("./st:ConstantValue/text()", namespaces=ns)
type_elem = constant_elem[0].xpath("./st:ConstantType/text()", namespaces=ns)
const_type = type_elem[0] if type_elem else ""
const_val = val_elem[0] if val_elem else "_ERR_CONSTVAL_"
# **CORRECCIÓN CLAVE**: Usar el valor extraído
access_str = const_val
# Opcional: añadir prefijos T#, L#, etc. si es necesario
# if const_type == "Time": access_str = f"T#{const_val}"
# elif const_type == "LTime": access_str = f"LT#{const_val}"
# ... otros tipos ...
else:
access_str = "/*_ERR_NOCONST_*/"
# --- Añadir más manejo de scopes aquí si es necesario ---
# elif scope == "Call": access_str = reconstruct_call(elem)
# elif scope == "Expression": access_str = reconstruct_expression(elem)
scl_parts.append(access_str)
elif tag == "Comment" or tag == "LineComment":
# Añadir comentarios
comment_text = elem.text if elem.text else ""
if tag == "Comment" and "\n" in comment_text: # Comentario multi-línea
scl_parts.append(f"(*{comment_text}*)")
else: # Comentario de una línea
scl_parts.append(f"// {comment_text}")
else:
# Ignorar otros tipos de nodos por ahora o añadir manejo específico
pass
comment_text = "".join(elem.xpath(".//text()")).strip()
if tag == "Comment":
scl_parts.append(f"(* {comment_text} *)")
else:
scl_parts.append(f"// {comment_text}")
# else: Ignorar otros nodos
# Unir todas las partes, limpiar espacios extra alrededor de saltos de línea
# Unir partes, limpiar espacios extra alrededor de operadores y saltos de línea
full_scl = "".join(scl_parts)
# Limpieza básica de formato
lines = [line.rstrip() for line in full_scl.split("\n")]
# Re-ensamblar, asegurando que líneas vacías (solo espacios previos) se mantengan
cleaned_scl = "\n".join(lines)
# Eliminar múltiples líneas vacías consecutivas (opcional)
# import re
# cleaned_scl = re.sub(r'\n\s*\n', '\n\n', cleaned_scl)
return cleaned_scl.strip() # Quitar espacios/saltos al inicio/final
# --- Función parse_network con XPath corregido para Title/Comment ---
# --- Función parse_network MODIFICADA (maneja multi-destino en Wire) ---
# Re-indentar líneas después de IF/THEN, etc. (Simplificado)
output_lines = []
indent_level = 0
for line in full_scl.split('\n'):
line = line.strip()
if not line: continue # Saltar líneas vacías
# Reducir indentación antes de procesar END_IF, ELSE, etc. (simplificado)
if line.startswith(('END_IF', 'END_WHILE', 'END_FOR', 'END_CASE', 'ELSE', 'ELSIF')):
indent_level = max(0, indent_level - 1)
output_lines.append(" " * indent_level + line) # Aplicar indentación
# Aumentar indentación después de IF, WHILE, FOR, CASE, ELSE, ELSIF (simplificado)
if line.endswith('THEN') or line.endswith('DO') or line.endswith('OF') or line == 'ELSE':
indent_level += 1
# Nota: Esto no maneja bloques BEGIN/END dentro de SCL
return "\n".join(output_lines)
# STL (Statement List) Parser
def get_access_text(access_element):
"""Reconstruye una representación textual simple de un Access en STL."""
if access_element is None:
return "_ERR_ACCESS_"
scope = access_element.get("Scope")
# Intenta reconstruir el símbolo
# CORREGIDO: Añadido namespaces=ns
symbol_elem = access_element.xpath("./stl:Symbol", namespaces=ns)
if symbol_elem:
# CORREGIDO: Añadido namespaces=ns
components = symbol_elem[0].xpath("./stl:Component", namespaces=ns)
parts = []
for comp in components:
name = comp.get("Name", "_ERR_COMP_")
# CORREGIDO: Añadido namespaces=ns
has_quotes_elem = comp.xpath("../stl:BooleanAttribute[@Name='HasQuotes']/text()", namespaces=ns)
has_quotes = has_quotes_elem and has_quotes_elem[0].lower() == "true"
# Usar nombre tal cual por ahora
parts.append(name)
# Añadir índices si existen
# CORREGIDO: Añadido namespaces=ns
index_access = comp.xpath("./stl:Access", namespaces=ns)
if index_access:
indices = [get_access_text(ia) for ia in index_access]
parts.append(f"[{','.join(indices)}]")
return ".".join(parts)
# Intenta reconstruir constante
# CORREGIDO: Añadido namespaces=ns
constant_elem = access_element.xpath("./stl:Constant", namespaces=ns)
if constant_elem:
# CORREGIDO: Añadido namespaces=ns
val_elem = constant_elem[0].xpath("./stl:ConstantValue/text()", namespaces=ns)
type_elem = constant_elem[0].xpath("./stl:ConstantType/text()", namespaces=ns) # Obtener tipo para mejor formato
const_type = type_elem[0] if type_elem else ""
const_val = val_elem[0] if val_elem else "_ERR_CONST_"
# Añadir prefijo de tipo si es necesario (ej. T# , L#) - Simplificado
if const_type == "Time": return f"T#{const_val}"
if const_type == "ARef": return f"{const_val}" # No necesita prefijo
# Añadir más tipos si es necesario
return const_val # Valor directo para otros tipos
# Intenta reconstruir etiqueta
# CORREGIDO: Añadido namespaces=ns
label_elem = access_element.xpath("./stl:Label", namespaces=ns)
if label_elem:
name = label_elem[0].get("Name", "_ERR_LABEL_")
return name
# Intenta reconstruir acceso indirecto (simplificado)
# CORREGIDO: Añadido namespaces=ns
indirect_elem = access_element.xpath("./stl:Indirect", namespaces=ns)
if indirect_elem:
reg = indirect_elem[0].get("Register", "AR?")
offset_str = indirect_elem[0].get("BitOffset", "0")
area = indirect_elem[0].get("Area", "DB")
width = indirect_elem[0].get("Width", "X")
# Convertir BitOffset a formato P#Byte.Bit
try:
bit_offset = int(offset_str)
byte_offset = bit_offset // 8
bit_in_byte = bit_offset % 8
p_format_offset = f"P#{byte_offset}.{bit_in_byte}"
except ValueError:
p_format_offset = "P#?.?"
# Formatear ancho
width_map = {"Bit": "X", "Byte": "B", "Word": "W", "Double": "D"}
width_char = width_map.get(width, width[0] if width else "?") # Usa primera letra si no mapeado
return f"{area}{width_char}[{reg},{p_format_offset}]"
# Intenta reconstruir dirección absoluta
# CORREGIDO: Añadido namespaces=ns
address_elem = access_element.xpath("./stl:Address", namespaces=ns)
if address_elem:
area = address_elem[0].get("Area", "??")
bit_offset_str = address_elem[0].get("BitOffset", "0")
addr_type_str = address_elem[0].get("Type", "Bool") # Obtener tipo para ancho
try:
bit_offset = int(bit_offset_str)
byte_offset = bit_offset // 8
bit_in_byte = bit_offset % 8
# Determinar ancho basado en tipo (simplificación)
addr_width = "X" # Default a Bit
if addr_type_str == "Byte": addr_width = "B"
elif addr_type_str == "Word": addr_width = "W"
elif addr_type_str in ["DWord", "DInt"]: addr_width = "D"
# Añadir más tipos si es necesario (Real, etc.)
# Mapear Area para STL estándar
area_map = { "Input": "I", "Output": "Q", "Memory": "M",
"PeripheryInput": "PI", "PeripheryOutput": "PQ",
"DB": "DB", "DI": "DI", "Local": "L", # L no siempre válido aquí
"Timer": "T", "Counter": "C" }
stl_area = area_map.get(area, area)
# Manejar DB/DI que necesitan número de bloque
if stl_area in ["DB", "DI"]:
block_num = address_elem[0].get("BlockNumber")
if block_num:
return f"{stl_area}{block_num}.{stl_area}{addr_width}{byte_offset}.{bit_in_byte}" # Ej: DB1.DBX0.1
else: # Acceso con registro DB/DI
return f"{stl_area}{addr_width}{byte_offset}.{bit_in_byte}" # Ej: DBX0.1
elif stl_area in ["T", "C"]:
return f"{stl_area}{byte_offset}" # Los timers/contadores solo usan el número
else: # I, Q, M, L, PI, PQ
return f"{stl_area}{addr_width}{byte_offset}.{bit_in_byte}" # Ej: M10.1, I0.0
except ValueError:
return f"{area}?{bit_offset_str}?"
return f"_{scope}_?" # Fallback
def get_comment_text(comment_element):
"""Extrae texto de un LineComment o Comment."""
if comment_element is None: return ""
# Usar get_multilingual_text si los comentarios son multilingües
# Si no, extraer texto directamente
ml_texts = comment_element.xpath(".//mlt:MultilingualTextItem/mlt:AttributeList/mlt:Text/text()",
namespaces={'mlt': "http://www.siemens.com/automation/Openness/SW/Interface/v5"}) # Asumiendo ns
if ml_texts:
# Podrías intentar obtener un idioma específico o simplemente el primero
return ml_texts[0].strip() if ml_texts else ""
# Fallback a texto directo si no hay estructura multilingüe
text_nodes = comment_element.xpath("./text()")
return "".join(text_nodes).strip()
def reconstruct_stl_from_statementlist(statement_list_node):
"""Reconstruye el código STL como una cadena de texto desde <StatementList>."""
if statement_list_node is None:
return "// Error: StatementList node not found.\n"
stl_lines = []
# CORREGIDO: Añadido namespaces=ns
statements = statement_list_node.xpath("./stl:StlStatement", namespaces=ns)
for stmt in statements:
line_parts = []
line_comment = "" # Comentario al final de la línea
# 1. Comentarios al inicio de la línea (como líneas separadas //)
# CORREGIDO: Añadido namespaces=ns
initial_comments = stmt.xpath("child::stl:Comment | child::stl:LineComment", namespaces=ns)
for comm in initial_comments:
comment_text = get_comment_text(comm)
if comment_text:
# Dividir comentarios multilínea en varias líneas //
for comment_line in comment_text.splitlines():
stl_lines.append(f"// {comment_line}")
# 2. Etiqueta (si existe)
# CORREGIDO: Añadido namespaces=ns
label_decl = stmt.xpath("./stl:LabelDeclaration", namespaces=ns)
label_str = ""
if label_decl:
# CORREGIDO: Añadido namespaces=ns
label_name_nodes = label_decl[0].xpath("./stl:Label/@Name", namespaces=ns)
if label_name_nodes:
label_str = f"{label_name_nodes[0]}:"
# Buscar comentarios DENTRO de LabelDeclaration pero después de Label
# CORREGIDO: Añadido namespaces=ns
label_comments = label_decl[0].xpath("./stl:Comment | ./stl:LineComment", namespaces=ns)
for lcomm in label_comments:
comment_text = get_comment_text(lcomm)
if comment_text: line_comment += f" // {comment_text}" # Añadir al comentario de línea
# 3. Token de Instrucción STL
# CORREGIDO: Añadido namespaces=ns
instruction_token = stmt.xpath("./stl:StlToken", namespaces=ns)
instruction_str = ""
if instruction_token:
token_text = instruction_token[0].get("Text", "_ERR_TOKEN_")
instruction_str = token_text
# Comentarios asociados directamente al token
# CORREGIDO: Añadido namespaces=ns
token_comments = instruction_token[0].xpath("./stl:Comment | ./stl:LineComment", namespaces=ns)
for tcomm in token_comments:
comment_text = get_comment_text(tcomm)
if comment_text: line_comment += f" // {comment_text}" # Añadir al comentario de línea
# 4. Acceso/Operando STL
# CORREGIDO: Añadido namespaces=ns
access_elem = stmt.xpath("./stl:Access", namespaces=ns)
access_str = ""
if access_elem:
access_text = get_access_text(access_elem[0])
access_str = access_text
# Comentarios DENTRO del Access (pueden ser de línea o bloque)
# CORREGIDO: Añadido namespaces=ns
access_comments = access_elem[0].xpath("child::stl:LineComment | child::stl:Comment", namespaces=ns)
for acc_comm in access_comments:
comment_text = get_comment_text(acc_comm)
if comment_text: line_comment += f" // {comment_text}" # Añadir al comentario de línea
# Construir la línea: Etiqueta (si hay) + Tab + Instrucción + Espacio + Operando (si hay) + Comentario(s)
current_line = ""
if label_str:
current_line += label_str
if instruction_str:
if current_line: # Si ya había etiqueta, añadir tabulador
current_line += "\t"
current_line += instruction_str
if access_str:
if current_line: # Si ya había algo, añadir espacio
current_line += " "
current_line += access_str
if line_comment:
# Añadir espacio antes del comentario si hay código en la línea
if current_line.strip():
current_line += f" {line_comment}"
else: # Si la línea estaba vacía (solo comentarios iniciales), poner el comentario de línea
current_line = line_comment
# Añadir la línea construida solo si no está vacía
if current_line.strip():
stl_lines.append(current_line.rstrip()) # Eliminar espacios finales
return "\n".join(stl_lines)
# --- Main Parsing Function ---
def parse_network(network_element):
"""
Parsea una red, extrae lógica y añade conexiones EN implícitas.
@ -792,8 +1036,6 @@ def parse_network(network_element):
"logic": network_logic_final,
}
# --- Función Principal convert_xml_to_json (sin cambios en su flujo general) ---
def convert_xml_to_json(xml_filepath, json_filepath):
print(f"Iniciando conversión de '{xml_filepath}' a '{json_filepath}'...")
if not os.path.exists(xml_filepath):
@ -989,6 +1231,38 @@ def convert_xml_to_json(xml_filepath, json_filepath):
],
}
# --- NUEVO MANEJO STL ---
elif programming_language == "STL":
statement_list_node = (
network_source_node.xpath("./stl:StatementList", namespaces=ns)
if network_source_node is not None
else None
)
reconstructed_stl = f"// STL extraction failed for Network {network_id}: StatementList node not found.\n"
if statement_list_node:
print(f" Reconstruyendo STL desde StatementList para red {network_id}...")
# Llama a la nueva función de reconstrucción STL
reconstructed_stl = reconstruct_stl_from_statementlist(statement_list_node[0])
# print(f" ... STL reconstruido (parcial):\n{reconstructed_stl[:200]}...") # Preview opcional
else:
print(f" Advertencia: No se encontró nodo <StatementList> para red STL {network_id}.")
# Guardar como un chunk de texto crudo
parsed_network_data = {
"id": network_id,
"title": network_title,
"comment": network_comment,
"language": "STL", # Indicar que es STL
"logic": [
{
"instruction_uid": f"STL_{network_id}", # UID inventado
"type": "RAW_STL_CHUNK", # Nuevo tipo para identificarlo
"stl": reconstructed_stl, # Guardar el texto reconstruido
}
],
}
elif programming_language in ["LAD", "FBD"]:
# Para LAD/FBD, llamar a parse_network (que espera FlgNet dentro de NetworkSource)
# parse_network ya maneja su propio título/comentario si es necesario, pero podemos pasar los extraídos
@ -1066,41 +1340,46 @@ def convert_xml_to_json(xml_filepath, json_filepath):
traceback.print_exc()
print("--- Fin Traceback ---")
# --- Punto de Entrada Principal ---
if __name__ == "__main__":
# Imports necesarios solo para la ejecución como script principal
import argparse
import os
import sys
# Configurar ArgumentParser para recibir la ruta del XML obligatoria
parser = argparse.ArgumentParser(
description="Convert Simatic XML LAD/FBD to simplified JSON."
description="Convert Simatic XML (LAD/FBD/SCL/STL) to simplified JSON. Expects XML filepath as argument."
)
parser.add_argument(
"xml_filepath",
nargs="?", # Argumento opcional
default="TestLAD.xml", # Valor por defecto si se ejecuta sin argumentos
help="Path to the input XML file (default: TestLAD.xml)",
"xml_filepath", # Argumento posicional obligatorio
help="Path to the input XML file passed from the main script (x0_main.py).",
)
args = parser.parse_args()
args = parser.parse_args() # Parsea los argumentos de sys.argv
xml_input_file = args.xml_filepath
xml_input_file = args.xml_filepath # Obtiene la ruta del argumento
# Verificar si el archivo de entrada existe
# Verificar si el archivo de entrada existe (es una buena práctica aunque x0 lo haga)
if not os.path.exists(xml_input_file):
print(f"Error Crítico: Archivo XML no encontrado: '{xml_input_file}'")
sys.exit(1) # Salir si el archivo no existe
print(f"Error Crítico (x1): Archivo XML no encontrado: '{xml_input_file}'")
sys.exit(1) # Salir si el archivo no existe
# Derivar nombre base para archivo de salida JSON
# os.path.basename obtiene el nombre del archivo de la ruta
# os.path.splitext divide el nombre y la extensión
# El archivo JSON se guardará en el mismo directorio que el XML de entrada
xml_filename_base = os.path.splitext(os.path.basename(xml_input_file))[0]
# Construir la ruta de salida en el mismo directorio que el script o el XML
output_dir = os.path.dirname(
xml_input_file
) # O usar os.path.dirname(__file__) para el directorio del script
output_dir = os.path.dirname(xml_input_file) # Directorio del XML de entrada
# Asegurarse de que el directorio de salida exista (aunque debería si el XML existe)
os.makedirs(output_dir, exist_ok=True)
json_output_file = os.path.join(output_dir, f"{xml_filename_base}_simplified.json")
# Llamar a la función principal con los nombres de archivo derivados
convert_xml_to_json(xml_input_file, json_output_file)
print(f"(x1) Convirtiendo: '{os.path.relpath(xml_input_file)}' -> '{os.path.relpath(json_output_file)}'")
# Llamar a la función principal de conversión del script
# Asumiendo que tu función principal se llama convert_xml_to_json(input_path, output_path)
try:
convert_xml_to_json(xml_input_file, json_output_file)
except Exception as e:
print(f"Error Crítico (x1) durante la conversión de '{xml_input_file}': {e}")
import traceback
traceback.print_exc()
sys.exit(1) # Salir con error si la función principal falla

View File

@ -23,8 +23,9 @@ SCL_SUFFIX = "_sympy_processed" # New suffix to indicate processing method
GROUPED_COMMENT = "// Logic included in grouped IF"
SIMPLIFIED_IF_COMMENT = "// Simplified IF condition by script" # May still be useful
# Global data variable
# Global data dictionary (consider passing 'data' as argument if needed elsewhere)
# It's currently used by process_group_ifs implicitly via the outer scope,
# which works but passing it explicitly might be cleaner.
data = {}
def process_group_ifs(instruction, network_id, sympy_map, symbol_manager, data):
@ -33,6 +34,7 @@ def process_group_ifs(instruction, network_id, sympy_map, symbol_manager, data):
y, si habilitan un grupo (>1) de bloques funcionales (con SCL ya generado),
construye el bloque IF agrupado CON LA CONDICIÓN SIMPLIFICADA.
Modifica el campo 'scl' de la instrucción generadora de condición.
(Esta es la implementación de la función como la tenías en el archivo original)
"""
instr_uid = instruction["instruction_uid"]
instr_type_original = instruction.get("type", "").replace(SCL_SUFFIX, "").replace("_error", "")
@ -215,45 +217,47 @@ def load_processors(processors_dir="processors"):
# Devolver el mapa (para lookup rápido si es necesario) y la lista ordenada
return processor_map, processor_list_sorted
# --- Bucle Principal de Procesamiento (Modificado) ---
# --- Bucle Principal de Procesamiento (Modificado para STL) ---
def process_json_to_scl(json_filepath):
"""
Lee el JSON simplificado, aplica los procesadores dinámicamente cargados
siguiendo un orden de prioridad, y guarda el JSON procesado.
siguiendo un orden de prioridad (ignorando redes STL), y guarda el JSON procesado.
"""
global data # Necesario si process_group_ifs (definido fuera) accede a data globalmente.
# Si process_group_ifs está definida DENTRO de process_json_to_scl,
# no necesitarías global, ya que accedería a la 'data' local.
# Lo más limpio es definir process_group_ifs fuera y pasarle 'data'
# como argumento (como ya se hace). Así que 'global data' aquí es probablemente innecesario.
# Eliminémoslo por ahora y aseguremos que data se pasa a process_group_ifs.
global data # Necesario para que load_processors y process_group_ifs (definidas fuera) puedan acceder a ella.
# Considerar pasar 'data' como argumento si es posible refactorizar.
if not os.path.exists(json_filepath): print(f"Error: JSON no encontrado: {json_filepath}"); return
if not os.path.exists(json_filepath):
print(f"Error: JSON no encontrado: {json_filepath}")
return
print(f"Cargando JSON desde: {json_filepath}")
try:
with open(json_filepath, "r", encoding="utf-8") as f: data = json.load(f)
except Exception as e: print(f"Error al cargar JSON: {e}"); traceback.print_exc(); return
with open(json_filepath, "r", encoding="utf-8") as f:
data = json.load(f) # Carga en 'data' global
except Exception as e:
print(f"Error al cargar JSON: {e}")
traceback.print_exc()
return
# --- Carga dinámica de procesadores (sin cambios) ---
script_dir = os.path.dirname(__file__); processors_dir_path = os.path.join(script_dir, 'processors')
# --- Carga dinámica de procesadores ---
script_dir = os.path.dirname(__file__)
processors_dir_path = os.path.join(script_dir, 'processors')
processor_map, sorted_processors = load_processors(processors_dir_path)
if not processor_map: print("Error crítico: No se cargaron procesadores. Abortando."); return
if not processor_map:
print("Error crítico: No se cargaron procesadores. Abortando.")
return
# --- Crear mapas de acceso por red (sin cambios) ---
# --- Crear mapas de acceso por red ---
network_access_maps = {}
# ... (logic to populate network_access_maps remains the same) ...
# (La lógica para llenar network_access_maps no cambia, puedes copiarla de tu original)
for network in data.get("networks", []):
net_id = network["id"]
current_access_map = {}
# Extraer todos los 'Access' usados en esta red
for instr in network.get("logic", []):
# Revisar Inputs
for _, source in instr.get("inputs", {}).items():
sources_to_check = (source if isinstance(source, list) else ([source] if isinstance(source, dict) else []))
for src in sources_to_check:
if (isinstance(src, dict) and src.get("uid") and src.get("type") in ["variable", "constant"]):
current_access_map[src["uid"]] = src
# Revisar Outputs
for _, dest_list in instr.get("outputs", {}).items():
if isinstance(dest_list, list):
for dest in dest_list:
@ -261,12 +265,9 @@ def process_json_to_scl(json_filepath):
current_access_map[dest["uid"]] = dest
network_access_maps[net_id] = current_access_map
# --- Inicializar mapa SymPy y SymbolManager por red ---
# Cada red puede tener su propio contexto de símbolos si es necesario,
# pero un SymbolManager global suele ser suficiente si no hay colisiones graves.
# Usaremos uno global por simplicidad ahora.
# --- Inicializar mapa SymPy y SymbolManager ---
symbol_manager = SymbolManager()
sympy_map = {} # Mapa para resultados SymPy intermedios (expresiones)
sympy_map = {}
max_passes = 30
passes = 0
@ -275,23 +276,27 @@ def process_json_to_scl(json_filepath):
print("\n--- Iniciando Bucle de Procesamiento Iterativo (con SymPy y prioridad) ---")
while passes < max_passes and not processing_complete:
passes += 1
made_change_in_base_pass = False # Renombrar: made_change_in_sympy_pass
made_change_in_base_pass = False
made_change_in_group_pass = False
# made_change_in_simplify_pass = False # Ya no existe Fase 3
print(f"\n--- Pase {passes} ---")
num_processed_this_pass = 0 # Renombrar: num_sympy_processed_this_pass
num_sympy_processed_this_pass = 0
num_grouped_this_pass = 0
# num_simplified_this_pass = 0 # Ya no existe Fase 3
# --- FASE 1: Procesadores Base (Ahora usan SymPy) ---
# --- FASE 1: Procesadores Base (Ignorando STL) ---
print(f" Fase 1 (SymPy Base - Orden por Prioridad):")
num_sympy_processed_this_pass = 0 # Contador específico
num_sympy_processed_this_pass = 0
for processor_info in sorted_processors:
current_type_name = processor_info['type_name']
func_to_call = processor_info['func']
for network in data.get("networks", []):
network_id = network["id"]
network_lang = network.get("language", "LAD") # Obtener lenguaje de la red
# *** IGNORAR REDES STL EN ESTA FASE ***
if network_lang == "STL":
continue # Saltar al siguiente network
access_map = network_access_maps.get(network_id, {})
network_logic = network.get("logic", [])
@ -299,25 +304,26 @@ def process_json_to_scl(json_filepath):
instr_uid = instruction.get("instruction_uid")
instr_type_original = instruction.get("type", "Unknown")
# Saltar si ya está procesado con el NUEVO método, es error, o agrupado
if (instr_type_original.endswith(SCL_SUFFIX) # Check new suffix
# Saltar si ya procesado, error, agrupado o es chunk STL/SCL/Unsupported
if (instr_type_original.endswith(SCL_SUFFIX)
or "_error" in instr_type_original
or instruction.get("grouped", False)):
or instruction.get("grouped", False)
or instr_type_original in ["RAW_STL_CHUNK", "RAW_SCL_CHUNK", "UNSUPPORTED_LANG"]):
continue
# Determinar tipo efectivo (como antes)
lookup_key = instr_type_original.lower()
effective_type_name = lookup_key
if instr_type_original == "Call": # ... (manejo Call FC/FB) ...
if instr_type_original == "Call":
block_type = instruction.get("block_type", "").upper()
if block_type == "FC": effective_type_name = "call_fc"
elif block_type == "FB": effective_type_name = "call_fb"
# Llamar al procesador si coincide el tipo
if effective_type_name == current_type_name:
try:
# *** Llamar al procesador refactorizado ***
# Pasa sympy_map y symbol_manager, no scl_map
changed = func_to_call(instruction, network_id, sympy_map, symbol_manager, data) # Pasamos SymbolManager
# Pasa sympy_map, symbol_manager y data
changed = func_to_call(instruction, network_id, sympy_map, symbol_manager, data)
if changed:
made_change_in_base_pass = True
num_sympy_processed_this_pass += 1
@ -326,24 +332,26 @@ def process_json_to_scl(json_filepath):
traceback.print_exc()
instruction["scl"] = f"// ERROR en SymPy procesador base: {e}"
instruction["type"] = instr_type_original + "_error"
made_change_in_base_pass = True
print(f" -> {num_sympy_processed_this_pass} instrucciones procesadas con SymPy.")
made_change_in_base_pass = True # Marcar cambio aunque sea error
print(f" -> {num_sympy_processed_this_pass} instrucciones (no STL) procesadas con SymPy.")
# --- FASE 2: Agrupación IF (Ahora usa SymPy para simplificar) ---
# Ejecutar si hubo cambios en base o es el primer pase
# --- FASE 2: Agrupación IF (Ignorando STL) ---
if made_change_in_base_pass or passes == 1:
print(f" Fase 2 (Agrupación IF con Simplificación):")
num_grouped_this_pass = 0 # Reiniciar contador
num_grouped_this_pass = 0
for network in data.get("networks", []):
network_id = network["id"]
# access_map = network_access_maps.get(network_id, {}) # No usado directamente por group_ifs
network_lang = network.get("language", "LAD") # Obtener lenguaje
# *** IGNORAR REDES STL EN ESTA FASE ***
if network_lang == "STL":
continue # Saltar red STL
network_logic = network.get("logic", [])
# Iterar sobre instrucciones que *pueden* generar condiciones booleanas
for instruction in network_logic:
# process_group_ifs ahora verifica internamente si la instr. fue procesada
try:
# *** Llamar a process_group_ifs adaptado ***
# Llama a process_group_ifs (que necesita acceso a 'data' global o pasado)
group_changed = process_group_ifs(instruction, network_id, sympy_map, symbol_manager, data)
if group_changed:
made_change_in_group_pass = True
@ -351,17 +359,14 @@ def process_json_to_scl(json_filepath):
except Exception as e:
print(f"ERROR(GroupLoop) al intentar agrupar desde UID {instruction.get('instruction_uid')}: {e}")
traceback.print_exc()
print(f" -> {num_grouped_this_pass} agrupaciones realizadas.")
print(f" -> {num_grouped_this_pass} agrupaciones realizadas (en redes no STL).")
# --- FASE 3 Eliminada ---
# --- Comprobar si se completó el procesamiento ---
# Solo considera Fase 1 (SymPy Base) y Fase 2 (Grouping)
if not made_change_in_base_pass and not made_change_in_group_pass:
print(f"\n--- No se hicieron más cambios en el pase {passes}. Proceso iterativo completado. ---")
processing_complete = True
else:
# Mensaje de fin de pase actualizado
print(f"--- Fin Pase {passes}: {num_sympy_processed_this_pass} proc SymPy, {num_grouped_this_pass} agrup. Continuando...")
# --- Comprobar límite de pases ---
@ -370,46 +375,45 @@ def process_json_to_scl(json_filepath):
# --- FIN BUCLE ITERATIVO ---
# --- Verificación Final ---
# La lógica aquí podría necesitar ajustes si el sufijo cambió o si el SCL final
# solo se genera en instrucciones terminales.
# --- Verificación Final (Ajustada para RAW_STL_CHUNK) ---
print("\n--- Verificación Final de Instrucciones No Procesadas ---")
unprocessed_count = 0
unprocessed_details = []
ignored_types = ['raw_scl_chunk', 'unsupported_lang']
# Añadir RAW_STL_CHUNK a los tipos ignorados
ignored_types = ['raw_scl_chunk', 'unsupported_lang', 'raw_stl_chunk'] # Añadido raw_stl_chunk
for network in data.get("networks", []):
network_id = network.get("id", "Unknown ID")
network_title = network.get("title", f"Network {network_id}")
network_lang = network.get("language", "LAD") # Obtener lenguaje
# No verificar instrucciones dentro de redes STL, ya que no se procesan
if network_lang == "STL":
continue
for instruction in network.get("logic", []):
instr_uid = instruction.get("instruction_uid", "Unknown UID")
instr_type = instruction.get("type", "Unknown Type")
is_grouped = instruction.get("grouped", False)
has_final_scl = bool(instruction.get("scl", "").strip()) and not instruction.get("scl", "").strip().startswith("//")
# Condición revisada: No tiene el sufijo nuevo Y no es error Y no está agrupada Y no es tipo ignorado
# Y ADEMÁS, ¿debería tener SCL final si es una instr. terminal?
# Simplificación: si no tiene sufijo, no es error, no agrupada, no ignorada -> problema
# Condición revisada para ignorar los chunks crudos
if (not instr_type.endswith(SCL_SUFFIX) and
"_error" not in instr_type and
not is_grouped and
instr_type.lower() not in ignored_types):
instr_type.lower() not in ignored_types): # Verifica contra lista actualizada
unprocessed_count += 1
unprocessed_details.append(
f" - Red '{network_title}' (ID: {network_id}), "
f"Instrucción UID: {instr_uid}, Tipo Original: '{instr_type}'"
f" - Red '{network_title}' (ID: {network_id}, Lang: {network_lang}), "
f"Instrucción UID: {instr_uid}, Tipo: '{instr_type}'"
)
# Opcional: añadir si tiene SCL o no
# unprocessed_details[-1] += f" (Tiene SCL final: {has_final_scl})"
if unprocessed_count > 0:
print(f"ADVERTENCIA: Se encontraron {unprocessed_count} instrucciones que no fueron procesadas:")
print(f"ADVERTENCIA: Se encontraron {unprocessed_count} instrucciones (no STL) que parecen no haber sido procesadas:")
for detail in unprocessed_details: print(detail)
else:
print("INFO: Todas las instrucciones relevantes parecen haber sido procesadas o agrupadas.")
print("INFO: Todas las instrucciones relevantes (no STL) parecen haber sido procesadas o agrupadas.")
# --- Guardar JSON Final (sin cambios) ---
# --- Guardar JSON Final ---
output_filename = json_filepath.replace("_simplified.json", "_simplified_processed.json")
print(f"\nGuardando JSON procesado en: {output_filename}")
try:
@ -420,28 +424,55 @@ def process_json_to_scl(json_filepath):
print(f"Error Crítico al guardar JSON procesado: {e}")
traceback.print_exc()
# --- Ejecución (igual que antes) ---
# --- Ejecución (sin cambios) ---
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Process simplified JSON to embed SCL logic.")
parser.add_argument(
"source_xml_filepath",
nargs="?",
default="TestLAD.xml",
help="Path to the original source XML file (used to derive JSON input name, default: TestLAD.xml)"
# Imports necesarios solo para la ejecución como script principal
import argparse
import os
import sys
# Configurar ArgumentParser para recibir la ruta del XML original obligatoria
parser = argparse.ArgumentParser(
description="Process simplified JSON (_simplified.json) to embed SCL logic (SymPy version). Expects original XML filepath as argument."
)
args = parser.parse_args()
parser.add_argument(
"source_xml_filepath", # Argumento posicional obligatorio
help="Path to the original source XML file (passed from x0_main.py, used to derive JSON input name).",
)
args = parser.parse_args() # Parsea los argumentos de sys.argv
xml_filename_base = os.path.splitext(os.path.basename(args.source_xml_filepath))[0]
# Usar directorio del script actual si el XML no tiene ruta, o la ruta del XML si la tiene
xml_dir = os.path.dirname(args.source_xml_filepath)
input_dir = xml_dir if xml_dir else os.path.dirname(__file__) # Directorio de entrada/salida
source_xml_file = args.source_xml_filepath # Obtiene la ruta del XML original
# Verificar si el archivo XML original existe (como referencia, útil para depuración)
# No es estrictamente necesario para la lógica aquí, pero ayuda a confirmar
if not os.path.exists(source_xml_file):
print(f"Advertencia (x2): Archivo XML original no encontrado: '{source_xml_file}', pero se intentará encontrar el JSON correspondiente.")
# No salir necesariamente, pero es bueno saberlo.
# Derivar nombre del archivo JSON de entrada (_simplified.json)
xml_filename_base = os.path.splitext(os.path.basename(source_xml_file))[0]
# Asumir que el JSON simplificado está en el mismo directorio que el XML original
input_dir = os.path.dirname(source_xml_file) # Directorio del XML original
input_json_file = os.path.join(input_dir, f"{xml_filename_base}_simplified.json")
# Determinar el nombre esperado del archivo JSON procesado de salida
output_json_file = os.path.join(input_dir, f"{xml_filename_base}_simplified_processed.json")
print(f"(x2) Procesando: '{os.path.relpath(input_json_file)}' -> '{os.path.relpath(output_json_file)}'")
# Verificar si el archivo JSON de entrada (_simplified.json) EXISTE antes de procesar
if not os.path.exists(input_json_file):
print(f"Error Fatal: El archivo de entrada JSON simplificado no existe: '{input_json_file}'")
print(f"Asegúrate de haber ejecutado 'x1_to_json.py' primero sobre '{args.source_xml_filepath}'.")
sys.exit(1)
print(f"Error Fatal (x2): El archivo de entrada JSON simplificado no existe: '{input_json_file}'")
print(f"Asegúrate de que 'x1_to_json.py' se ejecutó correctamente para '{os.path.relpath(source_xml_file)}'.")
sys.exit(1) # Salir si el archivo necesario no está
else:
process_json_to_scl(input_json_file)
# Llamar a la función principal de procesamiento del script
# Asumiendo que tu función principal se llama process_json_to_scl(input_json_path)
try:
process_json_to_scl(input_json_file)
except Exception as e:
print(f"Error Crítico (x2) durante el procesamiento de '{input_json_file}': {e}")
import traceback
traceback.print_exc()
sys.exit(1) # Salir con error si la función principal falla

View File

@ -212,49 +212,73 @@ def generate_scl(processed_json_filepath, output_scl_filepath):
scl_output.append("")
network_has_code = False
# Iterar sobre la 'logica' de la red
for instruction in network.get('logic', []):
instruction_type = instruction.get("type", "")
scl_code = instruction.get('scl', "") # Obtener SCL generado por x2
# Saltar instrucciones agrupadas
if instruction.get("grouped", False):
continue
# --- NUEVO MANEJO STL con formato Markdown ---
if network_lang == "STL":
network_has_code = True # Marcar que la red tiene contenido
if network.get('logic') and isinstance(network['logic'], list) and len(network['logic']) > 0:
stl_chunk = network['logic'][0]
if stl_chunk.get("type") == "RAW_STL_CHUNK" and "stl" in stl_chunk:
raw_stl_code = stl_chunk["stl"]
# Añadir marcador de inicio (como comentario SCL para evitar errores)
scl_output.append(f" {'//'} ```STL") # Doble '//' para asegurar que sea comentario
# Escribir el código STL crudo, indentado
for stl_line in raw_stl_code.splitlines():
# Añadir indentación estándar de SCL
scl_output.append(f" {stl_line}") # <-- STL sin comentar
# Añadir marcador de fin (como comentario SCL)
scl_output.append(f" {'//'} ```")
else:
scl_output.append(" // ERROR: Contenido STL inesperado en JSON.")
else:
scl_output.append(" // ERROR: No se encontró lógica STL en JSON para esta red.")
scl_output.append("") # Línea en blanco después de la red STL
# --- FIN NUEVO MANEJO STL con formato Markdown ---
else:
# Escribir SCL si es un tipo procesado y tiene código relevante
# (Ignorar comentarios de depuración de SymPy)
if instruction_type.endswith(SCL_SUFFIX) and scl_code:
is_internal_sympy_comment_only = scl_code.strip().startswith("// SymPy") or \
scl_code.strip().startswith("// PBox SymPy processed") or \
scl_code.strip().startswith("// NBox SymPy processed")
# O podría ser más genérico: ignorar cualquier línea que solo sea comentario SCL
is_only_comment = all(line.strip().startswith("//") for line in scl_code.splitlines())
# Iterar sobre la 'logica' de la red
for instruction in network.get('logic', []):
instruction_type = instruction.get("type", "")
scl_code = instruction.get('scl', "") # Obtener SCL generado por x2
# Saltar instrucciones agrupadas
if instruction.get("grouped", False):
continue
# Escribir SCL si es un tipo procesado y tiene código relevante
# (Ignorar comentarios de depuración de SymPy)
if instruction_type.endswith(SCL_SUFFIX) and scl_code:
is_internal_sympy_comment_only = scl_code.strip().startswith("// SymPy") or \
scl_code.strip().startswith("// PBox SymPy processed") or \
scl_code.strip().startswith("// NBox SymPy processed")
# O podría ser más genérico: ignorar cualquier línea que solo sea comentario SCL
is_only_comment = all(line.strip().startswith("//") for line in scl_code.splitlines())
# Escribir solo si NO es un comentario interno de SymPy O si es un bloque IF (que sí debe escribirse)
if not is_only_comment or scl_code.strip().startswith("IF"):
# Escribir solo si NO es un comentario interno de SymPy O si es un bloque IF (que sí debe escribirse)
if not is_only_comment or scl_code.strip().startswith("IF"):
network_has_code = True
for line in scl_code.splitlines():
# Añadir indentación estándar
scl_output.append(f" {line}")
# Incluir también tipos especiales directamente
elif instruction_type in ["RAW_SCL_CHUNK", "UNSUPPORTED_LANG"] and scl_code:
network_has_code = True
for line in scl_code.splitlines():
# Añadir indentación estándar
scl_output.append(f" {line}")
scl_output.append(f" {line}") # Indentar
# Incluir también tipos especiales directamente
elif instruction_type in ["RAW_SCL_CHUNK", "UNSUPPORTED_LANG"] and scl_code:
network_has_code = True
for line in scl_code.splitlines():
scl_output.append(f" {line}") # Indentar
# Podríamos añadir comentarios para errores si se desea
# elif "_error" in instruction_type:
# network_has_code = True
# scl_output.append(f" // ERROR processing instruction UID {instruction.get('instruction_uid')}: {instruction.get('scl', 'No details')}")
# Podríamos añadir comentarios para errores si se desea
# elif "_error" in instruction_type:
# network_has_code = True
# scl_output.append(f" // ERROR processing instruction UID {instruction.get('instruction_uid')}: {instruction.get('scl', 'No details')}")
if network_has_code:
scl_output.append("") # Línea en blanco después del código de la red
else:
scl_output.append(f" // Network did not produce printable SCL code.")
scl_output.append("")
if network_has_code:
scl_output.append("") # Línea en blanco después del código de la red
else:
scl_output.append(f" // Network did not produce printable SCL code.")
scl_output.append("")
# Fin del bloque
scl_output.append("END_FUNCTION_BLOCK") # O END_FUNCTION si es FC
@ -273,26 +297,51 @@ def generate_scl(processed_json_filepath, output_scl_filepath):
# --- Ejecución ---
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Generate final SCL file from processed JSON (SymPy version).")
parser.add_argument(
"source_xml_filepath",
nargs="?",
default="TestLAD.xml",
help="Path to the original source XML file (used to derive input/output names, default: TestLAD.xml)"
)
args = parser.parse_args()
# Imports necesarios solo para la ejecución como script principal
import argparse
import os
import sys
import traceback # Asegurarse que traceback está importado si se usa en generate_scl
xml_filename_base = os.path.splitext(os.path.basename(args.source_xml_filepath))[0]
# Usar directorio del script si no hay ruta, o la ruta del XML si la tiene
xml_dir = os.path.dirname(args.source_xml_filepath)
base_dir = xml_dir if xml_dir else os.path.dirname(__file__)
# Configurar ArgumentParser para recibir la ruta del XML original obligatoria
parser = argparse.ArgumentParser(
description="Generate final SCL file from processed JSON (_simplified_processed.json). Expects original XML filepath as argument."
)
parser.add_argument(
"source_xml_filepath", # Argumento posicional obligatorio
help="Path to the original source XML file (passed from x0_main.py, used to derive input/output names).",
)
args = parser.parse_args() # Parsea los argumentos de sys.argv
source_xml_file = args.source_xml_filepath # Obtiene la ruta del XML original
# Verificar si el archivo XML original existe (como referencia)
if not os.path.exists(source_xml_file):
print(f"Advertencia (x3): Archivo XML original no encontrado: '{source_xml_file}', pero se intentará encontrar el JSON procesado.")
# No salir necesariamente.
# Derivar nombres de archivos de entrada (JSON procesado) y salida (SCL)
xml_filename_base = os.path.splitext(os.path.basename(source_xml_file))[0]
# Asumir que los archivos están en el mismo directorio que el XML original
base_dir = os.path.dirname(source_xml_file) # Directorio del XML original
input_json_file = os.path.join(base_dir, f"{xml_filename_base}_simplified_processed.json")
output_scl_file = os.path.join(base_dir, f"{xml_filename_base}_simplified_processed.scl")
print(f"(x3) Generando SCL: '{os.path.relpath(input_json_file)}' -> '{os.path.relpath(output_scl_file)}'")
# Verificar si el archivo JSON procesado de entrada EXISTE
if not os.path.exists(input_json_file):
print(f"Error: Processed JSON file not found: '{input_json_file}'")
print(f"Ensure 'x2_process.py' ran successfully for '{args.source_xml_filepath}'.")
sys.exit(1)
print(f"Error Fatal (x3): Archivo JSON procesado no encontrado: '{input_json_file}'")
print(f"Asegúrate de que 'x2_process.py' se ejecutó correctamente para '{os.path.relpath(source_xml_file)}'.")
sys.exit(1) # Salir si el archivo necesario no está
else:
generate_scl(input_json_file, output_scl_file)
# Llamar a la función principal de generación SCL del script
# Asumiendo que tu función principal se llama generate_scl(input_json_path, output_scl_path)
try:
generate_scl(input_json_file, output_scl_file)
except Exception as e:
print(f"Error Crítico (x3) durante la generación de SCL desde '{input_json_file}': {e}")
# traceback ya debería estar importado si generate_scl lo necesita
traceback.print_exc()
sys.exit(1) # Salir con error si la función principal falla

View File

@ -97,6 +97,81 @@ def select_xml_file():
if __name__ == "__main__":
# Imports necesarios para esta sección
import os
import sys
import glob # Asegúrate de que glob esté importado al principio del archivo
# Directorio base donde buscar los archivos XML (relativo al script)
base_search_dir = "XML Project"
script_dir = os.path.dirname(__file__) # Directorio donde está x0_main.py
xml_project_dir = os.path.join(script_dir, base_search_dir)
print(f"Buscando archivos XML recursivamente en: '{xml_project_dir}'")
# Verificar si el directorio 'XML Project' existe
if not os.path.isdir(xml_project_dir):
print(f"Error: El directorio '{xml_project_dir}' no existe o no es un directorio.")
print("Por favor, crea el directorio 'XML Project' en la misma carpeta que este script y coloca tus archivos XML dentro.")
sys.exit(1)
# Buscar todos los archivos .xml recursivamente dentro de xml_project_dir
# Usamos os.path.join para construir la ruta de búsqueda correctamente
# y '**/*.xml' para la recursividad con glob
search_pattern = os.path.join(xml_project_dir, '**', '*.xml')
xml_files_found = glob.glob(search_pattern, recursive=True)
if not xml_files_found:
print(f"No se encontraron archivos XML en '{xml_project_dir}' o sus subdirectorios.")
sys.exit(0) # Salir limpiamente si no hay archivos
print(f"Se encontraron {len(xml_files_found)} archivos XML para procesar:")
# Ordenar para un procesamiento predecible (opcional)
xml_files_found.sort()
for xml_file in xml_files_found:
# Imprimir la ruta relativa desde el directorio del script para claridad
print(f" - {os.path.relpath(xml_file, script_dir)}")
# Scripts a ejecutar en secuencia (asegúrate que los nombres son correctos)
script1 = "x1_to_json.py"
script2 = "x2_process.py"
script3 = "x3_generate_scl.py"
# Procesar cada archivo encontrado
processed_count = 0
failed_count = 0
for xml_filepath in xml_files_found:
print(f"\n--- Iniciando pipeline para: {os.path.relpath(xml_filepath, script_dir)} ---")
# Usar la ruta absoluta para evitar problemas si los scripts cambian de directorio
absolute_xml_filepath = os.path.abspath(xml_filepath)
# Ejecutar los scripts en secuencia para el archivo actual
# La función run_script ya está definida en tu script x0_main.py
success = True
if not run_script(script1, absolute_xml_filepath):
print(f"\nPipeline falló en el script '{script1}' para el archivo: {os.path.relpath(xml_filepath, script_dir)}")
success = False
elif not run_script(script2, absolute_xml_filepath):
print(f"\nPipeline falló en el script '{script2}' para el archivo: {os.path.relpath(xml_filepath, script_dir)}")
success = False
elif not run_script(script3, absolute_xml_filepath):
print(f"\nPipeline falló en el script '{script3}' para el archivo: {os.path.relpath(xml_filepath, script_dir)}")
success = False
if success:
print(f"--- Pipeline completado exitosamente para: {os.path.relpath(xml_filepath, script_dir)} ---")
processed_count += 1
else:
failed_count += 1
print(f"--- Pipeline falló para: {os.path.relpath(xml_filepath, script_dir)} ---")
print("\n--- Resumen Final del Procesamiento ---")
print(f"Total de archivos XML encontrados: {len(xml_files_found)}")
print(f"Archivos procesados exitosamente por el pipeline completo: {processed_count}")
print(f"Archivos que fallaron en algún punto del pipeline: {failed_count}")
print("---------------------------------------")
xml_filename = None
# Comprobar si se pasó un argumento de línea de comandos

View File

@ -341,7 +341,6 @@ def reconstruct_scl_from_tokens(st_node):
full_scl = "".join(scl_parts)
# Re-indentar líneas después de IF/THEN, etc. (Simplificado)
output_lines = []
indent_level = 0
@ -1347,33 +1346,40 @@ if __name__ == "__main__":
import os
import sys
# Configurar ArgumentParser para recibir la ruta del XML obligatoria
parser = argparse.ArgumentParser(
description="Convert Simatic XML LAD/FBD to simplified JSON."
description="Convert Simatic XML (LAD/FBD/SCL/STL) to simplified JSON. Expects XML filepath as argument."
)
parser.add_argument(
"xml_filepath",
nargs="?", # Argumento opcional
default="TestLAD.xml", # Valor por defecto si se ejecuta sin argumentos
help="Path to the input XML file (default: TestLAD.xml)",
"xml_filepath", # Argumento posicional obligatorio
help="Path to the input XML file passed from the main script (x0_main.py).",
)
args = parser.parse_args()
args = parser.parse_args() # Parsea los argumentos de sys.argv
xml_input_file = args.xml_filepath
xml_input_file = args.xml_filepath # Obtiene la ruta del argumento
# Verificar si el archivo de entrada existe
# Verificar si el archivo de entrada existe (es una buena práctica aunque x0 lo haga)
if not os.path.exists(xml_input_file):
print(f"Error Crítico: Archivo XML no encontrado: '{xml_input_file}'")
sys.exit(1) # Salir si el archivo no existe
print(f"Error Crítico (x1): Archivo XML no encontrado: '{xml_input_file}'")
sys.exit(1) # Salir si el archivo no existe
# Derivar nombre base para archivo de salida JSON
# os.path.basename obtiene el nombre del archivo de la ruta
# os.path.splitext divide el nombre y la extensión
# El archivo JSON se guardará en el mismo directorio que el XML de entrada
xml_filename_base = os.path.splitext(os.path.basename(xml_input_file))[0]
# Construir la ruta de salida en el mismo directorio que el script o el XML
output_dir = os.path.dirname(
xml_input_file
) # O usar os.path.dirname(__file__) para el directorio del script
output_dir = os.path.dirname(xml_input_file) # Directorio del XML de entrada
# Asegurarse de que el directorio de salida exista (aunque debería si el XML existe)
os.makedirs(output_dir, exist_ok=True)
json_output_file = os.path.join(output_dir, f"{xml_filename_base}_simplified.json")
# Llamar a la función principal con los nombres de archivo derivados
convert_xml_to_json(xml_input_file, json_output_file)
print(f"(x1) Convirtiendo: '{os.path.relpath(xml_input_file)}' -> '{os.path.relpath(json_output_file)}'")
# Llamar a la función principal de conversión del script
# Asumiendo que tu función principal se llama convert_xml_to_json(input_path, output_path)
try:
convert_xml_to_json(xml_input_file, json_output_file)
except Exception as e:
print(f"Error Crítico (x1) durante la conversión de '{xml_input_file}': {e}")
import traceback
traceback.print_exc()
sys.exit(1) # Salir con error si la función principal falla

View File

@ -426,67 +426,53 @@ def process_json_to_scl(json_filepath):
# --- Ejecución (sin cambios) ---
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Process simplified JSON to embed SCL logic.")
parser.add_argument(
"source_xml_filepath",
nargs="?",
default="TestLAD.xml",
help="Path to the original source XML file (used to derive JSON input name, default: TestLAD.xml)"
# Imports necesarios solo para la ejecución como script principal
import argparse
import os
import sys
# Configurar ArgumentParser para recibir la ruta del XML original obligatoria
parser = argparse.ArgumentParser(
description="Process simplified JSON (_simplified.json) to embed SCL logic (SymPy version). Expects original XML filepath as argument."
)
args = parser.parse_args()
parser.add_argument(
"source_xml_filepath", # Argumento posicional obligatorio
help="Path to the original source XML file (passed from x0_main.py, used to derive JSON input name).",
)
args = parser.parse_args() # Parsea los argumentos de sys.argv
xml_filename_base = os.path.splitext(os.path.basename(args.source_xml_filepath))[0]
xml_dir = os.path.dirname(args.source_xml_filepath)
input_dir = xml_dir if xml_dir else os.path.dirname(__file__)
source_xml_file = args.source_xml_filepath # Obtiene la ruta del XML original
# Verificar si el archivo XML original existe (como referencia, útil para depuración)
# No es estrictamente necesario para la lógica aquí, pero ayuda a confirmar
if not os.path.exists(source_xml_file):
print(f"Advertencia (x2): Archivo XML original no encontrado: '{source_xml_file}', pero se intentará encontrar el JSON correspondiente.")
# No salir necesariamente, pero es bueno saberlo.
# Derivar nombre del archivo JSON de entrada (_simplified.json)
xml_filename_base = os.path.splitext(os.path.basename(source_xml_file))[0]
# Asumir que el JSON simplificado está en el mismo directorio que el XML original
input_dir = os.path.dirname(source_xml_file) # Directorio del XML original
input_json_file = os.path.join(input_dir, f"{xml_filename_base}_simplified.json")
# Determinar el nombre esperado del archivo JSON procesado de salida
output_json_file = os.path.join(input_dir, f"{xml_filename_base}_simplified_processed.json")
print(f"(x2) Procesando: '{os.path.relpath(input_json_file)}' -> '{os.path.relpath(output_json_file)}'")
# Verificar si el archivo JSON de entrada (_simplified.json) EXISTE antes de procesar
if not os.path.exists(input_json_file):
print(f"Error Fatal: El archivo de entrada JSON simplificado no existe: '{input_json_file}'")
print(f"Asegúrate de haber ejecutado 'x1_to_json.py' primero sobre '{args.source_xml_filepath}'.")
sys.exit(1)
print(f"Error Fatal (x2): El archivo de entrada JSON simplificado no existe: '{input_json_file}'")
print(f"Asegúrate de que 'x1_to_json.py' se ejecutó correctamente para '{os.path.relpath(source_xml_file)}'.")
sys.exit(1) # Salir si el archivo necesario no está
else:
process_json_to_scl(input_json_file)
parser = argparse.ArgumentParser(description="Process simplified JSON to embed SCL logic.")
parser.add_argument(
"source_xml_filepath",
nargs="?",
default="TestLAD.xml",
help="Path to the original source XML file (used to derive JSON input name, default: TestLAD.xml)"
)
args = parser.parse_args()
xml_filename_base = os.path.splitext(os.path.basename(args.source_xml_filepath))[0]
xml_dir = os.path.dirname(args.source_xml_filepath)
input_dir = xml_dir if xml_dir else os.path.dirname(__file__)
input_json_file = os.path.join(input_dir, f"{xml_filename_base}_simplified.json")
if not os.path.exists(input_json_file):
print(f"Error Fatal: El archivo de entrada JSON simplificado no existe: '{input_json_file}'")
print(f"Asegúrate de haber ejecutado 'x1_to_json.py' primero sobre '{args.source_xml_filepath}'.")
sys.exit(1)
else:
process_json_to_scl(input_json_file)
parser = argparse.ArgumentParser(description="Process simplified JSON to embed SCL logic.")
parser.add_argument(
"source_xml_filepath",
nargs="?",
default="TestLAD.xml",
help="Path to the original source XML file (used to derive JSON input name, default: TestLAD.xml)"
)
args = parser.parse_args()
xml_filename_base = os.path.splitext(os.path.basename(args.source_xml_filepath))[0]
# Usar directorio del script actual si el XML no tiene ruta, o la ruta del XML si la tiene
xml_dir = os.path.dirname(args.source_xml_filepath)
input_dir = xml_dir if xml_dir else os.path.dirname(__file__) # Directorio de entrada/salida
input_json_file = os.path.join(input_dir, f"{xml_filename_base}_simplified.json")
if not os.path.exists(input_json_file):
print(f"Error Fatal: El archivo de entrada JSON simplificado no existe: '{input_json_file}'")
print(f"Asegúrate de haber ejecutado 'x1_to_json.py' primero sobre '{args.source_xml_filepath}'.")
sys.exit(1)
else:
process_json_to_scl(input_json_file)
# Llamar a la función principal de procesamiento del script
# Asumiendo que tu función principal se llama process_json_to_scl(input_json_path)
try:
process_json_to_scl(input_json_file)
except Exception as e:
print(f"Error Crítico (x2) durante el procesamiento de '{input_json_file}': {e}")
import traceback
traceback.print_exc()
sys.exit(1) # Salir con error si la función principal falla

View File

@ -297,26 +297,51 @@ def generate_scl(processed_json_filepath, output_scl_filepath):
# --- Ejecución ---
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Generate final SCL file from processed JSON (SymPy version).")
parser.add_argument(
"source_xml_filepath",
nargs="?",
default="TestLAD.xml",
help="Path to the original source XML file (used to derive input/output names, default: TestLAD.xml)"
)
args = parser.parse_args()
# Imports necesarios solo para la ejecución como script principal
import argparse
import os
import sys
import traceback # Asegurarse que traceback está importado si se usa en generate_scl
xml_filename_base = os.path.splitext(os.path.basename(args.source_xml_filepath))[0]
# Usar directorio del script si no hay ruta, o la ruta del XML si la tiene
xml_dir = os.path.dirname(args.source_xml_filepath)
base_dir = xml_dir if xml_dir else os.path.dirname(__file__)
# Configurar ArgumentParser para recibir la ruta del XML original obligatoria
parser = argparse.ArgumentParser(
description="Generate final SCL file from processed JSON (_simplified_processed.json). Expects original XML filepath as argument."
)
parser.add_argument(
"source_xml_filepath", # Argumento posicional obligatorio
help="Path to the original source XML file (passed from x0_main.py, used to derive input/output names).",
)
args = parser.parse_args() # Parsea los argumentos de sys.argv
source_xml_file = args.source_xml_filepath # Obtiene la ruta del XML original
# Verificar si el archivo XML original existe (como referencia)
if not os.path.exists(source_xml_file):
print(f"Advertencia (x3): Archivo XML original no encontrado: '{source_xml_file}', pero se intentará encontrar el JSON procesado.")
# No salir necesariamente.
# Derivar nombres de archivos de entrada (JSON procesado) y salida (SCL)
xml_filename_base = os.path.splitext(os.path.basename(source_xml_file))[0]
# Asumir que los archivos están en el mismo directorio que el XML original
base_dir = os.path.dirname(source_xml_file) # Directorio del XML original
input_json_file = os.path.join(base_dir, f"{xml_filename_base}_simplified_processed.json")
output_scl_file = os.path.join(base_dir, f"{xml_filename_base}_simplified_processed.scl")
print(f"(x3) Generando SCL: '{os.path.relpath(input_json_file)}' -> '{os.path.relpath(output_scl_file)}'")
# Verificar si el archivo JSON procesado de entrada EXISTE
if not os.path.exists(input_json_file):
print(f"Error: Processed JSON file not found: '{input_json_file}'")
print(f"Ensure 'x2_process.py' ran successfully for '{args.source_xml_filepath}'.")
sys.exit(1)
print(f"Error Fatal (x3): Archivo JSON procesado no encontrado: '{input_json_file}'")
print(f"Asegúrate de que 'x2_process.py' se ejecutó correctamente para '{os.path.relpath(source_xml_file)}'.")
sys.exit(1) # Salir si el archivo necesario no está
else:
generate_scl(input_json_file, output_scl_file)
# Llamar a la función principal de generación SCL del script
# Asumiendo que tu función principal se llama generate_scl(input_json_path, output_scl_path)
try:
generate_scl(input_json_file, output_scl_file)
except Exception as e:
print(f"Error Crítico (x3) durante la generación de SCL desde '{input_json_file}': {e}")
# traceback ya debería estar importado si generate_scl lo necesita
traceback.print_exc()
sys.exit(1) # Salir con error si la función principal falla