Compare commits
No commits in common. "66c5a076aba98ea06e00a2b3eeea247ed7769442" and "c22f98d865a91da77591584c985825f72c441cc1" have entirely different histories.
66c5a076ab
...
c22f98d865
|
@ -8,8 +8,6 @@ __pycache__/
|
||||||
|
|
||||||
# Distribution / packaging
|
# Distribution / packaging
|
||||||
.Python
|
.Python
|
||||||
XML Project/
|
|
||||||
XML Proyect/
|
|
||||||
build/
|
build/
|
||||||
develop-eggs/
|
develop-eggs/
|
||||||
dist/
|
dist/
|
||||||
|
|
|
@ -0,0 +1,477 @@
|
||||||
|
<?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>
|
|
@ -0,0 +1,97 @@
|
||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
// 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
|
@ -0,0 +1,365 @@
|
||||||
|
// 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
|
@ -0,0 +1,995 @@
|
||||||
|
<?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="<>" 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="<>" 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="<>" 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="<>" 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="<>" 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="<>" 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="<>" 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>
|
|
@ -0,0 +1,63 @@
|
||||||
|
{
|
||||||
|
"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;"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
{
|
||||||
|
"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;"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
// 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
|
|
@ -0,0 +1,763 @@
|
||||||
|
<?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>
|
|
@ -0,0 +1,101 @@
|
||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
// 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
|
|
@ -3,8 +3,7 @@ import subprocess
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import locale
|
import locale
|
||||||
import glob # <--- Importar glob para buscar archivos
|
import glob # <--- Importar glob para buscar archivos
|
||||||
|
|
||||||
|
|
||||||
# (Función get_console_encoding y variable CONSOLE_ENCODING como en la respuesta anterior)
|
# (Función get_console_encoding y variable CONSOLE_ENCODING como en la respuesta anterior)
|
||||||
def get_console_encoding():
|
def get_console_encoding():
|
||||||
|
@ -12,14 +11,12 @@ def get_console_encoding():
|
||||||
try:
|
try:
|
||||||
return locale.getpreferredencoding(False)
|
return locale.getpreferredencoding(False)
|
||||||
except Exception:
|
except Exception:
|
||||||
return "cp1252"
|
return 'cp1252'
|
||||||
|
|
||||||
|
|
||||||
CONSOLE_ENCODING = get_console_encoding()
|
CONSOLE_ENCODING = get_console_encoding()
|
||||||
# Descomenta la siguiente línea si quieres ver la codificación detectada:
|
# Descomenta la siguiente línea si quieres ver la codificación detectada:
|
||||||
# print(f"Detected console encoding: {CONSOLE_ENCODING}")
|
# print(f"Detected console encoding: {CONSOLE_ENCODING}")
|
||||||
|
|
||||||
|
|
||||||
# (Función run_script como en la respuesta anterior, usando CONSOLE_ENCODING)
|
# (Función run_script como en la respuesta anterior, usando CONSOLE_ENCODING)
|
||||||
def run_script(script_name, xml_arg):
|
def run_script(script_name, xml_arg):
|
||||||
"""Runs a given script with the specified XML file argument."""
|
"""Runs a given script with the specified XML file argument."""
|
||||||
|
@ -27,14 +24,12 @@ def run_script(script_name, xml_arg):
|
||||||
command = [sys.executable, script_path, xml_arg]
|
command = [sys.executable, script_path, xml_arg]
|
||||||
print(f"\n--- Running {script_name} with argument: {xml_arg} ---")
|
print(f"\n--- Running {script_name} with argument: {xml_arg} ---")
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(
|
result = subprocess.run(command,
|
||||||
command,
|
check=True,
|
||||||
check=True,
|
capture_output=True,
|
||||||
capture_output=True,
|
text=True,
|
||||||
text=True,
|
encoding=CONSOLE_ENCODING,
|
||||||
encoding=CONSOLE_ENCODING,
|
errors='replace') # 'replace' para evitar errores
|
||||||
errors="replace",
|
|
||||||
) # 'replace' para evitar errores
|
|
||||||
|
|
||||||
# Imprimir stdout y stderr
|
# Imprimir stdout y stderr
|
||||||
# Eliminar saltos de línea extra al final si existen
|
# Eliminar saltos de línea extra al final si existen
|
||||||
|
@ -54,35 +49,26 @@ def run_script(script_name, xml_arg):
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
print(f"Error running {script_name}:")
|
print(f"Error running {script_name}:")
|
||||||
print(f"Return code: {e.returncode}")
|
print(f"Return code: {e.returncode}")
|
||||||
stdout_decoded = (
|
stdout_decoded = e.stdout.decode(CONSOLE_ENCODING, errors='replace').strip() if isinstance(e.stdout, bytes) else (e.stdout or "").strip()
|
||||||
e.stdout.decode(CONSOLE_ENCODING, errors="replace").strip()
|
stderr_decoded = e.stderr.decode(CONSOLE_ENCODING, errors='replace').strip() if isinstance(e.stderr, bytes) else (e.stderr or "").strip()
|
||||||
if isinstance(e.stdout, bytes)
|
|
||||||
else (e.stdout or "").strip()
|
|
||||||
)
|
|
||||||
stderr_decoded = (
|
|
||||||
e.stderr.decode(CONSOLE_ENCODING, errors="replace").strip()
|
|
||||||
if isinstance(e.stderr, bytes)
|
|
||||||
else (e.stderr or "").strip()
|
|
||||||
)
|
|
||||||
if stdout_decoded:
|
if stdout_decoded:
|
||||||
print("--- Stdout ---")
|
print("--- Stdout ---")
|
||||||
print(stdout_decoded)
|
print(stdout_decoded)
|
||||||
if stderr_decoded:
|
if stderr_decoded:
|
||||||
print("--- Stderr ---")
|
print("--- Stderr ---")
|
||||||
print(stderr_decoded)
|
print(stderr_decoded)
|
||||||
print("--------------")
|
print("--------------")
|
||||||
return False
|
return False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"An unexpected error occurred while running {script_name}: {e}")
|
print(f"An unexpected error occurred while running {script_name}: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
# --- NUEVA FUNCIÓN PARA SELECCIONAR ARCHIVO ---
|
# --- NUEVA FUNCIÓN PARA SELECCIONAR ARCHIVO ---
|
||||||
def select_xml_file():
|
def select_xml_file():
|
||||||
"""Busca archivos .xml, los lista y pide al usuario que elija uno."""
|
"""Busca archivos .xml, los lista y pide al usuario que elija uno."""
|
||||||
print("No XML file specified. Searching for XML files in current directory...")
|
print("No XML file specified. Searching for XML files in current directory...")
|
||||||
# Buscar archivos .xml en el directorio actual (.)
|
# Buscar archivos .xml en el directorio actual (.)
|
||||||
xml_files = sorted(glob.glob("*.xml")) # sorted para orden alfabético
|
xml_files = sorted(glob.glob('*.xml')) # sorted para orden alfabético
|
||||||
|
|
||||||
if not xml_files:
|
if not xml_files:
|
||||||
print("Error: No .xml files found in the current directory.")
|
print("Error: No .xml files found in the current directory.")
|
||||||
|
@ -94,9 +80,7 @@ def select_xml_file():
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
choice = input(
|
choice = input(f"Enter the number of the file to process (1-{len(xml_files)}): ")
|
||||||
f"Enter the number of the file to process (1-{len(xml_files)}): "
|
|
||||||
)
|
|
||||||
choice_num = int(choice)
|
choice_num = int(choice)
|
||||||
if 1 <= choice_num <= len(xml_files):
|
if 1 <= choice_num <= len(xml_files):
|
||||||
selected_file = xml_files[choice_num - 1]
|
selected_file = xml_files[choice_num - 1]
|
||||||
|
@ -106,109 +90,13 @@ def select_xml_file():
|
||||||
print("Invalid choice. Please enter a number from the list.")
|
print("Invalid choice. Please enter a number from the list.")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print("Invalid input. Please enter a number.")
|
print("Invalid input. Please enter a number.")
|
||||||
except EOFError: # Manejar si la entrada se cierra inesperadamente
|
except EOFError: # Manejar si la entrada se cierra inesperadamente
|
||||||
print("\nSelection cancelled.")
|
print("\nSelection cancelled.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
# --- FIN NUEVA FUNCIÓN ---
|
# --- FIN NUEVA FUNCIÓN ---
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
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
|
xml_filename = None
|
||||||
|
|
||||||
# Comprobar si se pasó un argumento de línea de comandos
|
# Comprobar si se pasó un argumento de línea de comandos
|
||||||
|
@ -254,4 +142,4 @@ if __name__ == "__main__":
|
||||||
else:
|
else:
|
||||||
print("\nPipeline failed at script:", script2)
|
print("\nPipeline failed at script:", script2)
|
||||||
else:
|
else:
|
||||||
print("\nPipeline failed at script:", script1)
|
print("\nPipeline failed at script:", script1)
|
File diff suppressed because it is too large
Load Diff
|
@ -5,78 +5,54 @@ import os
|
||||||
import copy
|
import copy
|
||||||
import traceback
|
import traceback
|
||||||
import re
|
import re
|
||||||
import importlib
|
import importlib
|
||||||
import sys
|
import sys
|
||||||
import sympy # Import sympy
|
import sympy # Import sympy
|
||||||
|
|
||||||
# Import necessary components from processors directory
|
# Import necessary components from processors directory
|
||||||
from processors.processor_utils import (
|
from processors.processor_utils import (
|
||||||
format_variable_name, # Keep if used outside processors
|
format_variable_name, # Keep if used outside processors
|
||||||
sympy_expr_to_scl, # Needed for IF grouping and maybe others
|
sympy_expr_to_scl, # Needed for IF grouping and maybe others
|
||||||
# get_target_scl_name might be used here? Unlikely.
|
# get_target_scl_name might be used here? Unlikely.
|
||||||
)
|
)
|
||||||
from processors.symbol_manager import SymbolManager # Import the manager
|
from processors.symbol_manager import SymbolManager # Import the manager
|
||||||
|
|
||||||
# --- Constantes y Configuración ---
|
# --- Constantes y Configuración ---
|
||||||
# SCL_SUFFIX = "_scl" # Old suffix
|
# SCL_SUFFIX = "_scl" # Old suffix
|
||||||
SCL_SUFFIX = "_sympy_processed" # New suffix to indicate processing method
|
SCL_SUFFIX = "_sympy_processed" # New suffix to indicate processing method
|
||||||
GROUPED_COMMENT = "// Logic included in grouped IF"
|
GROUPED_COMMENT = "// Logic included in grouped IF"
|
||||||
SIMPLIFIED_IF_COMMENT = "// Simplified IF condition by script" # May still be useful
|
SIMPLIFIED_IF_COMMENT = "// Simplified IF condition by script" # May still be useful
|
||||||
|
|
||||||
# Global data dictionary (consider passing 'data' as argument if needed elsewhere)
|
|
||||||
# It's currently used by process_group_ifs implicitly via the outer scope,
|
# Global data variable
|
||||||
# which works but passing it explicitly might be cleaner.
|
|
||||||
data = {}
|
data = {}
|
||||||
|
|
||||||
|
|
||||||
def process_group_ifs(instruction, network_id, sympy_map, symbol_manager, data):
|
def process_group_ifs(instruction, network_id, sympy_map, symbol_manager, data):
|
||||||
"""
|
"""
|
||||||
Busca condiciones (ya procesadas -> tienen expr SymPy en sympy_map)
|
Busca condiciones (ya procesadas -> tienen expr SymPy en sympy_map)
|
||||||
y, si habilitan un grupo (>1) de bloques funcionales (con SCL ya generado),
|
y, si habilitan un grupo (>1) de bloques funcionales (con SCL ya generado),
|
||||||
construye el bloque IF agrupado CON LA CONDICIÓN SIMPLIFICADA.
|
construye el bloque IF agrupado CON LA CONDICIÓN SIMPLIFICADA.
|
||||||
Modifica el campo 'scl' de la instrucción generadora de condición.
|
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_uid = instruction["instruction_uid"]
|
||||||
instr_type_original = (
|
instr_type_original = instruction.get("type", "").replace(SCL_SUFFIX, "").replace("_error", "")
|
||||||
instruction.get("type", "").replace(SCL_SUFFIX, "").replace("_error", "")
|
|
||||||
)
|
|
||||||
made_change = False
|
made_change = False
|
||||||
|
|
||||||
# Check if this instruction *could* generate a condition suitable for grouping
|
# Check if this instruction *could* generate a condition suitable for grouping
|
||||||
# It must have been processed by the new SymPy method
|
# It must have been processed by the new SymPy method
|
||||||
if (
|
if (
|
||||||
not instruction.get("type", "").endswith(
|
not instruction.get("type", "").endswith(SCL_SUFFIX) # Check if processed by new method
|
||||||
SCL_SUFFIX
|
|
||||||
) # Check if processed by new method
|
|
||||||
or "_error" in instruction.get("type", "")
|
or "_error" in instruction.get("type", "")
|
||||||
or instruction.get("grouped", False)
|
or instruction.get("grouped", False)
|
||||||
or instr_type_original
|
or instr_type_original not in [ # Original types that produce boolean results
|
||||||
not in [ # Original types that produce boolean results
|
"Contact", "O", "Eq", "Ne", "Gt", "Lt", "Ge", "Le", "PBox", "NBox", "And", "Xor", "Not" # Add others like comparison
|
||||||
"Contact",
|
|
||||||
"O",
|
|
||||||
"Eq",
|
|
||||||
"Ne",
|
|
||||||
"Gt",
|
|
||||||
"Lt",
|
|
||||||
"Ge",
|
|
||||||
"Le",
|
|
||||||
"PBox",
|
|
||||||
"NBox",
|
|
||||||
"And",
|
|
||||||
"Xor",
|
|
||||||
"Not", # Add others like comparison
|
|
||||||
]
|
]
|
||||||
):
|
):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Avoid reagruping if SCL already contains a complex IF (less likely now)
|
# Avoid reagruping if SCL already contains a complex IF (less likely now)
|
||||||
current_scl = instruction.get("scl", "")
|
current_scl = instruction.get("scl", "")
|
||||||
if (
|
if current_scl.strip().startswith("IF") and "END_IF;" in current_scl and GROUPED_COMMENT not in current_scl:
|
||||||
current_scl.strip().startswith("IF")
|
|
||||||
and "END_IF;" in current_scl
|
|
||||||
and GROUPED_COMMENT not in current_scl
|
|
||||||
):
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# *** Get the SymPy expression for the condition ***
|
# *** Get the SymPy expression for the condition ***
|
||||||
|
@ -84,34 +60,20 @@ def process_group_ifs(instruction, network_id, sympy_map, symbol_manager, data):
|
||||||
sympy_condition_expr = sympy_map.get(map_key_out)
|
sympy_condition_expr = sympy_map.get(map_key_out)
|
||||||
|
|
||||||
# No SymPy expression found or trivial conditions
|
# No SymPy expression found or trivial conditions
|
||||||
if sympy_condition_expr is None or sympy_condition_expr in [
|
if sympy_condition_expr is None or sympy_condition_expr in [sympy.true, sympy.false]:
|
||||||
sympy.true,
|
|
||||||
sympy.false,
|
|
||||||
]:
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# --- Find consumer instructions (logic similar to before) ---
|
# --- Find consumer instructions (logic similar to before) ---
|
||||||
grouped_instructions_cores = []
|
grouped_instructions_cores = []
|
||||||
consumer_instr_list = []
|
consumer_instr_list = []
|
||||||
network_logic = next(
|
network_logic = next((net["logic"] for net in data["networks"] if net["id"] == network_id), [])
|
||||||
(net["logic"] for net in data["networks"] if net["id"] == network_id), []
|
if not network_logic: return False
|
||||||
)
|
|
||||||
if not network_logic:
|
|
||||||
return False
|
|
||||||
|
|
||||||
groupable_types = [ # Types whose *final SCL* we want to group
|
groupable_types = [ # Types whose *final SCL* we want to group
|
||||||
"Move",
|
"Move", "Add", "Sub", "Mul", "Div", "Mod", "Convert",
|
||||||
"Add",
|
"Call_FC", "Call_FB", # Assuming these generate final SCL in their processors now
|
||||||
"Sub",
|
|
||||||
"Mul",
|
|
||||||
"Div",
|
|
||||||
"Mod",
|
|
||||||
"Convert",
|
|
||||||
"Call_FC",
|
|
||||||
"Call_FB", # Assuming these generate final SCL in their processors now
|
|
||||||
# SCoil/RCoil might also be groupable if their SCL is final assignment
|
# SCoil/RCoil might also be groupable if their SCL is final assignment
|
||||||
"SCoil",
|
"SCoil", "RCoil"
|
||||||
"RCoil",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
for consumer_instr in network_logic:
|
for consumer_instr in network_logic:
|
||||||
|
@ -120,45 +82,31 @@ def process_group_ifs(instruction, network_id, sympy_map, symbol_manager, data):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
consumer_en = consumer_instr.get("inputs", {}).get("en")
|
consumer_en = consumer_instr.get("inputs", {}).get("en")
|
||||||
consumer_type = consumer_instr.get("type", "") # Current type suffix matters
|
consumer_type = consumer_instr.get("type", "") # Current type suffix matters
|
||||||
consumer_type_original = consumer_type.replace(SCL_SUFFIX, "").replace(
|
consumer_type_original = consumer_type.replace(SCL_SUFFIX, "").replace("_error", "")
|
||||||
"_error", ""
|
|
||||||
)
|
|
||||||
|
|
||||||
is_enabled_by_us = False
|
is_enabled_by_us = False
|
||||||
if (
|
if ( isinstance(consumer_en, dict) and consumer_en.get("type") == "connection" and
|
||||||
isinstance(consumer_en, dict)
|
consumer_en.get("source_instruction_uid") == instr_uid and
|
||||||
and consumer_en.get("type") == "connection"
|
consumer_en.get("source_pin") == "out"):
|
||||||
and consumer_en.get("source_instruction_uid") == instr_uid
|
|
||||||
and consumer_en.get("source_pin") == "out"
|
|
||||||
):
|
|
||||||
is_enabled_by_us = True
|
is_enabled_by_us = True
|
||||||
|
|
||||||
# Check if consumer is groupable AND has its final SCL generated
|
# Check if consumer is groupable AND has its final SCL generated
|
||||||
# The suffix check needs adjustment based on how terminating processors set it.
|
# The suffix check needs adjustment based on how terminating processors set it.
|
||||||
# Assuming processors like Move, Add, Call, SCoil, RCoil NOW generate final SCL and add a suffix.
|
# Assuming processors like Move, Add, Call, SCoil, RCoil NOW generate final SCL and add a suffix.
|
||||||
if (
|
if ( is_enabled_by_us and consumer_type.endswith(SCL_SUFFIX) and # Or a specific "final_scl" suffix
|
||||||
is_enabled_by_us
|
consumer_type_original in groupable_types ):
|
||||||
and consumer_type.endswith(SCL_SUFFIX) # Or a specific "final_scl" suffix
|
|
||||||
and consumer_type_original in groupable_types
|
|
||||||
):
|
|
||||||
|
|
||||||
consumer_scl = consumer_instr.get("scl", "")
|
consumer_scl = consumer_instr.get("scl", "")
|
||||||
# Extract core SCL (logic is similar, maybe simpler if SCL is cleaner now)
|
# Extract core SCL (logic is similar, maybe simpler if SCL is cleaner now)
|
||||||
core_scl = None
|
core_scl = None
|
||||||
if consumer_scl:
|
if consumer_scl:
|
||||||
# If consumer SCL itself is an IF generated by EN, take the body
|
# If consumer SCL itself is an IF generated by EN, take the body
|
||||||
if consumer_scl.strip().startswith("IF"):
|
if consumer_scl.strip().startswith("IF"):
|
||||||
match = re.search(
|
match = re.search(r"THEN\s*(.*?)\s*END_IF;", consumer_scl, re.DOTALL | re.IGNORECASE)
|
||||||
r"THEN\s*(.*?)\s*END_IF;",
|
core_scl = match.group(1).strip() if match else None
|
||||||
consumer_scl,
|
elif not consumer_scl.strip().startswith("//"): # Otherwise, take the whole line if not comment
|
||||||
re.DOTALL | re.IGNORECASE,
|
core_scl = consumer_scl.strip()
|
||||||
)
|
|
||||||
core_scl = match.group(1).strip() if match else None
|
|
||||||
elif not consumer_scl.strip().startswith(
|
|
||||||
"//"
|
|
||||||
): # Otherwise, take the whole line if not comment
|
|
||||||
core_scl = consumer_scl.strip()
|
|
||||||
|
|
||||||
if core_scl:
|
if core_scl:
|
||||||
grouped_instructions_cores.append(core_scl)
|
grouped_instructions_cores.append(core_scl)
|
||||||
|
@ -166,19 +114,15 @@ def process_group_ifs(instruction, network_id, sympy_map, symbol_manager, data):
|
||||||
|
|
||||||
# --- If groupable consumers found ---
|
# --- If groupable consumers found ---
|
||||||
if len(grouped_instructions_cores) > 1:
|
if len(grouped_instructions_cores) > 1:
|
||||||
print(
|
print(f"INFO: Agrupando {len(grouped_instructions_cores)} instr. bajo condición de {instr_type_original} UID {instr_uid}")
|
||||||
f"INFO: Agrupando {len(grouped_instructions_cores)} instr. bajo condición de {instr_type_original} UID {instr_uid}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# *** Simplify the SymPy condition ***
|
# *** Simplify the SymPy condition ***
|
||||||
try:
|
try:
|
||||||
# simplified_expr = sympy.simplify_logic(sympy_condition_expr, force=True)
|
#simplified_expr = sympy.simplify_logic(sympy_condition_expr, force=True)
|
||||||
simplified_expr = sympy.logic.boolalg.to_dnf(
|
simplified_expr = sympy.logic.boolalg.to_dnf(sympy_condition_expr, simplify=True)
|
||||||
sympy_condition_expr, simplify=True
|
|
||||||
)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error simplifying condition for grouping UID {instr_uid}: {e}")
|
print(f"Error simplifying condition for grouping UID {instr_uid}: {e}")
|
||||||
simplified_expr = sympy_condition_expr # Fallback
|
simplified_expr = sympy_condition_expr # Fallback
|
||||||
|
|
||||||
# *** Convert simplified condition to SCL string ***
|
# *** Convert simplified condition to SCL string ***
|
||||||
condition_scl_simplified = sympy_expr_to_scl(simplified_expr, symbol_manager)
|
condition_scl_simplified = sympy_expr_to_scl(simplified_expr, symbol_manager)
|
||||||
|
@ -186,9 +130,7 @@ def process_group_ifs(instruction, network_id, sympy_map, symbol_manager, data):
|
||||||
# *** Build the grouped IF SCL ***
|
# *** Build the grouped IF SCL ***
|
||||||
scl_grouped_lines = [f"IF {condition_scl_simplified} THEN"]
|
scl_grouped_lines = [f"IF {condition_scl_simplified} THEN"]
|
||||||
for core_line in grouped_instructions_cores:
|
for core_line in grouped_instructions_cores:
|
||||||
indented_core = "\n".join(
|
indented_core = "\n".join([f" {line.strip()}" for line in core_line.splitlines()])
|
||||||
[f" {line.strip()}" for line in core_line.splitlines()]
|
|
||||||
)
|
|
||||||
scl_grouped_lines.append(indented_core)
|
scl_grouped_lines.append(indented_core)
|
||||||
scl_grouped_lines.append("END_IF;")
|
scl_grouped_lines.append("END_IF;")
|
||||||
final_grouped_scl = "\n".join(scl_grouped_lines)
|
final_grouped_scl = "\n".join(scl_grouped_lines)
|
||||||
|
@ -203,19 +145,18 @@ def process_group_ifs(instruction, network_id, sympy_map, symbol_manager, data):
|
||||||
|
|
||||||
return made_change
|
return made_change
|
||||||
|
|
||||||
|
|
||||||
def load_processors(processors_dir="processors"):
|
def load_processors(processors_dir="processors"):
|
||||||
"""
|
"""
|
||||||
Escanea el directorio, importa módulos, construye el mapa y una lista
|
Escanea el directorio, importa módulos, construye el mapa y una lista
|
||||||
ordenada por prioridad.
|
ordenada por prioridad.
|
||||||
"""
|
"""
|
||||||
processor_map = {}
|
processor_map = {}
|
||||||
processor_list_unsorted = [] # Lista para guardar (priority, type_name, func)
|
processor_list_unsorted = [] # Lista para guardar (priority, type_name, func)
|
||||||
default_priority = 10 # Prioridad si no se define en get_processor_info
|
default_priority = 10 # Prioridad si no se define en get_processor_info
|
||||||
|
|
||||||
if not os.path.isdir(processors_dir):
|
if not os.path.isdir(processors_dir):
|
||||||
print(f"Error: Directorio de procesadores no encontrado: '{processors_dir}'")
|
print(f"Error: Directorio de procesadores no encontrado: '{processors_dir}'")
|
||||||
return processor_map, [] # Devuelve mapa vacío y lista vacía
|
return processor_map, [] # Devuelve mapa vacío y lista vacía
|
||||||
|
|
||||||
print(f"Cargando procesadores desde: '{processors_dir}'")
|
print(f"Cargando procesadores desde: '{processors_dir}'")
|
||||||
processors_package = os.path.basename(processors_dir)
|
processors_package = os.path.basename(processors_dir)
|
||||||
|
@ -227,9 +168,7 @@ def load_processors(processors_dir="processors"):
|
||||||
try:
|
try:
|
||||||
module = importlib.import_module(full_module_name)
|
module = importlib.import_module(full_module_name)
|
||||||
|
|
||||||
if hasattr(module, "get_processor_info") and callable(
|
if hasattr(module, 'get_processor_info') and callable(module.get_processor_info):
|
||||||
module.get_processor_info
|
|
||||||
):
|
|
||||||
processor_info = module.get_processor_info()
|
processor_info = module.get_processor_info()
|
||||||
info_list = []
|
info_list = []
|
||||||
if isinstance(processor_info, dict):
|
if isinstance(processor_info, dict):
|
||||||
|
@ -237,51 +176,29 @@ def load_processors(processors_dir="processors"):
|
||||||
elif isinstance(processor_info, list):
|
elif isinstance(processor_info, list):
|
||||||
info_list = processor_info
|
info_list = processor_info
|
||||||
else:
|
else:
|
||||||
print(
|
print(f" Advertencia: get_processor_info en {full_module_name} devolvió tipo inesperado. Se ignora.")
|
||||||
f" Advertencia: get_processor_info en {full_module_name} devolvió tipo inesperado. Se ignora."
|
|
||||||
)
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for info in info_list:
|
for info in info_list:
|
||||||
if (
|
if isinstance(info, dict) and 'type_name' in info and 'processor_func' in info:
|
||||||
isinstance(info, dict)
|
type_name = info['type_name'].lower()
|
||||||
and "type_name" in info
|
processor_func = info['processor_func']
|
||||||
and "processor_func" in info
|
|
||||||
):
|
|
||||||
type_name = info["type_name"].lower()
|
|
||||||
processor_func = info["processor_func"]
|
|
||||||
# Obtener prioridad, usar default si no existe
|
# Obtener prioridad, usar default si no existe
|
||||||
priority = info.get("priority", default_priority)
|
priority = info.get('priority', default_priority)
|
||||||
|
|
||||||
if callable(processor_func):
|
if callable(processor_func):
|
||||||
if type_name in processor_map:
|
if type_name in processor_map:
|
||||||
print(
|
print(f" Advertencia: '{type_name}' en {full_module_name} sobrescribe definición anterior.")
|
||||||
f" Advertencia: '{type_name}' en {full_module_name} sobrescribe definición anterior."
|
|
||||||
)
|
|
||||||
processor_map[type_name] = processor_func
|
processor_map[type_name] = processor_func
|
||||||
# Añadir a la lista para ordenar
|
# Añadir a la lista para ordenar
|
||||||
processor_list_unsorted.append(
|
processor_list_unsorted.append({'priority': priority, 'type_name': type_name, 'func': processor_func})
|
||||||
{
|
print(f" - Cargado '{type_name}' (Prio: {priority}) desde {module_name_rel}.py")
|
||||||
"priority": priority,
|
|
||||||
"type_name": type_name,
|
|
||||||
"func": processor_func,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
print(
|
|
||||||
f" - Cargado '{type_name}' (Prio: {priority}) desde {module_name_rel}.py"
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
print(
|
print(f" Advertencia: 'processor_func' para '{type_name}' en {full_module_name} no es callable.")
|
||||||
f" Advertencia: 'processor_func' para '{type_name}' en {full_module_name} no es callable."
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
print(
|
print(f" Advertencia: Entrada inválida en {full_module_name}: {info}")
|
||||||
f" Advertencia: Entrada inválida en {full_module_name}: {info}"
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
print(
|
print(f" Advertencia: Módulo {module_name_rel}.py no tiene 'get_processor_info'.")
|
||||||
f" Advertencia: Módulo {module_name_rel}.py no tiene 'get_processor_info'."
|
|
||||||
)
|
|
||||||
|
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
print(f"Error importando {full_module_name}: {e}")
|
print(f"Error importando {full_module_name}: {e}")
|
||||||
|
@ -290,211 +207,162 @@ def load_processors(processors_dir="processors"):
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
# Ordenar la lista por prioridad (menor primero)
|
# Ordenar la lista por prioridad (menor primero)
|
||||||
processor_list_sorted = sorted(processor_list_unsorted, key=lambda x: x["priority"])
|
processor_list_sorted = sorted(processor_list_unsorted, key=lambda x: x['priority'])
|
||||||
|
|
||||||
print(f"\nTotal de tipos de procesadores cargados: {len(processor_map)}")
|
print(f"\nTotal de tipos de procesadores cargados: {len(processor_map)}")
|
||||||
print(
|
print(f"Orden de procesamiento por prioridad: {[item['type_name'] for item in processor_list_sorted]}")
|
||||||
f"Orden de procesamiento por prioridad: {[item['type_name'] for item in processor_list_sorted]}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Devolver el mapa (para lookup rápido si es necesario) y la lista ordenada
|
# Devolver el mapa (para lookup rápido si es necesario) y la lista ordenada
|
||||||
return processor_map, processor_list_sorted
|
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):
|
def process_json_to_scl(json_filepath):
|
||||||
"""
|
"""
|
||||||
Lee JSON simplificado, aplica procesadores dinámicos (ignorando redes STL y bloques DB),
|
Lee el JSON simplificado, aplica los procesadores dinámicamente cargados
|
||||||
y guarda JSON procesado.
|
siguiendo un orden de prioridad, y guarda el JSON procesado.
|
||||||
"""
|
"""
|
||||||
global data
|
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.
|
||||||
|
|
||||||
if not os.path.exists(json_filepath):
|
if not os.path.exists(json_filepath): print(f"Error: JSON no encontrado: {json_filepath}"); return
|
||||||
print(f"Error: JSON no encontrado: {json_filepath}")
|
|
||||||
return
|
|
||||||
print(f"Cargando JSON desde: {json_filepath}")
|
print(f"Cargando JSON desde: {json_filepath}")
|
||||||
try:
|
try:
|
||||||
with open(json_filepath, "r", encoding="utf-8") as f:
|
with open(json_filepath, "r", encoding="utf-8") as f: data = json.load(f)
|
||||||
data = json.load(f)
|
except Exception as e: print(f"Error al cargar JSON: {e}"); traceback.print_exc(); return
|
||||||
except Exception as e:
|
|
||||||
print(f"Error al cargar JSON: {e}")
|
|
||||||
traceback.print_exc()
|
|
||||||
return
|
|
||||||
|
|
||||||
# --- Obtener lenguaje del bloque principal ---
|
# --- Carga dinámica de procesadores (sin cambios) ---
|
||||||
block_language = data.get("language", "Unknown")
|
script_dir = os.path.dirname(__file__); processors_dir_path = os.path.join(script_dir, 'processors')
|
||||||
block_type = data.get("block_type", "Unknown") # FC, FB, GlobalDB
|
|
||||||
print(f"Procesando bloque tipo: {block_type}, Lenguaje principal: {block_language}")
|
|
||||||
|
|
||||||
# --- SI ES UN DB, SALTAR EL PROCESAMIENTO LÓGICO ---
|
|
||||||
if block_language == "DB":
|
|
||||||
print(
|
|
||||||
"INFO: El bloque es un Data Block (DB). Saltando procesamiento lógico de x2."
|
|
||||||
)
|
|
||||||
# Simplemente guardamos una copia (o el mismo archivo si no se requiere sufijo)
|
|
||||||
output_filename = json_filepath.replace(
|
|
||||||
"_simplified.json", "_simplified_processed.json"
|
|
||||||
)
|
|
||||||
print(f"Guardando JSON de DB (sin cambios lógicos) en: {output_filename}")
|
|
||||||
try:
|
|
||||||
with open(output_filename, "w", encoding="utf-8") as f:
|
|
||||||
json.dump(data, f, indent=4, ensure_ascii=False)
|
|
||||||
print("Guardado de DB completado.")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error Crítico al guardar JSON del DB: {e}")
|
|
||||||
traceback.print_exc()
|
|
||||||
return # <<< SALIR TEMPRANO PARA DBs
|
|
||||||
|
|
||||||
# --- SI NO ES DB, CONTINUAR CON EL PROCESAMIENTO LÓGICO (FC/FB) ---
|
|
||||||
print("INFO: El bloque es FC/FB. Iniciando procesamiento lógico...")
|
|
||||||
|
|
||||||
script_dir = os.path.dirname(__file__)
|
|
||||||
processors_dir_path = os.path.join(script_dir, "processors")
|
|
||||||
processor_map, sorted_processors = load_processors(processors_dir_path)
|
processor_map, sorted_processors = load_processors(processors_dir_path)
|
||||||
if not processor_map:
|
if not processor_map: print("Error crítico: No se cargaron procesadores. Abortando."); return
|
||||||
print("Error crítico: No se cargaron procesadores. Abortando.")
|
|
||||||
return
|
|
||||||
|
|
||||||
|
# --- Crear mapas de acceso por red (sin cambios) ---
|
||||||
network_access_maps = {}
|
network_access_maps = {}
|
||||||
# Crear mapas de acceso por red (copiado/adaptado de versión anterior)
|
# ... (logic to populate network_access_maps remains the same) ...
|
||||||
for network in data.get("networks", []):
|
for network in data.get("networks", []):
|
||||||
net_id = network["id"]
|
net_id = network["id"]
|
||||||
current_access_map = {}
|
current_access_map = {}
|
||||||
|
# Extraer todos los 'Access' usados en esta red
|
||||||
for instr in network.get("logic", []):
|
for instr in network.get("logic", []):
|
||||||
for _, source in instr.get("inputs", {}).items():
|
# Revisar Inputs
|
||||||
sources_to_check = (
|
for _, source in instr.get("inputs", {}).items():
|
||||||
source
|
sources_to_check = (source if isinstance(source, list) else ([source] if isinstance(source, dict) else []))
|
||||||
if isinstance(source, list)
|
for src in sources_to_check:
|
||||||
else ([source] if isinstance(source, dict) else [])
|
if (isinstance(src, dict) and src.get("uid") and src.get("type") in ["variable", "constant"]):
|
||||||
)
|
current_access_map[src["uid"]] = src
|
||||||
for src in sources_to_check:
|
# Revisar Outputs
|
||||||
if (
|
for _, dest_list in instr.get("outputs", {}).items():
|
||||||
isinstance(src, dict)
|
if isinstance(dest_list, list):
|
||||||
and src.get("uid")
|
for dest in dest_list:
|
||||||
and src.get("type") in ["variable", "constant"]
|
if (isinstance(dest, dict) and dest.get("uid") and dest.get("type") in ["variable", "constant"]):
|
||||||
):
|
current_access_map[dest["uid"]] = dest
|
||||||
current_access_map[src["uid"]] = src
|
|
||||||
for _, dest_list in instr.get("outputs", {}).items():
|
|
||||||
if isinstance(dest_list, list):
|
|
||||||
for dest in dest_list:
|
|
||||||
if (
|
|
||||||
isinstance(dest, dict)
|
|
||||||
and dest.get("uid")
|
|
||||||
and dest.get("type") in ["variable", "constant"]
|
|
||||||
):
|
|
||||||
current_access_map[dest["uid"]] = dest
|
|
||||||
network_access_maps[net_id] = current_access_map
|
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.
|
||||||
symbol_manager = SymbolManager()
|
symbol_manager = SymbolManager()
|
||||||
sympy_map = {}
|
sympy_map = {} # Mapa para resultados SymPy intermedios (expresiones)
|
||||||
|
|
||||||
max_passes = 30
|
max_passes = 30
|
||||||
passes = 0
|
passes = 0
|
||||||
processing_complete = False
|
processing_complete = False
|
||||||
|
|
||||||
print("\n--- Iniciando Bucle de Procesamiento Iterativo (FC/FB) ---")
|
print("\n--- Iniciando Bucle de Procesamiento Iterativo (con SymPy y prioridad) ---")
|
||||||
while passes < max_passes and not processing_complete:
|
while passes < max_passes and not processing_complete:
|
||||||
passes += 1
|
passes += 1
|
||||||
made_change_in_base_pass = False
|
made_change_in_base_pass = False # Renombrar: made_change_in_sympy_pass
|
||||||
made_change_in_group_pass = False
|
made_change_in_group_pass = False
|
||||||
|
# made_change_in_simplify_pass = False # Ya no existe Fase 3
|
||||||
print(f"\n--- Pase {passes} ---")
|
print(f"\n--- Pase {passes} ---")
|
||||||
num_sympy_processed_this_pass = 0
|
num_processed_this_pass = 0 # Renombrar: num_sympy_processed_this_pass
|
||||||
num_grouped_this_pass = 0
|
num_grouped_this_pass = 0
|
||||||
|
# num_simplified_this_pass = 0 # Ya no existe Fase 3
|
||||||
|
|
||||||
# --- FASE 1: Procesadores Base (Ignorando STL) ---
|
# --- FASE 1: Procesadores Base (Ahora usan SymPy) ---
|
||||||
print(f" Fase 1 (SymPy Base - Orden por Prioridad):")
|
print(f" Fase 1 (SymPy Base - Orden por Prioridad):")
|
||||||
num_sympy_processed_this_pass = 0 # Resetear contador para el pase
|
num_sympy_processed_this_pass = 0 # Contador específico
|
||||||
for processor_info in sorted_processors:
|
for processor_info in sorted_processors:
|
||||||
current_type_name = processor_info["type_name"]
|
current_type_name = processor_info['type_name']
|
||||||
func_to_call = processor_info["func"]
|
func_to_call = processor_info['func']
|
||||||
|
|
||||||
for network in data.get("networks", []):
|
for network in data.get("networks", []):
|
||||||
network_id = network["id"]
|
network_id = network["id"]
|
||||||
network_lang = network.get("language", "LAD")
|
|
||||||
if network_lang == "STL":
|
|
||||||
continue # Saltar STL
|
|
||||||
|
|
||||||
access_map = network_access_maps.get(network_id, {})
|
access_map = network_access_maps.get(network_id, {})
|
||||||
network_logic = network.get("logic", [])
|
network_logic = network.get("logic", [])
|
||||||
|
|
||||||
for instruction in network_logic:
|
for instruction in network_logic:
|
||||||
instr_uid = instruction.get("instruction_uid")
|
instr_uid = instruction.get("instruction_uid")
|
||||||
instr_type_original = instruction.get("type", "Unknown")
|
instr_type_original = instruction.get("type", "Unknown")
|
||||||
if (
|
|
||||||
instr_type_original.endswith(SCL_SUFFIX)
|
# Saltar si ya está procesado con el NUEVO método, es error, o agrupado
|
||||||
|
if (instr_type_original.endswith(SCL_SUFFIX) # Check new suffix
|
||||||
or "_error" in instr_type_original
|
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
|
continue
|
||||||
|
|
||||||
|
# Determinar tipo efectivo (como antes)
|
||||||
lookup_key = instr_type_original.lower()
|
lookup_key = instr_type_original.lower()
|
||||||
effective_type_name = lookup_key
|
effective_type_name = lookup_key
|
||||||
if instr_type_original == "Call":
|
if instr_type_original == "Call": # ... (manejo Call FC/FB) ...
|
||||||
block_type = instruction.get("block_type", "").upper()
|
block_type = instruction.get("block_type", "").upper()
|
||||||
if block_type == "FC":
|
if block_type == "FC": effective_type_name = "call_fc"
|
||||||
effective_type_name = "call_fc"
|
elif block_type == "FB": effective_type_name = "call_fb"
|
||||||
elif block_type == "FB":
|
|
||||||
effective_type_name = "call_fb"
|
|
||||||
|
|
||||||
if effective_type_name == current_type_name:
|
if effective_type_name == current_type_name:
|
||||||
try:
|
try:
|
||||||
changed = func_to_call(
|
# *** Llamar al procesador refactorizado ***
|
||||||
instruction, network_id, sympy_map, symbol_manager, data
|
# Pasa sympy_map y symbol_manager, no scl_map
|
||||||
)
|
changed = func_to_call(instruction, network_id, sympy_map, symbol_manager, data) # Pasamos SymbolManager
|
||||||
if changed:
|
if changed:
|
||||||
made_change_in_base_pass = True
|
made_change_in_base_pass = True
|
||||||
num_sympy_processed_this_pass += 1
|
num_sympy_processed_this_pass += 1
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(
|
print(f"ERROR(SymPy Base) al procesar {instr_type_original} UID {instr_uid}: {e}")
|
||||||
f"ERROR(SymPy Base) al procesar {instr_type_original} UID {instr_uid}: {e}"
|
traceback.print_exc()
|
||||||
)
|
instruction["scl"] = f"// ERROR en SymPy procesador base: {e}"
|
||||||
traceback.print_exc()
|
instruction["type"] = instr_type_original + "_error"
|
||||||
instruction["scl"] = (
|
made_change_in_base_pass = True
|
||||||
f"// ERROR en SymPy procesador base: {e}"
|
print(f" -> {num_sympy_processed_this_pass} instrucciones procesadas con SymPy.")
|
||||||
)
|
|
||||||
instruction["type"] = instr_type_original + "_error"
|
|
||||||
made_change_in_base_pass = True
|
|
||||||
print(
|
|
||||||
f" -> {num_sympy_processed_this_pass} instrucciones (no STL) procesadas con SymPy."
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- FASE 2: Agrupación IF (Ignorando STL) ---
|
|
||||||
if (
|
# --- FASE 2: Agrupación IF (Ahora usa SymPy para simplificar) ---
|
||||||
made_change_in_base_pass or passes == 1
|
# Ejecutar si hubo cambios en base o es el primer pase
|
||||||
): # Ejecutar siempre en el primer pase
|
if made_change_in_base_pass or passes == 1:
|
||||||
print(f" Fase 2 (Agrupación IF con Simplificación):")
|
print(f" Fase 2 (Agrupación IF con Simplificación):")
|
||||||
num_grouped_this_pass = 0 # Resetear contador para el pase
|
num_grouped_this_pass = 0 # Reiniciar contador
|
||||||
for network in data.get("networks", []):
|
for network in data.get("networks", []):
|
||||||
network_id = network["id"]
|
network_id = network["id"]
|
||||||
network_lang = network.get("language", "LAD")
|
# access_map = network_access_maps.get(network_id, {}) # No usado directamente por group_ifs
|
||||||
if network_lang == "STL":
|
|
||||||
continue # Saltar STL
|
|
||||||
network_logic = network.get("logic", [])
|
network_logic = network.get("logic", [])
|
||||||
|
# Iterar sobre instrucciones que *pueden* generar condiciones booleanas
|
||||||
for instruction in network_logic:
|
for instruction in network_logic:
|
||||||
|
# process_group_ifs ahora verifica internamente si la instr. fue procesada
|
||||||
try:
|
try:
|
||||||
group_changed = process_group_ifs(
|
# *** Llamar a process_group_ifs adaptado ***
|
||||||
instruction, network_id, sympy_map, symbol_manager, data
|
group_changed = process_group_ifs(instruction, network_id, sympy_map, symbol_manager, data)
|
||||||
)
|
if group_changed:
|
||||||
if group_changed:
|
made_change_in_group_pass = True
|
||||||
made_change_in_group_pass = True
|
num_grouped_this_pass += 1
|
||||||
num_grouped_this_pass += 1
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(
|
print(f"ERROR(GroupLoop) al intentar agrupar desde UID {instruction.get('instruction_uid')}: {e}")
|
||||||
f"ERROR(GroupLoop) al intentar agrupar desde UID {instruction.get('instruction_uid')}: {e}"
|
traceback.print_exc()
|
||||||
)
|
print(f" -> {num_grouped_this_pass} agrupaciones realizadas.")
|
||||||
traceback.print_exc()
|
|
||||||
print(
|
# --- FASE 3 Eliminada ---
|
||||||
f" -> {num_grouped_this_pass} agrupaciones realizadas (en redes no STL)."
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- Comprobar si se completó el procesamiento ---
|
# --- 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:
|
if not made_change_in_base_pass and not made_change_in_group_pass:
|
||||||
print(
|
print(f"\n--- No se hicieron más cambios en el pase {passes}. Proceso iterativo completado. ---")
|
||||||
f"\n--- No se hicieron más cambios en el pase {passes}. Proceso iterativo completado. ---"
|
|
||||||
)
|
|
||||||
processing_complete = True
|
processing_complete = True
|
||||||
else:
|
else:
|
||||||
print(
|
# Mensaje de fin de pase actualizado
|
||||||
f"--- Fin Pase {passes}: {num_sympy_processed_this_pass} proc SymPy, {num_grouped_this_pass} agrup. Continuando..."
|
print(f"--- Fin Pase {passes}: {num_sympy_processed_this_pass} proc SymPy, {num_grouped_this_pass} agrup. Continuando...")
|
||||||
)
|
|
||||||
|
|
||||||
# --- Comprobar límite de pases ---
|
# --- Comprobar límite de pases ---
|
||||||
if passes == max_passes and not processing_complete:
|
if passes == max_passes and not processing_complete:
|
||||||
|
@ -502,52 +370,48 @@ def process_json_to_scl(json_filepath):
|
||||||
|
|
||||||
# --- FIN BUCLE ITERATIVO ---
|
# --- FIN BUCLE ITERATIVO ---
|
||||||
|
|
||||||
# --- Verificación Final (Ajustada para RAW_STL_CHUNK) ---
|
# --- Verificación Final ---
|
||||||
print("\n--- Verificación Final de Instrucciones No Procesadas (FC/FB) ---")
|
# La lógica aquí podría necesitar ajustes si el sufijo cambió o si el SCL final
|
||||||
|
# solo se genera en instrucciones terminales.
|
||||||
|
print("\n--- Verificación Final de Instrucciones No Procesadas ---")
|
||||||
unprocessed_count = 0
|
unprocessed_count = 0
|
||||||
unprocessed_details = []
|
unprocessed_details = []
|
||||||
ignored_types = [
|
ignored_types = ['raw_scl_chunk', 'unsupported_lang']
|
||||||
"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")
|
|
||||||
if network_lang == "STL":
|
|
||||||
continue # No verificar redes STL
|
|
||||||
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)
|
|
||||||
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
|
|
||||||
):
|
|
||||||
unprocessed_count += 1
|
|
||||||
unprocessed_details.append(
|
|
||||||
f" - Red '{network_title}' (ID: {network_id}, Lang: {network_lang}), "
|
|
||||||
f"Instrucción UID: {instr_uid}, Tipo: '{instr_type}'"
|
|
||||||
)
|
|
||||||
if unprocessed_count > 0:
|
|
||||||
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 (no STL) parecen haber sido procesadas o agrupadas."
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- Guardar JSON Final ---
|
for network in data.get("networks", []):
|
||||||
output_filename = json_filepath.replace(
|
network_id = network.get("id", "Unknown ID")
|
||||||
"_simplified.json", "_simplified_processed.json"
|
network_title = network.get("title", f"Network {network_id}")
|
||||||
)
|
for instruction in network.get("logic", []):
|
||||||
print(f"\nGuardando JSON procesado (FC/FB) en: {output_filename}")
|
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
|
||||||
|
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):
|
||||||
|
unprocessed_count += 1
|
||||||
|
unprocessed_details.append(
|
||||||
|
f" - Red '{network_title}' (ID: {network_id}), "
|
||||||
|
f"Instrucción UID: {instr_uid}, Tipo Original: '{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:")
|
||||||
|
for detail in unprocessed_details: print(detail)
|
||||||
|
else:
|
||||||
|
print("INFO: Todas las instrucciones relevantes parecen haber sido procesadas o agrupadas.")
|
||||||
|
|
||||||
|
# --- Guardar JSON Final (sin cambios) ---
|
||||||
|
output_filename = json_filepath.replace("_simplified.json", "_simplified_processed.json")
|
||||||
|
print(f"\nGuardando JSON procesado en: {output_filename}")
|
||||||
try:
|
try:
|
||||||
with open(output_filename, "w", encoding="utf-8") as f:
|
with open(output_filename, "w", encoding="utf-8") as f:
|
||||||
json.dump(data, f, indent=4, ensure_ascii=False)
|
json.dump(data, f, indent=4, ensure_ascii=False)
|
||||||
|
@ -557,67 +421,27 @@ def process_json_to_scl(json_filepath):
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
|
|
||||||
# --- Ejecución (sin cambios) ---
|
# --- Ejecución (igual que antes) ---
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# Imports necesarios solo para la ejecución como script principal
|
parser = argparse.ArgumentParser(description="Process simplified JSON to embed SCL logic.")
|
||||||
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."
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"source_xml_filepath", # Argumento posicional obligatorio
|
"source_xml_filepath",
|
||||||
help="Path to the original source XML file (passed from x0_main.py, used to derive JSON input name).",
|
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() # Parsea los argumentos de sys.argv
|
args = parser.parse_args()
|
||||||
|
|
||||||
source_xml_file = args.source_xml_filepath # Obtiene la ruta del XML original
|
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
|
||||||
|
|
||||||
# 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")
|
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):
|
if not os.path.exists(input_json_file):
|
||||||
print(
|
print(f"Error Fatal: El archivo de entrada JSON simplificado no existe: '{input_json_file}'")
|
||||||
f"Error Fatal (x2): 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"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:
|
else:
|
||||||
# Llamar a la función principal de procesamiento del script
|
process_json_to_scl(input_json_file)
|
||||||
# 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
|
|
|
@ -5,481 +5,266 @@ import os
|
||||||
import re
|
import re
|
||||||
import argparse
|
import argparse
|
||||||
import sys
|
import sys
|
||||||
import traceback # Importar traceback para errores
|
import traceback # Importar traceback para errores
|
||||||
|
|
||||||
# --- Importar Utilidades y Constantes (Asumiendo ubicación) ---
|
# --- Importar Utilidades y Constantes (Asumiendo ubicación) ---
|
||||||
try:
|
try:
|
||||||
# Intenta importar desde el paquete de procesadores si está estructurado así
|
# Intenta importar desde el paquete de procesadores si está estructurado así
|
||||||
from processors.processor_utils import format_variable_name
|
from processors.processor_utils import format_variable_name
|
||||||
|
|
||||||
# Definir SCL_SUFFIX aquí o importarlo si está centralizado
|
# Definir SCL_SUFFIX aquí o importarlo si está centralizado
|
||||||
SCL_SUFFIX = "_sympy_processed" # Asegúrate que coincida con x2_process.py
|
SCL_SUFFIX = "_sympy_processed" # Asegúrate que coincida con x2_process.py
|
||||||
GROUPED_COMMENT = (
|
GROUPED_COMMENT = "// Logic included in grouped IF" # Opcional, si se usa para filtrar
|
||||||
"// Logic included in grouped IF" # Opcional, si se usa para filtrar
|
|
||||||
)
|
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print(
|
print("Advertencia: No se pudo importar 'format_variable_name' desde processors.processor_utils.")
|
||||||
"Advertencia: No se pudo importar 'format_variable_name' desde processors.processor_utils."
|
print("Usando una implementación local básica (¡PUEDE FALLAR CON NOMBRES COMPLEJOS!).")
|
||||||
)
|
|
||||||
print(
|
|
||||||
"Usando una implementación local básica (¡PUEDE FALLAR CON NOMBRES COMPLEJOS!)."
|
|
||||||
)
|
|
||||||
|
|
||||||
# Implementación local BÁSICA como fallback (MENOS RECOMENDADA)
|
# Implementación local BÁSICA como fallback (MENOS RECOMENDADA)
|
||||||
def format_variable_name(name):
|
def format_variable_name(name):
|
||||||
if not name:
|
if not name: return "_INVALID_NAME_"
|
||||||
return "_INVALID_NAME_"
|
if name.startswith('"') and name.endswith('"'): return name # Mantener comillas
|
||||||
if name.startswith('"') and name.endswith('"'):
|
|
||||||
return name # Mantener comillas
|
|
||||||
prefix = "#" if name.startswith("#") else ""
|
prefix = "#" if name.startswith("#") else ""
|
||||||
if prefix:
|
if prefix: name = name[1:]
|
||||||
name = name[1:]
|
if name and name[0].isdigit(): name = "_" + name
|
||||||
if name and name[0].isdigit():
|
|
||||||
name = "_" + name
|
|
||||||
name = re.sub(r"[^a-zA-Z0-9_]", "_", name)
|
name = re.sub(r"[^a-zA-Z0-9_]", "_", name)
|
||||||
return prefix + name
|
return prefix + name
|
||||||
|
|
||||||
SCL_SUFFIX = "_sympy_processed"
|
SCL_SUFFIX = "_sympy_processed"
|
||||||
GROUPED_COMMENT = "// Logic included in grouped IF"
|
GROUPED_COMMENT = "// Logic included in grouped IF"
|
||||||
|
|
||||||
|
|
||||||
# para formatear valores iniciales
|
|
||||||
def format_scl_start_value(value, datatype):
|
|
||||||
"""Formatea un valor para la inicialización SCL según el tipo."""
|
|
||||||
if value is None:
|
|
||||||
return None
|
|
||||||
datatype_lower = datatype.lower() if datatype else ""
|
|
||||||
value_str = str(value)
|
|
||||||
|
|
||||||
if "bool" in datatype_lower:
|
|
||||||
return "TRUE" if value_str.lower() == "true" else "FALSE"
|
|
||||||
elif "string" in datatype_lower:
|
|
||||||
escaped_value = value_str.replace("'", "''")
|
|
||||||
if escaped_value.startswith("'") and escaped_value.endswith("'"):
|
|
||||||
escaped_value = escaped_value[1:-1]
|
|
||||||
return f"'{escaped_value}'"
|
|
||||||
elif "char" in datatype_lower: # Añadido Char
|
|
||||||
escaped_value = value_str.replace("'", "''")
|
|
||||||
if escaped_value.startswith("'") and escaped_value.endswith("'"):
|
|
||||||
escaped_value = escaped_value[1:-1]
|
|
||||||
return f"'{escaped_value}'"
|
|
||||||
elif any(
|
|
||||||
t in datatype_lower
|
|
||||||
for t in [
|
|
||||||
"int",
|
|
||||||
"byte",
|
|
||||||
"word",
|
|
||||||
"dint",
|
|
||||||
"dword",
|
|
||||||
"lint",
|
|
||||||
"lword",
|
|
||||||
"sint",
|
|
||||||
"usint",
|
|
||||||
"uint",
|
|
||||||
"udint",
|
|
||||||
"ulint",
|
|
||||||
]
|
|
||||||
): # Ampliado
|
|
||||||
try:
|
|
||||||
return str(int(value_str))
|
|
||||||
except ValueError:
|
|
||||||
if re.match(r"^[a-zA-Z_][a-zA-Z0-9_]*$", value_str):
|
|
||||||
return value_str
|
|
||||||
return f"'{value_str}'" # O como string si no es entero ni símbolo
|
|
||||||
elif "real" in datatype_lower or "lreal" in datatype_lower:
|
|
||||||
try:
|
|
||||||
f_val = float(value_str)
|
|
||||||
s_val = str(f_val)
|
|
||||||
if "." not in s_val and "e" not in s_val.lower():
|
|
||||||
s_val += ".0"
|
|
||||||
return s_val
|
|
||||||
except ValueError:
|
|
||||||
if re.match(r"^[a-zA-Z_][a-zA-Z0-9_]*$", value_str):
|
|
||||||
return value_str
|
|
||||||
return f"'{value_str}'"
|
|
||||||
elif "time" in datatype_lower: # Añadido Time, S5Time, LTime
|
|
||||||
# Quitar T#, LT#, S5T# si existen
|
|
||||||
prefix = ""
|
|
||||||
if value_str.upper().startswith("T#"):
|
|
||||||
prefix = "T#"
|
|
||||||
value_str = value_str[2:]
|
|
||||||
elif value_str.upper().startswith("LT#"):
|
|
||||||
prefix = "LT#"
|
|
||||||
value_str = value_str[3:]
|
|
||||||
elif value_str.upper().startswith("S5T#"):
|
|
||||||
prefix = "S5T#"
|
|
||||||
value_str = value_str[4:]
|
|
||||||
# Devolver con el prefijo correcto o T# por defecto si no había
|
|
||||||
if prefix:
|
|
||||||
return f"{prefix}{value_str}"
|
|
||||||
elif "s5time" in datatype_lower:
|
|
||||||
return f"S5T#{value_str}"
|
|
||||||
elif "ltime" in datatype_lower:
|
|
||||||
return f"LT#{value_str}"
|
|
||||||
else:
|
|
||||||
return f"T#{value_str}" # Default a TIME
|
|
||||||
elif "date" in datatype_lower: # Añadido Date, DT, TOD
|
|
||||||
if value_str.upper().startswith("D#"):
|
|
||||||
return value_str
|
|
||||||
elif "dt" in datatype_lower or "date_and_time" in datatype_lower:
|
|
||||||
if value_str.upper().startswith("DT#"):
|
|
||||||
return value_str
|
|
||||||
else:
|
|
||||||
return f"DT#{value_str}" # Añadir prefijo DT#
|
|
||||||
elif "tod" in datatype_lower or "time_of_day" in datatype_lower:
|
|
||||||
if value_str.upper().startswith("TOD#"):
|
|
||||||
return value_str
|
|
||||||
else:
|
|
||||||
return f"TOD#{value_str}" # Añadir prefijo TOD#
|
|
||||||
else:
|
|
||||||
return f"D#{value_str}" # Default a Date
|
|
||||||
# Fallback genérico
|
|
||||||
else:
|
|
||||||
if re.match(
|
|
||||||
r'^[a-zA-Z_][a-zA-Z0-9_."#\[\]]+$', value_str
|
|
||||||
): # Permitir más caracteres en símbolos/tipos
|
|
||||||
# Si es un UDT o Struct complejo, podría venir con comillas, quitarlas
|
|
||||||
if value_str.startswith('"') and value_str.endswith('"'):
|
|
||||||
return value_str[1:-1]
|
|
||||||
return value_str
|
|
||||||
else:
|
|
||||||
escaped_value = value_str.replace("'", "''")
|
|
||||||
return f"'{escaped_value}'"
|
|
||||||
|
|
||||||
|
|
||||||
# --- NUEVA FUNCIÓN RECURSIVA para generar declaraciones SCL (VAR/STRUCT/ARRAY) ---
|
|
||||||
def generate_scl_declarations(variables, indent_level=1):
|
|
||||||
"""Genera las líneas SCL para declarar variables, structs y arrays."""
|
|
||||||
scl_lines = []
|
|
||||||
indent = " " * indent_level
|
|
||||||
for var in variables:
|
|
||||||
var_name_scl = format_variable_name(var.get("name"))
|
|
||||||
var_dtype_raw = var.get("datatype", "VARIANT")
|
|
||||||
# Limpiar comillas de tipos de datos UDT ("MyType" -> MyType)
|
|
||||||
var_dtype = (
|
|
||||||
var_dtype_raw.strip('"')
|
|
||||||
if var_dtype_raw.startswith('"') and var_dtype_raw.endswith('"')
|
|
||||||
else var_dtype_raw
|
|
||||||
)
|
|
||||||
|
|
||||||
var_comment = var.get("comment")
|
|
||||||
start_value = var.get("start_value")
|
|
||||||
children = var.get("children") # Para structs
|
|
||||||
array_elements = var.get("array_elements") # Para arrays
|
|
||||||
|
|
||||||
# Manejar tipos de datos Array especiales
|
|
||||||
array_match = re.match(r"(Array\[.*\]\s+of\s+)(.*)", var_dtype, re.IGNORECASE)
|
|
||||||
base_type_for_init = var_dtype
|
|
||||||
declaration_dtype = var_dtype
|
|
||||||
if array_match:
|
|
||||||
array_prefix = array_match.group(1)
|
|
||||||
base_type_raw = array_match.group(2).strip()
|
|
||||||
# Limpiar comillas del tipo base del array
|
|
||||||
base_type_for_init = (
|
|
||||||
base_type_raw.strip('"')
|
|
||||||
if base_type_raw.startswith('"') and base_type_raw.endswith('"')
|
|
||||||
else base_type_raw
|
|
||||||
)
|
|
||||||
declaration_dtype = (
|
|
||||||
f'{array_prefix}"{base_type_for_init}"'
|
|
||||||
if '"' not in base_type_raw
|
|
||||||
else f"{array_prefix}{base_type_raw}"
|
|
||||||
) # Reconstruir con comillas si es UDT
|
|
||||||
|
|
||||||
# Reconstruir declaración con comillas si es UDT y no array
|
|
||||||
elif (
|
|
||||||
not array_match and var_dtype != base_type_for_init
|
|
||||||
): # Es un tipo que necesita comillas (UDT)
|
|
||||||
declaration_dtype = f'"{var_dtype}"'
|
|
||||||
|
|
||||||
declaration_line = f"{indent}{var_name_scl} : {declaration_dtype}"
|
|
||||||
init_value = None
|
|
||||||
|
|
||||||
# ---- Arrays ----
|
|
||||||
if array_elements:
|
|
||||||
# Ordenar índices (asumiendo que son numéricos)
|
|
||||||
try:
|
|
||||||
sorted_indices = sorted(array_elements.keys(), key=int)
|
|
||||||
except ValueError:
|
|
||||||
sorted_indices = sorted(
|
|
||||||
array_elements.keys()
|
|
||||||
) # Fallback a orden alfabético
|
|
||||||
|
|
||||||
init_values = [
|
|
||||||
format_scl_start_value(array_elements[idx], base_type_for_init)
|
|
||||||
for idx in sorted_indices
|
|
||||||
]
|
|
||||||
valid_inits = [v for v in init_values if v is not None]
|
|
||||||
if valid_inits:
|
|
||||||
init_value = f"[{', '.join(valid_inits)}]"
|
|
||||||
|
|
||||||
# ---- Structs ----
|
|
||||||
elif children:
|
|
||||||
# No añadir comentario // Struct aquí, es redundante
|
|
||||||
scl_lines.append(declaration_line) # Añadir línea de declaración base
|
|
||||||
scl_lines.append(f"{indent}STRUCT")
|
|
||||||
scl_lines.extend(generate_scl_declarations(children, indent_level + 1))
|
|
||||||
scl_lines.append(f"{indent}END_STRUCT;")
|
|
||||||
if var_comment:
|
|
||||||
scl_lines.append(f"{indent}// {var_comment}")
|
|
||||||
scl_lines.append("") # Línea extra
|
|
||||||
continue # Saltar resto para Struct
|
|
||||||
|
|
||||||
# ---- Tipos Simples ----
|
|
||||||
else:
|
|
||||||
if start_value is not None:
|
|
||||||
init_value = format_scl_start_value(start_value, var_dtype)
|
|
||||||
|
|
||||||
# Añadir inicialización si existe
|
|
||||||
if init_value:
|
|
||||||
declaration_line += f" := {init_value}"
|
|
||||||
declaration_line += ";"
|
|
||||||
if var_comment:
|
|
||||||
declaration_line += f" // {var_comment}"
|
|
||||||
scl_lines.append(declaration_line)
|
|
||||||
|
|
||||||
return scl_lines
|
|
||||||
|
|
||||||
|
|
||||||
# --- Función Principal de Generación SCL ---
|
# --- Función Principal de Generación SCL ---
|
||||||
|
|
||||||
def generate_scl(processed_json_filepath, output_scl_filepath):
|
def generate_scl(processed_json_filepath, output_scl_filepath):
|
||||||
"""Genera un archivo SCL a partir del JSON procesado (FC/FB o DB)."""
|
"""Genera un archivo SCL a partir del JSON procesado por x2_process (versión SymPy)."""
|
||||||
|
|
||||||
if not os.path.exists(processed_json_filepath):
|
if not os.path.exists(processed_json_filepath):
|
||||||
print(
|
print(f"Error: Archivo JSON procesado no encontrado en '{processed_json_filepath}'")
|
||||||
f"Error: Archivo JSON procesado no encontrado en '{processed_json_filepath}'"
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
print(f"Cargando JSON procesado desde: {processed_json_filepath}")
|
print(f"Cargando JSON procesado desde: {processed_json_filepath}")
|
||||||
try:
|
try:
|
||||||
with open(processed_json_filepath, "r", encoding="utf-8") as f:
|
with open(processed_json_filepath, 'r', encoding='utf-8') as f:
|
||||||
data = json.load(f)
|
data = json.load(f)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error al cargar o parsear JSON: {e}")
|
print(f"Error al cargar o parsear JSON: {e}")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
return
|
return
|
||||||
|
|
||||||
# --- Extracción de Información del Bloque (Común) ---
|
# --- Extracción de Información del Bloque ---
|
||||||
block_name = data.get("block_name", "UnknownBlock")
|
block_name = data.get('block_name', 'UnknownBlock')
|
||||||
block_number = data.get("block_number")
|
block_number = data.get('block_number')
|
||||||
block_lang_original = data.get("language", "Unknown") # Será "DB" para Data Blocks
|
block_lang_original = data.get('language', 'LAD') # Lenguaje original
|
||||||
block_type = data.get("block_type", "Unknown") # FC, FB, GlobalDB
|
# Determinar tipo de bloque SCL (Asumir FB si no se especifica)
|
||||||
block_comment = data.get("block_comment", "")
|
# Idealmente, x1_to_json.py guardaría esto en data['block_type_scl'] = 'FC' o 'FB'
|
||||||
scl_block_name = format_variable_name(block_name) # Nombre SCL seguro
|
block_type_scl = data.get('block_type_scl', 'FUNCTION_BLOCK')
|
||||||
print(
|
block_comment = data.get('block_comment', '')
|
||||||
f"Generando SCL para: {block_type} '{scl_block_name}' (Original: {block_name}, Lang: {block_lang_original})"
|
|
||||||
)
|
# Usar format_variable_name para el nombre del bloque en SCL
|
||||||
|
scl_block_name = format_variable_name(block_name)
|
||||||
|
print(f"Generando SCL para {block_type_scl}: {scl_block_name} (Original: {block_name})")
|
||||||
|
|
||||||
|
# --- Identificación de Variables Temporales y Estáticas ---
|
||||||
|
# La detección basada en regex sobre el SCL final debería seguir funcionando
|
||||||
|
temp_vars = set()
|
||||||
|
stat_vars = set()
|
||||||
|
# Regex mejorado para capturar variables temporales que empiezan con # o _temp_
|
||||||
|
# y estáticas (si usas un prefijo como 'stat_' o para bits de memoria de flanco)
|
||||||
|
temp_pattern = re.compile(r'"?#(_temp_[a-zA-Z0-9_]+)"?|"?(_temp_[a-zA-Z0-9_]+)"?') # Captura con o sin #
|
||||||
|
stat_pattern = re.compile(r'"?(stat_[a-zA-Z0-9_]+)"?') # Para memorias de flanco si usan prefijo 'stat_'
|
||||||
|
|
||||||
|
edge_memory_bits = set() # Para detectar bits de memoria de flanco por nombre
|
||||||
|
|
||||||
|
for network in data.get('networks', []):
|
||||||
|
for instruction in network.get('logic', []):
|
||||||
|
scl_code = instruction.get('scl', '')
|
||||||
|
# Buscar también en _edge_mem_update_scl si existe
|
||||||
|
edge_update_code = instruction.get('_edge_mem_update_scl','')
|
||||||
|
code_to_scan = (scl_code if scl_code else '') + '\n' + (edge_update_code if edge_update_code else '')
|
||||||
|
|
||||||
|
if code_to_scan:
|
||||||
|
# Buscar #_temp_... o _temp_...
|
||||||
|
found_temps = temp_pattern.findall(code_to_scan)
|
||||||
|
for temp_tuple in found_temps:
|
||||||
|
# findall devuelve tuplas por los grupos de captura, tomar el no vacío
|
||||||
|
temp_name = next((t for t in temp_tuple if t), None)
|
||||||
|
if temp_name:
|
||||||
|
temp_vars.add("#"+temp_name if not temp_name.startswith("#") else temp_name) # Asegurar que empiece con #
|
||||||
|
|
||||||
|
# Buscar estáticas (ej: stat_...)
|
||||||
|
found_stats = stat_pattern.findall(code_to_scan)
|
||||||
|
stat_vars.update(found_stats)
|
||||||
|
|
||||||
|
# Identificar explícitamente bits de memoria usados por PBox/NBox
|
||||||
|
# Asumiendo que el nombre se guarda en el JSON (requiere ajuste en x1/x2)
|
||||||
|
# if instruction.get("type","").startswith(("PBox", "NBox")):
|
||||||
|
# mem_bit_info = instruction.get("inputs", {}).get("bit")
|
||||||
|
# if mem_bit_info and mem_bit_info.get("type") == "variable":
|
||||||
|
# edge_memory_bits.add(format_variable_name(mem_bit_info.get("name")))
|
||||||
|
|
||||||
|
|
||||||
|
print(f"Variables temporales (#_temp_...) detectadas: {len(temp_vars)}")
|
||||||
|
# Si se detectan memorias de flanco, añadirlas a stat_vars si no tienen prefijo 'stat_'
|
||||||
|
# stat_vars.update(edge_memory_bits - stat_vars) # Añadir solo las nuevas
|
||||||
|
print(f"Variables estáticas (stat_...) detectadas: {len(stat_vars)}")
|
||||||
|
|
||||||
|
# --- Construcción del String SCL ---
|
||||||
scl_output = []
|
scl_output = []
|
||||||
|
|
||||||
# --- GENERACIÓN PARA DATA BLOCK (DB) ---
|
# Cabecera del Bloque
|
||||||
if block_lang_original == "DB":
|
scl_output.append(f"// Block Name (Original): {block_name}")
|
||||||
print("Modo de generación: DATA_BLOCK")
|
if block_number: scl_output.append(f"// Block Number: {block_number}")
|
||||||
scl_output.append(f"// Block Type: {block_type}")
|
scl_output.append(f"// Original Language: {block_lang_original}")
|
||||||
scl_output.append(f"// Block Name (Original): {block_name}")
|
if block_comment: scl_output.append(f"// Block Comment: {block_comment}")
|
||||||
if block_number:
|
scl_output.append("")
|
||||||
scl_output.append(f"// Block Number: {block_number}")
|
scl_output.append(f"{block_type_scl} \"{scl_block_name}\"")
|
||||||
if block_comment:
|
scl_output.append("{ S7_Optimized_Access := 'TRUE' }")
|
||||||
scl_output.append(f"// Block Comment: {block_comment}")
|
scl_output.append("VERSION : 0.1")
|
||||||
scl_output.append("")
|
scl_output.append("")
|
||||||
scl_output.append(f'DATA_BLOCK "{scl_block_name}"')
|
|
||||||
scl_output.append("{ S7_Optimized_Access := 'TRUE' }") # Asumir optimizado
|
|
||||||
scl_output.append("VERSION : 0.1")
|
|
||||||
scl_output.append("")
|
|
||||||
interface_data = data.get("interface", {})
|
|
||||||
static_vars = interface_data.get("Static", [])
|
|
||||||
if static_vars:
|
|
||||||
scl_output.append("VAR")
|
|
||||||
scl_output.extend(generate_scl_declarations(static_vars, indent_level=1))
|
|
||||||
scl_output.append("END_VAR")
|
|
||||||
scl_output.append("")
|
|
||||||
else:
|
|
||||||
print(
|
|
||||||
"Advertencia: No se encontró sección 'Static' o está vacía en la interfaz del DB."
|
|
||||||
)
|
|
||||||
scl_output.append("VAR")
|
|
||||||
scl_output.append("END_VAR")
|
|
||||||
scl_output.append("")
|
|
||||||
scl_output.append("BEGIN")
|
|
||||||
scl_output.append("")
|
|
||||||
scl_output.append("END_DATA_BLOCK")
|
|
||||||
|
|
||||||
# --- GENERACIÓN PARA FUNCTION BLOCK / FUNCTION (FC/FB) ---
|
# Declaraciones de Interfaz (Implementación básica)
|
||||||
else:
|
interface_sections = ["Input", "Output", "InOut", "Static", "Temp", "Constant", "Return"]
|
||||||
print("Modo de generación: FUNCTION_BLOCK / FUNCTION")
|
interface_data = data.get('interface', {})
|
||||||
scl_block_keyword = "FUNCTION_BLOCK" if block_type == "FB" else "FUNCTION"
|
|
||||||
# Cabecera del Bloque
|
|
||||||
scl_output.append(f"// Block Type: {block_type}")
|
|
||||||
scl_output.append(f"// Block Name (Original): {block_name}")
|
|
||||||
if block_number:
|
|
||||||
scl_output.append(f"// Block Number: {block_number}")
|
|
||||||
scl_output.append(f"// Original Language: {block_lang_original}")
|
|
||||||
if block_comment:
|
|
||||||
scl_output.append(f"// Block Comment: {block_comment}")
|
|
||||||
scl_output.append("")
|
|
||||||
# Manejar tipo de retorno para FUNCTION
|
|
||||||
return_type = "Void" # Default
|
|
||||||
interface_data = data.get("interface", {})
|
|
||||||
if scl_block_keyword == "FUNCTION" and interface_data.get("Return"):
|
|
||||||
return_member = interface_data["Return"][
|
|
||||||
0
|
|
||||||
] # Asumir un solo valor de retorno
|
|
||||||
return_type_raw = return_member.get("datatype", "Void")
|
|
||||||
return_type = (
|
|
||||||
return_type_raw.strip('"')
|
|
||||||
if return_type_raw.startswith('"') and return_type_raw.endswith('"')
|
|
||||||
else return_type_raw
|
|
||||||
)
|
|
||||||
# Añadir comillas si es UDT
|
|
||||||
if return_type != return_type_raw:
|
|
||||||
return_type = f'"{return_type}"'
|
|
||||||
|
|
||||||
scl_output.append(
|
for section_name in interface_sections:
|
||||||
f'{scl_block_keyword} "{scl_block_name}" : {return_type}'
|
scl_section_name = section_name
|
||||||
if scl_block_keyword == "FUNCTION"
|
# Ajustar nombres de sección para SCL (Static -> STAT, Temp -> TEMP)
|
||||||
else f'{scl_block_keyword} "{scl_block_name}"'
|
if section_name == "Static": scl_section_name = "STAT"
|
||||||
)
|
if section_name == "Temp": scl_section_name = "TEMP" # Usar VAR_TEMP para variables #temp
|
||||||
scl_output.append("{ S7_Optimized_Access := 'TRUE' }")
|
|
||||||
scl_output.append("VERSION : 0.1")
|
|
||||||
scl_output.append("")
|
|
||||||
|
|
||||||
# Declaraciones de Interfaz FC/FB
|
vars_in_section = interface_data.get(section_name, [])
|
||||||
section_order = [
|
# No declarar VAR_TEMP aquí, se hará después con las detectadas/originales
|
||||||
"Input",
|
if section_name == "Temp": continue
|
||||||
"Output",
|
|
||||||
"InOut",
|
|
||||||
"Static",
|
|
||||||
"Temp",
|
|
||||||
"Constant",
|
|
||||||
] # Return ya está en cabecera
|
|
||||||
declared_temps = set()
|
|
||||||
for section_name in section_order:
|
|
||||||
vars_in_section = interface_data.get(section_name, [])
|
|
||||||
if vars_in_section:
|
|
||||||
scl_section_keyword = f"VAR_{section_name.upper()}"
|
|
||||||
if section_name == "Static":
|
|
||||||
scl_section_keyword = "VAR_STAT"
|
|
||||||
if section_name == "Temp":
|
|
||||||
scl_section_keyword = "VAR_TEMP"
|
|
||||||
if section_name == "Constant":
|
|
||||||
scl_section_keyword = "CONSTANT"
|
|
||||||
scl_output.append(scl_section_keyword)
|
|
||||||
scl_output.extend(
|
|
||||||
generate_scl_declarations(vars_in_section, indent_level=1)
|
|
||||||
)
|
|
||||||
if section_name == "Temp":
|
|
||||||
declared_temps.update(
|
|
||||||
format_variable_name(v.get("name"))
|
|
||||||
for v in vars_in_section
|
|
||||||
if v.get("name")
|
|
||||||
)
|
|
||||||
scl_output.append("END_VAR")
|
|
||||||
scl_output.append("")
|
|
||||||
|
|
||||||
# Declaraciones VAR_TEMP adicionales detectadas
|
# No declarar VAR_STAT aquí si ya lo hacemos abajo con las detectadas
|
||||||
temp_vars = set()
|
if section_name == "Static" and stat_vars: continue
|
||||||
temp_pattern = re.compile(
|
|
||||||
r'"?#(_temp_[a-zA-Z0-9_]+)"?|"?(_temp_[a-zA-Z0-9_]+)"?'
|
|
||||||
)
|
if vars_in_section or (section_name == "Static" and stat_vars): # Incluir STAT si hay detectadas
|
||||||
for network in data.get("networks", []):
|
# Usar VAR para Input/Output/InOut/Constant/Return
|
||||||
for instruction in network.get("logic", []):
|
var_keyword = "VAR" if section_name != "Static" else "VAR_STAT"
|
||||||
scl_code = instruction.get("scl", "")
|
scl_output.append(f"{var_keyword}_{section_name.upper()}")
|
||||||
edge_update_code = instruction.get("_edge_mem_update_scl", "")
|
|
||||||
code_to_scan = (
|
for var in vars_in_section:
|
||||||
(scl_code if scl_code else "")
|
var_name = var.get('name')
|
||||||
+ "\n"
|
var_dtype = var.get('datatype', 'VARIANT') # Default a VARIANT
|
||||||
+ (edge_update_code if edge_update_code else "")
|
if var_name:
|
||||||
)
|
# Usar format_variable_name CORRECTO
|
||||||
if code_to_scan:
|
scl_name = format_variable_name(var_name)
|
||||||
found_temps = temp_pattern.findall(code_to_scan)
|
scl_output.append(f" {scl_name} : {var_dtype};")
|
||||||
for temp_tuple in found_temps:
|
|
||||||
temp_name = next((t for t in temp_tuple if t), None)
|
# Declarar stat_vars detectadas si esta es la sección STAT
|
||||||
if temp_name:
|
if section_name == "Static" and stat_vars:
|
||||||
temp_vars.add(
|
for var_name in sorted(list(stat_vars)):
|
||||||
"#" + temp_name
|
# Asumir Bool para stat_, podría necesitar inferencia
|
||||||
if not temp_name.startswith("#")
|
scl_output.append(f" {format_variable_name(var_name)} : Bool; // Auto-detected STAT")
|
||||||
else temp_name
|
|
||||||
)
|
scl_output.append("END_VAR")
|
||||||
additional_temps = sorted(list(temp_vars - declared_temps))
|
scl_output.append("")
|
||||||
if additional_temps:
|
|
||||||
if not interface_data.get("Temp"):
|
# Declaraciones Estáticas (Si no estaban en la interfaz y se detectaron)
|
||||||
scl_output.append("VAR_TEMP")
|
# Esto es redundante si la sección VAR_STAT ya se generó arriba
|
||||||
for var_name in additional_temps:
|
# if stat_vars and not interface_data.get("Static"):
|
||||||
|
# scl_output.append("VAR_STAT")
|
||||||
|
# for var_name in sorted(list(stat_vars)):
|
||||||
|
# scl_output.append(f" {format_variable_name(var_name)} : Bool; // Auto-detected STAT")
|
||||||
|
# scl_output.append("END_VAR")
|
||||||
|
# scl_output.append("")
|
||||||
|
|
||||||
|
|
||||||
|
# Declaraciones Temporales (Interfaz Temp + _temp_ detectadas)
|
||||||
|
scl_output.append("VAR_TEMP")
|
||||||
|
declared_temps = set()
|
||||||
|
interface_temps = interface_data.get('Temp', [])
|
||||||
|
if interface_temps:
|
||||||
|
for var in interface_temps:
|
||||||
|
var_name = var.get('name')
|
||||||
|
var_dtype = var.get('datatype', 'VARIANT')
|
||||||
|
if var_name:
|
||||||
scl_name = format_variable_name(var_name)
|
scl_name = format_variable_name(var_name)
|
||||||
inferred_type = "Bool" # Asumir Bool
|
scl_output.append(f" {scl_name} : {var_dtype};")
|
||||||
scl_output.append(
|
declared_temps.add(scl_name) # Marcar como declarada
|
||||||
f" {scl_name} : {inferred_type}; // Auto-generated temporary"
|
|
||||||
)
|
|
||||||
if not interface_data.get("Temp"):
|
|
||||||
scl_output.append("END_VAR")
|
|
||||||
scl_output.append("")
|
|
||||||
|
|
||||||
# Cuerpo del Bloque FC/FB
|
# Declarar las _temp_ generadas si no estaban ya en la interfaz Temp
|
||||||
scl_output.append("BEGIN")
|
if temp_vars:
|
||||||
|
for var_name in sorted(list(temp_vars)):
|
||||||
|
scl_name = format_variable_name(var_name) # #_temp_...
|
||||||
|
if scl_name not in declared_temps:
|
||||||
|
# Inferencia básica de tipo
|
||||||
|
inferred_type = "Bool" # Asumir Bool para la mayoría de temps de lógica
|
||||||
|
# Se podría mejorar si los procesadores añadieran info de tipo
|
||||||
|
scl_output.append(f" {scl_name} : {inferred_type}; // Auto-generated temporary")
|
||||||
|
declared_temps.add(scl_name)
|
||||||
|
scl_output.append("END_VAR")
|
||||||
|
scl_output.append("")
|
||||||
|
|
||||||
|
# Cuerpo del Bloque
|
||||||
|
scl_output.append("BEGIN")
|
||||||
|
scl_output.append("")
|
||||||
|
|
||||||
|
# Iterar por redes y lógica
|
||||||
|
for i, network in enumerate(data.get('networks', [])):
|
||||||
|
network_title = network.get('title', f'Network {network.get("id")}')
|
||||||
|
network_comment = network.get('comment', '')
|
||||||
|
network_lang = network.get('language', 'LAD') # O el lenguaje original
|
||||||
|
|
||||||
|
scl_output.append(f" // Network {i+1}: {network_title} (Original Language: {network_lang})")
|
||||||
|
if network_comment:
|
||||||
|
for line in network_comment.splitlines():
|
||||||
|
scl_output.append(f" // {line}")
|
||||||
scl_output.append("")
|
scl_output.append("")
|
||||||
# Iterar por redes y lógica (como antes, incluyendo manejo STL Markdown)
|
|
||||||
for i, network in enumerate(data.get("networks", [])):
|
|
||||||
network_title = network.get("title", f'Network {network.get("id")}')
|
|
||||||
network_comment = network.get("comment", "")
|
|
||||||
network_lang = network.get("language", "LAD")
|
|
||||||
scl_output.append(
|
|
||||||
f" // Network {i+1}: {network_title} (Original Language: {network_lang})"
|
|
||||||
)
|
|
||||||
if network_comment:
|
|
||||||
for line in network_comment.splitlines():
|
|
||||||
scl_output.append(f" // {line}")
|
|
||||||
scl_output.append("")
|
|
||||||
network_has_code = False
|
|
||||||
if network_lang == "STL":
|
|
||||||
network_has_code = True
|
|
||||||
if (
|
|
||||||
network.get("logic")
|
|
||||||
and network["logic"][0].get("type") == "RAW_STL_CHUNK"
|
|
||||||
):
|
|
||||||
raw_stl_code = network["logic"][0].get(
|
|
||||||
"stl", "// ERROR: STL code missing"
|
|
||||||
)
|
|
||||||
scl_output.append(f" {'//'} ```STL")
|
|
||||||
for stl_line in raw_stl_code.splitlines():
|
|
||||||
scl_output.append(f" {stl_line}")
|
|
||||||
scl_output.append(f" {'//'} ```")
|
|
||||||
else:
|
|
||||||
scl_output.append(" // ERROR: Contenido STL inesperado.")
|
|
||||||
else: # LAD, FBD, SCL, etc.
|
|
||||||
for instruction in network.get("logic", []):
|
|
||||||
instruction_type = instruction.get("type", "")
|
|
||||||
scl_code = instruction.get("scl", "")
|
|
||||||
is_grouped = instruction.get("grouped", False)
|
|
||||||
if is_grouped:
|
|
||||||
continue
|
|
||||||
if (
|
|
||||||
instruction_type.endswith(SCL_SUFFIX)
|
|
||||||
or instruction_type in ["RAW_SCL_CHUNK", "UNSUPPORTED_LANG"]
|
|
||||||
) and scl_code:
|
|
||||||
is_only_comment = all(
|
|
||||||
line.strip().startswith("//")
|
|
||||||
for line in scl_code.splitlines()
|
|
||||||
if line.strip()
|
|
||||||
)
|
|
||||||
is_if_block = scl_code.strip().startswith("IF")
|
|
||||||
if not is_only_comment or is_if_block:
|
|
||||||
network_has_code = True
|
|
||||||
for line in scl_code.splitlines():
|
|
||||||
scl_output.append(f" {line}")
|
|
||||||
if network_has_code:
|
|
||||||
scl_output.append("")
|
|
||||||
else:
|
|
||||||
scl_output.append(f" // Network did not produce printable SCL code.")
|
|
||||||
scl_output.append("")
|
|
||||||
# Fin del bloque FC/FB
|
|
||||||
scl_output.append(f"END_{scl_block_keyword}")
|
|
||||||
|
|
||||||
# --- Escritura del Archivo SCL (Común) ---
|
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
|
||||||
|
|
||||||
|
# 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"):
|
||||||
|
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():
|
||||||
|
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')}")
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# --- Escritura del Archivo SCL ---
|
||||||
print(f"Escribiendo archivo SCL en: {output_scl_filepath}")
|
print(f"Escribiendo archivo SCL en: {output_scl_filepath}")
|
||||||
try:
|
try:
|
||||||
with open(output_scl_filepath, "w", encoding="utf-8") as f:
|
with open(output_scl_filepath, 'w', encoding='utf-8') as f:
|
||||||
for line in scl_output:
|
for line in scl_output:
|
||||||
f.write(line + "\n")
|
f.write(line + '\n')
|
||||||
print("Generación de SCL completada.")
|
print("Generación de SCL completada.")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error al escribir el archivo SCL: {e}")
|
print(f"Error al escribir el archivo SCL: {e}")
|
||||||
|
@ -488,65 +273,26 @@ def generate_scl(processed_json_filepath, output_scl_filepath):
|
||||||
|
|
||||||
# --- Ejecución ---
|
# --- Ejecución ---
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# Imports necesarios solo para la ejecución como script principal
|
parser = argparse.ArgumentParser(description="Generate final SCL file from processed JSON (SymPy version).")
|
||||||
import argparse
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import traceback # Asegurarse que traceback está importado si se usa en generate_scl
|
|
||||||
|
|
||||||
# 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(
|
parser.add_argument(
|
||||||
"source_xml_filepath", # Argumento posicional obligatorio
|
"source_xml_filepath",
|
||||||
help="Path to the original source XML file (passed from x0_main.py, used to derive input/output names).",
|
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() # Parsea los argumentos de sys.argv
|
args = parser.parse_args()
|
||||||
|
|
||||||
source_xml_file = args.source_xml_filepath # Obtiene la ruta del XML original
|
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__)
|
||||||
|
|
||||||
# Verificar si el archivo XML original existe (como referencia)
|
input_json_file = os.path.join(base_dir, f"{xml_filename_base}_simplified_processed.json")
|
||||||
if not os.path.exists(source_xml_file):
|
output_scl_file = os.path.join(base_dir, f"{xml_filename_base}_simplified_processed.scl")
|
||||||
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):
|
if not os.path.exists(input_json_file):
|
||||||
print(
|
print(f"Error: Processed JSON file not found: '{input_json_file}'")
|
||||||
f"Error Fatal (x3): Archivo JSON procesado no encontrado: '{input_json_file}'"
|
print(f"Ensure 'x2_process.py' ran successfully for '{args.source_xml_filepath}'.")
|
||||||
)
|
sys.exit(1)
|
||||||
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:
|
else:
|
||||||
# Llamar a la función principal de generación SCL del script
|
generate_scl(input_json_file, output_scl_file)
|
||||||
# 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
|
|
220
x0_main.py
220
x0_main.py
|
@ -3,163 +3,143 @@ import subprocess
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import locale
|
import locale
|
||||||
import glob
|
import glob # <--- Importar glob para buscar archivos
|
||||||
|
|
||||||
# (Función get_console_encoding y variable CONSOLE_ENCODING como antes)
|
# (Función get_console_encoding y variable CONSOLE_ENCODING como en la respuesta anterior)
|
||||||
def get_console_encoding():
|
def get_console_encoding():
|
||||||
"""Obtiene la codificación preferida de la consola, con fallback."""
|
"""Obtiene la codificación preferida de la consola, con fallback."""
|
||||||
try:
|
try:
|
||||||
return locale.getpreferredencoding(False)
|
return locale.getpreferredencoding(False)
|
||||||
except Exception:
|
except Exception:
|
||||||
# Fallback común en Windows si falla getpreferredencoding
|
return 'cp1252'
|
||||||
return "cp1252" # O prueba con 'utf-8' si cp1252 da problemas
|
|
||||||
|
|
||||||
CONSOLE_ENCODING = get_console_encoding()
|
CONSOLE_ENCODING = get_console_encoding()
|
||||||
|
# Descomenta la siguiente línea si quieres ver la codificación detectada:
|
||||||
# print(f"Detected console encoding: {CONSOLE_ENCODING}")
|
# print(f"Detected console encoding: {CONSOLE_ENCODING}")
|
||||||
|
|
||||||
# (Función run_script como antes, usando CONSOLE_ENCODING)
|
# (Función run_script como en la respuesta anterior, usando CONSOLE_ENCODING)
|
||||||
def run_script(script_name, xml_arg):
|
def run_script(script_name, xml_arg):
|
||||||
"""Runs a given script with the specified XML file argument."""
|
"""Runs a given script with the specified XML file argument."""
|
||||||
# Asegurarse que la ruta al script sea absoluta o relativa al script actual
|
script_path = os.path.join(os.path.dirname(__file__), script_name)
|
||||||
script_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), script_name)
|
command = [sys.executable, script_path, xml_arg]
|
||||||
# Usar la ruta absoluta al ejecutable de Python actual
|
|
||||||
python_executable = sys.executable
|
|
||||||
command = [python_executable, script_path, xml_arg] # Usar la ruta absoluta de python
|
|
||||||
print(f"\n--- Running {script_name} with argument: {xml_arg} ---")
|
print(f"\n--- Running {script_name} with argument: {xml_arg} ---")
|
||||||
try:
|
try:
|
||||||
# Ejecutar el proceso hijo
|
result = subprocess.run(command,
|
||||||
result = subprocess.run(
|
check=True,
|
||||||
command,
|
capture_output=True,
|
||||||
check=True, # Lanza excepción si el script falla (return code != 0)
|
text=True,
|
||||||
capture_output=True,# Captura stdout y stderr
|
encoding=CONSOLE_ENCODING,
|
||||||
text=True, # Decodifica stdout/stderr como texto
|
errors='replace') # 'replace' para evitar errores
|
||||||
encoding=CONSOLE_ENCODING, # Usa la codificación detectada
|
|
||||||
errors='replace' # Reemplaza caracteres no decodificables
|
|
||||||
)
|
|
||||||
|
|
||||||
# Imprimir stdout y stderr si no están vacíos
|
|
||||||
stdout_clean = result.stdout.strip() if result.stdout else ""
|
|
||||||
stderr_clean = result.stderr.strip() if result.stderr else ""
|
|
||||||
|
|
||||||
|
# Imprimir stdout y stderr
|
||||||
|
# Eliminar saltos de línea extra al final si existen
|
||||||
|
stdout_clean = result.stdout.strip()
|
||||||
|
stderr_clean = result.stderr.strip()
|
||||||
if stdout_clean:
|
if stdout_clean:
|
||||||
print(stdout_clean)
|
print(stdout_clean)
|
||||||
if stderr_clean:
|
if stderr_clean:
|
||||||
# Imprimir stderr claramente para errores del script hijo
|
print("--- Stderr ---")
|
||||||
print(f"--- Stderr ({script_name}) ---", file=sys.stderr) # Imprimir en stderr
|
print(stderr_clean)
|
||||||
print(stderr_clean, file=sys.stderr)
|
print("--------------")
|
||||||
print("--------------------------", file=sys.stderr)
|
|
||||||
|
|
||||||
print(f"--- {script_name} finished successfully ---")
|
print(f"--- {script_name} finished successfully ---")
|
||||||
return True # Indicar éxito
|
return True
|
||||||
|
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
# Error si el script python o el ejecutable no se encuentran
|
print(f"Error: Script '{script_path}' not found.")
|
||||||
print(f"Error: Script '{script_path}' or Python executable '{python_executable}' not found.", file=sys.stderr)
|
|
||||||
return False
|
return False
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
# Error si el script hijo devuelve un código de error (ej., sys.exit(1))
|
print(f"Error running {script_name}:")
|
||||||
print(f"Error running {script_name}: Script returned non-zero exit code {e.returncode}.", file=sys.stderr)
|
print(f"Return code: {e.returncode}")
|
||||||
|
stdout_decoded = e.stdout.decode(CONSOLE_ENCODING, errors='replace').strip() if isinstance(e.stdout, bytes) else (e.stdout or "").strip()
|
||||||
# Decodificar e imprimir stdout/stderr del proceso fallido
|
stderr_decoded = e.stderr.decode(CONSOLE_ENCODING, errors='replace').strip() if isinstance(e.stderr, bytes) else (e.stderr or "").strip()
|
||||||
stdout_decoded = e.stdout.strip() if e.stdout else ""
|
|
||||||
stderr_decoded = e.stderr.strip() if e.stderr else ""
|
|
||||||
|
|
||||||
if stdout_decoded:
|
if stdout_decoded:
|
||||||
print(f"--- Stdout ({script_name}) ---", file=sys.stderr)
|
print("--- Stdout ---")
|
||||||
print(stdout_decoded, file=sys.stderr)
|
print(stdout_decoded)
|
||||||
if stderr_decoded:
|
if stderr_decoded:
|
||||||
print(f"--- Stderr ({script_name}) ---", file=sys.stderr)
|
print("--- Stderr ---")
|
||||||
print(stderr_decoded, file=sys.stderr)
|
print(stderr_decoded)
|
||||||
print("--------------------------", file=sys.stderr)
|
print("--------------")
|
||||||
return False # Indicar fallo
|
return False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Otros errores inesperados
|
print(f"An unexpected error occurred while running {script_name}: {e}")
|
||||||
print(f"An unexpected error occurred while running {script_name}: {e}", file=sys.stderr)
|
return False
|
||||||
# Imprimir traceback para depuración
|
|
||||||
import traceback
|
|
||||||
traceback.print_exc(file=sys.stderr)
|
|
||||||
return False # Indicar fallo
|
|
||||||
|
|
||||||
|
# --- NUEVA FUNCIÓN PARA SELECCIONAR ARCHIVO ---
|
||||||
|
def select_xml_file():
|
||||||
|
"""Busca archivos .xml, los lista y pide al usuario que elija uno."""
|
||||||
|
print("No XML file specified. Searching for XML files in current directory...")
|
||||||
|
# Buscar archivos .xml en el directorio actual (.)
|
||||||
|
xml_files = sorted(glob.glob('*.xml')) # sorted para orden alfabético
|
||||||
|
|
||||||
|
if not xml_files:
|
||||||
|
print("Error: No .xml files found in the current directory.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print("\nAvailable XML files:")
|
||||||
|
for i, filename in enumerate(xml_files, start=1):
|
||||||
|
print(f" {i}: {filename}")
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
choice = input(f"Enter the number of the file to process (1-{len(xml_files)}): ")
|
||||||
|
choice_num = int(choice)
|
||||||
|
if 1 <= choice_num <= len(xml_files):
|
||||||
|
selected_file = xml_files[choice_num - 1]
|
||||||
|
print(f"Selected: {selected_file}")
|
||||||
|
return selected_file
|
||||||
|
else:
|
||||||
|
print("Invalid choice. Please enter a number from the list.")
|
||||||
|
except ValueError:
|
||||||
|
print("Invalid input. Please enter a number.")
|
||||||
|
except EOFError: # Manejar si la entrada se cierra inesperadamente
|
||||||
|
print("\nSelection cancelled.")
|
||||||
|
sys.exit(1)
|
||||||
|
# --- FIN NUEVA FUNCIÓN ---
|
||||||
|
|
||||||
# --- NO SE NECESITA select_xml_file() si procesamos todos ---
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# --- PARTE 1: BUSCAR ARCHIVOS ---
|
xml_filename = None
|
||||||
# Directorio base donde buscar los archivos XML (relativo al script)
|
|
||||||
base_search_dir = "XML Project"
|
|
||||||
# Obtener la ruta absoluta del directorio donde está x0_main.py
|
|
||||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
xml_project_dir = os.path.join(script_dir, base_search_dir)
|
|
||||||
|
|
||||||
print(f"Buscando archivos XML recursivamente en: '{xml_project_dir}'")
|
# Comprobar si se pasó un argumento de línea de comandos
|
||||||
|
# sys.argv[0] es el nombre del script, sys.argv[1] sería el primer argumento
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
# Si hay argumentos, usar argparse para parsearlo (permite -h, etc.)
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Run the Simatic XML processing pipeline."
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"xml_file",
|
||||||
|
# Ya no necesitamos nargs='?' ni default aquí porque sabemos que hay un argumento
|
||||||
|
help="Path to the XML file to process.",
|
||||||
|
)
|
||||||
|
# Parsear solo los argumentos conocidos, ignorar extras si los hubiera
|
||||||
|
args, unknown = parser.parse_known_args()
|
||||||
|
xml_filename = args.xml_file
|
||||||
|
print(f"XML file specified via argument: {xml_filename}")
|
||||||
|
else:
|
||||||
|
# Si no hay argumentos, llamar a la función interactiva
|
||||||
|
xml_filename = select_xml_file()
|
||||||
|
|
||||||
# Verificar si el directorio 'XML Project' existe
|
# --- El resto del script continúa igual, usando xml_filename ---
|
||||||
if not os.path.isdir(xml_project_dir):
|
|
||||||
print(f"Error: El directorio '{xml_project_dir}' no existe o no es un directorio.", file=sys.stderr)
|
|
||||||
print("Por favor, crea el directorio 'XML Project' en la misma carpeta que este script y coloca tus archivos XML dentro.")
|
|
||||||
sys.exit(1) # Salir con error
|
|
||||||
|
|
||||||
# Buscar todos los archivos .xml recursivamente
|
# Verificar si el archivo XML de entrada (seleccionado o pasado) existe
|
||||||
search_pattern = os.path.join(xml_project_dir, "**", "*.xml")
|
if not os.path.exists(xml_filename):
|
||||||
xml_files_found = glob.glob(search_pattern, recursive=True)
|
print(f"Error: Selected or specified XML file not found: {xml_filename}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
if not xml_files_found:
|
print(f"\nStarting pipeline for: {xml_filename}")
|
||||||
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:")
|
# Run scripts sequentially (asegúrate que los nombres son correctos)
|
||||||
xml_files_found.sort() # Ordenar para consistencia
|
|
||||||
for xml_file in xml_files_found:
|
|
||||||
print(f" - {os.path.relpath(xml_file, script_dir)}")
|
|
||||||
|
|
||||||
# --- PARTE 2: PROCESAR CADA ARCHIVO ---
|
|
||||||
# Scripts a ejecutar en secuencia
|
|
||||||
script1 = "x1_to_json.py"
|
script1 = "x1_to_json.py"
|
||||||
script2 = "x2_process.py"
|
script2 = "x2_process.py"
|
||||||
script3 = "x3_generate_scl.py"
|
script3 = "x3_generate_scl.py"
|
||||||
|
|
||||||
processed_count = 0
|
if run_script(script1, xml_filename):
|
||||||
failed_count = 0
|
if run_script(script2, xml_filename):
|
||||||
|
if run_script(script3, xml_filename):
|
||||||
# Procesar cada archivo encontrado en el bucle
|
print("\nPipeline completed successfully.")
|
||||||
for xml_filepath in xml_files_found:
|
else:
|
||||||
relative_path = os.path.relpath(xml_filepath, script_dir)
|
print("\nPipeline failed at script:", script3)
|
||||||
print(f"\n--- Iniciando pipeline para: {relative_path} ---")
|
|
||||||
|
|
||||||
# Usar la ruta absoluta para los scripts hijos
|
|
||||||
absolute_xml_filepath = os.path.abspath(xml_filepath)
|
|
||||||
|
|
||||||
# Ejecutar los scripts en secuencia
|
|
||||||
success = True
|
|
||||||
if not run_script(script1, absolute_xml_filepath):
|
|
||||||
print(f"\nPipeline falló en el script '{script1}' para el archivo: {relative_path}", file=sys.stderr)
|
|
||||||
success = False
|
|
||||||
elif not run_script(script2, absolute_xml_filepath):
|
|
||||||
print(f"\nPipeline falló en el script '{script2}' para el archivo: {relative_path}", file=sys.stderr)
|
|
||||||
success = False
|
|
||||||
elif not run_script(script3, absolute_xml_filepath):
|
|
||||||
print(f"\nPipeline falló en el script '{script3}' para el archivo: {relative_path}", file=sys.stderr)
|
|
||||||
success = False
|
|
||||||
|
|
||||||
# Actualizar contadores y mostrar estado
|
|
||||||
if success:
|
|
||||||
print(f"--- Pipeline completado exitosamente para: {relative_path} ---")
|
|
||||||
processed_count += 1
|
|
||||||
else:
|
else:
|
||||||
failed_count += 1
|
print("\nPipeline failed at script:", script2)
|
||||||
print(f"--- Pipeline falló para: {relative_path} ---", file=sys.stderr) # Indicar fallo
|
|
||||||
|
|
||||||
# --- PARTE 3: RESUMEN FINAL ---
|
|
||||||
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("---------------------------------------")
|
|
||||||
|
|
||||||
# Salir con código 0 si todo fue bien, 1 si hubo fallos
|
|
||||||
if failed_count > 0:
|
|
||||||
sys.exit(1)
|
|
||||||
else:
|
else:
|
||||||
sys.exit(0)
|
print("\nPipeline failed at script:", script1)
|
||||||
|
|
||||||
# --- FIN: Se elimina la lógica redundante que venía después del bucle ---
|
|
958
x1_to_json.py
958
x1_to_json.py
File diff suppressed because it is too large
Load Diff
603
x2_process.py
603
x2_process.py
|
@ -5,27 +5,29 @@ import os
|
||||||
import copy
|
import copy
|
||||||
import traceback
|
import traceback
|
||||||
import re
|
import re
|
||||||
import importlib
|
import importlib
|
||||||
import sys
|
import sys
|
||||||
import sympy # Import sympy
|
import sympy # Import sympy
|
||||||
|
|
||||||
# Import necessary components from processors directory
|
# Import necessary components from processors directory
|
||||||
from processors.processor_utils import (
|
from processors.processor_utils import (
|
||||||
format_variable_name, # Keep if used outside processors
|
format_variable_name, # Keep if used outside processors
|
||||||
sympy_expr_to_scl, # Needed for IF grouping and maybe others
|
sympy_expr_to_scl, # Needed for IF grouping and maybe others
|
||||||
# get_target_scl_name might be used here? Unlikely.
|
# get_target_scl_name might be used here? Unlikely.
|
||||||
)
|
)
|
||||||
from processors.symbol_manager import SymbolManager # Import the manager
|
from processors.symbol_manager import SymbolManager # Import the manager
|
||||||
|
|
||||||
# --- Constantes y Configuración ---
|
# --- Constantes y Configuración ---
|
||||||
SCL_SUFFIX = "_sympy_processed" # New suffix to indicate processing method
|
# SCL_SUFFIX = "_scl" # Old suffix
|
||||||
|
SCL_SUFFIX = "_sympy_processed" # New suffix to indicate processing method
|
||||||
GROUPED_COMMENT = "// Logic included in grouped IF"
|
GROUPED_COMMENT = "// Logic included in grouped IF"
|
||||||
SIMPLIFIED_IF_COMMENT = "// Simplified IF condition by script" # May still be useful
|
SIMPLIFIED_IF_COMMENT = "// Simplified IF condition by script" # May still be useful
|
||||||
|
|
||||||
# Global data dictionary
|
# 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 = {}
|
data = {}
|
||||||
|
|
||||||
# --- (Incluye aquí las funciones process_group_ifs y load_processors SIN CAMBIOS) ---
|
|
||||||
def process_group_ifs(instruction, network_id, sympy_map, symbol_manager, data):
|
def process_group_ifs(instruction, network_id, sympy_map, symbol_manager, data):
|
||||||
"""
|
"""
|
||||||
Busca condiciones (ya procesadas -> tienen expr SymPy en sympy_map)
|
Busca condiciones (ya procesadas -> tienen expr SymPy en sympy_map)
|
||||||
|
@ -35,45 +37,24 @@ def process_group_ifs(instruction, network_id, sympy_map, symbol_manager, data):
|
||||||
(Esta es la implementación de la función como la tenías en el archivo original)
|
(Esta es la implementación de la función como la tenías en el archivo original)
|
||||||
"""
|
"""
|
||||||
instr_uid = instruction["instruction_uid"]
|
instr_uid = instruction["instruction_uid"]
|
||||||
instr_type_original = (
|
instr_type_original = instruction.get("type", "").replace(SCL_SUFFIX, "").replace("_error", "")
|
||||||
instruction.get("type", "").replace(SCL_SUFFIX, "").replace("_error", "")
|
|
||||||
)
|
|
||||||
made_change = False
|
made_change = False
|
||||||
|
|
||||||
# Check if this instruction *could* generate a condition suitable for grouping
|
# Check if this instruction *could* generate a condition suitable for grouping
|
||||||
# It must have been processed by the new SymPy method
|
# It must have been processed by the new SymPy method
|
||||||
if (
|
if (
|
||||||
not instruction.get("type", "").endswith(
|
not instruction.get("type", "").endswith(SCL_SUFFIX) # Check if processed by new method
|
||||||
SCL_SUFFIX
|
|
||||||
) # Check if processed by new method
|
|
||||||
or "_error" in instruction.get("type", "")
|
or "_error" in instruction.get("type", "")
|
||||||
or instruction.get("grouped", False)
|
or instruction.get("grouped", False)
|
||||||
or instr_type_original
|
or instr_type_original not in [ # Original types that produce boolean results
|
||||||
not in [ # Original types that produce boolean results
|
"Contact", "O", "Eq", "Ne", "Gt", "Lt", "Ge", "Le", "PBox", "NBox", "And", "Xor", "Not" # Add others like comparison
|
||||||
"Contact",
|
|
||||||
"O",
|
|
||||||
"Eq",
|
|
||||||
"Ne",
|
|
||||||
"Gt",
|
|
||||||
"Lt",
|
|
||||||
"Ge",
|
|
||||||
"Le",
|
|
||||||
"PBox",
|
|
||||||
"NBox",
|
|
||||||
"And",
|
|
||||||
"Xor",
|
|
||||||
"Not", # Add others like comparison
|
|
||||||
]
|
]
|
||||||
):
|
):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Avoid reagruping if SCL already contains a complex IF (less likely now)
|
# Avoid reagruping if SCL already contains a complex IF (less likely now)
|
||||||
current_scl = instruction.get("scl", "")
|
current_scl = instruction.get("scl", "")
|
||||||
if (
|
if current_scl.strip().startswith("IF") and "END_IF;" in current_scl and GROUPED_COMMENT not in current_scl:
|
||||||
current_scl.strip().startswith("IF")
|
|
||||||
and "END_IF;" in current_scl
|
|
||||||
and GROUPED_COMMENT not in current_scl
|
|
||||||
):
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# *** Get the SymPy expression for the condition ***
|
# *** Get the SymPy expression for the condition ***
|
||||||
|
@ -81,37 +62,20 @@ def process_group_ifs(instruction, network_id, sympy_map, symbol_manager, data):
|
||||||
sympy_condition_expr = sympy_map.get(map_key_out)
|
sympy_condition_expr = sympy_map.get(map_key_out)
|
||||||
|
|
||||||
# No SymPy expression found or trivial conditions
|
# No SymPy expression found or trivial conditions
|
||||||
if sympy_condition_expr is None or sympy_condition_expr in [
|
if sympy_condition_expr is None or sympy_condition_expr in [sympy.true, sympy.false]:
|
||||||
sympy.true,
|
|
||||||
sympy.false,
|
|
||||||
]:
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# --- Find consumer instructions (logic similar to before) ---
|
# --- Find consumer instructions (logic similar to before) ---
|
||||||
grouped_instructions_cores = []
|
grouped_instructions_cores = []
|
||||||
consumer_instr_list = []
|
consumer_instr_list = []
|
||||||
network_logic = next(
|
network_logic = next((net["logic"] for net in data["networks"] if net["id"] == network_id), [])
|
||||||
(net["logic"] for net in data["networks"] if net["id"] == network_id), []
|
if not network_logic: return False
|
||||||
)
|
|
||||||
if not network_logic:
|
|
||||||
return False
|
|
||||||
|
|
||||||
groupable_types = [ # Types whose *final SCL* we want to group
|
groupable_types = [ # Types whose *final SCL* we want to group
|
||||||
"Move",
|
"Move", "Add", "Sub", "Mul", "Div", "Mod", "Convert",
|
||||||
"Add",
|
"Call_FC", "Call_FB", # Assuming these generate final SCL in their processors now
|
||||||
"Sub",
|
|
||||||
"Mul",
|
|
||||||
"Div",
|
|
||||||
"Mod",
|
|
||||||
"Convert",
|
|
||||||
"Call_FC",
|
|
||||||
"Call_FB", # Assuming these generate final SCL in their processors now
|
|
||||||
# SCoil/RCoil might also be groupable if their SCL is final assignment
|
# SCoil/RCoil might also be groupable if their SCL is final assignment
|
||||||
"SCoil",
|
"SCoil", "RCoil"
|
||||||
"RCoil",
|
|
||||||
"BLKMOV", # Added BLKMOV
|
|
||||||
"TON", "TOF", "TP", "Se", "Sd", # Added timers
|
|
||||||
"CTU", "CTD", "CTUD", # Added counters
|
|
||||||
]
|
]
|
||||||
|
|
||||||
for consumer_instr in network_logic:
|
for consumer_instr in network_logic:
|
||||||
|
@ -120,45 +84,31 @@ def process_group_ifs(instruction, network_id, sympy_map, symbol_manager, data):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
consumer_en = consumer_instr.get("inputs", {}).get("en")
|
consumer_en = consumer_instr.get("inputs", {}).get("en")
|
||||||
consumer_type = consumer_instr.get("type", "") # Current type suffix matters
|
consumer_type = consumer_instr.get("type", "") # Current type suffix matters
|
||||||
consumer_type_original = consumer_type.replace(SCL_SUFFIX, "").replace(
|
consumer_type_original = consumer_type.replace(SCL_SUFFIX, "").replace("_error", "")
|
||||||
"_error", ""
|
|
||||||
)
|
|
||||||
|
|
||||||
is_enabled_by_us = False
|
is_enabled_by_us = False
|
||||||
if (
|
if ( isinstance(consumer_en, dict) and consumer_en.get("type") == "connection" and
|
||||||
isinstance(consumer_en, dict)
|
consumer_en.get("source_instruction_uid") == instr_uid and
|
||||||
and consumer_en.get("type") == "connection"
|
consumer_en.get("source_pin") == "out"):
|
||||||
and consumer_en.get("source_instruction_uid") == instr_uid
|
|
||||||
and consumer_en.get("source_pin") == "out"
|
|
||||||
):
|
|
||||||
is_enabled_by_us = True
|
is_enabled_by_us = True
|
||||||
|
|
||||||
# Check if consumer is groupable AND has its final SCL generated
|
# Check if consumer is groupable AND has its final SCL generated
|
||||||
if (
|
# The suffix check needs adjustment based on how terminating processors set it.
|
||||||
is_enabled_by_us
|
# Assuming processors like Move, Add, Call, SCoil, RCoil NOW generate final SCL and add a suffix.
|
||||||
and consumer_type.endswith(SCL_SUFFIX) # Check if processed
|
if ( is_enabled_by_us and consumer_type.endswith(SCL_SUFFIX) and # Or a specific "final_scl" suffix
|
||||||
and consumer_type_original in groupable_types
|
consumer_type_original in groupable_types ):
|
||||||
):
|
|
||||||
|
|
||||||
consumer_scl = consumer_instr.get("scl", "")
|
consumer_scl = consumer_instr.get("scl", "")
|
||||||
# Extract core SCL
|
# Extract core SCL (logic is similar, maybe simpler if SCL is cleaner now)
|
||||||
core_scl = None
|
core_scl = None
|
||||||
if consumer_scl:
|
if consumer_scl:
|
||||||
# If consumer SCL itself is an IF generated by EN, take the body
|
# If consumer SCL itself is an IF generated by EN, take the body
|
||||||
if consumer_scl.strip().startswith("IF"):
|
if consumer_scl.strip().startswith("IF"):
|
||||||
match = re.search(
|
match = re.search(r"THEN\s*(.*?)\s*END_IF;", consumer_scl, re.DOTALL | re.IGNORECASE)
|
||||||
r"IF\s+.*?THEN\s*(.*?)\s*END_IF;", # More robust regex
|
core_scl = match.group(1).strip() if match else None
|
||||||
consumer_scl,
|
elif not consumer_scl.strip().startswith("//"): # Otherwise, take the whole line if not comment
|
||||||
re.DOTALL | re.IGNORECASE,
|
core_scl = consumer_scl.strip()
|
||||||
)
|
|
||||||
core_scl = match.group(1).strip() if match else None
|
|
||||||
# If body contains another IF, maybe don't group? (optional complexity)
|
|
||||||
# if core_scl and core_scl.strip().startswith("IF"): core_scl = None
|
|
||||||
elif not consumer_scl.strip().startswith(
|
|
||||||
"//"
|
|
||||||
): # Otherwise, take the whole line if not comment
|
|
||||||
core_scl = consumer_scl.strip()
|
|
||||||
|
|
||||||
if core_scl:
|
if core_scl:
|
||||||
grouped_instructions_cores.append(core_scl)
|
grouped_instructions_cores.append(core_scl)
|
||||||
|
@ -166,19 +116,15 @@ def process_group_ifs(instruction, network_id, sympy_map, symbol_manager, data):
|
||||||
|
|
||||||
# --- If groupable consumers found ---
|
# --- If groupable consumers found ---
|
||||||
if len(grouped_instructions_cores) > 1:
|
if len(grouped_instructions_cores) > 1:
|
||||||
print(
|
print(f"INFO: Agrupando {len(grouped_instructions_cores)} instr. bajo condición de {instr_type_original} UID {instr_uid}")
|
||||||
f"INFO: Agrupando {len(grouped_instructions_cores)} instr. bajo condición de {instr_type_original} UID {instr_uid}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# *** Simplify the SymPy condition ***
|
# *** Simplify the SymPy condition ***
|
||||||
try:
|
try:
|
||||||
# simplified_expr = sympy.simplify_logic(sympy_condition_expr, force=True)
|
#simplified_expr = sympy.simplify_logic(sympy_condition_expr, force=True)
|
||||||
simplified_expr = sympy.logic.boolalg.to_dnf(
|
simplified_expr = sympy.logic.boolalg.to_dnf(sympy_condition_expr, simplify=True)
|
||||||
sympy_condition_expr, simplify=True
|
|
||||||
)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error simplifying condition for grouping UID {instr_uid}: {e}")
|
print(f"Error simplifying condition for grouping UID {instr_uid}: {e}")
|
||||||
simplified_expr = sympy_condition_expr # Fallback
|
simplified_expr = sympy_condition_expr # Fallback
|
||||||
|
|
||||||
# *** Convert simplified condition to SCL string ***
|
# *** Convert simplified condition to SCL string ***
|
||||||
condition_scl_simplified = sympy_expr_to_scl(simplified_expr, symbol_manager)
|
condition_scl_simplified = sympy_expr_to_scl(simplified_expr, symbol_manager)
|
||||||
|
@ -186,9 +132,7 @@ def process_group_ifs(instruction, network_id, sympy_map, symbol_manager, data):
|
||||||
# *** Build the grouped IF SCL ***
|
# *** Build the grouped IF SCL ***
|
||||||
scl_grouped_lines = [f"IF {condition_scl_simplified} THEN"]
|
scl_grouped_lines = [f"IF {condition_scl_simplified} THEN"]
|
||||||
for core_line in grouped_instructions_cores:
|
for core_line in grouped_instructions_cores:
|
||||||
indented_core = "\n".join(
|
indented_core = "\n".join([f" {line.strip()}" for line in core_line.splitlines()])
|
||||||
[f" {line.strip()}" for line in core_line.splitlines()]
|
|
||||||
)
|
|
||||||
scl_grouped_lines.append(indented_core)
|
scl_grouped_lines.append(indented_core)
|
||||||
scl_grouped_lines.append("END_IF;")
|
scl_grouped_lines.append("END_IF;")
|
||||||
final_grouped_scl = "\n".join(scl_grouped_lines)
|
final_grouped_scl = "\n".join(scl_grouped_lines)
|
||||||
|
@ -203,19 +147,18 @@ def process_group_ifs(instruction, network_id, sympy_map, symbol_manager, data):
|
||||||
|
|
||||||
return made_change
|
return made_change
|
||||||
|
|
||||||
|
|
||||||
def load_processors(processors_dir="processors"):
|
def load_processors(processors_dir="processors"):
|
||||||
"""
|
"""
|
||||||
Escanea el directorio, importa módulos, construye el mapa y una lista
|
Escanea el directorio, importa módulos, construye el mapa y una lista
|
||||||
ordenada por prioridad.
|
ordenada por prioridad.
|
||||||
"""
|
"""
|
||||||
processor_map = {}
|
processor_map = {}
|
||||||
processor_list_unsorted = [] # Lista para guardar (priority, type_name, func)
|
processor_list_unsorted = [] # Lista para guardar (priority, type_name, func)
|
||||||
default_priority = 10 # Prioridad si no se define en get_processor_info
|
default_priority = 10 # Prioridad si no se define en get_processor_info
|
||||||
|
|
||||||
if not os.path.isdir(processors_dir):
|
if not os.path.isdir(processors_dir):
|
||||||
print(f"Error: Directorio de procesadores no encontrado: '{processors_dir}'")
|
print(f"Error: Directorio de procesadores no encontrado: '{processors_dir}'")
|
||||||
return processor_map, [] # Devuelve mapa vacío y lista vacía
|
return processor_map, [] # Devuelve mapa vacío y lista vacía
|
||||||
|
|
||||||
print(f"Cargando procesadores desde: '{processors_dir}'")
|
print(f"Cargando procesadores desde: '{processors_dir}'")
|
||||||
processors_package = os.path.basename(processors_dir)
|
processors_package = os.path.basename(processors_dir)
|
||||||
|
@ -227,9 +170,7 @@ def load_processors(processors_dir="processors"):
|
||||||
try:
|
try:
|
||||||
module = importlib.import_module(full_module_name)
|
module = importlib.import_module(full_module_name)
|
||||||
|
|
||||||
if hasattr(module, "get_processor_info") and callable(
|
if hasattr(module, 'get_processor_info') and callable(module.get_processor_info):
|
||||||
module.get_processor_info
|
|
||||||
):
|
|
||||||
processor_info = module.get_processor_info()
|
processor_info = module.get_processor_info()
|
||||||
info_list = []
|
info_list = []
|
||||||
if isinstance(processor_info, dict):
|
if isinstance(processor_info, dict):
|
||||||
|
@ -237,51 +178,29 @@ def load_processors(processors_dir="processors"):
|
||||||
elif isinstance(processor_info, list):
|
elif isinstance(processor_info, list):
|
||||||
info_list = processor_info
|
info_list = processor_info
|
||||||
else:
|
else:
|
||||||
print(
|
print(f" Advertencia: get_processor_info en {full_module_name} devolvió tipo inesperado. Se ignora.")
|
||||||
f" Advertencia: get_processor_info en {full_module_name} devolvió tipo inesperado. Se ignora."
|
|
||||||
)
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for info in info_list:
|
for info in info_list:
|
||||||
if (
|
if isinstance(info, dict) and 'type_name' in info and 'processor_func' in info:
|
||||||
isinstance(info, dict)
|
type_name = info['type_name'].lower()
|
||||||
and "type_name" in info
|
processor_func = info['processor_func']
|
||||||
and "processor_func" in info
|
|
||||||
):
|
|
||||||
type_name = info["type_name"].lower()
|
|
||||||
processor_func = info["processor_func"]
|
|
||||||
# Obtener prioridad, usar default si no existe
|
# Obtener prioridad, usar default si no existe
|
||||||
priority = info.get("priority", default_priority)
|
priority = info.get('priority', default_priority)
|
||||||
|
|
||||||
if callable(processor_func):
|
if callable(processor_func):
|
||||||
if type_name in processor_map:
|
if type_name in processor_map:
|
||||||
print(
|
print(f" Advertencia: '{type_name}' en {full_module_name} sobrescribe definición anterior.")
|
||||||
f" Advertencia: '{type_name}' en {full_module_name} sobrescribe definición anterior."
|
|
||||||
)
|
|
||||||
processor_map[type_name] = processor_func
|
processor_map[type_name] = processor_func
|
||||||
# Añadir a la lista para ordenar
|
# Añadir a la lista para ordenar
|
||||||
processor_list_unsorted.append(
|
processor_list_unsorted.append({'priority': priority, 'type_name': type_name, 'func': processor_func})
|
||||||
{
|
print(f" - Cargado '{type_name}' (Prio: {priority}) desde {module_name_rel}.py")
|
||||||
"priority": priority,
|
|
||||||
"type_name": type_name,
|
|
||||||
"func": processor_func,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
print(
|
|
||||||
f" - Cargado '{type_name}' (Prio: {priority}) desde {module_name_rel}.py"
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
print(
|
print(f" Advertencia: 'processor_func' para '{type_name}' en {full_module_name} no es callable.")
|
||||||
f" Advertencia: 'processor_func' para '{type_name}' en {full_module_name} no es callable."
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
print(
|
print(f" Advertencia: Entrada inválida en {full_module_name}: {info}")
|
||||||
f" Advertencia: Entrada inválida en {full_module_name}: {info}"
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
print(
|
print(f" Advertencia: Módulo {module_name_rel}.py no tiene 'get_processor_info'.")
|
||||||
f" Advertencia: Módulo {module_name_rel}.py no tiene 'get_processor_info'."
|
|
||||||
)
|
|
||||||
|
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
print(f"Error importando {full_module_name}: {e}")
|
print(f"Error importando {full_module_name}: {e}")
|
||||||
|
@ -290,23 +209,22 @@ def load_processors(processors_dir="processors"):
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
# Ordenar la lista por prioridad (menor primero)
|
# Ordenar la lista por prioridad (menor primero)
|
||||||
processor_list_sorted = sorted(processor_list_unsorted, key=lambda x: x["priority"])
|
processor_list_sorted = sorted(processor_list_unsorted, key=lambda x: x['priority'])
|
||||||
|
|
||||||
print(f"\nTotal de tipos de procesadores cargados: {len(processor_map)}")
|
print(f"\nTotal de tipos de procesadores cargados: {len(processor_map)}")
|
||||||
print(
|
print(f"Orden de procesamiento por prioridad: {[item['type_name'] for item in processor_list_sorted]}")
|
||||||
f"Orden de procesamiento por prioridad: {[item['type_name'] for item in processor_list_sorted]}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Devolver el mapa (para lookup rápido si es necesario) y la lista ordenada
|
# Devolver el mapa (para lookup rápido si es necesario) y la lista ordenada
|
||||||
return processor_map, processor_list_sorted
|
return processor_map, processor_list_sorted
|
||||||
|
|
||||||
# --- Bucle Principal de Procesamiento (Modificado para STL y tipo de bloque) ---
|
# --- Bucle Principal de Procesamiento (Modificado para STL) ---
|
||||||
def process_json_to_scl(json_filepath):
|
def process_json_to_scl(json_filepath):
|
||||||
"""
|
"""
|
||||||
Lee JSON simplificado, aplica procesadores dinámicos (ignorando redes STL y bloques DB),
|
Lee el JSON simplificado, aplica los procesadores dinámicamente cargados
|
||||||
y guarda JSON procesado.
|
siguiendo un orden de prioridad (ignorando redes STL), y guarda el JSON procesado.
|
||||||
"""
|
"""
|
||||||
global data
|
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):
|
if not os.path.exists(json_filepath):
|
||||||
print(f"Error: JSON no encontrado: {json_filepath}")
|
print(f"Error: JSON no encontrado: {json_filepath}")
|
||||||
|
@ -314,82 +232,48 @@ def process_json_to_scl(json_filepath):
|
||||||
print(f"Cargando JSON desde: {json_filepath}")
|
print(f"Cargando JSON desde: {json_filepath}")
|
||||||
try:
|
try:
|
||||||
with open(json_filepath, "r", encoding="utf-8") as f:
|
with open(json_filepath, "r", encoding="utf-8") as f:
|
||||||
data = json.load(f)
|
data = json.load(f) # Carga en 'data' global
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error al cargar JSON: {e}")
|
print(f"Error al cargar JSON: {e}")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
return
|
return
|
||||||
|
|
||||||
# --- MODIFICADO: Obtener tipo de bloque (FC, FB, GlobalDB, OB) ---
|
# --- Carga dinámica de procesadores ---
|
||||||
block_type = data.get("block_type", "Unknown") # FC, FB, GlobalDB, OB
|
|
||||||
print(f"Procesando bloque tipo: {block_type}, Lenguaje principal: {data.get('language', 'Unknown')}")
|
|
||||||
|
|
||||||
# --- MODIFICADO: SI ES UN GlobalDB, SALTAR EL PROCESAMIENTO LÓGICO ---
|
|
||||||
if block_type == "GlobalDB": # <-- Comprobar tipo de bloque
|
|
||||||
print(
|
|
||||||
"INFO: El bloque es un Data Block (GlobalDB). Saltando procesamiento lógico de x2."
|
|
||||||
)
|
|
||||||
# Simplemente guardamos una copia (o el mismo archivo si no se requiere sufijo)
|
|
||||||
output_filename = json_filepath.replace(
|
|
||||||
"_simplified.json", "_simplified_processed.json"
|
|
||||||
)
|
|
||||||
print(f"Guardando JSON de DB (sin cambios lógicos) en: {output_filename}")
|
|
||||||
try:
|
|
||||||
with open(output_filename, "w", encoding="utf-8") as f:
|
|
||||||
json.dump(data, f, indent=4, ensure_ascii=False)
|
|
||||||
print("Guardado de DB completado.")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error Crítico al guardar JSON del DB: {e}")
|
|
||||||
traceback.print_exc()
|
|
||||||
return # <<< SALIR TEMPRANO PARA DBs
|
|
||||||
|
|
||||||
# --- SI NO ES DB (FC, FB, OB), CONTINUAR CON EL PROCESAMIENTO LÓGICO ---
|
|
||||||
print(f"INFO: El bloque es {block_type}. Iniciando procesamiento lógico...") # <-- Mensaje actualizado
|
|
||||||
|
|
||||||
script_dir = os.path.dirname(__file__)
|
script_dir = os.path.dirname(__file__)
|
||||||
processors_dir_path = os.path.join(script_dir, "processors")
|
processors_dir_path = os.path.join(script_dir, 'processors')
|
||||||
processor_map, sorted_processors = load_processors(processors_dir_path)
|
processor_map, sorted_processors = load_processors(processors_dir_path)
|
||||||
if not processor_map:
|
if not processor_map:
|
||||||
print("Error crítico: No se cargaron procesadores. Abortando.")
|
print("Error crítico: No se cargaron procesadores. Abortando.")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# --- Crear mapas de acceso por red ---
|
||||||
network_access_maps = {}
|
network_access_maps = {}
|
||||||
# Crear mapas de acceso por red (copiado/adaptado de versión anterior)
|
# (La lógica para llenar network_access_maps no cambia, puedes copiarla de tu original)
|
||||||
for network in data.get("networks", []):
|
for network in data.get("networks", []):
|
||||||
net_id = network["id"]
|
net_id = network["id"]
|
||||||
current_access_map = {}
|
current_access_map = {}
|
||||||
for instr in network.get("logic", []):
|
for instr in network.get("logic", []):
|
||||||
for _, source in instr.get("inputs", {}).items():
|
for _, source in instr.get("inputs", {}).items():
|
||||||
sources_to_check = (
|
sources_to_check = (source if isinstance(source, list) else ([source] if isinstance(source, dict) else []))
|
||||||
source
|
for src in sources_to_check:
|
||||||
if isinstance(source, list)
|
if (isinstance(src, dict) and src.get("uid") and src.get("type") in ["variable", "constant"]):
|
||||||
else ([source] if isinstance(source, dict) else [])
|
current_access_map[src["uid"]] = src
|
||||||
)
|
for _, dest_list in instr.get("outputs", {}).items():
|
||||||
for src in sources_to_check:
|
if isinstance(dest_list, list):
|
||||||
if (
|
for dest in dest_list:
|
||||||
isinstance(src, dict)
|
if (isinstance(dest, dict) and dest.get("uid") and dest.get("type") in ["variable", "constant"]):
|
||||||
and src.get("uid")
|
current_access_map[dest["uid"]] = dest
|
||||||
and src.get("type") in ["variable", "constant"]
|
|
||||||
):
|
|
||||||
current_access_map[src["uid"]] = src
|
|
||||||
for _, dest_list in instr.get("outputs", {}).items():
|
|
||||||
if isinstance(dest_list, list):
|
|
||||||
for dest in dest_list:
|
|
||||||
if (
|
|
||||||
isinstance(dest, dict)
|
|
||||||
and dest.get("uid")
|
|
||||||
and dest.get("type") in ["variable", "constant"]
|
|
||||||
):
|
|
||||||
current_access_map[dest["uid"]] = dest
|
|
||||||
network_access_maps[net_id] = current_access_map
|
network_access_maps[net_id] = current_access_map
|
||||||
|
|
||||||
|
# --- Inicializar mapa SymPy y SymbolManager ---
|
||||||
symbol_manager = SymbolManager()
|
symbol_manager = SymbolManager()
|
||||||
sympy_map = {}
|
sympy_map = {}
|
||||||
|
|
||||||
max_passes = 30
|
max_passes = 30
|
||||||
passes = 0
|
passes = 0
|
||||||
processing_complete = False
|
processing_complete = False
|
||||||
|
|
||||||
print(f"\n--- Iniciando Bucle de Procesamiento Iterativo ({block_type}) ---") # <-- Mensaje actualizado
|
print("\n--- Iniciando Bucle de Procesamiento Iterativo (con SymPy y prioridad) ---")
|
||||||
while passes < max_passes and not processing_complete:
|
while passes < max_passes and not processing_complete:
|
||||||
passes += 1
|
passes += 1
|
||||||
made_change_in_base_pass = False
|
made_change_in_base_pass = False
|
||||||
|
@ -400,122 +284,90 @@ def process_json_to_scl(json_filepath):
|
||||||
|
|
||||||
# --- FASE 1: Procesadores Base (Ignorando STL) ---
|
# --- FASE 1: Procesadores Base (Ignorando STL) ---
|
||||||
print(f" Fase 1 (SymPy Base - Orden por Prioridad):")
|
print(f" Fase 1 (SymPy Base - Orden por Prioridad):")
|
||||||
num_sympy_processed_this_pass = 0 # Resetear contador para el pase
|
num_sympy_processed_this_pass = 0
|
||||||
for processor_info in sorted_processors:
|
for processor_info in sorted_processors:
|
||||||
current_type_name = processor_info["type_name"]
|
current_type_name = processor_info['type_name']
|
||||||
func_to_call = processor_info["func"]
|
func_to_call = processor_info['func']
|
||||||
|
|
||||||
for network in data.get("networks", []):
|
for network in data.get("networks", []):
|
||||||
network_id = network["id"]
|
network_id = network["id"]
|
||||||
network_lang = network.get("language", "LAD") # Lenguaje de la red
|
network_lang = network.get("language", "LAD") # Obtener lenguaje de la red
|
||||||
if network_lang == "STL": # Saltar redes STL
|
|
||||||
continue
|
# *** IGNORAR REDES STL EN ESTA FASE ***
|
||||||
|
if network_lang == "STL":
|
||||||
|
continue # Saltar al siguiente network
|
||||||
|
|
||||||
access_map = network_access_maps.get(network_id, {})
|
access_map = network_access_maps.get(network_id, {})
|
||||||
network_logic = network.get("logic", [])
|
network_logic = network.get("logic", [])
|
||||||
|
|
||||||
for instruction in network_logic:
|
for instruction in network_logic:
|
||||||
instr_uid = instruction.get("instruction_uid")
|
instr_uid = instruction.get("instruction_uid")
|
||||||
# Usar el tipo *actual* de la instrucción para el lookup
|
instr_type_original = instruction.get("type", "Unknown")
|
||||||
instr_type_current = instruction.get("type", "Unknown")
|
|
||||||
|
|
||||||
# Saltar si ya está procesado, es error, agrupado, o tipo crudo
|
# Saltar si ya procesado, error, agrupado o es chunk STL/SCL/Unsupported
|
||||||
if (
|
if (instr_type_original.endswith(SCL_SUFFIX)
|
||||||
instr_type_current.endswith(SCL_SUFFIX)
|
or "_error" in instr_type_original
|
||||||
or "_error" in instr_type_current
|
|
||||||
or instruction.get("grouped", False)
|
or instruction.get("grouped", False)
|
||||||
or instr_type_current
|
or instr_type_original in ["RAW_STL_CHUNK", "RAW_SCL_CHUNK", "UNSUPPORTED_LANG"]):
|
||||||
in ["RAW_STL_CHUNK", "RAW_SCL_CHUNK", "UNSUPPORTED_LANG", "UNSUPPORTED_CONTENT", "PARSING_ERROR"]
|
|
||||||
):
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# El lookup usa el tipo actual (que aún no tiene el sufijo)
|
# Determinar tipo efectivo (como antes)
|
||||||
lookup_key = instr_type_current.lower()
|
lookup_key = instr_type_original.lower()
|
||||||
effective_type_name = lookup_key
|
effective_type_name = lookup_key
|
||||||
|
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"
|
||||||
|
|
||||||
# Mapeo especial para llamadas FC/FB
|
# Llamar al procesador si coincide el tipo
|
||||||
if instr_type_current == "Call":
|
|
||||||
call_block_type = instruction.get("block_type", "").upper()
|
|
||||||
if call_block_type == "FC":
|
|
||||||
effective_type_name = "call_fc"
|
|
||||||
elif call_block_type == "FB":
|
|
||||||
effective_type_name = "call_fb"
|
|
||||||
# Añadir otros tipos de llamada si es necesario
|
|
||||||
|
|
||||||
# Si el tipo efectivo coincide con el procesador actual
|
|
||||||
if effective_type_name == current_type_name:
|
if effective_type_name == current_type_name:
|
||||||
try:
|
try:
|
||||||
# Pasar 'data' a la función del procesador
|
# Pasa sympy_map, symbol_manager y data
|
||||||
changed = func_to_call(
|
changed = func_to_call(instruction, network_id, sympy_map, symbol_manager, data)
|
||||||
instruction, network_id, sympy_map, symbol_manager, data
|
|
||||||
)
|
|
||||||
if changed:
|
if changed:
|
||||||
made_change_in_base_pass = True
|
made_change_in_base_pass = True
|
||||||
num_sympy_processed_this_pass += 1
|
num_sympy_processed_this_pass += 1
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(
|
print(f"ERROR(SymPy Base) al procesar {instr_type_original} UID {instr_uid}: {e}")
|
||||||
f"ERROR(SymPy Base) al procesar {instr_type_current} UID {instr_uid}: {e}"
|
traceback.print_exc()
|
||||||
)
|
instruction["scl"] = f"// ERROR en SymPy procesador base: {e}"
|
||||||
traceback.print_exc()
|
instruction["type"] = instr_type_original + "_error"
|
||||||
instruction["scl"] = (
|
made_change_in_base_pass = True # Marcar cambio aunque sea error
|
||||||
f"// ERROR en SymPy procesador base: {e}"
|
print(f" -> {num_sympy_processed_this_pass} instrucciones (no STL) procesadas con SymPy.")
|
||||||
)
|
|
||||||
# Añadir sufijo de error al tipo actual
|
|
||||||
instruction["type"] = instr_type_current + "_error"
|
|
||||||
made_change_in_base_pass = True # Se hizo un cambio (marcar como error)
|
|
||||||
print(
|
|
||||||
f" -> {num_sympy_processed_this_pass} instrucciones (no STL) procesadas con SymPy."
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# --- FASE 2: Agrupación IF (Ignorando STL) ---
|
# --- FASE 2: Agrupación IF (Ignorando STL) ---
|
||||||
if (
|
if made_change_in_base_pass or passes == 1:
|
||||||
made_change_in_base_pass or passes == 1
|
|
||||||
): # Ejecutar siempre en el primer pase o si hubo cambios
|
|
||||||
print(f" Fase 2 (Agrupación IF con Simplificación):")
|
print(f" Fase 2 (Agrupación IF con Simplificación):")
|
||||||
num_grouped_this_pass = 0 # Resetear contador para el pase
|
num_grouped_this_pass = 0
|
||||||
for network in data.get("networks", []):
|
for network in data.get("networks", []):
|
||||||
network_id = network["id"]
|
network_id = network["id"]
|
||||||
network_lang = network.get("language", "LAD")
|
network_lang = network.get("language", "LAD") # Obtener lenguaje
|
||||||
if network_lang == "STL":
|
|
||||||
continue # Saltar STL
|
# *** IGNORAR REDES STL EN ESTA FASE ***
|
||||||
network_logic = network.get("logic", [])
|
if network_lang == "STL":
|
||||||
# Iterar en orden por UID puede ser más estable para agrupación
|
continue # Saltar red STL
|
||||||
uids_in_network = sorted([instr.get("instruction_uid", "Z") for instr in network_logic if instr.get("instruction_uid")])
|
|
||||||
for uid_to_process in uids_in_network:
|
network_logic = network.get("logic", [])
|
||||||
instruction = next((instr for instr in network_logic if instr.get("instruction_uid") == uid_to_process), None)
|
for instruction in network_logic:
|
||||||
if not instruction: continue
|
try:
|
||||||
|
# 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
|
||||||
|
num_grouped_this_pass += 1
|
||||||
|
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 (en redes no STL).")
|
||||||
|
|
||||||
# Saltar si ya está agrupada, es error, etc.
|
|
||||||
if instruction.get("grouped") or "_error" in instruction.get("type", ""):
|
|
||||||
continue
|
|
||||||
# La agrupación sólo aplica a instrucciones que generan condiciones booleanas
|
|
||||||
# y que ya fueron procesadas (tienen el sufijo)
|
|
||||||
if instruction.get("type", "").endswith(SCL_SUFFIX):
|
|
||||||
try:
|
|
||||||
group_changed = process_group_ifs(
|
|
||||||
instruction, network_id, sympy_map, symbol_manager, data
|
|
||||||
)
|
|
||||||
if group_changed:
|
|
||||||
made_change_in_group_pass = True
|
|
||||||
num_grouped_this_pass += 1
|
|
||||||
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 (en redes no STL)."
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- Comprobar si se completó el procesamiento ---
|
# --- Comprobar si se completó el procesamiento ---
|
||||||
if not made_change_in_base_pass and not made_change_in_group_pass:
|
if not made_change_in_base_pass and not made_change_in_group_pass:
|
||||||
print(
|
print(f"\n--- No se hicieron más cambios en el pase {passes}. Proceso iterativo completado. ---")
|
||||||
f"\n--- No se hicieron más cambios en el pase {passes}. Proceso iterativo completado. ---"
|
|
||||||
)
|
|
||||||
processing_complete = True
|
processing_complete = True
|
||||||
else:
|
else:
|
||||||
print(
|
print(f"--- Fin Pase {passes}: {num_sympy_processed_this_pass} proc SymPy, {num_grouped_this_pass} agrup. Continuando...")
|
||||||
f"--- Fin Pase {passes}: {num_sympy_processed_this_pass} proc SymPy, {num_grouped_this_pass} agrup. Continuando..."
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- Comprobar límite de pases ---
|
# --- Comprobar límite de pases ---
|
||||||
if passes == max_passes and not processing_complete:
|
if passes == max_passes and not processing_complete:
|
||||||
|
@ -524,53 +376,46 @@ def process_json_to_scl(json_filepath):
|
||||||
# --- FIN BUCLE ITERATIVO ---
|
# --- FIN BUCLE ITERATIVO ---
|
||||||
|
|
||||||
# --- Verificación Final (Ajustada para RAW_STL_CHUNK) ---
|
# --- Verificación Final (Ajustada para RAW_STL_CHUNK) ---
|
||||||
print(f"\n--- Verificación Final de Instrucciones No Procesadas ({block_type}) ---") # <-- Mensaje actualizado
|
print("\n--- Verificación Final de Instrucciones No Procesadas ---")
|
||||||
unprocessed_count = 0
|
unprocessed_count = 0
|
||||||
unprocessed_details = []
|
unprocessed_details = []
|
||||||
ignored_types = [
|
# Añadir RAW_STL_CHUNK a los tipos ignorados
|
||||||
"raw_scl_chunk",
|
ignored_types = ['raw_scl_chunk', 'unsupported_lang', 'raw_stl_chunk'] # Añadido raw_stl_chunk
|
||||||
"unsupported_lang",
|
|
||||||
"raw_stl_chunk",
|
|
||||||
"unsupported_content", # Añadido de x1
|
|
||||||
"parsing_error", # Añadido de x1
|
|
||||||
]
|
|
||||||
for network in data.get("networks", []):
|
for network in data.get("networks", []):
|
||||||
network_id = network.get("id", "Unknown ID")
|
network_id = network.get("id", "Unknown ID")
|
||||||
network_title = network.get("title", f"Network {network_id}")
|
network_title = network.get("title", f"Network {network_id}")
|
||||||
network_lang = network.get("language", "LAD")
|
network_lang = network.get("language", "LAD") # Obtener lenguaje
|
||||||
if network_lang == "STL":
|
|
||||||
continue # No verificar redes STL
|
# No verificar instrucciones dentro de redes STL, ya que no se procesan
|
||||||
for instruction in network.get("logic", []):
|
if network_lang == "STL":
|
||||||
instr_uid = instruction.get("instruction_uid", "Unknown UID")
|
continue
|
||||||
instr_type = instruction.get("type", "Unknown Type")
|
|
||||||
is_grouped = instruction.get("grouped", False)
|
for instruction in network.get("logic", []):
|
||||||
if (
|
instr_uid = instruction.get("instruction_uid", "Unknown UID")
|
||||||
not instr_type.endswith(SCL_SUFFIX)
|
instr_type = instruction.get("type", "Unknown Type")
|
||||||
and "_error" not in instr_type
|
is_grouped = instruction.get("grouped", False)
|
||||||
and not is_grouped
|
|
||||||
and instr_type.lower() not in ignored_types
|
# Condición revisada para ignorar los chunks crudos
|
||||||
):
|
if (not instr_type.endswith(SCL_SUFFIX) and
|
||||||
unprocessed_count += 1
|
"_error" not in instr_type and
|
||||||
unprocessed_details.append(
|
not is_grouped and
|
||||||
f" - Red '{network_title}' (ID: {network_id}, Lang: {network_lang}), "
|
instr_type.lower() not in ignored_types): # Verifica contra lista actualizada
|
||||||
f"Instrucción UID: {instr_uid}, Tipo: '{instr_type}'"
|
unprocessed_count += 1
|
||||||
)
|
unprocessed_details.append(
|
||||||
|
f" - Red '{network_title}' (ID: {network_id}, Lang: {network_lang}), "
|
||||||
|
f"Instrucción UID: {instr_uid}, Tipo: '{instr_type}'"
|
||||||
|
)
|
||||||
|
|
||||||
if unprocessed_count > 0:
|
if unprocessed_count > 0:
|
||||||
print(
|
print(f"ADVERTENCIA: Se encontraron {unprocessed_count} instrucciones (no STL) que parecen no haber sido procesadas:")
|
||||||
f"ADVERTENCIA: Se encontraron {unprocessed_count} instrucciones (no STL) que parecen no haber sido procesadas:"
|
for detail in unprocessed_details: print(detail)
|
||||||
)
|
|
||||||
for detail in unprocessed_details:
|
|
||||||
print(detail)
|
|
||||||
else:
|
else:
|
||||||
print(
|
print("INFO: Todas las instrucciones relevantes (no STL) parecen haber sido procesadas o agrupadas.")
|
||||||
"INFO: Todas las instrucciones relevantes (no STL) parecen haber sido procesadas o agrupadas."
|
|
||||||
)
|
|
||||||
|
|
||||||
# --- Guardar JSON Final ---
|
# --- Guardar JSON Final ---
|
||||||
output_filename = json_filepath.replace(
|
output_filename = json_filepath.replace("_simplified.json", "_simplified_processed.json")
|
||||||
"_simplified.json", "_simplified_processed.json"
|
print(f"\nGuardando JSON procesado en: {output_filename}")
|
||||||
)
|
|
||||||
print(f"\nGuardando JSON procesado ({block_type}) en: {output_filename}") # <-- Mensaje actualizado
|
|
||||||
try:
|
try:
|
||||||
with open(output_filename, "w", encoding="utf-8") as f:
|
with open(output_filename, "w", encoding="utf-8") as f:
|
||||||
json.dump(data, f, indent=4, ensure_ascii=False)
|
json.dump(data, f, indent=4, ensure_ascii=False)
|
||||||
|
@ -579,65 +424,69 @@ def process_json_to_scl(json_filepath):
|
||||||
print(f"Error Crítico al guardar JSON procesado: {e}")
|
print(f"Error Crítico al guardar JSON procesado: {e}")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
|
# --- Ejecución (sin cambios) ---
|
||||||
# --- Ejecución (sin cambios en esta parte) ---
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# Imports necesarios solo para la ejecución como script principal
|
parser = argparse.ArgumentParser(description="Process simplified JSON to embed SCL logic.")
|
||||||
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."
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"source_xml_filepath", # Argumento posicional obligatorio
|
"source_xml_filepath",
|
||||||
help="Path to the original source XML file (passed from x0_main.py, used to derive JSON input name).",
|
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() # Parsea los argumentos de sys.argv
|
args = parser.parse_args()
|
||||||
|
|
||||||
source_xml_file = args.source_xml_filepath # Obtiene la ruta del XML original
|
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__)
|
||||||
|
|
||||||
# Verificar si el archivo XML original existe (como referencia, útil para depuración)
|
|
||||||
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."
|
|
||||||
)
|
|
||||||
|
|
||||||
# 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")
|
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):
|
if not os.path.exists(input_json_file):
|
||||||
print(
|
print(f"Error Fatal: El archivo de entrada JSON simplificado no existe: '{input_json_file}'")
|
||||||
f"Error Fatal (x2): 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"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:
|
else:
|
||||||
# Llamar a la función principal de procesamiento del script
|
process_json_to_scl(input_json_file)
|
||||||
try:
|
parser = argparse.ArgumentParser(description="Process simplified JSON to embed SCL logic.")
|
||||||
process_json_to_scl(input_json_file)
|
parser.add_argument(
|
||||||
except Exception as e:
|
"source_xml_filepath",
|
||||||
print(
|
nargs="?",
|
||||||
f"Error Crítico (x2) durante el procesamiento de '{input_json_file}': {e}"
|
default="TestLAD.xml",
|
||||||
)
|
help="Path to the original source XML file (used to derive JSON input name, default: TestLAD.xml)"
|
||||||
import traceback # Asegurar que traceback está importado
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
traceback.print_exc()
|
xml_filename_base = os.path.splitext(os.path.basename(args.source_xml_filepath))[0]
|
||||||
sys.exit(1) # Salir con error si la función principal falla
|
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)
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue