From 9b192a91fdf36f9c4db77be25ebab7629cd7fee5 Mon Sep 17 00:00:00 2001 From: Miguel Date: Sun, 20 Apr 2025 01:32:05 +0200 Subject: [PATCH] Usando Sympy para simplificar los parentesis en las expresiones logicas --- BlenderCtrl__Main_simplified.json | 1170 +++++------ BlenderCtrl__Main_simplified_processed.json | 1954 +++++++++---------- BlenderCtrl__Main_simplified_processed.scl | 82 +- TestLAD_simplified.json | 144 +- TestLAD_simplified_processed.json | 320 +-- TestLAD_simplified_processed.scl | 31 +- processors/process_add.py | 116 +- processors/process_blkmov.py | 136 +- processors/process_call.py | 168 +- processors/process_coil.py | 97 +- processors/process_comparison.py | 116 +- processors/process_contact.py | 99 +- processors/process_convert.py | 127 +- processors/process_counter.py | 140 +- processors/process_edge_detector.py | 112 +- processors/process_eq.py | 96 +- processors/process_math.py | 114 +- processors/process_mod.py | 105 +- processors/process_move.py | 113 +- processors/process_not.py | 67 +- processors/process_o.py | 91 +- processors/process_rcoil.py | 95 +- processors/process_scoil.py | 95 +- processors/process_sd.py | 96 +- processors/process_se.py | 155 +- processors/process_timer.py | 115 +- processors/processor_utils.py | 217 +- processors/symbol_manager.py | 58 + x2_process.py | 353 ++-- x3_generate_scl.py | 326 ++-- 30 files changed, 3563 insertions(+), 3345 deletions(-) create mode 100644 processors/symbol_manager.py diff --git a/BlenderCtrl__Main_simplified.json b/BlenderCtrl__Main_simplified.json index 672c9c3..a0f3142 100644 --- a/BlenderCtrl__Main_simplified.json +++ b/BlenderCtrl__Main_simplified.json @@ -96,14 +96,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"AUX FALSE\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -119,17 +119,17 @@ }, "negated_pins": {}, "inputs": { - "en": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "25", - "source_pin": "out" - }, "SRCBLK": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_PID\".\"PPM303\"" + }, + "en": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "25", + "source_pin": "out" } }, "outputs": { @@ -166,14 +166,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gIN_VoltageOk\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -187,17 +187,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "24", - "source_pin": "out" - }, "bit": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"M19000\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "24", + "source_pin": "out" } }, "outputs": { @@ -211,17 +211,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "NBox", - "source_instruction_uid": "25", - "source_pin": "out" - }, "operand": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"gEmergencyPressed\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "NBox", + "source_instruction_uid": "25", + "source_pin": "out" } }, "outputs": {} @@ -241,14 +241,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gIN_LinePressCO2Ok\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -262,14 +262,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"gWorkshopTest\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -285,17 +285,17 @@ "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "30", - "source_pin": "out" - }, "operand": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"gWorkshop_Co2_Presence\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "30", + "source_pin": "out" } }, "outputs": { @@ -311,17 +311,17 @@ "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "31", - "source_pin": "out" - }, "operand": { "uid": "24", "scope": "GlobalVariable", "type": "variable", "name": "\"gWorkshop_CIP_Signals\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "31", + "source_pin": "out" } }, "outputs": { @@ -361,17 +361,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "O", - "source_instruction_uid": "33", - "source_pin": "out" - }, "operand": { "uid": "25", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Digital\".\"_PAL_S11\".\"Filtered\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "O", + "source_instruction_uid": "33", + "source_pin": "out" } }, "outputs": { @@ -387,17 +387,17 @@ "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "O", - "source_instruction_uid": "33", - "source_pin": "out" - }, "operand": { "uid": "26", "scope": "GlobalVariable", "type": "variable", "name": "\"Disable_Bit\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "O", + "source_instruction_uid": "33", + "source_pin": "out" } }, "outputs": { @@ -437,17 +437,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "O", - "source_instruction_uid": "36", - "source_pin": "out" - }, "operand": { "uid": "27", "scope": "GlobalVariable", "type": "variable", "name": "\"gIN_VoltageOk\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "O", + "source_instruction_uid": "36", + "source_pin": "out" } }, "outputs": { @@ -461,17 +461,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "37", - "source_pin": "out" - }, "operand": { "uid": "28", "scope": "GlobalVariable", "type": "variable", "name": "\"gBlenderSuppliesOk\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "37", + "source_pin": "out" } }, "outputs": {} @@ -530,14 +530,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"FirstScan\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -551,18 +551,18 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "s": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "24", - "source_pin": "out" - }, "timer": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"mDelayPowerOnTmr\"" }, + "s": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "24", + "source_pin": "out" + }, "tv": { "uid": "23", "scope": "TypedConstant", @@ -594,14 +594,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Status\".\"System\".\"Blender_Prod_CIP\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -615,17 +615,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "23", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"gBlenderProdMode\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "23", + "source_pin": "out" } }, "outputs": {} @@ -647,14 +647,14 @@ "operand": true }, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Status\".\"System\".\"Blender_Prod_CIP\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -668,17 +668,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "25", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"gBlenderCIPMode\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "25", + "source_pin": "out" } }, "outputs": {} @@ -734,14 +734,14 @@ "operand": true }, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"AUX FALSE\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -755,17 +755,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "26", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Status\".\"Meters\".\"QTM3012_PRD_Fault\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "26", + "source_pin": "out" } }, "outputs": {} @@ -777,17 +777,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "26", - "source_pin": "out" - }, "operand": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"gmPDS2000_Error_Fault\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "26", + "source_pin": "out" } }, "outputs": {} @@ -799,17 +799,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "26", - "source_pin": "out" - }, "operand": { "uid": "24", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Status\".\"Meters\".\"QTM3012_PRD_Run\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "26", + "source_pin": "out" } }, "outputs": {} @@ -821,17 +821,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "26", - "source_pin": "out" - }, "operand": { "uid": "25", "scope": "GlobalVariable", "type": "variable", "name": "\"gNoFreezeProductMeter\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "26", + "source_pin": "out" } }, "outputs": {} @@ -853,14 +853,14 @@ "operand": true }, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"System_RunOut_Variables\".\"ProdPipeRunOutWaterCount\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -874,17 +874,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "23", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"System_RunOut_Variables\".\"ProdPipeRunOutFillerBott\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "23", + "source_pin": "out" } }, "outputs": {} @@ -904,14 +904,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_StillWaterByPass\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -925,14 +925,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_ByPassDeair\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -948,17 +948,17 @@ "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "28", - "source_pin": "out" - }, "operand": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_Deaireation\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "28", + "source_pin": "out" } }, "outputs": { @@ -998,17 +998,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "O", - "source_instruction_uid": "30", - "source_pin": "out" - }, "operand": { "uid": "24", "scope": "GlobalVariable", "type": "variable", "name": "\"Blender_Variables_Pers\".\"gWaterRecipe\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "O", + "source_instruction_uid": "30", + "source_pin": "out" } }, "outputs": { @@ -1024,17 +1024,17 @@ "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "31", - "source_pin": "out" - }, "operand": { "uid": "25", "scope": "GlobalVariable", "type": "variable", "name": "\"Blender_Variables_Pers\".\"gCarboStillRecipe\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "31", + "source_pin": "out" } }, "outputs": { @@ -1048,17 +1048,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "32", - "source_pin": "out" - }, "operand": { "uid": "26", "scope": "GlobalVariable", "type": "variable", "name": "\"gStillWaterByPassEn\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "32", + "source_pin": "out" } }, "outputs": {} @@ -1078,14 +1078,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_BlendFillSystem\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -1099,17 +1099,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "26", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_StillWaterByPass\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "26", + "source_pin": "out" } }, "outputs": { @@ -1123,17 +1123,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "27", - "source_pin": "out" - }, "operand": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"Blender_Variables_Pers\".\"gWaterRecipe\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "27", + "source_pin": "out" } }, "outputs": { @@ -1149,17 +1149,17 @@ "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "28", - "source_pin": "out" - }, "operand": { "uid": "24", "scope": "GlobalVariable", "type": "variable", "name": "\"Blender_Variables_Pers\".\"gCarboStillRecipe\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "28", + "source_pin": "out" } }, "outputs": { @@ -1173,17 +1173,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "29", - "source_pin": "out" - }, "operand": { "uid": "25", "scope": "GlobalVariable", "type": "variable", "name": "\"gBlendFiStillWaterByPass\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "29", + "source_pin": "out" } }, "outputs": {} @@ -1203,14 +1203,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gSyrupRoomEn\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -1226,17 +1226,17 @@ "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "30", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"gIN_HVP301_Aux\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "30", + "source_pin": "out" } }, "outputs": { @@ -1252,17 +1252,17 @@ "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "31", - "source_pin": "out" - }, "operand": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_FastChangeOverEnabled\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "31", + "source_pin": "out" } }, "outputs": { @@ -1276,17 +1276,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "32", - "source_pin": "out" - }, "operand": { "uid": "24", "scope": "GlobalVariable", "type": "variable", "name": "\"Procedure_Variables\".\"FTP302Line_Preparation\".\"Done\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "32", + "source_pin": "out" } }, "outputs": { @@ -1302,17 +1302,17 @@ "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "33", - "source_pin": "out" - }, "operand": { "uid": "25", "scope": "GlobalVariable", "type": "variable", "name": "\"Procedure_Variables\".\"Syr_RunOut\".\"Done\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "33", + "source_pin": "out" } }, "outputs": { @@ -1326,17 +1326,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "31", - "source_pin": "out" - }, "operand": { "uid": "26", "scope": "GlobalVariable", "type": "variable", "name": "\"gBlenderCIPMode\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "31", + "source_pin": "out" } }, "outputs": { @@ -1350,17 +1350,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "35", - "source_pin": "out" - }, "operand": { "uid": "27", "scope": "GlobalVariable", "type": "variable", "name": "\"gIN_CIP_CIPRunning\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "35", + "source_pin": "out" } }, "outputs": { @@ -1374,17 +1374,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "36", - "source_pin": "out" - }, "operand": { "uid": "28", "scope": "GlobalVariable", "type": "variable", "name": "\"Procedure_Variables\".\"Blender_Run\".\"Running\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "36", + "source_pin": "out" } }, "outputs": { @@ -1424,17 +1424,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "O", - "source_instruction_uid": "38", - "source_pin": "out" - }, "operand": { "uid": "29", "scope": "GlobalVariable", "type": "variable", "name": "\"gHVP301_Open\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "O", + "source_instruction_uid": "38", + "source_pin": "out" } }, "outputs": {} @@ -1454,14 +1454,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gIN_HVM302_Aux\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -1475,18 +1475,18 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "s": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "25", - "source_pin": "out" - }, "timer": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"mHVM302_Dly\"" }, + "s": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "25", + "source_pin": "out" + }, "tv": { "uid": "22", "scope": "TypedConstant", @@ -1512,17 +1512,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Sd", - "source_instruction_uid": "26", - "source_pin": "q" - }, "operand": { "uid": "24", "scope": "GlobalVariable", "type": "variable", "name": "\"gHVM302_Open\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Sd", + "source_instruction_uid": "26", + "source_pin": "q" } }, "outputs": {} @@ -1542,14 +1542,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_BrixMeter\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -1565,18 +1565,18 @@ }, "negated_pins": {}, "inputs": { - "pre": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "24", - "source_pin": "out" - }, "in1": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_MeterType\"" }, + "pre": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "24", + "source_pin": "out" + }, "in2": { "uid": "23", "scope": "LiteralConstant", @@ -1620,14 +1620,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_BrixMeter\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -1643,18 +1643,18 @@ }, "negated_pins": {}, "inputs": { - "pre": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "24", - "source_pin": "out" - }, "in1": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_MeterType\"" }, + "pre": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "24", + "source_pin": "out" + }, "in2": { "uid": "23", "scope": "LiteralConstant", @@ -1698,14 +1698,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_SyrBrixMeter\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -1743,14 +1743,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_BrixMeter\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -1766,18 +1766,18 @@ }, "negated_pins": {}, "inputs": { - "pre": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "24", - "source_pin": "out" - }, "in1": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_MeterType\"" }, + "pre": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "24", + "source_pin": "out" + }, "in2": { "uid": "23", "scope": "LiteralConstant", @@ -1886,14 +1886,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_InverterRecirPumpPPM306\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -1952,14 +1952,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gBlenderProdMode\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -1973,17 +1973,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "25", - "source_pin": "out" - }, "bit": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"M19001\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "25", + "source_pin": "out" } }, "outputs": { @@ -1999,17 +1999,17 @@ "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "PBox", - "source_instruction_uid": "26", - "source_pin": "out" - }, "operand": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"mDelayPowerOnTmr\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "PBox", + "source_instruction_uid": "26", + "source_pin": "out" } }, "outputs": { @@ -2023,17 +2023,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "27", - "source_pin": "out" - }, "operand": { "uid": "24", "scope": "GlobalVariable", "type": "variable", "name": "\"gProductionONS\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "27", + "source_pin": "out" } }, "outputs": {} @@ -2053,14 +2053,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gProductionONS\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -2074,14 +2074,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"Procedure_Variables\".\"Blender_Rinse\".\"ONS_Done\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -2123,17 +2123,17 @@ "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "O", - "source_instruction_uid": "26", - "source_pin": "out" - }, "operand": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"Blender_Variables_Pers\".\"gBlenderStarted\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "O", + "source_instruction_uid": "26", + "source_pin": "out" } }, "outputs": { @@ -2171,14 +2171,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Status\".\"System\".\"Blender_Prod_CIP\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -2192,17 +2192,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "25", - "source_pin": "out" - }, "bit": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"M19002\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "25", + "source_pin": "out" } }, "outputs": { @@ -2218,17 +2218,17 @@ "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "PBox", - "source_instruction_uid": "26", - "source_pin": "out" - }, "operand": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"mDelayPowerOnTmr\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "PBox", + "source_instruction_uid": "26", + "source_pin": "out" } }, "outputs": { @@ -2242,17 +2242,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "27", - "source_pin": "out" - }, "operand": { "uid": "24", "scope": "GlobalVariable", "type": "variable", "name": "\"gRinseONS\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "27", + "source_pin": "out" } }, "outputs": {} @@ -2272,14 +2272,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gBlenderCIPMode\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -2293,17 +2293,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "25", - "source_pin": "out" - }, "bit": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"M19003\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "25", + "source_pin": "out" } }, "outputs": { @@ -2319,17 +2319,17 @@ "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "PBox", - "source_instruction_uid": "26", - "source_pin": "out" - }, "operand": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"mDelayPowerOnTmr\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "PBox", + "source_instruction_uid": "26", + "source_pin": "out" } }, "outputs": { @@ -2343,17 +2343,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "27", - "source_pin": "out" - }, "operand": { "uid": "24", "scope": "GlobalVariable", "type": "variable", "name": "\"gCIPONS\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "27", + "source_pin": "out" } }, "outputs": {} @@ -2373,14 +2373,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gCIPONS\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -2653,14 +2653,14 @@ "operand": true }, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"mDelayPowerOnTmr\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -2742,14 +2742,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_Report\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -2892,14 +2892,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gBlendResetTotalizer\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -2913,18 +2913,18 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "s": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "24", - "source_pin": "out" - }, "timer": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"mResetTotalizerTmr\"" }, + "s": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "24", + "source_pin": "out" + }, "tv": { "uid": "22", "scope": "TypedConstant", @@ -2956,14 +2956,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gFTN301_ResetTot\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -2977,14 +2977,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"mResetTotalizerTmr\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -3024,18 +3024,18 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "s": { - "type": "connection", - "source_instruction_type": "O", - "source_instruction_uid": "28", - "source_pin": "out" - }, "timer": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"mResetFTN301TotTmr\"" }, + "s": { + "type": "connection", + "source_instruction_type": "O", + "source_instruction_uid": "28", + "source_pin": "out" + }, "tv": { "uid": "24", "scope": "TypedConstant", @@ -3061,17 +3061,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Se", - "source_instruction_uid": "29", - "source_pin": "q" - }, "operand": { "uid": "25", "scope": "LocalVariable", "type": "variable", "name": "\"mResetWaterTot\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Se", + "source_instruction_uid": "29", + "source_pin": "q" } }, "outputs": {} @@ -3091,14 +3091,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gFTN301_ResetTot\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -3112,17 +3112,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "23", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"gFTN301_ResetTot\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "23", + "source_pin": "out" } }, "outputs": {} @@ -3142,14 +3142,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gFTP302_ResetTot\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -3163,14 +3163,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"mResetTotalizerTmr\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -3210,18 +3210,18 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "s": { - "type": "connection", - "source_instruction_type": "O", - "source_instruction_uid": "29", - "source_pin": "out" - }, "timer": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"mResetFTP302TotTmr\"" }, + "s": { + "type": "connection", + "source_instruction_type": "O", + "source_instruction_uid": "29", + "source_pin": "out" + }, "tv": { "uid": "24", "scope": "TypedConstant", @@ -3247,17 +3247,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Se", - "source_instruction_uid": "30", - "source_pin": "q" - }, "operand": { "uid": "25", "scope": "GlobalVariable", "type": "variable", "name": "\"gSyrupRoomEn\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Se", + "source_instruction_uid": "30", + "source_pin": "q" } }, "outputs": { @@ -3271,17 +3271,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "31", - "source_pin": "out" - }, "operand": { "uid": "26", "scope": "LocalVariable", "type": "variable", "name": "\"mResetSyrupTot\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "31", + "source_pin": "out" } }, "outputs": {} @@ -3301,14 +3301,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gFTP302_ResetTot\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -3322,17 +3322,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "23", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"gFTP302_ResetTot\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "23", + "source_pin": "out" } }, "outputs": {} @@ -3352,14 +3352,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gFTM303_ResetTot\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -3373,14 +3373,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"mResetTotalizerTmr\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -3420,18 +3420,18 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "s": { - "type": "connection", - "source_instruction_type": "O", - "source_instruction_uid": "28", - "source_pin": "out" - }, "timer": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"mResetFTM303TotTmr\"" }, + "s": { + "type": "connection", + "source_instruction_type": "O", + "source_instruction_uid": "28", + "source_pin": "out" + }, "tv": { "uid": "24", "scope": "TypedConstant", @@ -3457,17 +3457,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Se", - "source_instruction_uid": "29", - "source_pin": "q" - }, "operand": { "uid": "25", "scope": "LocalVariable", "type": "variable", "name": "\"mResetCO2Tot\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Se", + "source_instruction_uid": "29", + "source_pin": "q" } }, "outputs": {} @@ -3487,14 +3487,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gFTM303_ResetTot\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -3508,17 +3508,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "23", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"gFTM303_ResetTot\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "23", + "source_pin": "out" } }, "outputs": {} @@ -3538,14 +3538,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gProductMFMResetTot\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -3559,14 +3559,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"mResetTotalizerTmr\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -3606,18 +3606,18 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "s": { - "type": "connection", - "source_instruction_type": "O", - "source_instruction_uid": "28", - "source_pin": "out" - }, "timer": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"mResetProductTotTmr\"" }, + "s": { + "type": "connection", + "source_instruction_type": "O", + "source_instruction_uid": "28", + "source_pin": "out" + }, "tv": { "uid": "24", "scope": "TypedConstant", @@ -3643,17 +3643,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Se", - "source_instruction_uid": "29", - "source_pin": "q" - }, "operand": { "uid": "25", "scope": "LocalVariable", "type": "variable", "name": "\"mResetProductTot\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Se", + "source_instruction_uid": "29", + "source_pin": "q" } }, "outputs": {} @@ -3673,14 +3673,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gProductMFMResetTot\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -3694,17 +3694,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "23", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"gProductMFMResetTot\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "23", + "source_pin": "out" } }, "outputs": {} @@ -3724,14 +3724,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gBlendResetTotalizer\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -3745,17 +3745,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "23", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"gBlendResetTotalizer\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "23", + "source_pin": "out" } }, "outputs": {} @@ -3777,14 +3777,14 @@ "operand": true }, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_Simulation\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -3885,14 +3885,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Cmd\".\"Commands_From_HMI\".\"F7_DeviceControl\".\"Command\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -3906,17 +3906,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "25", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Cmd\".\"Commands_From_HMI\".\"F7_DeviceControl\".\"Enable\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "25", + "source_pin": "out" } }, "outputs": { @@ -3930,17 +3930,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "26", - "source_pin": "out" - }, "bit": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"M19011\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "26", + "source_pin": "out" } }, "outputs": { @@ -3970,17 +3970,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "26", - "source_pin": "out" - }, "operand": { "uid": "24", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Cmd\".\"Commands_From_HMI\".\"F7_DeviceControl\".\"Light\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "26", + "source_pin": "out" } }, "outputs": {} @@ -4021,14 +4021,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Cmd\".\"Recipe\".\"Main_Page\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -4044,17 +4044,17 @@ "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "33", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"mFP_Recip_Main_Page\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "33", + "source_pin": "out" } }, "outputs": { @@ -4068,17 +4068,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "34", - "source_pin": "out" - }, "operand": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"mAux_FP_M700_1\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "34", + "source_pin": "out" } }, "outputs": {} @@ -4090,17 +4090,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "33", - "source_pin": "out" - }, "operand": { "uid": "24", "scope": "GlobalVariable", "type": "variable", "name": "\"mFP_Recip_Main_Page\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "33", + "source_pin": "out" } }, "outputs": {} @@ -4112,14 +4112,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "25", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Cmd\".\"Recipe\".\"Main_Page\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -4133,17 +4133,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "37", - "source_pin": "out" - }, "operand": { "uid": "26", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Cmd\".\"Recipe\".\"Edit\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "37", + "source_pin": "out" } }, "outputs": { @@ -4157,18 +4157,18 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "s": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "38", - "source_pin": "out" - }, "timer": { "uid": "27", "scope": "GlobalVariable", "type": "variable", "name": "\"T_Pulse_Recipe_Edit\"" }, + "s": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "38", + "source_pin": "out" + }, "tv": { "uid": "28", "scope": "TypedConstant", @@ -4194,17 +4194,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "SdCoil", - "source_instruction_uid": "39", - "source_pin": "q" - }, "operand": { "uid": "29", "scope": "GlobalVariable", "type": "variable", "name": "\"T_Pulse_Recipe_Edit\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "SdCoil", + "source_instruction_uid": "39", + "source_pin": "q" } }, "outputs": { @@ -4218,17 +4218,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "40", - "source_pin": "out" - }, "operand": { "uid": "30", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Cmd\".\"Recipe\".\"Edit\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "40", + "source_pin": "out" } }, "outputs": {} @@ -4240,14 +4240,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "31", "scope": "GlobalVariable", "type": "variable", "name": "\"mAux_FP_M700_1\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { @@ -4261,17 +4261,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "42", - "source_pin": "out" - }, "operand": { "uid": "32", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Cmd\".\"Recipe\".\"Edit\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "42", + "source_pin": "out" } }, "outputs": {} @@ -4291,14 +4291,14 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"AUX TRUE\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { diff --git a/BlenderCtrl__Main_simplified_processed.json b/BlenderCtrl__Main_simplified_processed.json index 3cb1130..39593e9 100644 --- a/BlenderCtrl__Main_simplified_processed.json +++ b/BlenderCtrl__Main_simplified_processed.json @@ -50,7 +50,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "Clock Signal", "block_type": "FC", "inputs": { @@ -72,7 +72,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "BlenderCtrl_MachineInit", "block_type": "FC", "inputs": { @@ -94,45 +94,45 @@ { "instruction_uid": "25", "uid": "25", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"AUX FALSE\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"AUX FALSE\"" + "scl": "// SymPy Contact: v0_" }, { "instruction_uid": "26", "uid": "26", - "type": "BLKMOV_scl", + "type": "BLKMOV_sympy_processed", "template_values": { "blk_type": "Type" }, "negated_pins": {}, "inputs": { - "en": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "25", - "source_pin": "out" - }, "SRCBLK": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_PID\".\"PPM303\"" + }, + "en": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "25", + "source_pin": "out" } }, "outputs": { @@ -166,73 +166,73 @@ { "instruction_uid": "24", "uid": "24", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gIN_VoltageOk\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"gIN_VoltageOk\"" + "scl": "// SymPy Contact: v1_" }, { "instruction_uid": "25", "uid": "25", - "type": "NBox_scl", + "type": "NBox_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "24", - "source_pin": "out" - }, "bit": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"M19000\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "24", + "source_pin": "out" } }, "outputs": { "out": [] }, - "_edge_mem_update_scl": "\"M19000\" := \"gIN_VoltageOk\"; // N_TRIG(\"gIN_VoltageOk\")", - "scl": "// Logic moved to Coil 26" + "_edge_mem_update_scl": "\"M19000\" := \"gIN_VoltageOk\"; // N_TRIG(\"gIN_VoltageOk\") - Mem: \"M19000\"", + "scl": "// Edge Logic handled by Coil 26" }, { "instruction_uid": "26", "uid": "26", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "NBox", - "source_instruction_uid": "25", - "source_pin": "out" - }, "operand": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"gEmergencyPressed\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "NBox", + "source_instruction_uid": "25", + "source_pin": "out" } }, "outputs": {}, - "scl": "\"gEmergencyPressed\" := NOT \"gIN_VoltageOk\" AND \"M19000\";\n\"M19000\" := \"gIN_VoltageOk\"; // N_TRIG(\"gIN_VoltageOk\")" + "scl": "\"gEmergencyPressed\" := \"M19000\" AND NOT \"gIN_VoltageOk\";\n\"M19000\" := \"gIN_VoltageOk\"; // N_TRIG(\"gIN_VoltageOk\") - Mem: \"M19000\"" } ], "language": "LAD" @@ -245,105 +245,105 @@ { "instruction_uid": "29", "uid": "29", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gIN_LinePressCO2Ok\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"gIN_LinePressCO2Ok\"" + "scl": "// SymPy Contact: v2_" }, { "instruction_uid": "30", "uid": "30", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"gWorkshopTest\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"gWorkshopTest\"" + "scl": "// SymPy Contact: v3_" }, { "instruction_uid": "31", "uid": "31", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": { "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "30", - "source_pin": "out" - }, "operand": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"gWorkshop_Co2_Presence\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "30", + "source_pin": "out" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"gWorkshopTest\" AND (NOT \"gWorkshop_Co2_Presence\")" + "scl": "// SymPy Contact: v3_ & ~v4_" }, { "instruction_uid": "32", "uid": "32", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": { "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "31", - "source_pin": "out" - }, "operand": { "uid": "24", "scope": "GlobalVariable", "type": "variable", "name": "\"gWorkshop_CIP_Signals\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "31", + "source_pin": "out" } }, "outputs": { "out": [] }, - "scl": "// RLO: (\"gWorkshopTest\" AND (NOT \"gWorkshop_Co2_Presence\")) AND (NOT \"gWorkshop_CIP_Signals\")" + "scl": "// SymPy Contact: v3_ & ~v4_ & ~v5_" }, { "instruction_uid": "33", "uid": "33", - "type": "O_scl", + "type": "O_sympy_processed", "template_values": { "Card": "Cardinality" }, @@ -365,64 +365,64 @@ "outputs": { "out": [] }, - "scl": "// Logic O 33: \"gIN_LinePressCO2Ok\" OR (\"gWorkshopTest\" AND (NOT \"gWorkshop_Co2_Presence\")) AND (NOT \"gWorkshop_CIP_Signals\")" + "scl": "// SymPy O: v2_ | (v3_ & ~v4_ & ~v5_)" }, { "instruction_uid": "34", "uid": "34", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "O", - "source_instruction_uid": "33", - "source_pin": "out" - }, "operand": { "uid": "25", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Digital\".\"_PAL_S11\".\"Filtered\"" - } - }, - "outputs": { - "out": [] - }, - "scl": "// RLO: (\"gIN_LinePressCO2Ok\" OR (\"gWorkshopTest\" AND (NOT \"gWorkshop_Co2_Presence\")) AND (NOT \"gWorkshop_CIP_Signals\")) AND \"HMI_Digital\".\"_PAL_S11\".\"Filtered\"" - }, - { - "instruction_uid": "35", - "uid": "35", - "type": "Contact_scl", - "template_values": {}, - "negated_pins": { - "operand": true - }, - "inputs": { + }, "in": { "type": "connection", "source_instruction_type": "O", "source_instruction_uid": "33", "source_pin": "out" - }, - "operand": { - "uid": "26", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Disable_Bit\"" } }, "outputs": { "out": [] }, - "scl": "// RLO: (\"gIN_LinePressCO2Ok\" OR (\"gWorkshopTest\" AND (NOT \"gWorkshop_Co2_Presence\")) AND (NOT \"gWorkshop_CIP_Signals\")) AND (NOT \"Disable_Bit\")" + "scl": "// SymPy Contact: v6_ & (v2_ | (v3_ & ~v4_ & ~v5_))" + }, + { + "instruction_uid": "35", + "uid": "35", + "type": "Contact_sympy_processed", + "template_values": {}, + "negated_pins": { + "operand": true + }, + "inputs": { + "operand": { + "uid": "26", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"Disable_Bit\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "O", + "source_instruction_uid": "33", + "source_pin": "out" + } + }, + "outputs": { + "out": [] + }, + "scl": "// SymPy Contact: ~v7_ & (v2_ | (v3_ & ~v4_ & ~v5_))" }, { "instruction_uid": "36", "uid": "36", - "type": "O_scl", + "type": "O_sympy_processed", "template_values": { "Card": "Cardinality" }, @@ -444,55 +444,55 @@ "outputs": { "out": [] }, - "scl": "// Logic O 36: ((\"gIN_LinePressCO2Ok\" OR (\"gWorkshopTest\" AND (NOT \"gWorkshop_Co2_Presence\")) AND (NOT \"gWorkshop_CIP_Signals\")) AND \"HMI_Digital\".\"_PAL_S11\".\"Filtered\") OR (\"gIN_LinePressCO2Ok\" OR (\"gWorkshopTest\" AND (NOT \"gWorkshop_Co2_Presence\")) AND (NOT \"gWorkshop_CIP_Signals\")) AND (NOT \"Disable_Bit\")" + "scl": "// SymPy O: (v6_ & (v2_ | (v3_ & ~v4_ & ~v5_))) | (~v7_ & (v2_ | (v3_ & ~v4_ & ~v5_)))" }, { "instruction_uid": "37", "uid": "37", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "O", - "source_instruction_uid": "36", - "source_pin": "out" - }, "operand": { "uid": "27", "scope": "GlobalVariable", "type": "variable", "name": "\"gIN_VoltageOk\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "O", + "source_instruction_uid": "36", + "source_pin": "out" } }, "outputs": { "out": [] }, - "scl": "// RLO: ((\"gIN_LinePressCO2Ok\" OR (\"gWorkshopTest\" AND (NOT \"gWorkshop_Co2_Presence\")) AND (NOT \"gWorkshop_CIP_Signals\")) AND \"HMI_Digital\".\"_PAL_S11\".\"Filtered\") OR (\"gIN_LinePressCO2Ok\" OR (\"gWorkshopTest\" AND (NOT \"gWorkshop_Co2_Presence\")) AND (NOT \"gWorkshop_CIP_Signals\")) AND (NOT \"Disable_Bit\") AND \"gIN_VoltageOk\"" + "scl": "// SymPy Contact: v1_ & ((v6_ & (v2_ | (v3_ & ~v4_ & ~v5_))) | (~v7_ & (v2_ | (v3_ & ~v4_ & ~v5_))))" }, { "instruction_uid": "38", "uid": "38", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "37", - "source_pin": "out" - }, "operand": { "uid": "28", "scope": "GlobalVariable", "type": "variable", "name": "\"gBlenderSuppliesOk\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "37", + "source_pin": "out" } }, "outputs": {}, - "scl": "\"gBlenderSuppliesOk\" := ((\"gIN_LinePressCO2Ok\" OR (\"gWorkshopTest\" AND (NOT \"gWorkshop_Co2_Presence\")) AND (NOT \"gWorkshop_CIP_Signals\")) AND \"HMI_Digital\".\"_PAL_S11\".\"Filtered\") OR (\"gIN_LinePressCO2Ok\" OR (\"gWorkshopTest\" AND (NOT \"gWorkshop_Co2_Presence\")) AND (NOT \"gWorkshop_CIP_Signals\")) AND (NOT \"Disable_Bit\") AND \"gIN_VoltageOk\";" + "scl": "\"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\");" } ], "language": "LAD" @@ -505,7 +505,7 @@ { "instruction_uid": "23", "uid": "23", - "type": "Move_scl", + "type": "Move_sympy_processed", "template_values": { "Card": "Cardinality" }, @@ -545,44 +545,44 @@ { "instruction_uid": "24", "uid": "24", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"FirstScan\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"FirstScan\"" + "scl": "// SymPy Contact: v8_" }, { "instruction_uid": "25", "uid": "25", - "type": "Se_scl", + "type": "Se_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "s": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "24", - "source_pin": "out" - }, "timer": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"mDelayPowerOnTmr\"" }, + "s": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "24", + "source_pin": "out" + }, "tv": { "uid": "23", "scope": "TypedConstant", @@ -598,7 +598,7 @@ } }, "outputs": {}, - "scl": "\"mDelayPowerOnTmr\"(IN := \"FirstScan\", PT := S5T#2S); // TODO: Declarar \"mDelayPowerOnTmr\" : TP; en VAR_STAT o VAR" + "scl": "\"mDelayPowerOnTmr\"(IN := \"FirstScan\", PT := S5T#2S); // TODO: Declarar \"mDelayPowerOnTmr\" : TP;" } ], "language": "LAD" @@ -611,43 +611,43 @@ { "instruction_uid": "23", "uid": "23", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Status\".\"System\".\"Blender_Prod_CIP\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"HMI_Variables_Status\".\"System\".\"Blender_Prod_CIP\"" + "scl": "// SymPy Contact: v9_" }, { "instruction_uid": "24", "uid": "24", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "23", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"gBlenderProdMode\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "23", + "source_pin": "out" } }, "outputs": {}, @@ -664,54 +664,54 @@ { "instruction_uid": "25", "uid": "25", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": { "operand": true }, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Status\".\"System\".\"Blender_Prod_CIP\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: (NOT \"HMI_Variables_Status\".\"System\".\"Blender_Prod_CIP\")" + "scl": "// SymPy Contact: ~v9_" }, { "instruction_uid": "26", "uid": "26", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "25", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"gBlenderCIPMode\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "25", + "source_pin": "out" } }, "outputs": {}, - "scl": "\"gBlenderCIPMode\" := (NOT \"HMI_Variables_Status\".\"System\".\"Blender_Prod_CIP\");" + "scl": "\"gBlenderCIPMode\" := NOT \"HMI_Variables_Status\".\"System\".\"Blender_Prod_CIP\";" }, { "instruction_uid": "27", "uid": "27", - "type": "Move_scl", + "type": "Move_sympy_processed", "template_values": { "Card": "Cardinality" }, @@ -741,7 +741,7 @@ } ] }, - "scl": "IF (NOT \"HMI_Variables_Status\".\"System\".\"Blender_Prod_CIP\") THEN\n \"HMI_Variables_Status\".\"Procedures\".\"BlenderStateNum\" := 19;\nEND_IF;" + "scl": "IF NOT \"HMI_Variables_Status\".\"System\".\"Blender_Prod_CIP\" THEN\n \"HMI_Variables_Status\".\"Procedures\".\"BlenderStateNum\" := 19;\nEND_IF;" } ], "language": "LAD" @@ -754,118 +754,118 @@ { "instruction_uid": "26", "uid": "26", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": { "operand": true }, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"AUX FALSE\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: (NOT \"AUX FALSE\")" + "scl": "// SymPy Contact: ~v0_" }, { "instruction_uid": "27", "uid": "27", - "type": "RCoil_scl", + "type": "RCoil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "26", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Status\".\"Meters\".\"QTM3012_PRD_Fault\"" - } - }, - "outputs": {}, - "scl": "IF (NOT \"AUX FALSE\") THEN\n \"HMI_Variables_Status\".\"Meters\".\"QTM3012_PRD_Fault\" := FALSE;\nEND_IF;" - }, - { - "instruction_uid": "28", - "uid": "28", - "type": "RCoil_scl", - "template_values": {}, - "negated_pins": {}, - "inputs": { + }, "in": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "26", "source_pin": "out" - }, + } + }, + "outputs": {}, + "scl": "IF NOT \"AUX FALSE\" THEN\n \"HMI_Variables_Status\".\"Meters\".\"QTM3012_PRD_Fault\" := FALSE;\nEND_IF;" + }, + { + "instruction_uid": "28", + "uid": "28", + "type": "RCoil_sympy_processed", + "template_values": {}, + "negated_pins": {}, + "inputs": { "operand": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"gmPDS2000_Error_Fault\"" - } - }, - "outputs": {}, - "scl": "IF (NOT \"AUX FALSE\") THEN\n \"gmPDS2000_Error_Fault\" := FALSE;\nEND_IF;" - }, - { - "instruction_uid": "29", - "uid": "29", - "type": "RCoil_scl", - "template_values": {}, - "negated_pins": {}, - "inputs": { + }, "in": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "26", "source_pin": "out" - }, + } + }, + "outputs": {}, + "scl": "IF NOT \"AUX FALSE\" THEN\n \"gmPDS2000_Error_Fault\" := FALSE;\nEND_IF;" + }, + { + "instruction_uid": "29", + "uid": "29", + "type": "RCoil_sympy_processed", + "template_values": {}, + "negated_pins": {}, + "inputs": { "operand": { "uid": "24", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Status\".\"Meters\".\"QTM3012_PRD_Run\"" - } - }, - "outputs": {}, - "scl": "IF (NOT \"AUX FALSE\") THEN\n \"HMI_Variables_Status\".\"Meters\".\"QTM3012_PRD_Run\" := FALSE;\nEND_IF;" - }, - { - "instruction_uid": "30", - "uid": "30", - "type": "RCoil_scl", - "template_values": {}, - "negated_pins": {}, - "inputs": { + }, "in": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "26", "source_pin": "out" - }, + } + }, + "outputs": {}, + "scl": "IF NOT \"AUX FALSE\" THEN\n \"HMI_Variables_Status\".\"Meters\".\"QTM3012_PRD_Run\" := FALSE;\nEND_IF;" + }, + { + "instruction_uid": "30", + "uid": "30", + "type": "RCoil_sympy_processed", + "template_values": {}, + "negated_pins": {}, + "inputs": { "operand": { "uid": "25", "scope": "GlobalVariable", "type": "variable", "name": "\"gNoFreezeProductMeter\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "26", + "source_pin": "out" } }, "outputs": {}, - "scl": "IF (NOT \"AUX FALSE\") THEN\n \"gNoFreezeProductMeter\" := FALSE;\nEND_IF;" + "scl": "IF NOT \"AUX FALSE\" THEN\n \"gNoFreezeProductMeter\" := FALSE;\nEND_IF;" } ], "language": "LAD" @@ -878,49 +878,49 @@ { "instruction_uid": "23", "uid": "23", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": { "operand": true }, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"System_RunOut_Variables\".\"ProdPipeRunOutWaterCount\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: (NOT \"System_RunOut_Variables\".\"ProdPipeRunOutWaterCount\")" + "scl": "// SymPy Contact: ~v10_" }, { "instruction_uid": "24", "uid": "24", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "23", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"System_RunOut_Variables\".\"ProdPipeRunOutFillerBott\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "23", + "source_pin": "out" } }, "outputs": {}, - "scl": "\"System_RunOut_Variables\".\"ProdPipeRunOutFillerBott\" := (NOT \"System_RunOut_Variables\".\"ProdPipeRunOutWaterCount\");" + "scl": "\"System_RunOut_Variables\".\"ProdPipeRunOutFillerBott\" := NOT \"System_RunOut_Variables\".\"ProdPipeRunOutWaterCount\";" } ], "language": "LAD" @@ -933,78 +933,78 @@ { "instruction_uid": "27", "uid": "27", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_StillWaterByPass\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_StillWaterByPass\"" + "scl": "// SymPy Contact: v11_" }, { "instruction_uid": "28", "uid": "28", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_ByPassDeair\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_ByPassDeair\"" + "scl": "// SymPy Contact: v12_" }, { "instruction_uid": "29", "uid": "29", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": { "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "28", - "source_pin": "out" - }, "operand": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_Deaireation\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "28", + "source_pin": "out" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_ByPassDeair\" AND (NOT \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_Deaireation\")" + "scl": "// SymPy Contact: v12_ & ~v13_" }, { "instruction_uid": "30", "uid": "30", - "type": "O_scl", + "type": "O_sympy_processed", "template_values": { "Card": "Cardinality" }, @@ -1026,82 +1026,82 @@ "outputs": { "out": [] }, - "scl": "// Logic O 30: \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_StillWaterByPass\" OR (\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_ByPassDeair\" AND (NOT \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_Deaireation\"))" + "scl": "// SymPy O: v11_ | (v12_ & ~v13_)" }, { "instruction_uid": "31", "uid": "31", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "O", - "source_instruction_uid": "30", - "source_pin": "out" - }, "operand": { "uid": "24", "scope": "GlobalVariable", "type": "variable", "name": "\"Blender_Variables_Pers\".\"gWaterRecipe\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "O", + "source_instruction_uid": "30", + "source_pin": "out" } }, "outputs": { "out": [] }, - "scl": "// RLO: (\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_StillWaterByPass\" OR (\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_ByPassDeair\" AND (NOT \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_Deaireation\"))) AND \"Blender_Variables_Pers\".\"gWaterRecipe\"" + "scl": "// SymPy Contact: v14_ & (v11_ | (v12_ & ~v13_))" }, { "instruction_uid": "32", "uid": "32", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": { "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "31", - "source_pin": "out" - }, "operand": { "uid": "25", "scope": "GlobalVariable", "type": "variable", "name": "\"Blender_Variables_Pers\".\"gCarboStillRecipe\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "31", + "source_pin": "out" } }, "outputs": { "out": [] }, - "scl": "// RLO: ((\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_StillWaterByPass\" OR (\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_ByPassDeair\" AND (NOT \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_Deaireation\"))) AND \"Blender_Variables_Pers\".\"gWaterRecipe\") AND (NOT \"Blender_Variables_Pers\".\"gCarboStillRecipe\")" + "scl": "// SymPy Contact: v14_ & ~v15_ & (v11_ | (v12_ & ~v13_))" }, { "instruction_uid": "33", "uid": "33", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "32", - "source_pin": "out" - }, "operand": { "uid": "26", "scope": "GlobalVariable", "type": "variable", "name": "\"gStillWaterByPassEn\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "32", + "source_pin": "out" } }, "outputs": {}, - "scl": "\"gStillWaterByPassEn\" := ((\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_StillWaterByPass\" OR (\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_ByPassDeair\" AND (NOT \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_Deaireation\"))) AND \"Blender_Variables_Pers\".\"gWaterRecipe\") AND (NOT \"Blender_Variables_Pers\".\"gCarboStillRecipe\");" + "scl": "\"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\");" } ], "language": "LAD" @@ -1114,124 +1114,124 @@ { "instruction_uid": "26", "uid": "26", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_BlendFillSystem\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_BlendFillSystem\"" + "scl": "// SymPy Contact: v16_" }, { "instruction_uid": "27", "uid": "27", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "26", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_StillWaterByPass\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "26", + "source_pin": "out" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_BlendFillSystem\" AND \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_StillWaterByPass\"" + "scl": "// SymPy Contact: v11_ & v16_" }, { "instruction_uid": "28", "uid": "28", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "27", - "source_pin": "out" - }, "operand": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"Blender_Variables_Pers\".\"gWaterRecipe\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "27", + "source_pin": "out" } }, "outputs": { "out": [] }, - "scl": "// RLO: (\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_BlendFillSystem\" AND \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_StillWaterByPass\") AND \"Blender_Variables_Pers\".\"gWaterRecipe\"" + "scl": "// SymPy Contact: v11_ & v14_ & v16_" }, { "instruction_uid": "29", "uid": "29", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": { "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "28", - "source_pin": "out" - }, "operand": { "uid": "24", "scope": "GlobalVariable", "type": "variable", "name": "\"Blender_Variables_Pers\".\"gCarboStillRecipe\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "28", + "source_pin": "out" } }, "outputs": { "out": [] }, - "scl": "// RLO: ((\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_BlendFillSystem\" AND \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_StillWaterByPass\") AND \"Blender_Variables_Pers\".\"gWaterRecipe\") AND (NOT \"Blender_Variables_Pers\".\"gCarboStillRecipe\")" + "scl": "// SymPy Contact: v11_ & v14_ & v16_ & ~v15_" }, { "instruction_uid": "30", "uid": "30", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "29", - "source_pin": "out" - }, "operand": { "uid": "25", "scope": "GlobalVariable", "type": "variable", "name": "\"gBlendFiStillWaterByPass\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "29", + "source_pin": "out" } }, "outputs": {}, - "scl": "\"gBlendFiStillWaterByPass\" := ((\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_BlendFillSystem\" AND \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_StillWaterByPass\") AND \"Blender_Variables_Pers\".\"gWaterRecipe\") AND (NOT \"Blender_Variables_Pers\".\"gCarboStillRecipe\");" + "scl": "\"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\";" } ], "language": "LAD" @@ -1244,210 +1244,210 @@ { "instruction_uid": "30", "uid": "30", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gSyrupRoomEn\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"gSyrupRoomEn\"" + "scl": "// SymPy Contact: v17_" }, { "instruction_uid": "31", "uid": "31", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": { "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "30", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"gIN_HVP301_Aux\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "30", + "source_pin": "out" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"gSyrupRoomEn\" AND (NOT \"gIN_HVP301_Aux\")" + "scl": "// SymPy Contact: v17_ & ~v18_" }, { "instruction_uid": "32", "uid": "32", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": { "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "31", - "source_pin": "out" - }, "operand": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_FastChangeOverEnabled\"" - } - }, - "outputs": { - "out": [] - }, - "scl": "// RLO: (\"gSyrupRoomEn\" AND (NOT \"gIN_HVP301_Aux\")) AND (NOT \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_FastChangeOverEnabled\")" - }, - { - "instruction_uid": "33", - "uid": "33", - "type": "Contact_scl", - "template_values": {}, - "negated_pins": {}, - "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "32", - "source_pin": "out" }, - "operand": { - "uid": "24", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Procedure_Variables\".\"FTP302Line_Preparation\".\"Done\"" - } - }, - "outputs": { - "out": [] - }, - "scl": "// RLO: (\"gSyrupRoomEn\" AND (NOT \"gIN_HVP301_Aux\")) AND (NOT \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_FastChangeOverEnabled\") AND \"Procedure_Variables\".\"FTP302Line_Preparation\".\"Done\"" - }, - { - "instruction_uid": "34", - "uid": "34", - "type": "Contact_scl", - "template_values": {}, - "negated_pins": { - "operand": true - }, - "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "33", - "source_pin": "out" - }, - "operand": { - "uid": "25", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Procedure_Variables\".\"Syr_RunOut\".\"Done\"" - } - }, - "outputs": { - "out": [] - }, - "scl": "// RLO: ((\"gSyrupRoomEn\" AND (NOT \"gIN_HVP301_Aux\")) AND (NOT \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_FastChangeOverEnabled\") AND \"Procedure_Variables\".\"FTP302Line_Preparation\".\"Done\") AND (NOT \"Procedure_Variables\".\"Syr_RunOut\".\"Done\")" - }, - { - "instruction_uid": "35", - "uid": "35", - "type": "Contact_scl", - "template_values": {}, - "negated_pins": {}, - "inputs": { "in": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "31", "source_pin": "out" + } + }, + "outputs": { + "out": [] + }, + "scl": "// SymPy Contact: v17_ & ~v18_ & ~v19_" + }, + { + "instruction_uid": "33", + "uid": "33", + "type": "Contact_sympy_processed", + "template_values": {}, + "negated_pins": {}, + "inputs": { + "operand": { + "uid": "24", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"Procedure_Variables\".\"FTP302Line_Preparation\".\"Done\"" }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "32", + "source_pin": "out" + } + }, + "outputs": { + "out": [] + }, + "scl": "// SymPy Contact: v17_ & v20_ & ~v18_ & ~v19_" + }, + { + "instruction_uid": "34", + "uid": "34", + "type": "Contact_sympy_processed", + "template_values": {}, + "negated_pins": { + "operand": true + }, + "inputs": { + "operand": { + "uid": "25", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"Procedure_Variables\".\"Syr_RunOut\".\"Done\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "33", + "source_pin": "out" + } + }, + "outputs": { + "out": [] + }, + "scl": "// SymPy Contact: v17_ & v20_ & ~v18_ & ~v19_ & ~v21_" + }, + { + "instruction_uid": "35", + "uid": "35", + "type": "Contact_sympy_processed", + "template_values": {}, + "negated_pins": {}, + "inputs": { "operand": { "uid": "26", "scope": "GlobalVariable", "type": "variable", "name": "\"gBlenderCIPMode\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "31", + "source_pin": "out" } }, "outputs": { "out": [] }, - "scl": "// RLO: (\"gSyrupRoomEn\" AND (NOT \"gIN_HVP301_Aux\")) AND \"gBlenderCIPMode\"" + "scl": "// SymPy Contact: v17_ & v22_ & ~v18_" }, { "instruction_uid": "36", "uid": "36", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "35", - "source_pin": "out" - }, "operand": { "uid": "27", "scope": "GlobalVariable", "type": "variable", "name": "\"gIN_CIP_CIPRunning\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "35", + "source_pin": "out" } }, "outputs": { "out": [] }, - "scl": "// RLO: ((\"gSyrupRoomEn\" AND (NOT \"gIN_HVP301_Aux\")) AND \"gBlenderCIPMode\") AND \"gIN_CIP_CIPRunning\"" + "scl": "// SymPy Contact: v17_ & v22_ & v23_ & ~v18_" }, { "instruction_uid": "37", "uid": "37", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "36", - "source_pin": "out" - }, "operand": { "uid": "28", "scope": "GlobalVariable", "type": "variable", "name": "\"Procedure_Variables\".\"Blender_Run\".\"Running\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "36", + "source_pin": "out" } }, "outputs": { "out": [] }, - "scl": "// RLO: (((\"gSyrupRoomEn\" AND (NOT \"gIN_HVP301_Aux\")) AND \"gBlenderCIPMode\") AND \"gIN_CIP_CIPRunning\") AND \"Procedure_Variables\".\"Blender_Run\".\"Running\"" + "scl": "// SymPy Contact: v17_ & v22_ & v23_ & v24_ & ~v18_" }, { "instruction_uid": "38", "uid": "38", - "type": "O_scl", + "type": "O_sympy_processed", "template_values": { "Card": "Cardinality" }, @@ -1469,30 +1469,30 @@ "outputs": { "out": [] }, - "scl": "// Logic O 38: ((\"gSyrupRoomEn\" AND (NOT \"gIN_HVP301_Aux\")) AND (NOT \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_FastChangeOverEnabled\") AND \"Procedure_Variables\".\"FTP302Line_Preparation\".\"Done\") AND (NOT \"Procedure_Variables\".\"Syr_RunOut\".\"Done\") OR ((((\"gSyrupRoomEn\" AND (NOT \"gIN_HVP301_Aux\")) AND \"gBlenderCIPMode\") AND \"gIN_CIP_CIPRunning\") AND \"Procedure_Variables\".\"Blender_Run\".\"Running\")" + "scl": "// SymPy O: (v17_ & v22_ & v23_ & v24_ & ~v18_) | (v17_ & v20_ & ~v18_ & ~v19_ & ~v21_)" }, { "instruction_uid": "39", "uid": "39", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "O", - "source_instruction_uid": "38", - "source_pin": "out" - }, "operand": { "uid": "29", "scope": "GlobalVariable", "type": "variable", "name": "\"gHVP301_Open\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "O", + "source_instruction_uid": "38", + "source_pin": "out" } }, "outputs": {}, - "scl": "\"gHVP301_Open\" := ((\"gSyrupRoomEn\" AND (NOT \"gIN_HVP301_Aux\")) AND (NOT \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_FastChangeOverEnabled\") AND \"Procedure_Variables\".\"FTP302Line_Preparation\".\"Done\") AND (NOT \"Procedure_Variables\".\"Syr_RunOut\".\"Done\") OR ((((\"gSyrupRoomEn\" AND (NOT \"gIN_HVP301_Aux\")) AND \"gBlenderCIPMode\") AND \"gIN_CIP_CIPRunning\") AND \"Procedure_Variables\".\"Blender_Run\".\"Running\");" + "scl": "\"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\");" } ], "language": "LAD" @@ -1505,44 +1505,44 @@ { "instruction_uid": "25", "uid": "25", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gIN_HVM302_Aux\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"gIN_HVM302_Aux\"" + "scl": "// SymPy Contact: v25_" }, { "instruction_uid": "26", "uid": "26", - "type": "Sd_scl", + "type": "Sd_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "s": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "25", - "source_pin": "out" - }, "timer": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"mHVM302_Dly\"" }, + "s": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "25", + "source_pin": "out" + }, "tv": { "uid": "22", "scope": "TypedConstant", @@ -1560,26 +1560,26 @@ "outputs": { "q": [] }, - "scl": "\"mHVM302_Dly\"(IN := \"gIN_HVM302_Aux\", PT := S5T#1S); // TODO: Declarar \"mHVM302_Dly\" : TON; en VAR_STAT o VAR" + "scl": "\"mHVM302_Dly\"(IN := \"gIN_HVM302_Aux\", PT := S5T#1S); // TODO: Declarar \"mHVM302_Dly\" : TON;" }, { "instruction_uid": "27", "uid": "27", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Sd", - "source_instruction_uid": "26", - "source_pin": "q" - }, "operand": { "uid": "24", "scope": "GlobalVariable", "type": "variable", "name": "\"gHVM302_Open\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Sd", + "source_instruction_uid": "26", + "source_pin": "q" } }, "outputs": {}, @@ -1596,46 +1596,46 @@ { "instruction_uid": "24", "uid": "24", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_BrixMeter\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_BrixMeter\"" + "scl": "// SymPy Contact: v26_" }, { "instruction_uid": "25", "uid": "25", - "type": "Eq_scl", + "type": "Eq_sympy_processed", "template_values": { "SrcType": "Type" }, "negated_pins": {}, "inputs": { - "pre": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "24", - "source_pin": "out" - }, "in1": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_MeterType\"" }, + "pre": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "24", + "source_pin": "out" + }, "in2": { "uid": "23", "scope": "LiteralConstant", @@ -1647,12 +1647,12 @@ "outputs": { "out": [] }, - "scl": "// Comparison Eq 25: \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_MeterType\" = 6" + "scl": "// SymPy EQ: Eq(v56_, 6)" }, { "instruction_uid": "26", "uid": "26", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "Maselli_PA_Control", "block_type": "FC", "inputs": { @@ -1664,7 +1664,7 @@ } }, "outputs": {}, - "scl": "IF \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_MeterType\" = 6 THEN\n Maselli_PA_Control();\nEND_IF;" + "scl": "IF Eq(\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_MeterType\", 6) THEN\n Maselli_PA_Control();\nEND_IF;" } ], "language": "LAD" @@ -1677,46 +1677,46 @@ { "instruction_uid": "24", "uid": "24", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_BrixMeter\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_BrixMeter\"" + "scl": "// SymPy Contact: v26_" }, { "instruction_uid": "25", "uid": "25", - "type": "Eq_scl", + "type": "Eq_sympy_processed", "template_values": { "SrcType": "Type" }, "negated_pins": {}, "inputs": { - "pre": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "24", - "source_pin": "out" - }, "in1": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_MeterType\"" }, + "pre": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "24", + "source_pin": "out" + }, "in2": { "uid": "23", "scope": "LiteralConstant", @@ -1728,12 +1728,12 @@ "outputs": { "out": [] }, - "scl": "// Comparison Eq 25: \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_MeterType\" = 5" + "scl": "// SymPy EQ: Eq(v56_, 5)" }, { "instruction_uid": "26", "uid": "26", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "mPDS_PA_Control", "block_type": "FC", "inputs": { @@ -1745,7 +1745,7 @@ } }, "outputs": {}, - "scl": "IF \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_MeterType\" = 5 THEN\n mPDS_PA_Control();\nEND_IF;" + "scl": "IF Eq(\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_MeterType\", 5) THEN\n mPDS_PA_Control();\nEND_IF;" } ], "language": "LAD" @@ -1758,29 +1758,29 @@ { "instruction_uid": "22", "uid": "22", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_SyrBrixMeter\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_SyrBrixMeter\"" + "scl": "// SymPy Contact: v27_" }, { "instruction_uid": "23", "uid": "23", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "mPDS_SYR_PA_Control", "block_type": "FC", "inputs": { @@ -1805,46 +1805,46 @@ { "instruction_uid": "24", "uid": "24", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_BrixMeter\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_BrixMeter\"" + "scl": "// SymPy Contact: v26_" }, { "instruction_uid": "25", "uid": "25", - "type": "Eq_scl", + "type": "Eq_sympy_processed", "template_values": { "SrcType": "Type" }, "negated_pins": {}, "inputs": { - "pre": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "24", - "source_pin": "out" - }, "in1": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_MeterType\"" }, + "pre": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "24", + "source_pin": "out" + }, "in2": { "uid": "23", "scope": "LiteralConstant", @@ -1856,12 +1856,12 @@ "outputs": { "out": [] }, - "scl": "// Comparison Eq 25: \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_MeterType\" = 3" + "scl": "// SymPy EQ: Eq(v56_, 3)" }, { "instruction_uid": "26", "uid": "26", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "GetProdBrixCO2_Anal_Inpt", "block_type": "FC", "inputs": { @@ -1873,7 +1873,7 @@ } }, "outputs": {}, - "scl": "IF \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_MeterType\" = 3 THEN\n GetProdBrixCO2_Anal_Inpt();\nEND_IF;" + "scl": "IF Eq(\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_MeterType\", 3) THEN\n GetProdBrixCO2_Anal_Inpt();\nEND_IF;" } ], "language": "LAD" @@ -1886,7 +1886,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "ProductQuality", "block_type": "FC", "inputs": { @@ -1908,7 +1908,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FB_scl", + "type": "Call_FB_sympy_processed", "block_name": "Input", "block_type": "FB", "instance_db": "\"Input_Data\"", @@ -1932,7 +1932,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "SelCheckBrixSource", "block_type": "FC", "inputs": { @@ -1954,29 +1954,29 @@ { "instruction_uid": "22", "uid": "22", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_InverterRecirPumpPPM306\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_InverterRecirPumpPPM306\"" + "scl": "// SymPy Contact: v28_" }, { "instruction_uid": "23", "uid": "23", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "CTRLCoolingSystem", "block_type": "FC", "inputs": { @@ -2001,7 +2001,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "TankLevel", "block_type": "FC", "inputs": { @@ -2023,100 +2023,100 @@ { "instruction_uid": "25", "uid": "25", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gBlenderProdMode\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"gBlenderProdMode\"" + "scl": "// SymPy Contact: v29_" }, { "instruction_uid": "26", "uid": "26", - "type": "PBox_scl", + "type": "PBox_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "25", - "source_pin": "out" - }, "bit": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"M19001\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "25", + "source_pin": "out" } }, "outputs": { "out": [] }, - "_edge_mem_update_scl": "\"M19001\" := \"gBlenderProdMode\"; // P_TRIG(\"gBlenderProdMode\")", - "scl": "// PBox Logic moved to consumer Coil" + "_edge_mem_update_scl": "\"M19001\" := \"gBlenderProdMode\"; // P_TRIG(\"gBlenderProdMode\") - Mem: \"M19001\"", + "scl": "// PBox SymPy processed, logic in consumer" }, { "instruction_uid": "27", "uid": "27", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": { "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "PBox", - "source_instruction_uid": "26", - "source_pin": "out" - }, "operand": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"mDelayPowerOnTmr\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "PBox", + "source_instruction_uid": "26", + "source_pin": "out" } }, "outputs": { "out": [] }, - "scl": "// RLO: (\"gBlenderProdMode\" AND NOT \"M19001\") AND (NOT \"mDelayPowerOnTmr\")" + "scl": "// SymPy Contact: v29_ & ~v30_ & ~v51_" }, { "instruction_uid": "28", "uid": "28", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "27", - "source_pin": "out" - }, "operand": { "uid": "24", "scope": "GlobalVariable", "type": "variable", "name": "\"gProductionONS\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "27", + "source_pin": "out" } }, "outputs": {}, - "scl": "\"gProductionONS\" := (\"gBlenderProdMode\" AND NOT \"M19001\") AND (NOT \"mDelayPowerOnTmr\");" + "scl": "\"gProductionONS\" := \"gBlenderProdMode\" AND NOT \"mDelayPowerOnTmr\" AND NOT \"M19001\";" } ], "language": "LAD" @@ -2129,51 +2129,51 @@ { "instruction_uid": "24", "uid": "24", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gProductionONS\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"gProductionONS\"" + "scl": "// SymPy Contact: v31_" }, { "instruction_uid": "25", "uid": "25", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"Procedure_Variables\".\"Blender_Rinse\".\"ONS_Done\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"Procedure_Variables\".\"Blender_Rinse\".\"ONS_Done\"" + "scl": "// SymPy Contact: v32_" }, { "instruction_uid": "26", "uid": "26", - "type": "O_scl", + "type": "O_sympy_processed", "template_values": { "Card": "Cardinality" }, @@ -2195,39 +2195,39 @@ "outputs": { "out": [] }, - "scl": "// Logic O 26: \"gProductionONS\" OR \"Procedure_Variables\".\"Blender_Rinse\".\"ONS_Done\"" + "scl": "// SymPy O: v31_ | v32_" }, { "instruction_uid": "27", "uid": "27", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": { "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "O", - "source_instruction_uid": "26", - "source_pin": "out" - }, "operand": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"Blender_Variables_Pers\".\"gBlenderStarted\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "O", + "source_instruction_uid": "26", + "source_pin": "out" } }, "outputs": { "out": [] }, - "scl": "// RLO: (\"gProductionONS\" OR \"Procedure_Variables\".\"Blender_Rinse\".\"ONS_Done\") AND (NOT \"Blender_Variables_Pers\".\"gBlenderStarted\")" + "scl": "// SymPy Contact: ~v33_ & (v31_ | v32_)" }, { "instruction_uid": "28", "uid": "28", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "BlenderCtrl_ProdModeInit", "block_type": "FC", "inputs": { @@ -2239,7 +2239,7 @@ } }, "outputs": {}, - "scl": "IF (\"gProductionONS\" OR \"Procedure_Variables\".\"Blender_Rinse\".\"ONS_Done\") AND (NOT \"Blender_Variables_Pers\".\"gBlenderStarted\") THEN\n BlenderCtrl_ProdModeInit();\nEND_IF;" + "scl": "IF (\"gProductionONS\" AND NOT \"Blender_Variables_Pers\".\"gBlenderStarted\") OR (\"Procedure_Variables\".\"Blender_Rinse\".\"ONS_Done\" AND NOT \"Blender_Variables_Pers\".\"gBlenderStarted\") THEN\n BlenderCtrl_ProdModeInit();\nEND_IF;" } ], "language": "LAD" @@ -2252,100 +2252,100 @@ { "instruction_uid": "25", "uid": "25", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Status\".\"System\".\"Blender_Prod_CIP\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"HMI_Variables_Status\".\"System\".\"Blender_Prod_CIP\"" + "scl": "// SymPy Contact: v9_" }, { "instruction_uid": "26", "uid": "26", - "type": "PBox_scl", + "type": "PBox_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "25", - "source_pin": "out" - }, "bit": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"M19002\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "25", + "source_pin": "out" } }, "outputs": { "out": [] }, - "_edge_mem_update_scl": "\"M19002\" := \"HMI_Variables_Status\".\"System\".\"Blender_Prod_CIP\"; // P_TRIG(\"HMI_Variables_Status\".\"System\".\"Blender_Prod_CIP\")", - "scl": "// PBox Logic moved to consumer Coil" + "_edge_mem_update_scl": "\"M19002\" := \"HMI_Variables_Status\".\"System\".\"Blender_Prod_CIP\"; // P_TRIG(\"HMI_Variables_Status\".\"System\".\"Blender_Prod_CIP\") - Mem: \"M19002\"", + "scl": "// PBox SymPy processed, logic in consumer" }, { "instruction_uid": "27", "uid": "27", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": { "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "PBox", - "source_instruction_uid": "26", - "source_pin": "out" - }, "operand": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"mDelayPowerOnTmr\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "PBox", + "source_instruction_uid": "26", + "source_pin": "out" } }, "outputs": { "out": [] }, - "scl": "// RLO: (\"HMI_Variables_Status\".\"System\".\"Blender_Prod_CIP\" AND NOT \"M19002\") AND (NOT \"mDelayPowerOnTmr\")" + "scl": "// SymPy Contact: v9_ & ~v30_ & ~v52_" }, { "instruction_uid": "28", "uid": "28", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "27", - "source_pin": "out" - }, "operand": { "uid": "24", "scope": "GlobalVariable", "type": "variable", "name": "\"gRinseONS\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "27", + "source_pin": "out" } }, "outputs": {}, - "scl": "\"gRinseONS\" := (\"HMI_Variables_Status\".\"System\".\"Blender_Prod_CIP\" AND NOT \"M19002\") AND (NOT \"mDelayPowerOnTmr\");" + "scl": "\"gRinseONS\" := \"HMI_Variables_Status\".\"System\".\"Blender_Prod_CIP\" AND NOT \"mDelayPowerOnTmr\" AND NOT \"M19002\";" } ], "language": "LAD" @@ -2358,100 +2358,100 @@ { "instruction_uid": "25", "uid": "25", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gBlenderCIPMode\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"gBlenderCIPMode\"" + "scl": "// SymPy Contact: v22_" }, { "instruction_uid": "26", "uid": "26", - "type": "PBox_scl", + "type": "PBox_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "25", - "source_pin": "out" - }, "bit": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"M19003\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "25", + "source_pin": "out" } }, "outputs": { "out": [] }, - "_edge_mem_update_scl": "\"M19003\" := \"gBlenderCIPMode\"; // P_TRIG(\"gBlenderCIPMode\")", - "scl": "// PBox Logic moved to consumer Coil" + "_edge_mem_update_scl": "\"M19003\" := \"gBlenderCIPMode\"; // P_TRIG(\"gBlenderCIPMode\") - Mem: \"M19003\"", + "scl": "// PBox SymPy processed, logic in consumer" }, { "instruction_uid": "27", "uid": "27", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": { "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "PBox", - "source_instruction_uid": "26", - "source_pin": "out" - }, "operand": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"mDelayPowerOnTmr\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "PBox", + "source_instruction_uid": "26", + "source_pin": "out" } }, "outputs": { "out": [] }, - "scl": "// RLO: (\"gBlenderCIPMode\" AND NOT \"M19003\") AND (NOT \"mDelayPowerOnTmr\")" + "scl": "// SymPy Contact: v22_ & ~v30_ & ~v53_" }, { "instruction_uid": "28", "uid": "28", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "27", - "source_pin": "out" - }, "operand": { "uid": "24", "scope": "GlobalVariable", "type": "variable", "name": "\"gCIPONS\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "27", + "source_pin": "out" } }, "outputs": {}, - "scl": "\"gCIPONS\" := (\"gBlenderCIPMode\" AND NOT \"M19003\") AND (NOT \"mDelayPowerOnTmr\");" + "scl": "\"gCIPONS\" := \"gBlenderCIPMode\" AND NOT \"mDelayPowerOnTmr\" AND NOT \"M19003\";" } ], "language": "LAD" @@ -2464,29 +2464,29 @@ { "instruction_uid": "22", "uid": "22", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gCIPONS\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"gCIPONS\"" + "scl": "// SymPy Contact: v34_" }, { "instruction_uid": "23", "uid": "23", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "BlenderCtrl_CIPModeInit", "block_type": "FC", "inputs": { @@ -2511,7 +2511,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "BlenderCtrl_ResetSPWord", "block_type": "FC", "inputs": { @@ -2533,7 +2533,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "BlenderRun__Control", "block_type": "FC", "inputs": { @@ -2555,7 +2555,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "Prod Tank PressCtrl", "block_type": "FC", "inputs": { @@ -2577,7 +2577,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "Baialage", "block_type": "FC", "inputs": { @@ -2599,7 +2599,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FB_scl", + "type": "Call_FB_sympy_processed", "block_name": "ProcedureFirstProduction", "block_type": "FB", "instance_db": "\"FirstProduction_Data\"", @@ -2623,7 +2623,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "CIPMain", "block_type": "FC", "inputs": { @@ -2645,7 +2645,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "BlenderRinse", "block_type": "FC", "inputs": { @@ -2667,7 +2667,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "Safeties", "block_type": "FC", "inputs": { @@ -2689,7 +2689,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "Instrument_Scanner", "block_type": "FC", "inputs": { @@ -2711,7 +2711,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "VacuumCtrl", "block_type": "FC", "inputs": { @@ -2733,7 +2733,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "SyrupRoomCtrl", "block_type": "FC", "inputs": { @@ -2755,31 +2755,31 @@ { "instruction_uid": "22", "uid": "22", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": { "operand": true }, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"mDelayPowerOnTmr\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: (NOT \"mDelayPowerOnTmr\")" + "scl": "// SymPy Contact: ~v30_" }, { "instruction_uid": "23", "uid": "23", - "type": "Call_FB_scl", + "type": "Call_FB_sympy_processed", "block_name": "Procedure", "block_type": "FB", "instance_db": "\"Blender_Procedure Data\"", @@ -2793,7 +2793,7 @@ } }, "outputs": {}, - "scl": "IF (NOT \"mDelayPowerOnTmr\") THEN\n \"Blender_Procedure Data\"();\nEND_IF;" + "scl": "IF NOT \"mDelayPowerOnTmr\" THEN\n \"Blender_Procedure Data\"();\nEND_IF;" } ], "language": "LAD" @@ -2806,7 +2806,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "Pneumatic Valve Ctrl", "block_type": "FC", "inputs": { @@ -2828,7 +2828,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "PumpsControl", "block_type": "FC", "inputs": { @@ -2850,29 +2850,29 @@ { "instruction_uid": "22", "uid": "22", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_Report\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_Report\"" + "scl": "// SymPy Contact: v35_" }, { "instruction_uid": "23", "uid": "23", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "ProdReportManager", "block_type": "FC", "inputs": { @@ -2897,7 +2897,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "Output", "block_type": "FC", "inputs": { @@ -2919,7 +2919,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "SLIM_Block", "block_type": "FC", "inputs": { @@ -2941,7 +2941,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "Interlocking_Panel_1", "block_type": "FC", "inputs": { @@ -2963,7 +2963,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "FillerControl", "block_type": "FC", "inputs": { @@ -2985,7 +2985,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "BlenderCtrl_UpdatePWord", "block_type": "FC", "inputs": { @@ -3007,44 +3007,44 @@ { "instruction_uid": "24", "uid": "24", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gBlendResetTotalizer\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"gBlendResetTotalizer\"" + "scl": "// SymPy Contact: v36_" }, { "instruction_uid": "25", "uid": "25", - "type": "Se_scl", + "type": "Se_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "s": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "24", - "source_pin": "out" - }, "timer": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"mResetTotalizerTmr\"" }, + "s": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "24", + "source_pin": "out" + }, "tv": { "uid": "22", "scope": "TypedConstant", @@ -3060,7 +3060,7 @@ } }, "outputs": {}, - "scl": "\"mResetTotalizerTmr\"(IN := \"gBlendResetTotalizer\", PT := S5T#2S); // TODO: Declarar \"mResetTotalizerTmr\" : TP; en VAR_STAT o VAR" + "scl": "\"mResetTotalizerTmr\"(IN := \"gBlendResetTotalizer\", PT := S5T#2S); // TODO: Declarar \"mResetTotalizerTmr\" : TP;" } ], "language": "LAD" @@ -3073,51 +3073,51 @@ { "instruction_uid": "26", "uid": "26", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gFTN301_ResetTot\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"gFTN301_ResetTot\"" + "scl": "// SymPy Contact: v37_" }, { "instruction_uid": "27", "uid": "27", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"mResetTotalizerTmr\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"mResetTotalizerTmr\"" + "scl": "// SymPy Contact: v38_" }, { "instruction_uid": "28", "uid": "28", - "type": "O_scl", + "type": "O_sympy_processed", "template_values": { "Card": "Cardinality" }, @@ -3139,27 +3139,27 @@ "outputs": { "out": [] }, - "scl": "// Logic O 28: \"gFTN301_ResetTot\" OR \"mResetTotalizerTmr\"" + "scl": "// SymPy O: v37_ | v38_" }, { "instruction_uid": "29", "uid": "29", - "type": "Se_scl", + "type": "Se_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "s": { - "type": "connection", - "source_instruction_type": "O", - "source_instruction_uid": "28", - "source_pin": "out" - }, "timer": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"mResetFTN301TotTmr\"" }, + "s": { + "type": "connection", + "source_instruction_type": "O", + "source_instruction_uid": "28", + "source_pin": "out" + }, "tv": { "uid": "24", "scope": "TypedConstant", @@ -3177,26 +3177,26 @@ "outputs": { "q": [] }, - "scl": "\"mResetFTN301TotTmr\"(IN := \"gFTN301_ResetTot\" OR \"mResetTotalizerTmr\", PT := S5T#2S); // TODO: Declarar \"mResetFTN301TotTmr\" : TP; en VAR_STAT o VAR" + "scl": "\"mResetFTN301TotTmr\"(IN := \"gFTN301_ResetTot\" OR \"mResetTotalizerTmr\", PT := S5T#2S); // TODO: Declarar \"mResetFTN301TotTmr\" : TP;" }, { "instruction_uid": "30", "uid": "30", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Se", - "source_instruction_uid": "29", - "source_pin": "q" - }, "operand": { "uid": "25", "scope": "LocalVariable", "type": "variable", "name": "\"mResetWaterTot\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Se", + "source_instruction_uid": "29", + "source_pin": "q" } }, "outputs": {}, @@ -3213,43 +3213,43 @@ { "instruction_uid": "23", "uid": "23", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gFTN301_ResetTot\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"gFTN301_ResetTot\"" + "scl": "// SymPy Contact: v37_" }, { "instruction_uid": "24", "uid": "24", - "type": "RCoil_scl", + "type": "RCoil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "23", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"gFTN301_ResetTot\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "23", + "source_pin": "out" } }, "outputs": {}, @@ -3266,51 +3266,51 @@ { "instruction_uid": "27", "uid": "27", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gFTP302_ResetTot\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"gFTP302_ResetTot\"" + "scl": "// SymPy Contact: v39_" }, { "instruction_uid": "28", "uid": "28", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"mResetTotalizerTmr\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"mResetTotalizerTmr\"" + "scl": "// SymPy Contact: v38_" }, { "instruction_uid": "29", "uid": "29", - "type": "O_scl", + "type": "O_sympy_processed", "template_values": { "Card": "Cardinality" }, @@ -3332,27 +3332,27 @@ "outputs": { "out": [] }, - "scl": "// Logic O 29: \"gFTP302_ResetTot\" OR \"mResetTotalizerTmr\"" + "scl": "// SymPy O: v38_ | v39_" }, { "instruction_uid": "30", "uid": "30", - "type": "Se_scl", + "type": "Se_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "s": { - "type": "connection", - "source_instruction_type": "O", - "source_instruction_uid": "29", - "source_pin": "out" - }, "timer": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"mResetFTP302TotTmr\"" }, + "s": { + "type": "connection", + "source_instruction_type": "O", + "source_instruction_uid": "29", + "source_pin": "out" + }, "tv": { "uid": "24", "scope": "TypedConstant", @@ -3370,55 +3370,55 @@ "outputs": { "q": [] }, - "scl": "\"mResetFTP302TotTmr\"(IN := \"gFTP302_ResetTot\" OR \"mResetTotalizerTmr\", PT := S5T#2S); // TODO: Declarar \"mResetFTP302TotTmr\" : TP; en VAR_STAT o VAR" + "scl": "\"mResetFTP302TotTmr\"(IN := \"mResetTotalizerTmr\" OR \"gFTP302_ResetTot\", PT := S5T#2S); // TODO: Declarar \"mResetFTP302TotTmr\" : TP;" }, { "instruction_uid": "31", "uid": "31", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Se", - "source_instruction_uid": "30", - "source_pin": "q" - }, "operand": { "uid": "25", "scope": "GlobalVariable", "type": "variable", "name": "\"gSyrupRoomEn\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Se", + "source_instruction_uid": "30", + "source_pin": "q" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"mResetFTP302TotTmr\".Q AND \"gSyrupRoomEn\"" + "scl": "// SymPy Contact: v17_ & v61_" }, { "instruction_uid": "32", "uid": "32", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "31", - "source_pin": "out" - }, "operand": { "uid": "26", "scope": "LocalVariable", "type": "variable", "name": "\"mResetSyrupTot\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "31", + "source_pin": "out" } }, "outputs": {}, - "scl": "\"mResetSyrupTot\" := \"mResetFTP302TotTmr\".Q AND \"gSyrupRoomEn\";" + "scl": "\"mResetSyrupTot\" := \"gSyrupRoomEn\" AND \"mResetFTP302TotTmr\".Q;" } ], "language": "LAD" @@ -3431,43 +3431,43 @@ { "instruction_uid": "23", "uid": "23", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gFTP302_ResetTot\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"gFTP302_ResetTot\"" + "scl": "// SymPy Contact: v39_" }, { "instruction_uid": "24", "uid": "24", - "type": "RCoil_scl", + "type": "RCoil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "23", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"gFTP302_ResetTot\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "23", + "source_pin": "out" } }, "outputs": {}, @@ -3484,51 +3484,51 @@ { "instruction_uid": "26", "uid": "26", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gFTM303_ResetTot\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"gFTM303_ResetTot\"" + "scl": "// SymPy Contact: v40_" }, { "instruction_uid": "27", "uid": "27", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"mResetTotalizerTmr\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"mResetTotalizerTmr\"" + "scl": "// SymPy Contact: v38_" }, { "instruction_uid": "28", "uid": "28", - "type": "O_scl", + "type": "O_sympy_processed", "template_values": { "Card": "Cardinality" }, @@ -3550,27 +3550,27 @@ "outputs": { "out": [] }, - "scl": "// Logic O 28: \"gFTM303_ResetTot\" OR \"mResetTotalizerTmr\"" + "scl": "// SymPy O: v38_ | v40_" }, { "instruction_uid": "29", "uid": "29", - "type": "Se_scl", + "type": "Se_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "s": { - "type": "connection", - "source_instruction_type": "O", - "source_instruction_uid": "28", - "source_pin": "out" - }, "timer": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"mResetFTM303TotTmr\"" }, + "s": { + "type": "connection", + "source_instruction_type": "O", + "source_instruction_uid": "28", + "source_pin": "out" + }, "tv": { "uid": "24", "scope": "TypedConstant", @@ -3588,26 +3588,26 @@ "outputs": { "q": [] }, - "scl": "\"mResetFTM303TotTmr\"(IN := \"gFTM303_ResetTot\" OR \"mResetTotalizerTmr\", PT := S5T#2S); // TODO: Declarar \"mResetFTM303TotTmr\" : TP; en VAR_STAT o VAR" + "scl": "\"mResetFTM303TotTmr\"(IN := \"mResetTotalizerTmr\" OR \"gFTM303_ResetTot\", PT := S5T#2S); // TODO: Declarar \"mResetFTM303TotTmr\" : TP;" }, { "instruction_uid": "30", "uid": "30", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Se", - "source_instruction_uid": "29", - "source_pin": "q" - }, "operand": { "uid": "25", "scope": "LocalVariable", "type": "variable", "name": "\"mResetCO2Tot\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Se", + "source_instruction_uid": "29", + "source_pin": "q" } }, "outputs": {}, @@ -3624,43 +3624,43 @@ { "instruction_uid": "23", "uid": "23", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gFTM303_ResetTot\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"gFTM303_ResetTot\"" + "scl": "// SymPy Contact: v40_" }, { "instruction_uid": "24", "uid": "24", - "type": "RCoil_scl", + "type": "RCoil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "23", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"gFTM303_ResetTot\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "23", + "source_pin": "out" } }, "outputs": {}, @@ -3677,51 +3677,51 @@ { "instruction_uid": "26", "uid": "26", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gProductMFMResetTot\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"gProductMFMResetTot\"" + "scl": "// SymPy Contact: v41_" }, { "instruction_uid": "27", "uid": "27", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"mResetTotalizerTmr\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"mResetTotalizerTmr\"" + "scl": "// SymPy Contact: v38_" }, { "instruction_uid": "28", "uid": "28", - "type": "O_scl", + "type": "O_sympy_processed", "template_values": { "Card": "Cardinality" }, @@ -3743,27 +3743,27 @@ "outputs": { "out": [] }, - "scl": "// Logic O 28: \"gProductMFMResetTot\" OR \"mResetTotalizerTmr\"" + "scl": "// SymPy O: v38_ | v41_" }, { "instruction_uid": "29", "uid": "29", - "type": "Se_scl", + "type": "Se_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "s": { - "type": "connection", - "source_instruction_type": "O", - "source_instruction_uid": "28", - "source_pin": "out" - }, "timer": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"mResetProductTotTmr\"" }, + "s": { + "type": "connection", + "source_instruction_type": "O", + "source_instruction_uid": "28", + "source_pin": "out" + }, "tv": { "uid": "24", "scope": "TypedConstant", @@ -3781,26 +3781,26 @@ "outputs": { "q": [] }, - "scl": "\"mResetProductTotTmr\"(IN := \"gProductMFMResetTot\" OR \"mResetTotalizerTmr\", PT := S5T#2S); // TODO: Declarar \"mResetProductTotTmr\" : TP; en VAR_STAT o VAR" + "scl": "\"mResetProductTotTmr\"(IN := \"mResetTotalizerTmr\" OR \"gProductMFMResetTot\", PT := S5T#2S); // TODO: Declarar \"mResetProductTotTmr\" : TP;" }, { "instruction_uid": "30", "uid": "30", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Se", - "source_instruction_uid": "29", - "source_pin": "q" - }, "operand": { "uid": "25", "scope": "LocalVariable", "type": "variable", "name": "\"mResetProductTot\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Se", + "source_instruction_uid": "29", + "source_pin": "q" } }, "outputs": {}, @@ -3817,43 +3817,43 @@ { "instruction_uid": "23", "uid": "23", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gProductMFMResetTot\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"gProductMFMResetTot\"" + "scl": "// SymPy Contact: v41_" }, { "instruction_uid": "24", "uid": "24", - "type": "RCoil_scl", + "type": "RCoil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "23", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"gProductMFMResetTot\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "23", + "source_pin": "out" } }, "outputs": {}, @@ -3870,43 +3870,43 @@ { "instruction_uid": "23", "uid": "23", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"gBlendResetTotalizer\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"gBlendResetTotalizer\"" + "scl": "// SymPy Contact: v36_" }, { "instruction_uid": "24", "uid": "24", - "type": "RCoil_scl", + "type": "RCoil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "23", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"gBlendResetTotalizer\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "23", + "source_pin": "out" } }, "outputs": {}, @@ -3923,31 +3923,31 @@ { "instruction_uid": "26", "uid": "26", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": { "operand": true }, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_Simulation\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: (NOT \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_Simulation\")" + "scl": "// SymPy Contact: ~v42_" }, { "instruction_uid": "27", "uid": "27", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "BlenderCtrl_MFM Command", "block_type": "FC", "inputs": { @@ -3959,7 +3959,7 @@ } }, "outputs": {}, - "scl": "IF (NOT \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_Simulation\") THEN\n BlenderCtrl_MFM_Command();\nEND_IF;" + "scl": "IF NOT \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_Simulation\" THEN\n BlenderCtrl_MFM_Command();\nEND_IF;" } ], "language": "LAD" @@ -3972,7 +3972,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "CPU_DP Global Diag", "block_type": "FC", "inputs": { @@ -3994,7 +3994,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "Profibus Network", "block_type": "FC", "inputs": { @@ -4016,7 +4016,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "ModValveFault", "block_type": "FC", "inputs": { @@ -4038,80 +4038,80 @@ { "instruction_uid": "25", "uid": "25", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Cmd\".\"Commands_From_HMI\".\"F7_DeviceControl\".\"Command\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"HMI_Variables_Cmd\".\"Commands_From_HMI\".\"F7_DeviceControl\".\"Command\"" + "scl": "// SymPy Contact: v43_" }, { "instruction_uid": "26", "uid": "26", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "25", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Cmd\".\"Commands_From_HMI\".\"F7_DeviceControl\".\"Enable\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "25", + "source_pin": "out" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"HMI_Variables_Cmd\".\"Commands_From_HMI\".\"F7_DeviceControl\".\"Command\" AND \"HMI_Variables_Cmd\".\"Commands_From_HMI\".\"F7_DeviceControl\".\"Enable\"" + "scl": "// SymPy Contact: v43_ & v44_" }, { "instruction_uid": "27", "uid": "27", - "type": "NBox_scl", + "type": "NBox_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "26", - "source_pin": "out" - }, "bit": { "uid": "23", "scope": "GlobalVariable", "type": "variable", "name": "\"M19011\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "26", + "source_pin": "out" } }, "outputs": { "out": [] }, - "_edge_mem_update_scl": "\"M19011\" := (\"HMI_Variables_Cmd\".\"Commands_From_HMI\".\"F7_DeviceControl\".\"Command\" AND \"HMI_Variables_Cmd\".\"Commands_From_HMI\".\"F7_DeviceControl\".\"Enable\"); // N_TRIG((\"HMI_Variables_Cmd\".\"Commands_From_HMI\".\"F7_DeviceControl\".\"Command\" AND \"HMI_Variables_Cmd\".\"Commands_From_HMI\".\"F7_DeviceControl\".\"Enable\"))", - "scl": "// NBox Logic moved to consumer Coil" + "_edge_mem_update_scl": "\"M19011\" := \"HMI_Variables_Cmd\".\"Commands_From_HMI\".\"F7_DeviceControl\".\"Command\" AND \"HMI_Variables_Cmd\".\"Commands_From_HMI\".\"F7_DeviceControl\".\"Enable\"; // N_TRIG(\"HMI_Variables_Cmd\".\"Commands_From_HMI\".\"F7_DeviceControl\".\"Command\" AND \"HMI_Variables_Cmd\".\"Commands_From_HMI\".\"F7_DeviceControl\".\"Enable\") - Mem: \"M19011\"", + "scl": "// NBox SymPy processed, logic in consumer" }, { "instruction_uid": "28", "uid": "28", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "BlenderCtrl_All Auto", "block_type": "FC", "inputs": { @@ -4123,26 +4123,26 @@ } }, "outputs": {}, - "scl": "IF NOT (\"HMI_Variables_Cmd\".\"Commands_From_HMI\".\"F7_DeviceControl\".\"Command\" AND \"HMI_Variables_Cmd\".\"Commands_From_HMI\".\"F7_DeviceControl\".\"Enable\") AND \"M19011\" THEN\n BlenderCtrl_All_Auto();\nEND_IF;" + "scl": "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\n BlenderCtrl_All_Auto();\nEND_IF;" }, { "instruction_uid": "29", "uid": "29", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "26", - "source_pin": "out" - }, "operand": { "uid": "24", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Cmd\".\"Commands_From_HMI\".\"F7_DeviceControl\".\"Light\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "26", + "source_pin": "out" } }, "outputs": {}, @@ -4159,7 +4159,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "BlenderCtrl_ManualActive", "block_type": "FC", "inputs": { @@ -4181,93 +4181,93 @@ { "instruction_uid": "33", "uid": "33", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Cmd\".\"Recipe\".\"Main_Page\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"HMI_Variables_Cmd\".\"Recipe\".\"Main_Page\"" + "scl": "// SymPy Contact: v45_" }, { "instruction_uid": "34", "uid": "34", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": { "operand": true }, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "33", - "source_pin": "out" - }, "operand": { "uid": "22", "scope": "GlobalVariable", "type": "variable", "name": "\"mFP_Recip_Main_Page\"" - } - }, - "outputs": { - "out": [] - }, - "scl": "// RLO: \"HMI_Variables_Cmd\".\"Recipe\".\"Main_Page\" AND (NOT \"mFP_Recip_Main_Page\")" - }, - { - "instruction_uid": "35", - "uid": "35", - "type": "Coil_scl", - "template_values": {}, - "negated_pins": {}, - "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "34", - "source_pin": "out" }, - "operand": { - "uid": "23", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"mAux_FP_M700_1\"" - } - }, - "outputs": {}, - "scl": "\"mAux_FP_M700_1\" := \"HMI_Variables_Cmd\".\"Recipe\".\"Main_Page\" AND (NOT \"mFP_Recip_Main_Page\");" - }, - { - "instruction_uid": "36", - "uid": "36", - "type": "Coil_scl", - "template_values": {}, - "negated_pins": {}, - "inputs": { "in": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "33", "source_pin": "out" + } + }, + "outputs": { + "out": [] + }, + "scl": "// SymPy Contact: v45_ & ~v46_" + }, + { + "instruction_uid": "35", + "uid": "35", + "type": "Coil_sympy_processed", + "template_values": {}, + "negated_pins": {}, + "inputs": { + "operand": { + "uid": "23", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"mAux_FP_M700_1\"" }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "34", + "source_pin": "out" + } + }, + "outputs": {}, + "scl": "\"mAux_FP_M700_1\" := \"HMI_Variables_Cmd\".\"Recipe\".\"Main_Page\" AND NOT \"mFP_Recip_Main_Page\";" + }, + { + "instruction_uid": "36", + "uid": "36", + "type": "Coil_sympy_processed", + "template_values": {}, + "negated_pins": {}, + "inputs": { "operand": { "uid": "24", "scope": "GlobalVariable", "type": "variable", "name": "\"mFP_Recip_Main_Page\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "33", + "source_pin": "out" } }, "outputs": {}, @@ -4276,69 +4276,69 @@ { "instruction_uid": "37", "uid": "37", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "25", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Cmd\".\"Recipe\".\"Main_Page\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"HMI_Variables_Cmd\".\"Recipe\".\"Main_Page\"" + "scl": "// SymPy Contact: v45_" }, { "instruction_uid": "38", "uid": "38", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "37", - "source_pin": "out" - }, "operand": { "uid": "26", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Cmd\".\"Recipe\".\"Edit\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "37", + "source_pin": "out" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"HMI_Variables_Cmd\".\"Recipe\".\"Main_Page\" AND \"HMI_Variables_Cmd\".\"Recipe\".\"Edit\"" + "scl": "// SymPy Contact: v45_ & v47_" }, { "instruction_uid": "39", "uid": "39", - "type": "Se_scl", + "type": "Se_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "s": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "38", - "source_pin": "out" - }, "timer": { "uid": "27", "scope": "GlobalVariable", "type": "variable", "name": "\"T_Pulse_Recipe_Edit\"" }, + "s": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "38", + "source_pin": "out" + }, "tv": { "uid": "28", "scope": "TypedConstant", @@ -4356,96 +4356,96 @@ "outputs": { "q": [] }, - "scl": "\"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; en VAR_STAT o VAR" + "scl": "\"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;" }, { "instruction_uid": "40", "uid": "40", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "SdCoil", - "source_instruction_uid": "39", - "source_pin": "q" - }, "operand": { "uid": "29", "scope": "GlobalVariable", "type": "variable", "name": "\"T_Pulse_Recipe_Edit\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "SdCoil", + "source_instruction_uid": "39", + "source_pin": "q" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"T_Pulse_Recipe_Edit\".Q AND \"T_Pulse_Recipe_Edit\"" + "scl": "// SymPy Contact: v48_ & v64_" }, { "instruction_uid": "41", "uid": "41", - "type": "RCoil_scl", + "type": "RCoil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "40", - "source_pin": "out" - }, "operand": { "uid": "30", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Cmd\".\"Recipe\".\"Edit\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "40", + "source_pin": "out" } }, "outputs": {}, - "scl": "IF \"T_Pulse_Recipe_Edit\".Q AND \"T_Pulse_Recipe_Edit\" THEN\n \"HMI_Variables_Cmd\".\"Recipe\".\"Edit\" := FALSE;\nEND_IF;" + "scl": "IF \"T_Pulse_Recipe_Edit\" AND \"T_Pulse_Recipe_Edit\".Q THEN\n \"HMI_Variables_Cmd\".\"Recipe\".\"Edit\" := FALSE;\nEND_IF;" }, { "instruction_uid": "42", "uid": "42", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "31", "scope": "GlobalVariable", "type": "variable", "name": "\"mAux_FP_M700_1\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"mAux_FP_M700_1\"" + "scl": "// SymPy Contact: v49_" }, { "instruction_uid": "43", "uid": "43", - "type": "SCoil_scl", + "type": "SCoil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "42", - "source_pin": "out" - }, "operand": { "uid": "32", "scope": "GlobalVariable", "type": "variable", "name": "\"HMI_Variables_Cmd\".\"Recipe\".\"Edit\"" + }, + "in": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "42", + "source_pin": "out" } }, "outputs": {}, @@ -4462,29 +4462,29 @@ { "instruction_uid": "42", "uid": "42", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "in": { - "type": "powerrail" - }, "operand": { "uid": "21", "scope": "GlobalVariable", "type": "variable", "name": "\"AUX TRUE\"" + }, + "in": { + "type": "powerrail" } }, "outputs": { "out": [] }, - "scl": "// RLO: \"AUX TRUE\"" + "scl": "// SymPy Contact: v50_" }, { "instruction_uid": "43", "uid": "43", - "type": "Call_FB_scl", + "type": "Call_FB_sympy_processed", "block_name": "RecipeManagement - Prod", "block_type": "FB", "instance_db": "\"RecipeManagement_Data\"", @@ -4511,7 +4511,7 @@ { "instruction_uid": "21", "uid": "21", - "type": "Call_FC_scl", + "type": "Call_FC_sympy_processed", "block_name": "RecipeCalculation", "block_type": "FC", "inputs": { diff --git a/BlenderCtrl__Main_simplified_processed.scl b/BlenderCtrl__Main_simplified_processed.scl index 1cf79be..cf43236 100644 --- a/BlenderCtrl__Main_simplified_processed.scl +++ b/BlenderCtrl__Main_simplified_processed.scl @@ -6,13 +6,8 @@ FUNCTION_BLOCK "BlenderCtrl__Main" { S7_Optimized_Access := 'TRUE' } VERSION : 0.1 -VAR_INPUT -END_VAR - -VAR_OUTPUT -END_VAR - -VAR_IN_OUT +VAR_RETURN + Ret_Val : Void; END_VAR VAR_TEMP @@ -43,13 +38,12 @@ BEGIN // Network 4: Emergency Pressed (Original Language: LAD) - // Logic moved to Coil 26 - "gEmergencyPressed" := NOT "gIN_VoltageOk" AND "M19000"; - "M19000" := "gIN_VoltageOk"; // N_TRIG("gIN_VoltageOk") + "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_LinePressCO2Ok" OR ("gWorkshopTest" AND (NOT "gWorkshop_Co2_Presence")) AND (NOT "gWorkshop_CIP_Signals")) AND "HMI_Digital"."_PAL_S11"."Filtered") OR ("gIN_LinePressCO2Ok" OR ("gWorkshopTest" AND (NOT "gWorkshop_Co2_Presence")) AND (NOT "gWorkshop_CIP_Signals")) AND (NOT "Disable_Bit") AND "gIN_VoltageOk"; + "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) @@ -57,7 +51,7 @@ BEGIN // Network 7: Delay Power On (Original Language: LAD) - "mDelayPowerOnTmr"(IN := "FirstScan", PT := S5T#2S); // TODO: Declarar "mDelayPowerOnTmr" : TP; en VAR_STAT o VAR + "mDelayPowerOnTmr"(IN := "FirstScan", PT := S5T#2S); // TODO: Declarar "mDelayPowerOnTmr" : TP; // Network 8: Production Mode (Original Language: LAD) @@ -65,56 +59,56 @@ BEGIN // 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 + "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 + IF NOT "AUX FALSE" THEN "HMI_Variables_Status"."Meters"."QTM3012_PRD_Fault" := FALSE; END_IF; - IF (NOT "AUX FALSE") THEN + IF NOT "AUX FALSE" THEN "gmPDS2000_Error_Fault" := FALSE; END_IF; - IF (NOT "AUX FALSE") THEN + IF NOT "AUX FALSE" THEN "HMI_Variables_Status"."Meters"."QTM3012_PRD_Run" := FALSE; END_IF; - IF (NOT "AUX FALSE") THEN + 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"); + "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" OR ("HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_ByPassDeair" AND (NOT "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_Deaireation"))) AND "Blender_Variables_Pers"."gWaterRecipe") AND (NOT "Blender_Variables_Pers"."gCarboStillRecipe"); + "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"."_BlendFillSystem" AND "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_StillWaterByPass") AND "Blender_Variables_Pers"."gWaterRecipe") AND (NOT "Blender_Variables_Pers"."gCarboStillRecipe"); + "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 (NOT "gIN_HVP301_Aux")) AND (NOT "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_FastChangeOverEnabled") AND "Procedure_Variables"."FTP302Line_Preparation"."Done") AND (NOT "Procedure_Variables"."Syr_RunOut"."Done") OR (((("gSyrupRoomEn" AND (NOT "gIN_HVP301_Aux")) AND "gBlenderCIPMode") AND "gIN_CIP_CIPRunning") AND "Procedure_Variables"."Blender_Run"."Running"); + "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; en VAR_STAT o VAR + "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 "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_MeterType" = 6 THEN + 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 "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_MeterType" = 5 THEN + IF Eq("HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_MeterType", 5) THEN mPDS_PA_Control(); END_IF; @@ -129,7 +123,7 @@ BEGIN // CALL "GetProdBrixCO2_FromAn" // NOP 0 - IF "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_MeterType" = 3 THEN + IF Eq("HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_MeterType", 3) THEN GetProdBrixCO2_Anal_Inpt(); END_IF; @@ -157,24 +151,21 @@ BEGIN // Network 25: Production ONS (Original Language: LAD) - // PBox Logic moved to consumer Coil - "gProductionONS" := ("gBlenderProdMode" AND NOT "M19001") AND (NOT "mDelayPowerOnTmr"); + "gProductionONS" := "gBlenderProdMode" AND NOT "mDelayPowerOnTmr" AND NOT "M19001"; // Network 26: Blender Prod Mode Init (Original Language: LAD) - IF ("gProductionONS" OR "Procedure_Variables"."Blender_Rinse"."ONS_Done") AND (NOT "Blender_Variables_Pers"."gBlenderStarted") THEN + 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) - // PBox Logic moved to consumer Coil - "gRinseONS" := ("HMI_Variables_Status"."System"."Blender_Prod_CIP" AND NOT "M19002") AND (NOT "mDelayPowerOnTmr"); + "gRinseONS" := "HMI_Variables_Status"."System"."Blender_Prod_CIP" AND NOT "mDelayPowerOnTmr" AND NOT "M19002"; // Network 28: CIP ONS (Original Language: LAD) - // PBox Logic moved to consumer Coil - "gCIPONS" := ("gBlenderCIPMode" AND NOT "M19003") AND (NOT "mDelayPowerOnTmr"); + "gCIPONS" := "gBlenderCIPMode" AND NOT "mDelayPowerOnTmr" AND NOT "M19003"; // Network 29: CIp Mode Init (Original Language: LAD) @@ -228,7 +219,7 @@ BEGIN // Network 41: Blend Procedure Data (Original Language: LAD) - IF (NOT "mDelayPowerOnTmr") THEN + IF NOT "mDelayPowerOnTmr" THEN "Blender_Procedure Data"(); END_IF; @@ -268,11 +259,11 @@ BEGIN // Network 50: ResetTotalizer (Original Language: LAD) - "mResetTotalizerTmr"(IN := "gBlendResetTotalizer", PT := S5T#2S); // TODO: Declarar "mResetTotalizerTmr" : TP; en VAR_STAT o VAR + "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; en VAR_STAT o VAR + "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) @@ -283,8 +274,8 @@ BEGIN // Network 53: ResetCO2Tot (Original Language: LAD) - "mResetFTP302TotTmr"(IN := "gFTP302_ResetTot" OR "mResetTotalizerTmr", PT := S5T#2S); // TODO: Declarar "mResetFTP302TotTmr" : TP; en VAR_STAT o VAR - "mResetSyrupTot" := "mResetFTP302TotTmr".Q AND "gSyrupRoomEn"; + "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) @@ -294,7 +285,7 @@ BEGIN // Network 55: ResetProductTot (Original Language: LAD) - "mResetFTM303TotTmr"(IN := "gFTM303_ResetTot" OR "mResetTotalizerTmr", PT := S5T#2S); // TODO: Declarar "mResetFTM303TotTmr" : TP; en VAR_STAT o VAR + "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) @@ -305,7 +296,7 @@ BEGIN // Network 57: ResetCO2Tot (Original Language: LAD) - "mResetProductTotTmr"(IN := "gProductMFMResetTot" OR "mResetTotalizerTmr", PT := S5T#2S); // TODO: Declarar "mResetProductTotTmr" : TP; en VAR_STAT o VAR + "mResetProductTotTmr"(IN := "mResetTotalizerTmr" OR "gProductMFMResetTot", PT := S5T#2S); // TODO: Declarar "mResetProductTotTmr" : TP; "mResetProductTot" := "mResetProductTotTmr".Q; // Network 58: Reset Totalizer (Original Language: LAD) @@ -322,7 +313,7 @@ BEGIN // Network 60: Blender Ctrl Command (Original Language: LAD) - IF (NOT "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_Simulation") THEN + IF NOT "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_Simulation" THEN BlenderCtrl_MFM_Command(); END_IF; @@ -340,8 +331,7 @@ BEGIN // Network 64: All Auto (Original Language: LAD) - // NBox Logic moved to consumer Coil - IF NOT ("HMI_Variables_Cmd"."Commands_From_HMI"."F7_DeviceControl"."Command" AND "HMI_Variables_Cmd"."Commands_From_HMI"."F7_DeviceControl"."Enable") AND "M19011" THEN + 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"; @@ -352,10 +342,10 @@ BEGIN // Network 66: Mod Copy Recipe (Original Language: LAD) - "mAux_FP_M700_1" := "HMI_Variables_Cmd"."Recipe"."Main_Page" AND (NOT "mFP_Recip_Main_Page"); + "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; en VAR_STAT o VAR - IF "T_Pulse_Recipe_Edit".Q AND "T_Pulse_Recipe_Edit" THEN + "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 diff --git a/TestLAD_simplified.json b/TestLAD_simplified.json index b963520..41de9f8 100644 --- a/TestLAD_simplified.json +++ b/TestLAD_simplified.json @@ -251,17 +251,17 @@ }, "negated_pins": {}, "inputs": { - "in2": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "37", - "source_pin": "out" - }, "in1": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "34", "source_pin": "out" + }, + "in2": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "37", + "source_pin": "out" } }, "outputs": { @@ -326,18 +326,18 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "timer": { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"mHVM302_Dly\"" - }, "s": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "25", "source_pin": "out" }, + "timer": { + "uid": "22", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"mHVM302_Dly\"" + }, "tv": { "uid": "23", "scope": "TypedConstant", @@ -414,18 +414,18 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "timer": { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"mResetTotalizerTmr\"" - }, "s": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "24", "source_pin": "out" }, + "timer": { + "uid": "22", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"mResetTotalizerTmr\"" + }, "tv": { "uid": "23", "scope": "TypedConstant", @@ -501,17 +501,17 @@ }, "negated_pins": {}, "inputs": { - "in2": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "27", - "source_pin": "out" - }, "in1": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "26", "source_pin": "out" + }, + "in2": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "27", + "source_pin": "out" } }, "outputs": { @@ -525,18 +525,18 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "timer": { - "uid": "23", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"mResetFTN301TotTmr\"" - }, "s": { "type": "connection", "source_instruction_type": "O", "source_instruction_uid": "28", "source_pin": "out" }, + "timer": { + "uid": "23", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"mResetFTN301TotTmr\"" + }, "tv": { "uid": "24", "scope": "TypedConstant", @@ -636,17 +636,17 @@ }, "negated_pins": {}, "inputs": { - "in2": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "28", - "source_pin": "out" - }, "in1": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "27", "source_pin": "out" + }, + "in2": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "28", + "source_pin": "out" } }, "outputs": { @@ -660,18 +660,18 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "timer": { - "uid": "23", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"mResetFTP302TotTmr\"" - }, "s": { "type": "connection", "source_instruction_type": "O", "source_instruction_uid": "29", "source_pin": "out" }, + "timer": { + "uid": "23", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"mResetFTP302TotTmr\"" + }, "tv": { "uid": "24", "scope": "TypedConstant", @@ -795,17 +795,17 @@ }, "negated_pins": {}, "inputs": { - "in2": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "27", - "source_pin": "out" - }, "in1": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "26", "source_pin": "out" + }, + "in2": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "27", + "source_pin": "out" } }, "outputs": { @@ -819,18 +819,18 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "timer": { - "uid": "23", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"mResetFTM303TotTmr\"" - }, "s": { "type": "connection", "source_instruction_type": "O", "source_instruction_uid": "28", "source_pin": "out" }, + "timer": { + "uid": "23", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"mResetFTM303TotTmr\"" + }, "tv": { "uid": "24", "scope": "TypedConstant", @@ -930,17 +930,17 @@ }, "negated_pins": {}, "inputs": { - "in2": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "27", - "source_pin": "out" - }, "in1": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "26", "source_pin": "out" + }, + "in2": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "27", + "source_pin": "out" } }, "outputs": { @@ -954,18 +954,18 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "timer": { - "uid": "23", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"mResetProductTotTmr\"" - }, "s": { "type": "connection", "source_instruction_type": "O", "source_instruction_uid": "28", "source_pin": "out" }, + "timer": { + "uid": "23", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"mResetProductTotTmr\"" + }, "tv": { "uid": "24", "scope": "TypedConstant", @@ -1157,12 +1157,6 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "timer": { - "uid": "27", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"T_Pulse_Recipe_Edit\"" - }, "tv": { "uid": "28", "scope": "TypedConstant", @@ -1170,6 +1164,12 @@ "datatype": "TypedConstant", "value": "S5T#500ms" }, + "timer": { + "uid": "27", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"T_Pulse_Recipe_Edit\"" + }, "s": { "type": "connection", "source_instruction_type": "Contact", diff --git a/TestLAD_simplified_processed.json b/TestLAD_simplified_processed.json index e7f5802..449f7ff 100644 --- a/TestLAD_simplified_processed.json +++ b/TestLAD_simplified_processed.json @@ -50,7 +50,7 @@ { "instruction_uid": "30", "uid": "30", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -67,12 +67,12 @@ "outputs": { "out": [] }, - "scl": "// RLO: \"gSyrupRoomEn\"" + "scl": "// SymPy Contact: v0_" }, { "instruction_uid": "31", "uid": "31", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": { "operand": true @@ -94,12 +94,12 @@ "outputs": { "out": [] }, - "scl": "// RLO: \"gSyrupRoomEn\" AND (NOT \"gIN_HVP301_Aux\")" + "scl": "// SymPy Contact: v0_ & ~v1_" }, { "instruction_uid": "32", "uid": "32", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": { "operand": true @@ -121,12 +121,12 @@ "outputs": { "out": [] }, - "scl": "// RLO: (\"gSyrupRoomEn\" AND (NOT \"gIN_HVP301_Aux\")) AND (NOT \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_FastChangeOverEnabled\")" + "scl": "// SymPy Contact: v0_ & ~v1_ & ~v2_" }, { "instruction_uid": "33", "uid": "33", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -146,12 +146,12 @@ "outputs": { "out": [] }, - "scl": "// RLO: (\"gSyrupRoomEn\" AND (NOT \"gIN_HVP301_Aux\")) AND (NOT \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_FastChangeOverEnabled\") AND \"Procedure_Variables\".\"FTP302Line_Preparation\".\"Done\"" + "scl": "// SymPy Contact: v0_ & v3_ & ~v1_ & ~v2_" }, { "instruction_uid": "34", "uid": "34", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": { "operand": true @@ -173,12 +173,12 @@ "outputs": { "out": [] }, - "scl": "// RLO: ((\"gSyrupRoomEn\" AND (NOT \"gIN_HVP301_Aux\")) AND (NOT \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_FastChangeOverEnabled\") AND \"Procedure_Variables\".\"FTP302Line_Preparation\".\"Done\") AND (NOT \"Procedure_Variables\".\"Syr_RunOut\".\"Done\")" + "scl": "// SymPy Contact: v0_ & v3_ & ~v1_ & ~v2_ & ~v4_" }, { "instruction_uid": "35", "uid": "35", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -198,12 +198,12 @@ "outputs": { "out": [] }, - "scl": "// RLO: (\"gSyrupRoomEn\" AND (NOT \"gIN_HVP301_Aux\")) AND \"gBlenderCIPMode\"" + "scl": "// SymPy Contact: v0_ & v5_ & ~v1_" }, { "instruction_uid": "36", "uid": "36", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -223,12 +223,12 @@ "outputs": { "out": [] }, - "scl": "// RLO: ((\"gSyrupRoomEn\" AND (NOT \"gIN_HVP301_Aux\")) AND \"gBlenderCIPMode\") AND \"gIN_CIP_CIPRunning\"" + "scl": "// SymPy Contact: v0_ & v5_ & v6_ & ~v1_" }, { "instruction_uid": "37", "uid": "37", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -248,39 +248,39 @@ "outputs": { "out": [] }, - "scl": "// RLO: (((\"gSyrupRoomEn\" AND (NOT \"gIN_HVP301_Aux\")) AND \"gBlenderCIPMode\") AND \"gIN_CIP_CIPRunning\") AND \"Procedure_Variables\".\"Blender_Run\".\"Running\"" + "scl": "// SymPy Contact: v0_ & v5_ & v6_ & v7_ & ~v1_" }, { "instruction_uid": "38", "uid": "38", - "type": "O_scl", + "type": "O_sympy_processed", "template_values": { "Card": "Cardinality" }, "negated_pins": {}, "inputs": { - "in2": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "37", - "source_pin": "out" - }, "in1": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "34", "source_pin": "out" + }, + "in2": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "37", + "source_pin": "out" } }, "outputs": { "out": [] }, - "scl": "// Logic O 38: ((\"gSyrupRoomEn\" AND (NOT \"gIN_HVP301_Aux\")) AND (NOT \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_FastChangeOverEnabled\") AND \"Procedure_Variables\".\"FTP302Line_Preparation\".\"Done\") AND (NOT \"Procedure_Variables\".\"Syr_RunOut\".\"Done\") OR ((((\"gSyrupRoomEn\" AND (NOT \"gIN_HVP301_Aux\")) AND \"gBlenderCIPMode\") AND \"gIN_CIP_CIPRunning\") AND \"Procedure_Variables\".\"Blender_Run\".\"Running\")" + "scl": "// SymPy O: (v0_ & v5_ & v6_ & v7_ & ~v1_) | (v0_ & v3_ & ~v1_ & ~v2_ & ~v4_)" }, { "instruction_uid": "39", "uid": "39", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -298,7 +298,7 @@ } }, "outputs": {}, - "scl": "\"gHVP301_Open\" := ((\"gSyrupRoomEn\" AND (NOT \"gIN_HVP301_Aux\")) AND (NOT \"HMI_Blender_Parameters\".\"Processor_Options\".\"Blender_OPT\".\"_FastChangeOverEnabled\") AND \"Procedure_Variables\".\"FTP302Line_Preparation\".\"Done\") AND (NOT \"Procedure_Variables\".\"Syr_RunOut\".\"Done\") OR ((((\"gSyrupRoomEn\" AND (NOT \"gIN_HVP301_Aux\")) AND \"gBlenderCIPMode\") AND \"gIN_CIP_CIPRunning\") AND \"Procedure_Variables\".\"Blender_Run\".\"Running\");" + "scl": "\"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\");" } ], "language": "LAD" @@ -311,7 +311,7 @@ { "instruction_uid": "25", "uid": "25", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -328,27 +328,27 @@ "outputs": { "out": [] }, - "scl": "// RLO: \"gIN_HVM302_Aux\"" + "scl": "// SymPy Contact: v8_" }, { "instruction_uid": "26", "uid": "26", - "type": "Sd_scl", + "type": "Sd_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "timer": { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"mHVM302_Dly\"" - }, "s": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "25", "source_pin": "out" }, + "timer": { + "uid": "22", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"mHVM302_Dly\"" + }, "tv": { "uid": "23", "scope": "TypedConstant", @@ -366,12 +366,12 @@ "outputs": { "q": [] }, - "scl": "\"mHVM302_Dly\"(IN := \"gIN_HVM302_Aux\", PT := S5T#1S); // TODO: Declarar \"mHVM302_Dly\" : TON; en VAR_STAT o VAR" + "scl": "\"mHVM302_Dly\"(IN := \"gIN_HVM302_Aux\", PT := S5T#1S); // TODO: Declarar \"mHVM302_Dly\" : TON;" }, { "instruction_uid": "27", "uid": "27", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -402,7 +402,7 @@ { "instruction_uid": "24", "uid": "24", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -419,27 +419,27 @@ "outputs": { "out": [] }, - "scl": "// RLO: \"gBlendResetTotalizer\"" + "scl": "// SymPy Contact: v9_" }, { "instruction_uid": "25", "uid": "25", - "type": "Se_scl", + "type": "Se_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "timer": { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"mResetTotalizerTmr\"" - }, "s": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "24", "source_pin": "out" }, + "timer": { + "uid": "22", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"mResetTotalizerTmr\"" + }, "tv": { "uid": "23", "scope": "TypedConstant", @@ -455,7 +455,7 @@ } }, "outputs": {}, - "scl": "\"mResetTotalizerTmr\"(IN := \"gBlendResetTotalizer\", PT := S5T#2S); // TODO: Declarar \"mResetTotalizerTmr\" : TP; en VAR_STAT o VAR" + "scl": "\"mResetTotalizerTmr\"(IN := \"gBlendResetTotalizer\", PT := S5T#2S); // TODO: Declarar \"mResetTotalizerTmr\" : TP;" } ], "language": "LAD" @@ -468,7 +468,7 @@ { "instruction_uid": "26", "uid": "26", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -485,12 +485,12 @@ "outputs": { "out": [] }, - "scl": "// RLO: \"gFTN301_ResetTot\"" + "scl": "// SymPy Contact: v10_" }, { "instruction_uid": "27", "uid": "27", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -507,54 +507,54 @@ "outputs": { "out": [] }, - "scl": "// RLO: \"mResetTotalizerTmr\"" + "scl": "// SymPy Contact: v11_" }, { "instruction_uid": "28", "uid": "28", - "type": "O_scl", + "type": "O_sympy_processed", "template_values": { "Card": "Cardinality" }, "negated_pins": {}, "inputs": { - "in2": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "27", - "source_pin": "out" - }, "in1": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "26", "source_pin": "out" + }, + "in2": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "27", + "source_pin": "out" } }, "outputs": { "out": [] }, - "scl": "// Logic O 28: \"gFTN301_ResetTot\" OR \"mResetTotalizerTmr\"" + "scl": "// SymPy O: v10_ | v11_" }, { "instruction_uid": "29", "uid": "29", - "type": "Se_scl", + "type": "Se_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "timer": { - "uid": "23", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"mResetFTN301TotTmr\"" - }, "s": { "type": "connection", "source_instruction_type": "O", "source_instruction_uid": "28", "source_pin": "out" }, + "timer": { + "uid": "23", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"mResetFTN301TotTmr\"" + }, "tv": { "uid": "24", "scope": "TypedConstant", @@ -572,12 +572,12 @@ "outputs": { "q": [] }, - "scl": "\"mResetFTN301TotTmr\"(IN := \"gFTN301_ResetTot\" OR \"mResetTotalizerTmr\", PT := S5T#2S); // TODO: Declarar \"mResetFTN301TotTmr\" : TP; en VAR_STAT o VAR" + "scl": "\"mResetFTN301TotTmr\"(IN := \"gFTN301_ResetTot\" OR \"mResetTotalizerTmr\", PT := S5T#2S); // TODO: Declarar \"mResetFTN301TotTmr\" : TP;" }, { "instruction_uid": "30", "uid": "30", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -608,7 +608,7 @@ { "instruction_uid": "27", "uid": "27", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -625,12 +625,12 @@ "outputs": { "out": [] }, - "scl": "// RLO: \"gFTP302_ResetTot\"" + "scl": "// SymPy Contact: v12_" }, { "instruction_uid": "28", "uid": "28", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -647,54 +647,54 @@ "outputs": { "out": [] }, - "scl": "// RLO: \"mResetTotalizerTmr\"" + "scl": "// SymPy Contact: v11_" }, { "instruction_uid": "29", "uid": "29", - "type": "O_scl", + "type": "O_sympy_processed", "template_values": { "Card": "Cardinality" }, "negated_pins": {}, "inputs": { - "in2": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "28", - "source_pin": "out" - }, "in1": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "27", "source_pin": "out" + }, + "in2": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "28", + "source_pin": "out" } }, "outputs": { "out": [] }, - "scl": "// Logic O 29: \"gFTP302_ResetTot\" OR \"mResetTotalizerTmr\"" + "scl": "// SymPy O: v11_ | v12_" }, { "instruction_uid": "30", "uid": "30", - "type": "Se_scl", + "type": "Se_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "timer": { - "uid": "23", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"mResetFTP302TotTmr\"" - }, "s": { "type": "connection", "source_instruction_type": "O", "source_instruction_uid": "29", "source_pin": "out" }, + "timer": { + "uid": "23", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"mResetFTP302TotTmr\"" + }, "tv": { "uid": "24", "scope": "TypedConstant", @@ -712,12 +712,12 @@ "outputs": { "q": [] }, - "scl": "\"mResetFTP302TotTmr\"(IN := \"gFTP302_ResetTot\" OR \"mResetTotalizerTmr\", PT := S5T#2S); // TODO: Declarar \"mResetFTP302TotTmr\" : TP; en VAR_STAT o VAR" + "scl": "\"mResetFTP302TotTmr\"(IN := \"mResetTotalizerTmr\" OR \"gFTP302_ResetTot\", PT := S5T#2S); // TODO: Declarar \"mResetFTP302TotTmr\" : TP;" }, { "instruction_uid": "31", "uid": "31", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -737,12 +737,12 @@ "outputs": { "out": [] }, - "scl": "// RLO: \"mResetFTP302TotTmr\".Q AND \"gSyrupRoomEn\"" + "scl": "// SymPy Contact: v0_ & v23_" }, { "instruction_uid": "32", "uid": "32", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -760,7 +760,7 @@ } }, "outputs": {}, - "scl": "\"mResetSyrupTot\" := \"mResetFTP302TotTmr\".Q AND \"gSyrupRoomEn\";" + "scl": "\"mResetSyrupTot\" := \"gSyrupRoomEn\" AND \"mResetFTP302TotTmr\".Q;" } ], "language": "LAD" @@ -773,7 +773,7 @@ { "instruction_uid": "26", "uid": "26", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -790,12 +790,12 @@ "outputs": { "out": [] }, - "scl": "// RLO: \"gFTM303_ResetTot\"" + "scl": "// SymPy Contact: v13_" }, { "instruction_uid": "27", "uid": "27", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -812,54 +812,54 @@ "outputs": { "out": [] }, - "scl": "// RLO: \"mResetTotalizerTmr\"" + "scl": "// SymPy Contact: v11_" }, { "instruction_uid": "28", "uid": "28", - "type": "O_scl", + "type": "O_sympy_processed", "template_values": { "Card": "Cardinality" }, "negated_pins": {}, "inputs": { - "in2": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "27", - "source_pin": "out" - }, "in1": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "26", "source_pin": "out" + }, + "in2": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "27", + "source_pin": "out" } }, "outputs": { "out": [] }, - "scl": "// Logic O 28: \"gFTM303_ResetTot\" OR \"mResetTotalizerTmr\"" + "scl": "// SymPy O: v11_ | v13_" }, { "instruction_uid": "29", "uid": "29", - "type": "Se_scl", + "type": "Se_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "timer": { - "uid": "23", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"mResetFTM303TotTmr\"" - }, "s": { "type": "connection", "source_instruction_type": "O", "source_instruction_uid": "28", "source_pin": "out" }, + "timer": { + "uid": "23", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"mResetFTM303TotTmr\"" + }, "tv": { "uid": "24", "scope": "TypedConstant", @@ -877,12 +877,12 @@ "outputs": { "q": [] }, - "scl": "\"mResetFTM303TotTmr\"(IN := \"gFTM303_ResetTot\" OR \"mResetTotalizerTmr\", PT := S5T#2S); // TODO: Declarar \"mResetFTM303TotTmr\" : TP; en VAR_STAT o VAR" + "scl": "\"mResetFTM303TotTmr\"(IN := \"mResetTotalizerTmr\" OR \"gFTM303_ResetTot\", PT := S5T#2S); // TODO: Declarar \"mResetFTM303TotTmr\" : TP;" }, { "instruction_uid": "30", "uid": "30", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -913,7 +913,7 @@ { "instruction_uid": "26", "uid": "26", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -930,12 +930,12 @@ "outputs": { "out": [] }, - "scl": "// RLO: \"gProductMFMResetTot\"" + "scl": "// SymPy Contact: v14_" }, { "instruction_uid": "27", "uid": "27", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -952,54 +952,54 @@ "outputs": { "out": [] }, - "scl": "// RLO: \"mResetTotalizerTmr\"" + "scl": "// SymPy Contact: v11_" }, { "instruction_uid": "28", "uid": "28", - "type": "O_scl", + "type": "O_sympy_processed", "template_values": { "Card": "Cardinality" }, "negated_pins": {}, "inputs": { - "in2": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "27", - "source_pin": "out" - }, "in1": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "26", "source_pin": "out" + }, + "in2": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "27", + "source_pin": "out" } }, "outputs": { "out": [] }, - "scl": "// Logic O 28: \"gProductMFMResetTot\" OR \"mResetTotalizerTmr\"" + "scl": "// SymPy O: v11_ | v14_" }, { "instruction_uid": "29", "uid": "29", - "type": "Se_scl", + "type": "Se_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "timer": { - "uid": "23", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"mResetProductTotTmr\"" - }, "s": { "type": "connection", "source_instruction_type": "O", "source_instruction_uid": "28", "source_pin": "out" }, + "timer": { + "uid": "23", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"mResetProductTotTmr\"" + }, "tv": { "uid": "24", "scope": "TypedConstant", @@ -1017,12 +1017,12 @@ "outputs": { "q": [] }, - "scl": "\"mResetProductTotTmr\"(IN := \"gProductMFMResetTot\" OR \"mResetTotalizerTmr\", PT := S5T#2S); // TODO: Declarar \"mResetProductTotTmr\" : TP; en VAR_STAT o VAR" + "scl": "\"mResetProductTotTmr\"(IN := \"mResetTotalizerTmr\" OR \"gProductMFMResetTot\", PT := S5T#2S); // TODO: Declarar \"mResetProductTotTmr\" : TP;" }, { "instruction_uid": "30", "uid": "30", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -1053,7 +1053,7 @@ { "instruction_uid": "33", "uid": "33", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -1070,12 +1070,12 @@ "outputs": { "out": [] }, - "scl": "// RLO: \"HMI_Variables_Cmd\".\"Recipe\".\"Main_Page\"" + "scl": "// SymPy Contact: v15_" }, { "instruction_uid": "34", "uid": "34", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": { "operand": true @@ -1097,12 +1097,12 @@ "outputs": { "out": [] }, - "scl": "// RLO: \"HMI_Variables_Cmd\".\"Recipe\".\"Main_Page\" AND (NOT \"mFP_Recip_Main_Page\")" + "scl": "// SymPy Contact: v15_ & ~v16_" }, { "instruction_uid": "35", "uid": "35", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -1120,12 +1120,12 @@ } }, "outputs": {}, - "scl": "\"mAux_FP_M700_1\" := \"HMI_Variables_Cmd\".\"Recipe\".\"Main_Page\" AND (NOT \"mFP_Recip_Main_Page\");" + "scl": "\"mAux_FP_M700_1\" := \"HMI_Variables_Cmd\".\"Recipe\".\"Main_Page\" AND NOT \"mFP_Recip_Main_Page\";" }, { "instruction_uid": "36", "uid": "36", - "type": "Coil_scl", + "type": "Coil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -1148,7 +1148,7 @@ { "instruction_uid": "37", "uid": "37", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -1165,12 +1165,12 @@ "outputs": { "out": [] }, - "scl": "// RLO: \"HMI_Variables_Cmd\".\"Recipe\".\"Main_Page\"" + "scl": "// SymPy Contact: v15_" }, { "instruction_uid": "38", "uid": "38", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -1190,21 +1190,15 @@ "outputs": { "out": [] }, - "scl": "// RLO: \"HMI_Variables_Cmd\".\"Recipe\".\"Main_Page\" AND \"HMI_Variables_Cmd\".\"Recipe\".\"Edit\"" + "scl": "// SymPy Contact: v15_ & v17_" }, { "instruction_uid": "39", "uid": "39", - "type": "Se_scl", + "type": "Se_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { - "timer": { - "uid": "27", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"T_Pulse_Recipe_Edit\"" - }, "tv": { "uid": "28", "scope": "TypedConstant", @@ -1212,6 +1206,12 @@ "datatype": "TypedConstant", "value": "S5T#500ms" }, + "timer": { + "uid": "27", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"T_Pulse_Recipe_Edit\"" + }, "s": { "type": "connection", "source_instruction_type": "Contact", @@ -1228,12 +1228,12 @@ "outputs": { "q": [] }, - "scl": "\"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; en VAR_STAT o VAR" + "scl": "\"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;" }, { "instruction_uid": "40", "uid": "40", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -1253,12 +1253,12 @@ "outputs": { "out": [] }, - "scl": "// RLO: \"T_Pulse_Recipe_Edit\".Q AND \"T_Pulse_Recipe_Edit\"" + "scl": "// SymPy Contact: v18_ & v26_" }, { "instruction_uid": "41", "uid": "41", - "type": "RCoil_scl", + "type": "RCoil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -1276,12 +1276,12 @@ } }, "outputs": {}, - "scl": "IF \"T_Pulse_Recipe_Edit\".Q AND \"T_Pulse_Recipe_Edit\" THEN\n \"HMI_Variables_Cmd\".\"Recipe\".\"Edit\" := FALSE;\nEND_IF;" + "scl": "IF \"T_Pulse_Recipe_Edit\" AND \"T_Pulse_Recipe_Edit\".Q THEN\n \"HMI_Variables_Cmd\".\"Recipe\".\"Edit\" := FALSE;\nEND_IF;" }, { "instruction_uid": "42", "uid": "42", - "type": "Contact_scl", + "type": "Contact_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { @@ -1298,12 +1298,12 @@ "outputs": { "out": [] }, - "scl": "// RLO: \"mAux_FP_M700_1\"" + "scl": "// SymPy Contact: v19_" }, { "instruction_uid": "43", "uid": "43", - "type": "SCoil_scl", + "type": "SCoil_sympy_processed", "template_values": {}, "negated_pins": {}, "inputs": { diff --git a/TestLAD_simplified_processed.scl b/TestLAD_simplified_processed.scl index 4f05b74..9dff9d7 100644 --- a/TestLAD_simplified_processed.scl +++ b/TestLAD_simplified_processed.scl @@ -6,13 +6,8 @@ FUNCTION_BLOCK "TestLAD" { S7_Optimized_Access := 'TRUE' } VERSION : 0.1 -VAR_INPUT -END_VAR - -VAR_OUTPUT -END_VAR - -VAR_IN_OUT +VAR_RETURN + Ret_Val : Void; END_VAR VAR_TEMP @@ -29,43 +24,43 @@ BEGIN // Network 1: Manual Syrup Drain Valve Open - Operator Alarm (Original Language: LAD) - "gHVP301_Open" := (("gSyrupRoomEn" AND (NOT "gIN_HVP301_Aux")) AND (NOT "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_FastChangeOverEnabled") AND "Procedure_Variables"."FTP302Line_Preparation"."Done") AND (NOT "Procedure_Variables"."Syr_RunOut"."Done") OR (((("gSyrupRoomEn" AND (NOT "gIN_HVP301_Aux")) AND "gBlenderCIPMode") AND "gIN_CIP_CIPRunning") AND "Procedure_Variables"."Blender_Run"."Running"); + "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 2: Manual Syrup Drain Valve Open - Operator Alarm (Original Language: LAD) - "mHVM302_Dly"(IN := "gIN_HVM302_Aux", PT := S5T#1S); // TODO: Declarar "mHVM302_Dly" : TON; en VAR_STAT o VAR + "mHVM302_Dly"(IN := "gIN_HVM302_Aux", PT := S5T#1S); // TODO: Declarar "mHVM302_Dly" : TON; "gHVM302_Open" := "mHVM302_Dly".Q; // Network 3: ResetTotalizer (Original Language: LAD) - "mResetTotalizerTmr"(IN := "gBlendResetTotalizer", PT := S5T#2S); // TODO: Declarar "mResetTotalizerTmr" : TP; en VAR_STAT o VAR + "mResetTotalizerTmr"(IN := "gBlendResetTotalizer", PT := S5T#2S); // TODO: Declarar "mResetTotalizerTmr" : TP; // Network 4: ResetWaterTot (Original Language: LAD) - "mResetFTN301TotTmr"(IN := "gFTN301_ResetTot" OR "mResetTotalizerTmr", PT := S5T#2S); // TODO: Declarar "mResetFTN301TotTmr" : TP; en VAR_STAT o VAR + "mResetFTN301TotTmr"(IN := "gFTN301_ResetTot" OR "mResetTotalizerTmr", PT := S5T#2S); // TODO: Declarar "mResetFTN301TotTmr" : TP; "mResetWaterTot" := "mResetFTN301TotTmr".Q; // Network 5: ResetCO2Tot (Original Language: LAD) - "mResetFTP302TotTmr"(IN := "gFTP302_ResetTot" OR "mResetTotalizerTmr", PT := S5T#2S); // TODO: Declarar "mResetFTP302TotTmr" : TP; en VAR_STAT o VAR - "mResetSyrupTot" := "mResetFTP302TotTmr".Q AND "gSyrupRoomEn"; + "mResetFTP302TotTmr"(IN := "mResetTotalizerTmr" OR "gFTP302_ResetTot", PT := S5T#2S); // TODO: Declarar "mResetFTP302TotTmr" : TP; + "mResetSyrupTot" := "gSyrupRoomEn" AND "mResetFTP302TotTmr".Q; // Network 6: ResetProductTot (Original Language: LAD) - "mResetFTM303TotTmr"(IN := "gFTM303_ResetTot" OR "mResetTotalizerTmr", PT := S5T#2S); // TODO: Declarar "mResetFTM303TotTmr" : TP; en VAR_STAT o VAR + "mResetFTM303TotTmr"(IN := "mResetTotalizerTmr" OR "gFTM303_ResetTot", PT := S5T#2S); // TODO: Declarar "mResetFTM303TotTmr" : TP; "mResetCO2Tot" := "mResetFTM303TotTmr".Q; // Network 7: ResetCO2Tot (Original Language: LAD) - "mResetProductTotTmr"(IN := "gProductMFMResetTot" OR "mResetTotalizerTmr", PT := S5T#2S); // TODO: Declarar "mResetProductTotTmr" : TP; en VAR_STAT o VAR + "mResetProductTotTmr"(IN := "mResetTotalizerTmr" OR "gProductMFMResetTot", PT := S5T#2S); // TODO: Declarar "mResetProductTotTmr" : TP; "mResetProductTot" := "mResetProductTotTmr".Q; // Network 8: Mod Copy Recipe (Original Language: LAD) - "mAux_FP_M700_1" := "HMI_Variables_Cmd"."Recipe"."Main_Page" AND (NOT "mFP_Recip_Main_Page"); + "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; en VAR_STAT o VAR - IF "T_Pulse_Recipe_Edit".Q AND "T_Pulse_Recipe_Edit" THEN + "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 diff --git a/processors/process_add.py b/processors/process_add.py index 2bc9362..3c7fb6f 100644 --- a/processors/process_add.py +++ b/processors/process_add.py @@ -1,75 +1,87 @@ +# processors/process_add.py # -*- coding: utf-8 -*- -from .processor_utils import get_scl_representation, format_variable_name,get_target_scl_name +import sympy +import traceback +import re # Importar re si se usa para formateo +# Usar las nuevas utilidades +from .processor_utils import get_sympy_representation, sympy_expr_to_scl, get_target_scl_name, format_variable_name +from .symbol_manager import SymbolManager -# TODO: Import necessary functions from processor_utils -# Example: from .processor_utils import get_scl_representation, format_variable_name -# Or: import processors.processor_utils as utils +SCL_SUFFIX = "_sympy_processed" # Usar el nuevo sufijo -# TODO: Define constants if needed (e.g., SCL_SUFFIX) or import them -SCL_SUFFIX = "_scl" - -# --- Function code starts --- -def process_add(instruction, network_id, scl_map, access_map, data): +def process_add(instruction, network_id, sympy_map, symbol_manager: SymbolManager, data): + """Genera SCL para Add, simplificando la condición EN.""" instr_uid = instruction["instruction_uid"] - instr_type = instruction["type"] - if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + instr_type_original = instruction.get("type", "Add") + current_type = instruction.get("type","") + if current_type.endswith(SCL_SUFFIX) or "_error" in current_type: return False + # Obtener EN (SymPy), IN1, IN2 (SymPy o Constante/String) en_input = instruction["inputs"].get("en") - en_scl = ( - get_scl_representation(en_input, network_id, scl_map, access_map) - if en_input - else "TRUE" - ) in1_info = instruction["inputs"].get("in1") in2_info = instruction["inputs"].get("in2") - in1_scl = get_scl_representation(in1_info, network_id, scl_map, access_map) - in2_scl = get_scl_representation(in2_info, network_id, scl_map, access_map) + sympy_en_expr = get_sympy_representation(en_input, network_id, sympy_map, symbol_manager) if en_input else sympy.true + op1_sympy_or_const = get_sympy_representation(in1_info, network_id, sympy_map, symbol_manager) + op2_sympy_or_const = get_sympy_representation(in2_info, network_id, sympy_map, symbol_manager) - if en_scl is None or in1_scl is None or in2_scl is None: + # Obtener destino SCL + target_scl_name = get_target_scl_name(instruction, "out", network_id, default_to_temp=True) + + # Verificar dependencias + if sympy_en_expr is None or op1_sympy_or_const is None or op2_sympy_or_const is None or target_scl_name is None: + # print(f"DEBUG Add {instr_uid}: Dependency not ready") return False - target_scl = get_target_scl_name( - instruction, "out", network_id, default_to_temp=True - ) - if target_scl is None: - print(f"Error: Sin destino ADD {instr_uid}") - instruction["scl"] = f"// ERROR: Add {instr_uid} sin destino" - instruction["type"] += "_error" - return True + # Convertir operandos SymPy/Constante a SCL strings + op1_scl = sympy_expr_to_scl(op1_sympy_or_const, symbol_manager) + op2_scl = sympy_expr_to_scl(op2_sympy_or_const, symbol_manager) - # Formatear operandos si son variables - op1 = ( - format_variable_name(in1_scl) - if in1_info and in1_info.get("type") == "variable" - else in1_scl - ) - op2 = ( - format_variable_name(in2_scl) - if in2_info and in2_info.get("type") == "variable" - else in2_scl - ) + # Añadir paréntesis si contienen operadores (más seguro para SCL) + op1_scl_formatted = f"({op1_scl})" if re.search(r'[+\-*/ ]', op1_scl) else op1_scl + op2_scl_formatted = f"({op2_scl})" if re.search(r'[+\-*/ ]', op2_scl) else op2_scl - # Añadir paréntesis si es necesario - op1 = f"({op1})" if " " in op1 and not op1.startswith("(") else op1 - op2 = f"({op2})" if " " in op2 and not op2.startswith("(") else op2 + # Generar SCL Core + scl_core = f"{target_scl_name} := {op1_scl_formatted} + {op2_scl_formatted};" - scl_core = f"{target_scl} := {op1} + {op2};" - scl_final = ( - f"IF {en_scl} THEN\n {scl_core}\nEND_IF;" if en_scl != "TRUE" else scl_core - ) + # Aplicar Condición EN (Simplificando EN) + scl_final = "" + if sympy_en_expr != sympy.true: + try: + #simplified_en_expr = sympy.simplify_logic(sympy_en_expr, force=True) + simplified_en_expr = sympy.logic.boolalg.to_dnf(sympy_en_expr, simplify=True) + + except Exception as e: + print(f"Error simplifying EN for {instr_type_original} {instr_uid}: {e}") + simplified_en_expr = sympy_en_expr # Fallback + en_condition_scl = sympy_expr_to_scl(simplified_en_expr, symbol_manager) - instruction["scl"] = scl_final - instruction["type"] = instr_type + SCL_SUFFIX + # Evitar IF TRUE THEN... + if en_condition_scl == "TRUE": + scl_final = scl_core + # Evitar IF FALSE THEN... + elif en_condition_scl == "FALSE": + scl_final = f"// {instr_type_original} {instr_uid} condition simplified to FALSE." + else: + indented_core = "\n".join([f" {line}" for line in scl_core.splitlines()]) + scl_final = f"IF {en_condition_scl} THEN\n{indented_core}\nEND_IF;" + else: + scl_final = scl_core + + # Actualizar instrucción y mapa + instruction["scl"] = scl_final # SCL final generado + instruction["type"] = instr_type_original + SCL_SUFFIX + + # Propagar valor de salida (nombre SCL del destino) y ENO (expresión SymPy) map_key_out = (network_id, instr_uid, "out") - scl_map[map_key_out] = target_scl + sympy_map[map_key_out] = target_scl_name # Guardar nombre del destino (string) map_key_eno = (network_id, instr_uid, "eno") - scl_map[map_key_eno] = en_scl - return True + sympy_map[map_key_eno] = sympy_en_expr # Guardar la expresión SymPy para ENO -# --- Function code ends --- + return True # --- Processor Information Function --- def get_processor_info(): """Devuelve la información para el procesador Add.""" - return {'type_name': 'add', 'processor_func': process_add, 'priority': 4} + # Asegurar que la clave coincida con el tipo en JSON ('add') + return {'type_name': 'add', 'processor_func': process_add, 'priority': 4} \ No newline at end of file diff --git a/processors/process_blkmov.py b/processors/process_blkmov.py index d365b4a..9d9ccd7 100644 --- a/processors/process_blkmov.py +++ b/processors/process_blkmov.py @@ -1,112 +1,118 @@ +# processors/process_blkmov.py # -*- coding: utf-8 -*- -from .processor_utils import get_scl_representation, format_variable_name,get_target_scl_name +import sympy +import traceback +import re +# Usar las nuevas utilidades +from .processor_utils import get_sympy_representation, sympy_expr_to_scl, get_target_scl_name, format_variable_name +from .symbol_manager import SymbolManager, extract_plc_variable_name -# TODO: Import necessary functions from processor_utils -# Example: from .processor_utils import get_scl_representation, format_variable_name -# Or: import processors.processor_utils as utils +SCL_SUFFIX = "_sympy_processed" # Usar el nuevo sufijo -# TODO: Define constants if needed (e.g., SCL_SUFFIX) or import them -SCL_SUFFIX = "_scl" - -# --- Function code starts --- -def process_blkmov(instruction, network_id, scl_map, access_map, data): +def process_blkmov(instruction, network_id, sympy_map, symbol_manager: SymbolManager, data): """ Genera SCL usando BLKMOV directamente como nombre de función, - sin COUNT y con formato específico, según solicitud del usuario. - ADVERTENCIA: Es MUY PROBABLE que esto NO compile en TIA Portal estándar, - ya que BLKMOV no es una función SCL y MOVE_BLK requiere COUNT. + simplificando la condición EN. + ADVERTENCIA: Sintaxis BLKMOV probablemente no compile en TIA estándar. """ instr_uid = instruction["instruction_uid"] - instr_type = instruction["type"] - if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: - return False # Ya procesado o con error + instr_type_original = instruction.get("type", "BlkMov") # Asegurar que el tipo base sea correcto + current_type = instruction.get("type","") + if current_type.endswith(SCL_SUFFIX) or "_error" in current_type: + return False # --- Obtener Entradas --- en_input = instruction["inputs"].get("en") - en_scl = ( - get_scl_representation(en_input, network_id, scl_map, access_map) - if en_input - else "TRUE" - ) + # Obtener EN como expresión SymPy + sympy_en_expr = get_sympy_representation(en_input, network_id, sympy_map, symbol_manager) if en_input else sympy.true + srcblk_info = instruction["inputs"].get("SRCBLK") - # ¡IMPORTANTE! Obtenemos el nombre RAW antes de formatearlo para usarlo como pide el usuario + # Obtener nombre RAW de SRCBLK (como se hacía antes, si es necesario para BLKMOV) + # Este nombre NO pasa por SymPy, se usa directo en el string SCL final raw_srcblk_name = srcblk_info.get("name") if srcblk_info else None - # Verificar dependencias de entrada (solo necesitamos que EN esté resuelto) - if en_scl is None: - return False # Dependencia EN no lista + # Verificar dependencias (EN debe estar resuelto, SRCBLK debe tener nombre) + if sympy_en_expr is None: + # print(f"DEBUG BlkMov {instr_uid}: EN dependency not ready") + return False if raw_srcblk_name is None: print(f"Error: BLKMOV {instr_uid} sin información válida para SRCBLK.") instruction["scl"] = f"// ERROR: BLKMOV {instr_uid} sin SRCBLK válido." - instruction["type"] += "_error" + instruction["type"] = instr_type_original + "_error" return True # --- Obtener Destinos (Salidas) --- - # RET_VAL (Usamos get_target_scl_name para manejar variables temporales si es necesario) - retval_target_scl = get_target_scl_name( - instruction, "RET_VAL", network_id, default_to_temp=True - ) - if retval_target_scl is None: - print(f"Error: BLKMOV {instr_uid} sin destino claro para RET_VAL.") - instruction["scl"] = f"// ERROR: BLKMOV {instr_uid} sin destino RET_VAL" - instruction["type"] += "_error" + # RET_VAL (Obtener nombre SCL formateado) + retval_target_scl = get_target_scl_name(instruction, "RET_VAL", network_id, default_to_temp=True) + if retval_target_scl is None: # get_target_scl_name ya imprime error si falla y default_to_temp=True + instruction["scl"] = f"// ERROR: BLKMOV {instr_uid} no pudo generar destino RET_VAL" + instruction["type"] = instr_type_original + "_error" return True - # DSTBLK (Obtenemos el nombre RAW para usarlo como pide el usuario) + # DSTBLK (Obtener nombre RAW como antes, si se necesita) raw_dstblk_name = None dstblk_output_list = instruction.get("outputs", {}).get("DSTBLK", []) if dstblk_output_list and isinstance(dstblk_output_list, list) and len(dstblk_output_list) == 1: dest_access = dstblk_output_list[0] if dest_access.get("type") == "variable": - raw_dstblk_name = dest_access.get("name") # Nombre raw del JSON - else: - print(f"Advertencia: Destino DSTBLK de BLKMOV {instr_uid} no es una variable (Tipo: {dest_access.get('type')}).") - else: - print(f"Error: No se encontró un destino único y válido para DSTBLK en BLKMOV {instr_uid}.") - + raw_dstblk_name = dest_access.get("name") + # Manejar error si no se encuentra DSTBLK if raw_dstblk_name is None: + print(f"Error: No se encontró un destino único y válido para DSTBLK en BLKMOV {instr_uid}.") instruction["scl"] = f"// ERROR: BLKMOV {instr_uid} sin destino DSTBLK válido." - instruction["type"] += "_error" + instruction["type"] = instr_type_original + "_error" return True - # --- Formateo especial para SRCBLK/DSTBLK como pidió el usuario --- - # Asume formato "DB".Variable o "Struct".Variable del JSON y lo mantiene - # (Esto anula la limpieza normal de format_variable_name para estos parámetros) - srcblk_final_str = raw_srcblk_name if raw_srcblk_name else "_ERROR_SRC_" - dstblk_final_str = raw_dstblk_name if raw_dstblk_name else "_ERROR_DST_" + # --- Formateo especial (mantener nombres raw si es necesario para BLKMOV) --- + # Estos nombres van directo al string SCL, no necesitan pasar por SymPy + srcblk_final_str = raw_srcblk_name # Asumiendo que ya viene con comillas si las necesita + dstblk_final_str = raw_dstblk_name # Asumiendo que ya viene con comillas si las necesita - # --- Generar SCL Exacto Solicitado --- + # --- Generar SCL Core (Usando la sintaxis no estándar BLKMOV) --- scl_core = ( f"{retval_target_scl} := BLKMOV(SRCBLK := {srcblk_final_str}, " - f"DSTBLK => {dstblk_final_str}); " + f"DSTBLK => {dstblk_final_str}); " # Usar => para Out/InOut f"// ADVERTENCIA: BLKMOV usado directamente, probablemente no compile!" ) - # Añadir condición EN (usando la representación SCL obtenida para EN) - scl_final = ( - f"IF {en_scl} THEN\n {scl_core}\nEND_IF;" if en_scl != "TRUE" else scl_core - ) + # --- Aplicar Condición EN (Simplificando EN) --- + scl_final = "" + if sympy_en_expr != sympy.true: + try: + #simplified_en_expr = sympy.simplify_logic(sympy_en_expr, force=True) + simplified_en_expr = sympy.logic.boolalg.to_dnf(sympy_en_expr, simplify=True) + except Exception as e: + print(f"Error simplifying EN for {instr_type_original} {instr_uid}: {e}") + simplified_en_expr = sympy_en_expr # Fallback + en_condition_scl = sympy_expr_to_scl(simplified_en_expr, symbol_manager) - # --- Actualizar Instrucción y Mapa SCL --- - instruction["scl"] = scl_final - instruction["type"] = instr_type + SCL_SUFFIX + # Evitar IF TRUE/FALSE THEN... + if en_condition_scl == "TRUE": + scl_final = scl_core + elif en_condition_scl == "FALSE": + scl_final = f"// {instr_type_original} {instr_uid} condition simplified to FALSE." + else: + indented_core = "\n".join([f" {line}" for line in scl_core.splitlines()]) + scl_final = f"IF {en_condition_scl} THEN\n{indented_core}\nEND_IF;" + else: + scl_final = scl_core - # Propagar ENO (igual que EN) + # --- Actualizar Instrucción y Mapa SymPy --- + instruction["scl"] = scl_final # SCL final generado + instruction["type"] = instr_type_original + SCL_SUFFIX + + # Propagar ENO (expresión SymPy) map_key_eno = (network_id, instr_uid, "eno") - scl_map[map_key_eno] = en_scl + sympy_map[map_key_eno] = sympy_en_expr - # Propagar el valor de retorno (el contenido de la variable asignada a RET_VAL) + # Propagar el valor de retorno (nombre SCL string del destino de RET_VAL) map_key_ret_val = (network_id, instr_uid, "RET_VAL") - scl_map[map_key_ret_val] = retval_target_scl # El valor es lo que sea que se asigne + sympy_map[map_key_ret_val] = retval_target_scl return True -# ... (Asegúrate de que esta función está registrada en processor_map como antes) ... - -# --- Function code ends --- - # --- Processor Information Function --- def get_processor_info(): """Devuelve la información para el procesador BLKMOV.""" - # Asumiendo que 'BLKMOV' es el type en el JSON simplificado - return {'type_name': 'blkmov', 'processor_func': process_blkmov, 'priority': 6} + # Asegurarse que el type_name coincida con el JSON ('blkmov' parece probable) + return {'type_name': 'blkmov', 'processor_func': process_blkmov, 'priority': 6} \ No newline at end of file diff --git a/processors/process_call.py b/processors/process_call.py index 730c9f7..7902697 100644 --- a/processors/process_call.py +++ b/processors/process_call.py @@ -1,141 +1,131 @@ +# processors/process_call.py # -*- coding: utf-8 -*- -from .processor_utils import get_scl_representation, format_variable_name,get_target_scl_name +import sympy +import traceback +# Asumiendo que estas funciones ahora existen y están adaptadas +from .processor_utils import get_sympy_representation, sympy_expr_to_scl, format_variable_name, get_target_scl_name +from .symbol_manager import SymbolManager # Necesitamos pasar el symbol_manager -# TODO: Import necessary functions from processor_utils -# Example: from .processor_utils import get_scl_representation, format_variable_name -# Or: import processors.processor_utils as utils +# Definir sufijo globalmente o importar +SCL_SUFFIX = "_sympy_processed" -# TODO: Define constants if needed (e.g., SCL_SUFFIX) or import them -SCL_SUFFIX = "_scl" - -# --- Function code starts --- -def process_call(instruction, network_id, scl_map, access_map, data): +def process_call(instruction, network_id, sympy_map, symbol_manager: SymbolManager, data): instr_uid = instruction["instruction_uid"] - instr_type = instruction.get("type", "") # Usar get con default - if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + instr_type_original = instruction.get("type", "") # Tipo antes de añadir sufijo + if instr_type_original.endswith(SCL_SUFFIX) or "_error" in instr_type_original: return False block_name = instruction.get("block_name", f"UnknownCall_{instr_uid}") block_type = instruction.get("block_type") # FC, FB instance_db = instruction.get("instance_db") # Nombre del DB de instancia (para FB) - # Formatear nombres + # Formatear nombres SCL (para la llamada final) block_name_scl = format_variable_name(block_name) instance_db_scl = format_variable_name(instance_db) if instance_db else None # --- Manejo de EN --- en_input = instruction["inputs"].get("en") - en_scl = ( - get_scl_representation(en_input, network_id, scl_map, access_map) - if en_input - else "TRUE" - ) - if en_scl is None: - return False # Dependencia EN no resuelta + sympy_en_expr = get_sympy_representation(en_input, network_id, sympy_map, symbol_manager) if en_input else sympy.true - # --- Procesar Parámetros de Entrada/Salida --- - # Necesitamos iterar sobre los pines definidos en la interfaz del bloque llamado. - # Esta información no está directamente en la instrucción 'Call' del JSON simplificado. - # ¡Limitación! Sin la interfaz del bloque llamado, solo podemos manejar EN/ENO - # y asumir una llamada sin parámetros o con parámetros conectados implícitamente. + if sympy_en_expr is None: + # print(f"DEBUG Call {instr_uid}: EN dependency not ready.") + return False # Dependencia EN no resuelta - # Solución temporal: Buscar conexiones en 'inputs' y 'outputs' que NO sean 'en'/'eno' - # y construir la llamada basándose en eso. Esto es muy heurístico. + # --- Procesar Parámetros de Entrada --- scl_call_params = [] - processed_inputs = {"en"} # Marcar 'en' como ya procesado - for pin_name, source_info in instruction.get("inputs", {}).items(): + processed_inputs = {"en"} + dependencies_resolved = True + + # Ordenar para consistencia + input_pin_names = sorted(instruction.get("inputs", {}).keys()) + + for pin_name in input_pin_names: if pin_name not in processed_inputs: - param_scl = get_scl_representation( - source_info, network_id, scl_map, access_map - ) - if param_scl is None: - # print(f"DEBUG: Call {instr_uid} esperando parámetro de entrada {pin_name}") - return False # Dependencia de parámetro no resuelta - # Formatear si es variable - param_scl_formatted = ( - format_variable_name(param_scl) - if source_info.get("type") == "variable" - else param_scl - ) - scl_call_params.append( - f"{format_variable_name(pin_name)} := {param_scl_formatted}" - ) + source_info = instruction["inputs"][pin_name] + # Obtener la representación de la fuente (puede ser SymPy o Constante/String) + source_sympy_or_const = get_sympy_representation(source_info, network_id, sympy_map, symbol_manager) + + if source_sympy_or_const is None: + # print(f"DEBUG Call {instr_uid}: Input param '{pin_name}' dependency not ready.") + dependencies_resolved = False + break # Salir si una dependencia no está lista + + # Convertir la expresión/constante a SCL para la llamada + # Simplificar ANTES de convertir? Probablemente no necesario para parámetros de entrada + # a menos que queramos optimizar el valor pasado. Por ahora, convertir directo. + param_scl_value = sympy_expr_to_scl(source_sympy_or_const, symbol_manager) + + # El nombre del pin SÍ necesita formateo + pin_name_scl = format_variable_name(pin_name) + scl_call_params.append(f"{pin_name_scl} := {param_scl_value}") processed_inputs.add(pin_name) - # Procesar parámetros de salida (asignaciones después de la llamada o pasados como VAR_IN_OUT/VAR_OUTPUT) - # Esto es aún más complejo. SCL normalmente asigna salidas después o usa punteros/referencias. - # Simplificación: Asumir que las salidas se manejan por asignación posterior si es necesario, - # o que son VAR_OUTPUT y se acceden como instancia.salida. - # Por ahora, no generamos asignaciones explícitas para las salidas aquí. + if not dependencies_resolved: + return False - # --- Construcción de la Llamada SCL --- + # --- Construcción de la Llamada SCL (similar a antes) --- scl_call_body = "" param_string = ", ".join(scl_call_params) if block_type == "FB": if not instance_db_scl: - print( - f"Error: Llamada a FB '{block_name_scl}' (UID {instr_uid}) sin DB de instancia especificado." - ) + print(f"Error: Call FB '{block_name_scl}' (UID {instr_uid}) sin instancia.") instruction["scl"] = f"// ERROR: FB Call {block_name_scl} sin instancia" - instruction["type"] = "Call_FB_error" - return True # Procesado con error - # Llamada a FB con DB de instancia + instruction["type"] = f"Call_FB_error" + return True scl_call_body = f"{instance_db_scl}({param_string});" elif block_type == "FC": - # Llamada a FC scl_call_body = f"{block_name_scl}({param_string});" else: - print( - f"Advertencia: Tipo de bloque no soportado para Call UID {instr_uid}: {block_type}" - ) + print(f"Advertencia: Tipo de bloque no soportado para Call UID {instr_uid}: {block_type}") scl_call_body = f"// ERROR: Call a bloque tipo '{block_type}' no soportado: {block_name_scl}" - instruction["type"] = f"Call_{block_type}_error" # Marcar como error parcial + instruction["type"] = f"Call_{block_type}_error" # Marcar como error - # --- Aplicar Condición EN --- + # --- Aplicar Condición EN (usando la expresión SymPy EN) --- scl_final = "" - if en_scl != "TRUE": - # Indentar la llamada dentro del IF + if sympy_en_expr != sympy.true: + # Simplificar la condición EN ANTES de convertirla a SCL + try: + #simplified_en_expr = sympy.simplify_logic(sympy_en_expr, force=True) + simplified_en_expr = sympy.logic.boolalg.to_dnf(sympy_en_expr, simplify=True) + except Exception as e: + print(f"Error simplifying EN for Call {instr_uid}: {e}") + simplified_en_expr = sympy_en_expr # Fallback + en_condition_scl = sympy_expr_to_scl(simplified_en_expr, symbol_manager) + indented_call = "\n".join([f" {line}" for line in scl_call_body.splitlines()]) - scl_final = f"IF {en_scl} THEN\n{indented_call}\nEND_IF;" + scl_final = f"IF {en_condition_scl} THEN\n{indented_call}\nEND_IF;" else: scl_final = scl_call_body - # --- Actualizar JSON y Mapa SCL --- - instruction["scl"] = scl_final - instruction["type"] = ( - f"Call_{block_type}_scl" - if "_error" not in instruction["type"] - else instruction["type"] - ) + # --- Actualizar Instrucción y Mapa SymPy --- + instruction["scl"] = scl_final # Guardar el SCL final generado + instruction["type"] = (f"Call_{block_type}{SCL_SUFFIX}" if "_error" not in instruction["type"] else instruction["type"]) - # Actualizar scl_map con el estado ENO (igual a EN para llamadas simples sin manejo explícito de ENO) + # Actualizar sympy_map con el estado ENO (es la expresión SymPy de EN) map_key_eno = (network_id, instr_uid, "eno") - scl_map[map_key_eno] = en_scl + sympy_map[map_key_eno] = sympy_en_expr # Guardar la expresión SymPy para ENO - # Propagar valores de salida (si pudiéramos determinarlos) - # Ejemplo: Si supiéramos que hay una salida 'Out1' de tipo INT - # map_key_out1 = (network_id, instr_uid, "Out1") - # if block_type == "FB" and instance_db_scl: - # scl_map[map_key_out1] = f"{instance_db_scl}.Out1" # Acceso a salida de instancia - # else: - # # Para FCs, necesitaríamos una variable temporal o asignación explícita - # temp_out1 = generate_temp_var_name(network_id, instr_uid, "Out1") - # # Modificar scl_call_body para incluir la asignación: Out1 => temp_out1 - # scl_map[map_key_out1] = temp_out1 + # Propagar valores de salida (requiere info de interfaz o heurística) + # Si se sabe que hay una salida 'MyOutput', se podría añadir su SCL al mapa + # Ejemplo MUY simplificado: + # for pin_name, dest_list in instruction.get("outputs", {}).items(): + # if pin_name != 'eno' and dest_list: # Asumir que hay un destino + # map_key_out = (network_id, instr_uid, pin_name) + # if block_type == "FB" and instance_db_scl: + # sympy_map[map_key_out] = f"{instance_db_scl}.{format_variable_name(pin_name)}" # Guardar el *string* de acceso SCL + # # Para FCs es más complejo, necesitaría asignación explícita a temp + # # else: # FC output -> necesita temp var + # # temp_var = generate_temp_var_name(...) + # # sympy_map[map_key_out] = temp_var return True -# --- Procesador de Temporizadores (TON, TOF) --- - -# --- Function code ends --- # --- Processor Information Function --- def get_processor_info(): """Devuelve la información para las llamadas a FC y FB.""" - # Esta función maneja tanto FC como FB. El despachador en x2_process.py - # usará 'call_fc' o 'call_fb' como clave basada en block_type. return [ {'type_name': 'call_fc', 'processor_func': process_call, 'priority': 6}, {'type_name': 'call_fb', 'processor_func': process_call, 'priority': 6} - ] + ] \ No newline at end of file diff --git a/processors/process_coil.py b/processors/process_coil.py index d26f3dd..3cb689c 100644 --- a/processors/process_coil.py +++ b/processors/process_coil.py @@ -1,79 +1,82 @@ -# -*- coding: utf-8 -*- -from .processor_utils import get_scl_representation, format_variable_name,get_target_scl_name +# processors/process_coil.py +import sympy +from .processor_utils import get_sympy_representation, sympy_expr_to_scl, get_target_scl_name, format_variable_name +from .symbol_manager import SymbolManager, extract_plc_variable_name +SCL_SUFFIX = "_sympy_processed" -# TODO: Import necessary functions from processor_utils -# Example: from .processor_utils import get_scl_representation, format_variable_name -# Or: import processors.processor_utils as utils - -# TODO: Define constants if needed (e.g., SCL_SUFFIX) or import them -SCL_SUFFIX = "_scl" - -# --- Function code starts --- -def process_coil(instruction, network_id, scl_map, access_map, data): - """Genera la asignación para Coil. Si la entrada viene de PBox/NBox, - añade la actualización de memoria del flanco DESPUÉS de la asignación.""" +def process_coil(instruction, network_id, sympy_map, symbol_manager, data): + """Genera la asignación SCL para Coil, simplificando la entrada SymPy.""" instr_uid = instruction["instruction_uid"] - instr_type = instruction["type"] - if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + instr_type_original = instruction.get("type", "Coil") + + if instr_type_original.endswith(SCL_SUFFIX) or "_error" in instr_type_original: return False + # Get input expression from SymPy map coil_input_info = instruction["inputs"].get("in") - operand_info = instruction["inputs"].get("operand") + sympy_expr_in = get_sympy_representation(coil_input_info, network_id, sympy_map, symbol_manager) - in_rlo_scl = get_scl_representation(coil_input_info, network_id, scl_map, access_map) - operand_scl = get_scl_representation(operand_info, network_id, scl_map, access_map) + # Get target variable SCL name + target_scl_name = get_target_scl_name(instruction, "operand", network_id, default_to_temp=False) # Coil must have explicit target - if in_rlo_scl is None or operand_scl is None: return False + # Check dependencies + if sympy_expr_in is None: + # print(f"DEBUG Coil {instr_uid}: Input dependency not ready.") + return False + if target_scl_name is None: + print(f"Error: Coil {instr_uid} operando no es variable o falta info.") + instruction["scl"] = f"// ERROR: Coil {instr_uid} operando no es variable." + instruction["type"] = instr_type_original + "_error" + return True # Processed with error - if not (operand_info and operand_info.get("type") == "variable"): - instruction["scl"] = f"// ERROR: Coil {instr_uid} operando no es variable o falta info" - instruction["type"] = instr_type + "_error" - return True + # *** Perform Simplification *** + try: + #simplified_expr = sympy.simplify_logic(sympy_expr_in, force=False) + #simplified_expr = sympy_expr_in + simplified_expr = sympy.logic.boolalg.to_dnf(sympy_expr_in, simplify=True) + except Exception as e: + print(f"Error during SymPy simplification for Coil {instr_uid}: {e}") + simplified_expr = sympy_expr_in # Fallback to original expression - operand_scl_formatted = format_variable_name(operand_scl) - if in_rlo_scl == "(TRUE)": in_rlo_scl = "TRUE" - elif in_rlo_scl == "(FALSE)": in_rlo_scl = "FALSE" + # *** Convert simplified expression back to SCL string *** + condition_scl = sympy_expr_to_scl(simplified_expr, symbol_manager) - # Generar la asignación SCL principal de la bobina - scl_assignment = f"{operand_scl_formatted} := {in_rlo_scl};" - scl_final = scl_assignment # Inicializar SCL final + # Generate the final SCL assignment + scl_assignment = f"{target_scl_name} := {condition_scl};" + scl_final = scl_assignment - # --- Lógica para añadir actualización de memoria de flancos --- + # --- Handle Edge Detector Memory Update (Logic similar to before) --- + # Check if input comes from PBox/NBox and append memory update mem_update_scl_combined = None if isinstance(coil_input_info, dict) and coil_input_info.get("type") == "connection": source_uid = coil_input_info.get("source_instruction_uid") source_pin = coil_input_info.get("source_pin") - - # Buscar la instrucción fuente PBox/NBox source_instruction = None network_logic = next((net["logic"] for net in data["networks"] if net["id"] == network_id), []) for instr in network_logic: if instr.get("instruction_uid") == source_uid: source_instruction = instr break - if source_instruction: - source_type = source_instruction.get("type","").replace('_scl','').replace('_error','') - # Si la fuente es PBox o NBox y tiene el campo temporal con la actualización - if source_type in ["PBox", "NBox"] and '_edge_mem_update_scl' in source_instruction: - mem_update_scl_combined = source_instruction.get('_edge_mem_update_scl') # Obtener update+comment - + # Check for the original type before suffix was added + orig_source_type = source_instruction.get("type", "").replace(SCL_SUFFIX, '').replace('_error', '') + if orig_source_type in ["PBox", "NBox"] and '_edge_mem_update_scl' in source_instruction: + mem_update_scl_combined = source_instruction.get('_edge_mem_update_scl') if mem_update_scl_combined: - # Añadir la actualización DESPUÉS de la asignación de la bobina, USANDO \n scl_final = f"{scl_assignment}\n{mem_update_scl_combined}" - # Marcar la instrucción PBox/NBox para que x3 no escriba su SCL (que ahora está vacío/comentario) - source_instruction['scl'] = f"// Logic moved to Coil {instr_uid}" # Actualizar PBox/NBox SCL + # Clear the source SCL? + source_instruction['scl'] = f"// Edge Logic handled by Coil {instr_uid}" + + # Update instruction instruction["scl"] = scl_final - instruction["type"] = instr_type + SCL_SUFFIX + instruction["type"] = instr_type_original + SCL_SUFFIX + # Coil typically doesn't output to scl_map + return True -# EN x2_process.py, junto a otras funciones process_xxx - -# --- Function code ends --- - # --- Processor Information Function --- def get_processor_info(): """Devuelve la información para el procesador Coil.""" - return {'type_name': 'coil', 'processor_func': process_coil, 'priority': 3} + return {'type_name': 'coil', 'processor_func': process_coil, 'priority': 3} \ No newline at end of file diff --git a/processors/process_comparison.py b/processors/process_comparison.py index c757b5f..cf0bfcd 100644 --- a/processors/process_comparison.py +++ b/processors/process_comparison.py @@ -1,81 +1,87 @@ +# processors/process_comparison.py # -*- coding: utf-8 -*- -from .processor_utils import get_scl_representation, format_variable_name,get_target_scl_name +import sympy +import traceback +from .processor_utils import get_sympy_representation, format_variable_name # No necesita sympy_expr_to_scl aquí +from .symbol_manager import SymbolManager # Necesita acceso al manager +SCL_SUFFIX = "_sympy_processed" -# TODO: Import necessary functions from processor_utils -# Example: from .processor_utils import get_scl_representation, format_variable_name -# Or: import processors.processor_utils as utils - -# TODO: Define constants if needed (e.g., SCL_SUFFIX) or import them -SCL_SUFFIX = "_scl" - -# --- Function code starts --- -def process_comparison(instruction, network_id, scl_map, access_map, data): +def process_comparison(instruction, network_id, sympy_map, symbol_manager: SymbolManager, data): """ - Genera la expresión SCL para Comparadores (GT, LT, GE, LE, NE). - El resultado se propaga por scl_map['out']. + Genera la expresión SymPy para Comparadores (GT, LT, GE, LE, NE). + El resultado se propaga por sympy_map['out']. """ instr_uid = instruction["instruction_uid"] - instr_type = instruction["type"] # GT, LT, GE, LE, NE - if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + instr_type_original = instruction.get("type", "") # GT, LT, GE, LE, NE + if instr_type_original.endswith(SCL_SUFFIX) or "_error" in instr_type_original: return False - # Mapa de tipos a operadores SCL - op_map = {"GT": ">", "LT": "<", "GE": ">=", "LE": "<=", "NE": "<>"} - scl_operator = op_map.get(instr_type) - if not scl_operator: - instruction["scl"] = f"// ERROR: Tipo de comparación no soportado: {instr_type}" - instruction["type"] += "_error" + # Mapa de tipos a funciones/clases SymPy Relational + # Nota: Asegúrate de que los tipos coincidan (ej. si son números o booleanos) + op_map = { + "GT": sympy.Gt, # Greater Than > + "LT": sympy.Lt, # Less Than < + "GE": sympy.Ge, # Greater or Equal >= + "LE": sympy.Le, # Less or Equal <= + "NE": sympy.Ne # Not Equal <> (sympy.Ne maneja esto) + } + sympy_relation_func = op_map.get(instr_type_original.upper()) + if not sympy_relation_func: + instruction["scl"] = f"// ERROR: Tipo de comparación no soportado para SymPy: {instr_type_original}" + instruction["type"] = instr_type_original + "_error" return True - # Obtener operandos + # Obtener operandos como expresiones SymPy o constantes/strings in1_info = instruction["inputs"].get("in1") in2_info = instruction["inputs"].get("in2") - in1_scl = get_scl_representation(in1_info, network_id, scl_map, access_map) - in2_scl = get_scl_representation(in2_info, network_id, scl_map, access_map) + op1_sympy = get_sympy_representation(in1_info, network_id, sympy_map, symbol_manager) + op2_sympy = get_sympy_representation(in2_info, network_id, sympy_map, symbol_manager) - if in1_scl is None or in2_scl is None: - return False # Dependencias no listas + # Obtener 'pre' (RLO anterior) como expresión SymPy + pre_input = instruction["inputs"].get("pre") # Asumiendo que 'pre' es la entrada RLO + sympy_pre_rlo = get_sympy_representation(pre_input, network_id, sympy_map, symbol_manager) if pre_input else sympy.true - # Formatear operandos si son variables - op1 = format_variable_name(in1_scl) if in1_info and in1_info.get("type") == "variable" else in1_scl - op2 = format_variable_name(in2_scl) if in2_info and in2_info.get("type") == "variable" else in2_scl + # Verificar dependencias + if op1_sympy is None or op2_sympy is None or sympy_pre_rlo is None: + # print(f"DEBUG Comparison {instr_uid}: Dependency not ready") + return False - # Añadir paréntesis si contienen espacios (poco probable tras formatear) - op1 = f"({op1})" if " " in op1 and not op1.startswith("(") else op1 - op2 = f"({op2})" if " " in op2 and not op2.startswith("(") else op2 + # Crear la expresión de comparación SymPy + try: + # Convertir constantes string a número si es posible (Sympy puede necesitarlo) + # Esto es heurístico y puede fallar. Mejor si los tipos son conocidos. + op1_eval = sympy.sympify(op1_sympy) if isinstance(op1_sympy, str) else op1_sympy + op2_eval = sympy.sympify(op2_sympy) if isinstance(op2_sympy, str) else op2_sympy + comparison_expr = sympy_relation_func(op1_eval, op2_eval) + except (SyntaxError, TypeError, ValueError) as e: + print(f"Error creating SymPy comparison for {instr_uid}: {e}") + instruction["scl"] = f"// ERROR creando expr SymPy Comparison {instr_uid}: {e}" + instruction["type"] = instr_type_original + "_error" + return True - comparison_scl = f"{op1} {scl_operator} {op2}" - - # Guardar resultado en el mapa para 'out' + # Guardar resultado en el mapa para 'out' (es una expresión booleana SymPy) map_key_out = (network_id, instr_uid, "out") - scl_map[map_key_out] = f"({comparison_scl})" # Poner paréntesis por seguridad - - # Manejar entrada 'pre'/RLO -> ENO (como en EQ) - pre_input = instruction["inputs"].get("pre") # Asumir 'pre' como en EQ - en_scl = get_scl_representation(pre_input, network_id, scl_map, access_map) if pre_input else "TRUE" - if en_scl is None: - return False # Dependencia 'pre'/'en' no lista + sympy_map[map_key_out] = comparison_expr + # Guardar el RLO de entrada ('pre') como ENO en el mapa SymPy map_key_eno = (network_id, instr_uid, "eno") - scl_map[map_key_eno] = en_scl + sympy_map[map_key_eno] = sympy_pre_rlo - instruction["scl"] = f"// Comparison {instr_type} {instr_uid}: {comparison_scl}" - instruction["type"] = instr_type + SCL_SUFFIX + # Marcar como procesado, SCL principal es solo comentario + instruction["scl"] = f"// SymPy Comparison {instr_type_original}: {comparison_expr}" # Comentario opcional + instruction["type"] = instr_type_original + SCL_SUFFIX return True -# --- Procesador de Matemáticas (ADD ya existe, añadir otros) --- - -# --- Function code ends --- # --- Processor Information Function --- def get_processor_info(): - """Devuelve la información para los comparadores (excepto EQ).""" - # Esta función maneja múltiples tipos de comparación. + """Devuelve la información para los comparadores (excepto EQ, que debe ser similar).""" return [ - {'type_name': 'gt', 'processor_func': process_comparison, 'priority': 2}, # > - {'type_name': 'lt', 'processor_func': process_comparison, 'priority': 2}, # < - {'type_name': 'ge', 'processor_func': process_comparison, 'priority': 2}, # >= - {'type_name': 'le', 'processor_func': process_comparison, 'priority': 2}, # <= - {'type_name': 'ne', 'processor_func': process_comparison, 'priority': 2} # <> - ] + {'type_name': 'gt', 'processor_func': process_comparison, 'priority': 2}, + {'type_name': 'lt', 'processor_func': process_comparison, 'priority': 2}, + {'type_name': 'ge', 'processor_func': process_comparison, 'priority': 2}, + {'type_name': 'le', 'processor_func': process_comparison, 'priority': 2}, + {'type_name': 'ne', 'processor_func': process_comparison, 'priority': 2} + # Asegúrate de tener también un procesador para 'eq' usando sympy.Eq + ] \ No newline at end of file diff --git a/processors/process_contact.py b/processors/process_contact.py index d53924e..ec5b0ab 100644 --- a/processors/process_contact.py +++ b/processors/process_contact.py @@ -1,73 +1,60 @@ -# -*- coding: utf-8 -*- -from .processor_utils import get_scl_representation, format_variable_name,get_target_scl_name +# processors/process_contact.py +import sympy +from .processor_utils import get_sympy_representation, format_variable_name # Use new util +from .symbol_manager import SymbolManager, extract_plc_variable_name # Need symbol manager access +# Define SCL_SUFFIX or import if needed globally +SCL_SUFFIX = "_sympy_processed" # Indicate processing type -# TODO: Import necessary functions from processor_utils -# Example: from .processor_utils import get_scl_representation, format_variable_name -# Or: import processors.processor_utils as utils - -# TODO: Define constants if needed (e.g., SCL_SUFFIX) or import them -SCL_SUFFIX = "_scl" - -# --- Function code starts --- -def process_contact(instruction, network_id, scl_map, access_map, data): - """Traduce Contact (normal o negado) a una expresión booleana SCL.""" +def process_contact(instruction, network_id, sympy_map, symbol_manager, data): # Pass symbol_manager + """Genera la expresión SymPy para Contact (normal o negado).""" instr_uid = instruction["instruction_uid"] - instr_type = instruction["type"] - if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + instr_type_original = instruction.get("type", "Contact") + + # Check if already processed with the new method + if instr_type_original.endswith(SCL_SUFFIX) or "_error" in instr_type_original: return False - # --- INICIO LEER NEGACIÓN --- - # Verificar si el pin 'operand' está marcado como negado en el JSON is_negated = instruction.get("negated_pins", {}).get("operand", False) - # --- FIN LEER NEGACIÓN --- - - # print(f"DEBUG: Intentando procesar CONTACT{' (N)' if is_negated else ''} - UID: {instr_uid} en Red: {network_id}") + # Get incoming SymPy expression (RLO) in_input = instruction["inputs"].get("in") - in_rlo_scl = ( - "TRUE" - if in_input is None - else get_scl_representation(in_input, network_id, scl_map, access_map) - ) - operand_scl = get_scl_representation( - instruction["inputs"].get("operand"), network_id, scl_map, access_map - ) + sympy_expr_in = get_sympy_representation(in_input, network_id, sympy_map, symbol_manager) - if in_rlo_scl is None or operand_scl is None: - return False + # Get operand SymPy Symbol + operand_info = instruction["inputs"].get("operand") + operand_plc_name = extract_plc_variable_name(operand_info) + sympy_symbol_operand = symbol_manager.get_symbol(operand_plc_name) if operand_plc_name else None - # Usar is_negated para aplicar NOT - term = f"NOT {operand_scl}" if is_negated else operand_scl - if not (term.startswith('"') and term.endswith('"')): - # Añadir paréntesis si es NOT o si contiene espacios/operadores - if is_negated or ( - " " in term and not (term.startswith("(") and term.endswith(")")) - ): - term = f"({term})" + # Check dependencies + if sympy_expr_in is None or sympy_symbol_operand is None: + # print(f"DEBUG Contact {instr_uid}: Dependency not ready (In: {sympy_expr_in is not None}, Op: {sympy_symbol_operand is not None})") + return False # Dependencies not ready - new_rlo_scl = ( - term - if in_rlo_scl == "TRUE" - else ( - f"({in_rlo_scl}) AND {term}" - if ("AND" in in_rlo_scl or "OR" in in_rlo_scl) - and not (in_rlo_scl.startswith("(") and in_rlo_scl.endswith(")")) - else f"{in_rlo_scl} AND {term}" - ) - ) + # Apply negation using SymPy + current_term = sympy.Not(sympy_symbol_operand) if is_negated else sympy_symbol_operand + + # Combine with previous RLO using SymPy + # Simplify common cases: TRUE AND X -> X + if sympy_expr_in == sympy.true: + sympy_expr_out = current_term + else: + # Could add FALSE AND X -> FALSE optimization here too + sympy_expr_out = sympy.And(sympy_expr_in, current_term) + + # Store the resulting SymPy expression object in the map + map_key_out = (network_id, instr_uid, "out") + sympy_map[map_key_out] = sympy_expr_out + + # Mark instruction as processed (SCL field is now less relevant here) + instruction["scl"] = f"// SymPy Contact: {sympy_expr_out}" # Optional debug comment + instruction["type"] = instr_type_original + SCL_SUFFIX # Use the new suffix + # Contact doesn't usually have ENO, it modifies the RLO ('out') - map_key = (network_id, instr_uid, "out") - scl_map[map_key] = new_rlo_scl - instruction["scl"] = f"// RLO: {new_rlo_scl}" - instruction["type"] = instr_type + SCL_SUFFIX return True -# --- process_edge_detector MODIFICADA --- - -# --- Function code ends --- - # --- Processor Information Function --- def get_processor_info(): """Devuelve la información para el procesador Contact.""" - return {'type_name': 'contact', 'processor_func': process_contact, 'priority': 1} + # Ensure 'data' argument is added if needed by the processor function signature change + return {'type_name': 'contact', 'processor_func': process_contact, 'priority': 1} \ No newline at end of file diff --git a/processors/process_convert.py b/processors/process_convert.py index df7e34c..0825c21 100644 --- a/processors/process_convert.py +++ b/processors/process_convert.py @@ -1,81 +1,90 @@ +# processors/process_convert.py # -*- coding: utf-8 -*- -from .processor_utils import get_scl_representation, format_variable_name,get_target_scl_name +import sympy +import traceback +from .processor_utils import get_sympy_representation, sympy_expr_to_scl, get_target_scl_name, format_variable_name +from .symbol_manager import SymbolManager +SCL_SUFFIX = "_sympy_processed" -# TODO: Import necessary functions from processor_utils -# Example: from .processor_utils import get_scl_representation, format_variable_name -# Or: import processors.processor_utils as utils - -# TODO: Define constants if needed (e.g., SCL_SUFFIX) or import them -SCL_SUFFIX = "_scl" - -# --- Function code starts --- -def process_convert(instruction, network_id, scl_map, access_map, data): +def process_convert(instruction, network_id, sympy_map, symbol_manager: SymbolManager, data): + """Genera SCL para Convert, tratando la conversión como una asignación.""" instr_uid = instruction["instruction_uid"] - instr_type = instruction["type"] - if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + instr_type_original = instruction.get("type", "Convert") + if instr_type_original.endswith(SCL_SUFFIX) or "_error" in instr_type_original: return False + # Obtener EN y IN en_input = instruction["inputs"].get("en") - en_scl = ( - get_scl_representation(en_input, network_id, scl_map, access_map) - if en_input - else "TRUE" - ) + sympy_en_expr = get_sympy_representation(en_input, network_id, sympy_map, symbol_manager) if en_input else sympy.true in_info = instruction["inputs"].get("in") - in_scl = get_scl_representation(in_info, network_id, scl_map, access_map) + sympy_or_const_in = get_sympy_representation(in_info, network_id, sympy_map, symbol_manager) - if en_scl is None or in_scl is None: - return False # Esperar si dependencias no listas + # Obtener destino SCL + target_scl_name = get_target_scl_name(instruction, "out", network_id, default_to_temp=True) - target_scl = get_target_scl_name( - instruction, "out", network_id, default_to_temp=True - ) - if target_scl is None: - print(f"Error: Sin destino claro para CONVERT {instr_uid}") - instruction["scl"] = f"// ERROR: Convert {instr_uid} sin destino" - instruction["type"] += "_error" - return True # Procesado con error + # Verificar dependencias + if sympy_en_expr is None or sympy_or_const_in is None or target_scl_name is None: + return False - # Formatear entrada si es variable - in_scl_formatted = ( - format_variable_name(in_scl) - if in_info and in_info.get("type") == "variable" - else in_scl - ) + # Convertir la entrada (SymPy o Constante) a SCL + # La simplificación aquí no suele aplicar a la conversión en sí, + # pero sí podría aplicar a la condición EN. + input_scl = sympy_expr_to_scl(sympy_or_const_in, symbol_manager) - # Determinar el tipo de destino (simplificado, necesitaría info del XML original) - # Asumimos que el tipo está en TemplateValues o inferirlo del nombre/contexto - target_type = instruction.get("template_values", {}).get( - "destType", "VARIANT" - ) # Ejemplo, ajustar según XML real - conversion_func = f"{target_type}_TO_" # Necesita el tipo de origen también - # Esta parte es compleja sin saber los tipos exactos. Usaremos una conversión genérica o MOVE. - # Para una conversión real, necesitaríamos algo como: - # conversion_expr = f"CONVERT(IN := {in_scl_formatted}, OUT => {target_scl})" # Sintaxis inventada - # O usar funciones específicas: INT_TO_REAL, etc. + # Determinar el tipo de destino (esto sigue siendo un desafío sin info completa) + # Usaremos funciones de conversión SCL explícitas si podemos inferirlas. + target_type_hint = instruction.get("template_values", {}).get("destType", "").upper() # Ejemplo + source_type_hint = "" # Necesitaríamos info del tipo de origen + conversion_func_name = None - # Simplificación: Usar asignación directa (MOVE implícito) o función genérica si existe - # Asumiremos asignación directa por ahora. - conversion_expr = in_scl_formatted - scl_core = f"{target_scl} := {conversion_expr};" + # Heurística MUY básica (necesita mejorar con info de tipos real) + if target_type_hint and source_type_hint and target_type_hint != source_type_hint: + conversion_func_name = f"{source_type_hint}_TO_{target_type_hint}" - # Añadir IF EN si es necesario - scl_final = ( - f"IF {en_scl} THEN\n {scl_core}\nEND_IF;" if en_scl != "TRUE" else scl_core - ) + # Generar SCL Core + if conversion_func_name: + # Usar función explícita si la inferimos + scl_core = f"{target_scl_name} := {conversion_func_name}({input_scl});" + else: + # Asignación directa (MOVE implícito) si no hay conversión clara + # ADVERTENCIA: Esto puede causar errores de tipo en el PLC si los tipos no coinciden. + scl_core = f"{target_scl_name} := {input_scl};" + if target_type_hint: # Añadir comentario si al menos conocemos el destino + scl_core += f" // TODO: Verify implicit conversion to {target_type_hint}" - instruction["scl"] = scl_final - instruction["type"] = instr_type + SCL_SUFFIX + + # Aplicar Condición EN (Simplificando EN) + scl_final = "" + if sympy_en_expr != sympy.true: + try: + #simplified_en_expr = sympy.simplify_logic(sympy_en_expr, force=True) + simplified_en_expr = sympy.logic.boolalg.to_dnf(sympy_en_expr, simplify=True) + except Exception as e: + print(f"Error simplifying EN for Convert {instr_uid}: {e}") + simplified_en_expr = sympy_en_expr # Fallback + en_condition_scl = sympy_expr_to_scl(simplified_en_expr, symbol_manager) + + indented_core = "\n".join([f" {line}" for line in scl_core.splitlines()]) + scl_final = f"IF {en_condition_scl} THEN\n{indented_core}\nEND_IF;" + else: + scl_final = scl_core + + # Actualizar instrucción y mapa + instruction["scl"] = scl_final # SCL final generado + instruction["type"] = instr_type_original + SCL_SUFFIX + + # Propagar valor de salida (el contenido del destino) y ENO map_key_out = (network_id, instr_uid, "out") - scl_map[map_key_out] = target_scl # El valor de salida es el contenido del destino + # Guardar el *nombre* SCL del destino en el mapa, ya que contiene el valor + # O podríamos crear un símbolo SymPy para ello si fuera necesario aguas abajo? Por ahora, string. + sympy_map[map_key_out] = target_scl_name map_key_eno = (network_id, instr_uid, "eno") - scl_map[map_key_eno] = en_scl # ENO sigue a EN - return True + sympy_map[map_key_eno] = sympy_en_expr # Guardar la expresión SymPy para ENO -# --- Function code ends --- + return True # --- Processor Information Function --- def get_processor_info(): """Devuelve la información para el procesador Convert.""" - return {'type_name': 'convert', 'processor_func': process_convert, 'priority': 4} + return {'type_name': 'convert', 'processor_func': process_convert, 'priority': 4} \ No newline at end of file diff --git a/processors/process_counter.py b/processors/process_counter.py index 6538b78..693355a 100644 --- a/processors/process_counter.py +++ b/processors/process_counter.py @@ -1,94 +1,110 @@ +# processors/process_counter.py # -*- coding: utf-8 -*- -from .processor_utils import get_scl_representation, format_variable_name,get_target_scl_name +import sympy +import traceback +from .processor_utils import get_sympy_representation, sympy_expr_to_scl, format_variable_name, get_target_scl_name +from .symbol_manager import SymbolManager +SCL_SUFFIX = "_sympy_processed" -# TODO: Import necessary functions from processor_utils -# Example: from .processor_utils import get_scl_representation, format_variable_name -# Or: import processors.processor_utils as utils - -# TODO: Define constants if needed (e.g., SCL_SUFFIX) or import them -SCL_SUFFIX = "_scl" - -# --- Function code starts --- -def process_counter(instruction, network_id, scl_map, access_map, data): +def process_counter(instruction, network_id, sympy_map, symbol_manager: SymbolManager, data): """ Genera SCL para Contadores (CTU, CTD, CTUD). Requiere datos de instancia (DB o STAT). """ instr_uid = instruction["instruction_uid"] - instr_type = instruction["type"] # CTU, CTD, CTUD - if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + instr_type_original = instruction.get("type", "") # CTU, CTD, CTUD + if instr_type_original.endswith(SCL_SUFFIX) or "_error" in instr_type_original: return False - # 1. Obtener Inputs (varía según tipo) - params = [] - resolved = True + # 1. Definir pines de entrada esperados + input_pins_map = { + "CTU": ["CU", "R", "PV"], + "CTD": ["CD", "LD", "PV"], + "CTUD": ["CU", "CD", "R", "LD", "PV"] + } + input_pins = input_pins_map.get(instr_type_original.upper()) + if not input_pins: + instruction["scl"] = f"// ERROR: Tipo de contador no soportado: {instr_type_original}" + instruction["type"] = instr_type_original + "_error" + return True - input_pins = [] - if instr_type == "CTU": input_pins = ["CU", "R", "PV"] - elif instr_type == "CTD": input_pins = ["CD", "LD", "PV"] - elif instr_type == "CTUD": input_pins = ["CU", "CD", "R", "LD", "PV"] - else: - instruction["scl"] = f"// ERROR: Tipo de contador no soportado: {instr_type}" - instruction["type"] += "_error" - return True # Procesado con error + # 2. Procesar Parámetros de Entrada + scl_call_params = [] + dependencies_resolved = True + optional_pins = {"R", "LD"} # Estos pueden no estar conectados for pin in input_pins: pin_info = instruction["inputs"].get(pin) - if pin_info is None and pin not in ["R", "LD"]: # R y LD pueden no estar conectados - print(f"Error: Falta entrada requerida '{pin}' para {instr_type} UID {instr_uid}.") - # Permitir continuar si solo faltan R o LD opcionales? Por ahora no. - instruction["scl"] = f"// ERROR: Falta entrada requerida '{pin}' para {instr_type} UID {instr_uid}." - instruction["type"] += "_error" - return True # Error - elif pin_info: # Si el pin existe en el JSON - scl_pin = get_scl_representation(pin_info, network_id, scl_map, access_map) - if scl_pin is None: - resolved = False - break # Salir si una dependencia no está lista - scl_pin_formatted = format_variable_name(scl_pin) if pin_info.get("type") == "variable" else scl_pin - params.append(f"{pin} := {scl_pin_formatted}") + if pin_info: # Si el pin está definido en el JSON + source_sympy_or_const = get_sympy_representation(pin_info, network_id, sympy_map, symbol_manager) + if source_sympy_or_const is None: + # print(f"DEBUG Counter {instr_uid}: Input param '{pin}' dependency not ready.") + dependencies_resolved = False + break + # Convertir a SCL para la llamada (sin simplificar aquí) + param_scl_value = sympy_expr_to_scl(source_sympy_or_const, symbol_manager) + pin_name_scl = format_variable_name(pin) # Formatear nombre del parámetro + scl_call_params.append(f"{pin_name_scl} := {param_scl_value}") + elif pin not in optional_pins: # Si falta un pin requerido + print(f"Error: Falta entrada requerida '{pin}' para {instr_type_original} UID {instr_uid}.") + instruction["scl"] = f"// ERROR: Falta entrada requerida '{pin}' para {instr_type_original} UID {instr_uid}." + instruction["type"] = instr_type_original + "_error" + return True - if not resolved: return False + if not dependencies_resolved: + return False - # 2. Obtener Nombre de Instancia (NECESITA MEJORA EN x1.py) - instance_name = instruction.get("instance_db") - if not instance_name: - instance_name = f"#COUNTER_INSTANCE_{instr_uid}" # Placeholder - print(f"Advertencia: No se encontró instancia para {instr_type} UID {instr_uid}. Usando placeholder '{instance_name}'. Ajustar x1.py y declarar en x3.py.") - else: - instance_name = format_variable_name(instance_name) + # 3. Obtener Nombre de Instancia + # Asumiendo que x1 o una fase previa llena 'instance_db' si es un FB multi-instancia + instance_name_raw = instruction.get("instance_db") + if not instance_name_raw: + # Asumiendo que es STAT si no hay DB instancia explícito (requiere declaración en x3) + instance_name_raw = instruction.get("instance_name") # Buscar nombre directo si x1 lo provee + if not instance_name_raw: + instance_name_raw = f"#CTR_INSTANCE_{instr_uid}" # Placeholder final + print(f"Advertencia: No se encontró nombre/instancia para {instr_type_original} UID {instr_uid}. Usando placeholder '{instance_name_raw}'.") + instance_name_scl = format_variable_name(instance_name_raw) - # 3. Generar la llamada SCL - param_string = ", ".join(params) - scl_call = f"{instance_name}({param_string}); // TODO: Declarar {instance_name} : {instr_type}; en VAR_STAT o VAR" + # 4. Generar la llamada SCL + param_string = ", ".join(scl_call_params) + scl_call = f"{instance_name_scl}({param_string}); // TODO: Declarar {instance_name_scl} : {instr_type_original.upper()}; en VAR_STAT o VAR" - instruction["scl"] = scl_call - instruction["type"] = instr_type + SCL_SUFFIX + # Contadores no suelen tener EN/ENO explícito en LAD, se asume siempre habilitado + instruction["scl"] = scl_call # SCL final generado + instruction["type"] = instr_type_original + SCL_SUFFIX - # 4. Actualizar scl_map para las salidas (QU, QD, CV) - output_pins = [] - if instr_type == "CTU": output_pins = ["QU", "CV"] - elif instr_type == "CTD": output_pins = ["QD", "CV"] - elif instr_type == "CTUD": output_pins = ["QU", "QD", "CV"] + # 4. Actualizar sympy_map para las salidas (QU, QD, CV) + output_pins_map = { + "CTU": ["QU", "CV"], + "CTD": ["QD", "CV"], + "CTUD": ["QU", "QD", "CV"] + } + output_pins = output_pins_map.get(instr_type_original.upper(), []) for pin in output_pins: - map_key = (network_id, instr_uid, pin) - scl_map[map_key] = f"{instance_name}.{pin}" - # Contadores no tienen ENO estándar en LAD/FBD + map_key = (network_id, instr_uid, pin) + output_scl_access = f"{instance_name_scl}.{pin.upper()}" + if pin.upper() in ["QU", "QD"]: # These are boolean outputs + # *** Store SymPy Symbol for boolean outputs QU/QD *** + sympy_out_symbol = symbol_manager.get_symbol(output_scl_access) + if sympy_out_symbol: + sympy_map[map_key] = sympy_out_symbol # Store SYMBOL + else: + print(f"Error: Could not create symbol for {output_scl_access} in {instr_type_original} {instr_uid}") + sympy_map[map_key] = None + else: + # For non-boolean (like CV - count value), store SCL access string + sympy_map[map_key] = output_scl_access return True -# --- Procesador de Comparadores (EQ ya existe, añadir otros) --- - -# --- Function code ends --- # --- Processor Information Function --- def get_processor_info(): """Devuelve la información para los contadores CTU, CTD, CTUD.""" - # Asumiendo que los tipos en el JSON son CTU, CTD, CTUD return [ {'type_name': 'ctu', 'processor_func': process_counter, 'priority': 5}, {'type_name': 'ctd', 'processor_func': process_counter, 'priority': 5}, {'type_name': 'ctud', 'processor_func': process_counter, 'priority': 5} - ] + ] \ No newline at end of file diff --git a/processors/process_edge_detector.py b/processors/process_edge_detector.py index 25e3dc1..6ff2fd3 100644 --- a/processors/process_edge_detector.py +++ b/processors/process_edge_detector.py @@ -1,91 +1,85 @@ +# processors/process_edge_detector.py # -*- coding: utf-8 -*- -from .processor_utils import get_scl_representation, format_variable_name,get_target_scl_name +import sympy +import traceback +from .processor_utils import get_sympy_representation, sympy_expr_to_scl, format_variable_name +from .symbol_manager import SymbolManager, extract_plc_variable_name +SCL_SUFFIX = "_sympy_processed" -# TODO: Import necessary functions from processor_utils -# Example: from .processor_utils import get_scl_representation, format_variable_name -# Or: import processors.processor_utils as utils - -# TODO: Define constants if needed (e.g., SCL_SUFFIX) or import them -SCL_SUFFIX = "_scl" - -# --- Function code starts --- -def process_edge_detector(instruction, network_id, scl_map, access_map, data): - """Genera SCL para PBox (P_TRIG) o NBox (N_TRIG). - Guarda la expresión del pulso en scl_map['out'] y la actualización - de memoria en un campo temporal '_edge_mem_update_scl'. +def process_edge_detector(instruction, network_id, sympy_map, symbol_manager: SymbolManager, data): + """ + Genera la expresión SymPy para el pulso de PBox (P_TRIG) o NBox (N_TRIG). + Guarda la expresión SymPy del pulso en sympy_map['out']. + Genera y guarda el SCL para la actualización de memoria en '_edge_mem_update_scl'. El campo 'scl' principal se deja casi vacío/comentario. - Usa el nombre de memoria original sin renombrar. """ instr_uid = instruction["instruction_uid"] - instr_type_original = instruction["type"] # PBox o NBox - + instr_type_original = instruction.get("type", "") # PBox o NBox if instr_type_original.endswith(SCL_SUFFIX) or "_error" in instr_type_original: - return False # Ya procesado o error + return False - # 1. Obtener CLK y MemBit original + # 1. Obtener CLK (como SymPy expr) y MemBit (como SymPy Symbol) clk_input = instruction["inputs"].get("in") mem_bit_input = instruction["inputs"].get("bit") - clk_scl = get_scl_representation(clk_input, network_id, scl_map, access_map) - mem_bit_scl_original = get_scl_representation(mem_bit_input, network_id, scl_map, access_map) # Ej: "M19001" - # 2. Verificar dependencias y tipo de MemBit - if clk_scl is None: return False - if mem_bit_scl_original is None: - instruction["scl"] = f"// ERROR: {instr_type_original} {instr_uid} MemBit no resuelto." - instruction["type"] = instr_type_original + "_error" - return True - if not (mem_bit_input and mem_bit_input.get("type") == "variable"): - instruction["scl"] = f"// ERROR: {instr_type_original} {instr_uid} 'bit' no es variable." + sympy_clk_expr = get_sympy_representation(clk_input, network_id, sympy_map, symbol_manager) + mem_bit_plc_name = extract_plc_variable_name(mem_bit_input) + sympy_mem_bit_symbol = symbol_manager.get_symbol(mem_bit_plc_name) if mem_bit_plc_name else None + + # 2. Verificar dependencias + if sympy_clk_expr is None: return False + if sympy_mem_bit_symbol is None: + err_msg = f"MemBit no resuelto o no es variable para {instr_type_original} UID {instr_uid}" + print(f"Error: {err_msg}") + instruction["scl"] = f"// ERROR: {err_msg}" instruction["type"] = instr_type_original + "_error" return True - # 3. Formatear CLK (usa memoria original) - clk_scl_formatted = clk_scl - if clk_scl not in ["TRUE", "FALSE"] and \ - (' ' in clk_scl or 'AND' in clk_scl or 'OR' in clk_scl or ':=' in clk_scl) and \ - not (clk_scl.startswith('(') and clk_scl.endswith(')')): - clk_scl_formatted = f"({clk_scl})" - - # 4. Generar Lógica SCL del *pulso* - result_pulse_expression = "FALSE" - scl_comment = "" - if instr_type_original == "PBox": # P_TRIG - result_pulse_expression = f"{clk_scl_formatted} AND NOT {mem_bit_scl_original}" - scl_comment = f"// P_TRIG({clk_scl_formatted})" - elif instr_type_original == "NBox": # N_TRIG - result_pulse_expression = f"NOT {clk_scl_formatted} AND {mem_bit_scl_original}" - scl_comment = f"// N_TRIG({clk_scl_formatted})" + # 3. Generar Lógica SymPy del *pulso* + result_pulse_sympy_expr = sympy.false # Default + scl_comment_prefix = "" + if instr_type_original.upper() == "PBOX": # P_TRIG + result_pulse_sympy_expr = sympy.And(sympy_clk_expr, sympy.Not(sympy_mem_bit_symbol)) + scl_comment_prefix = "P_TRIG" + elif instr_type_original.upper() == "NBOX": # N_TRIG + result_pulse_sympy_expr = sympy.And(sympy.Not(sympy_clk_expr), sympy_mem_bit_symbol) + scl_comment_prefix = "N_TRIG" else: # Error instruction["scl"] = f"// ERROR: Tipo de flanco inesperado {instr_type_original}" instruction["type"] = instr_type_original + "_error" return True - # 5. Generar la actualización del bit de memoria - scl_mem_update = f"{mem_bit_scl_original} := {clk_scl_formatted};" + # 4. Generar el SCL para la actualización del bit de memoria + # Necesitamos la representación SCL de la entrada CLK + clk_scl_str = sympy_expr_to_scl(sympy_clk_expr, symbol_manager) + # Usamos el nombre PLC original formateado para el bit de memoria + mem_bit_scl_name = format_variable_name(mem_bit_plc_name) + scl_mem_update = f"{mem_bit_scl_name} := {clk_scl_str};" + scl_comment_for_update = f"// {scl_comment_prefix}({clk_scl_str}) - Mem: {mem_bit_scl_name}" - # 6. Almacenar Resultados + # 5. Almacenar Resultados map_key_out = (network_id, instr_uid, "out") - scl_map[map_key_out] = result_pulse_expression # Guardar EXPRESIÓN del pulso + sympy_map[map_key_out] = result_pulse_sympy_expr # Guardar EXPRESIÓN SymPy del pulso - instruction['_edge_mem_update_scl'] = f"{scl_mem_update} {scl_comment}" # Guardar UPDATE + Comentario en campo temporal - instruction['scl'] = f"// {instr_type_original} Logic moved to consumer Coil" # Dejar SCL principal vacío/comentario + # Guardar SCL de actualización + Comentario en campo temporal + instruction['_edge_mem_update_scl'] = f"{scl_mem_update} {scl_comment_for_update}" + + # Marcar como procesado, SCL principal es solo comentario + instruction['scl'] = f"// {instr_type_original} SymPy processed, logic in consumer" instruction["type"] = instr_type_original + SCL_SUFFIX - # 7. Propagar ENO + # 6. Propagar ENO (es la expresión SymPy de CLK) map_key_eno = (network_id, instr_uid, "eno") - scl_map[map_key_eno] = clk_scl + sympy_map[map_key_eno] = sympy_clk_expr return True -# --- process_coil MODIFICADA (con \n correcto) --- - -# --- Function code ends --- # --- Processor Information Function --- def get_processor_info(): - """Devuelve la información para los detectores de flanco PBox (P_TRIG) y NBox (N_TRIG).""" + """Devuelve la info para los detectores de flanco PBox y NBox.""" return [ - {'type_name': 'pbox', 'processor_func': process_edge_detector, 'priority': 2}, # Flanco positivo - {'type_name': 'nbox', 'processor_func': process_edge_detector, 'priority': 2} # Flanco negativo - ] + {'type_name': 'pbox', 'processor_func': process_edge_detector, 'priority': 2}, + {'type_name': 'nbox', 'processor_func': process_edge_detector, 'priority': 2} + ] \ No newline at end of file diff --git a/processors/process_eq.py b/processors/process_eq.py index 2d1d7bd..3b16a32 100644 --- a/processors/process_eq.py +++ b/processors/process_eq.py @@ -1,74 +1,64 @@ +# processors/process_eq.py # -*- coding: utf-8 -*- -from .processor_utils import get_scl_representation, format_variable_name,get_target_scl_name +import sympy +import traceback +# Usar las nuevas utilidades de SymPy +from .processor_utils import get_sympy_representation, format_variable_name +from .symbol_manager import SymbolManager +SCL_SUFFIX = "_sympy_processed" # Nuevo sufijo -# TODO: Import necessary functions from processor_utils -# Example: from .processor_utils import get_scl_representation, format_variable_name -# Or: import processors.processor_utils as utils - -# TODO: Define constants if needed (e.g., SCL_SUFFIX) or import them -SCL_SUFFIX = "_scl" - -# --- Function code starts --- -def process_eq(instruction, network_id, scl_map, access_map, data): +def process_eq(instruction, network_id, sympy_map, symbol_manager: SymbolManager, data): + """ + Genera la expresión SymPy para el comparador de igualdad (EQ). + El resultado se propaga por sympy_map['out']. + """ instr_uid = instruction["instruction_uid"] - instr_type = instruction["type"] - if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + instr_type_original = instruction.get("type", "Eq") + if instr_type_original.endswith(SCL_SUFFIX) or "_error" in instr_type_original: return False + # Obtener operandos como expresiones SymPy o constantes/strings in1_info = instruction["inputs"].get("in1") in2_info = instruction["inputs"].get("in2") - in1_scl = get_scl_representation(in1_info, network_id, scl_map, access_map) - in2_scl = get_scl_representation(in2_info, network_id, scl_map, access_map) + op1_sympy = get_sympy_representation(in1_info, network_id, sympy_map, symbol_manager) + op2_sympy = get_sympy_representation(in2_info, network_id, sympy_map, symbol_manager) - if in1_scl is None or in2_scl is None: - return False # Dependencias no listas + # Obtener 'pre' (RLO anterior) como expresión SymPy + pre_input = instruction["inputs"].get("pre") # Asumir 'pre' como entrada RLO estándar + sympy_pre_rlo = get_sympy_representation(pre_input, network_id, sympy_map, symbol_manager) if pre_input else sympy.true - # Formatear operandos si son variables - op1 = ( - format_variable_name(in1_scl) - if in1_info and in1_info.get("type") == "variable" - else in1_scl - ) - op2 = ( - format_variable_name(in2_scl) - if in2_info and in2_info.get("type") == "variable" - else in2_scl - ) + # Verificar dependencias + if op1_sympy is None or op2_sympy is None or sympy_pre_rlo is None: + # print(f"DEBUG EQ {instr_uid}: Dependency not ready") + return False - # Añadir paréntesis si los operandos contienen espacios (poco probable después de formatear) - op1 = f"({op1})" if " " in op1 and not op1.startswith("(") else op1 - op2 = f"({op2})" if " " in op2 and not op2.startswith("(") else op2 + # Crear la expresión de igualdad SymPy + try: + # sympify puede ser necesario si los operandos son strings de constantes + op1_eval = sympy.sympify(op1_sympy) if isinstance(op1_sympy, str) else op1_sympy + op2_eval = sympy.sympify(op2_sympy) if isinstance(op2_sympy, str) else op2_sympy + comparison_expr = sympy.Eq(op1_eval, op2_eval) # Eq para igualdad + except (SyntaxError, TypeError, ValueError) as e: + print(f"Error creating SymPy equality for {instr_uid}: {e}") + instruction["scl"] = f"// ERROR creando expr SymPy EQ {instr_uid}: {e}" + instruction["type"] = instr_type_original + "_error" + return True - comparison_scl = f"{op1} = {op2}" - - # Guardar el resultado booleano de la comparación en el mapa SCL para la salida 'out' + # Guardar resultado (Expresión SymPy booleana) en el mapa para 'out' map_key_out = (network_id, instr_uid, "out") - scl_map[map_key_out] = comparison_scl + sympy_map[map_key_out] = comparison_expr - # Procesar la entrada 'pre' (RLO anterior) para determinar ENO - pre_input = instruction["inputs"].get("pre") - pre_scl = ( - "TRUE" - if pre_input is None - else get_scl_representation(pre_input, network_id, scl_map, access_map) - ) - if pre_scl is None: - return False # Dependencia 'pre' no lista - - # Guardar el estado de 'pre' como ENO + # Guardar el RLO de entrada ('pre') como ENO en el mapa SymPy map_key_eno = (network_id, instr_uid, "eno") - scl_map[map_key_eno] = pre_scl + sympy_map[map_key_eno] = sympy_pre_rlo - # El SCL generado es solo un comentario indicando la condición, - # ya que la lógica se propaga a través de scl_map['out'] - instruction["scl"] = f"// Comparison Eq {instr_uid}: {comparison_scl}" - instruction["type"] = instr_type + SCL_SUFFIX + # Marcar como procesado, SCL principal es solo comentario + instruction["scl"] = f"// SymPy EQ: {comparison_expr}" # Comentario opcional + instruction["type"] = instr_type_original + SCL_SUFFIX return True -# --- Function code ends --- - # --- Processor Information Function --- def get_processor_info(): """Devuelve la información para el comparador de igualdad (EQ).""" - return {'type_name': 'eq', 'processor_func': process_eq, 'priority': 2} + return {'type_name': 'eq', 'processor_func': process_eq, 'priority': 2} \ No newline at end of file diff --git a/processors/process_math.py b/processors/process_math.py index 67189ca..b181a12 100644 --- a/processors/process_math.py +++ b/processors/process_math.py @@ -1,82 +1,90 @@ +# processors/process_math.py # -*- coding: utf-8 -*- -from .processor_utils import get_scl_representation, format_variable_name,get_target_scl_name +import sympy +import traceback +# Usar las nuevas utilidades +from .processor_utils import get_sympy_representation, sympy_expr_to_scl, get_target_scl_name, format_variable_name +from .symbol_manager import SymbolManager +SCL_SUFFIX = "_sympy_processed" -# TODO: Import necessary functions from processor_utils -# Example: from .processor_utils import get_scl_representation, format_variable_name -# Or: import processors.processor_utils as utils - -# TODO: Define constants if needed (e.g., SCL_SUFFIX) or import them -SCL_SUFFIX = "_scl" - -# --- Function code starts --- -def process_math(instruction, network_id, scl_map, access_map, data): +def process_math(instruction, network_id, sympy_map, symbol_manager: SymbolManager, data): """ - Genera SCL para operaciones matemáticas (SUB, MUL, DIV). + Genera SCL para operaciones matemáticas (SUB, MUL, DIV), simplificando EN. """ instr_uid = instruction["instruction_uid"] - instr_type = instruction["type"] # SUB, MUL, DIV - if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + instr_type_original = instruction.get("type", "") # SUB, MUL, DIV + if instr_type_original.endswith(SCL_SUFFIX) or "_error" in instr_type_original: return False - # Mapa de tipos a operadores SCL + # Mapa de tipos a operadores SCL string op_map = {"SUB": "-", "MUL": "*", "DIV": "/"} - scl_operator = op_map.get(instr_type) + scl_operator = op_map.get(instr_type_original.upper()) if not scl_operator: - instruction["scl"] = f"// ERROR: Operación matemática no soportada: {instr_type}" - instruction["type"] += "_error" + instruction["scl"] = f"// ERROR: Operación matemática no soportada: {instr_type_original}" + instruction["type"] = instr_type_original + "_error" return True - # Obtener EN, IN1, IN2 + # Obtener EN (SymPy), IN1, IN2 (SymPy o Constante/String) en_input = instruction["inputs"].get("en") in1_info = instruction["inputs"].get("in1") in2_info = instruction["inputs"].get("in2") - en_scl = get_scl_representation(en_input, network_id, scl_map, access_map) if en_input else "TRUE" - in1_scl = get_scl_representation(in1_info, network_id, scl_map, access_map) - in2_scl = get_scl_representation(in2_info, network_id, scl_map, access_map) + sympy_en_expr = get_sympy_representation(en_input, network_id, sympy_map, symbol_manager) if en_input else sympy.true + op1_sympy_or_const = get_sympy_representation(in1_info, network_id, sympy_map, symbol_manager) + op2_sympy_or_const = get_sympy_representation(in2_info, network_id, sympy_map, symbol_manager) - if en_scl is None or in1_scl is None or in2_scl is None: - return False # Dependencias no listas + # Obtener destino SCL + target_scl_name = get_target_scl_name(instruction, "out", network_id, default_to_temp=True) - # Obtener destino 'out' - target_scl = get_target_scl_name(instruction, "out", network_id, default_to_temp=True) - if target_scl is None: - instruction["scl"] = f"// ERROR: {instr_type} {instr_uid} sin destino 'out'." - instruction["type"] += "_error" - return True + # Verificar dependencias + if sympy_en_expr is None or op1_sympy_or_const is None or op2_sympy_or_const is None or target_scl_name is None: + return False - # Formatear operandos si son variables - op1 = format_variable_name(in1_scl) if in1_info and in1_info.get("type") == "variable" else in1_scl - op2 = format_variable_name(in2_scl) if in2_info and in2_info.get("type") == "variable" else in2_scl + # Convertir operandos SymPy/Constante a SCL strings + op1_scl = sympy_expr_to_scl(op1_sympy_or_const, symbol_manager) + op2_scl = sympy_expr_to_scl(op2_sympy_or_const, symbol_manager) - # Añadir paréntesis si es necesario (especialmente para expresiones) - op1 = f"({op1})" if (" " in op1 or "+" in op1 or "-" in op1 or "*" in op1 or "/" in op1) and not op1.startswith("(") else op1 - op2 = f"({op2})" if (" " in op2 or "+" in op2 or "-" in op2 or "*" in op2 or "/" in op2) and not op2.startswith("(") else op2 + # Añadir paréntesis si contienen operadores (más seguro) + # La función sympy_expr_to_scl debería idealmente manejar esto, pero doble chequeo simple: + op1_scl_formatted = f"({op1_scl})" if re.search(r'[+\-*/ ]', op1_scl) else op1_scl + op2_scl_formatted = f"({op2_scl})" if re.search(r'[+\-*/ ]', op2_scl) else op2_scl - # Generar SCL - scl_core = f"{target_scl} := {op1} {scl_operator} {op2};" - scl_final = f"IF {en_scl} THEN\n {scl_core}\nEND_IF;" if en_scl != "TRUE" else scl_core + # Generar SCL Core + scl_core = f"{target_scl_name} := {op1_scl_formatted} {scl_operator} {op2_scl_formatted};" - instruction["scl"] = scl_final - instruction["type"] = instr_type + SCL_SUFFIX + # Aplicar Condición EN (Simplificando EN) + scl_final = "" + if sympy_en_expr != sympy.true: + try: + #simplified_en_expr = sympy.simplify_logic(sympy_en_expr, force=True) + simplified_en_expr = sympy.logic.boolalg.to_dnf(sympy_en_expr, simplify=True) + except Exception as e: + print(f"Error simplifying EN for {instr_type_original} {instr_uid}: {e}") + simplified_en_expr = sympy_en_expr # Fallback + en_condition_scl = sympy_expr_to_scl(simplified_en_expr, symbol_manager) - # Actualizar mapa SCL + indented_core = "\n".join([f" {line}" for line in scl_core.splitlines()]) + scl_final = f"IF {en_condition_scl} THEN\n{indented_core}\nEND_IF;" + else: + scl_final = scl_core + + # Actualizar instrucción y mapa + instruction["scl"] = scl_final # SCL final generado + instruction["type"] = instr_type_original + SCL_SUFFIX + + # Propagar valor de salida (nombre SCL del destino) y ENO (expresión SymPy) map_key_out = (network_id, instr_uid, "out") - scl_map[map_key_out] = target_scl + sympy_map[map_key_out] = target_scl_name # Guardar nombre del destino map_key_eno = (network_id, instr_uid, "eno") - scl_map[map_key_eno] = en_scl + sympy_map[map_key_eno] = sympy_en_expr # Guardar la expresión SymPy para ENO + return True -# --- Procesador NOT --- - -# --- Function code ends --- - # --- Processor Information Function --- def get_processor_info(): - """Devuelve la información para operaciones matemáticas (excepto ADD, MOD).""" - # Esta función maneja SUB, MUL, DIV. + """Devuelve info para SUB, MUL, DIV.""" return [ - {'type_name': 'sub', 'processor_func': process_math, 'priority': 4}, # Resta - {'type_name': 'mul', 'processor_func': process_math, 'priority': 4}, # Multiplicación - {'type_name': 'div', 'processor_func': process_math, 'priority': 4} # División - ] + {'type_name': 'sub', 'processor_func': process_math, 'priority': 4}, + {'type_name': 'mul', 'processor_func': process_math, 'priority': 4}, + {'type_name': 'div', 'processor_func': process_math, 'priority': 4} + ] \ No newline at end of file diff --git a/processors/process_mod.py b/processors/process_mod.py index 8f65620..03c0ef1 100644 --- a/processors/process_mod.py +++ b/processors/process_mod.py @@ -1,76 +1,75 @@ +# processors/process_mod.py # -*- coding: utf-8 -*- -from .processor_utils import get_scl_representation, format_variable_name,get_target_scl_name +import sympy +import traceback +import re # Importar re si no estaba +from .processor_utils import get_sympy_representation, sympy_expr_to_scl, get_target_scl_name, format_variable_name +from .symbol_manager import SymbolManager +SCL_SUFFIX = "_sympy_processed" -# TODO: Import necessary functions from processor_utils -# Example: from .processor_utils import get_scl_representation, format_variable_name -# Or: import processors.processor_utils as utils - -# TODO: Define constants if needed (e.g., SCL_SUFFIX) or import them -SCL_SUFFIX = "_scl" - -# --- Function code starts --- -def process_mod(instruction, network_id, scl_map, access_map, data): +def process_mod(instruction, network_id, sympy_map, symbol_manager: SymbolManager, data): + """Genera SCL para Modulo (MOD), simplificando EN.""" instr_uid = instruction["instruction_uid"] - instr_type = instruction["type"] - if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + instr_type_original = instruction.get("type", "Mod") + if instr_type_original.endswith(SCL_SUFFIX) or "_error" in instr_type_original: return False + # Obtener EN (SymPy), IN1, IN2 (SymPy o Constante/String) en_input = instruction["inputs"].get("en") - en_scl = ( - get_scl_representation(en_input, network_id, scl_map, access_map) - if en_input - else "TRUE" - ) in1_info = instruction["inputs"].get("in1") in2_info = instruction["inputs"].get("in2") - in1_scl = get_scl_representation(in1_info, network_id, scl_map, access_map) - in2_scl = get_scl_representation(in2_info, network_id, scl_map, access_map) + sympy_en_expr = get_sympy_representation(en_input, network_id, sympy_map, symbol_manager) if en_input else sympy.true + op1_sympy_or_const = get_sympy_representation(in1_info, network_id, sympy_map, symbol_manager) + op2_sympy_or_const = get_sympy_representation(in2_info, network_id, sympy_map, symbol_manager) - if en_scl is None or in1_scl is None or in2_scl is None: + # Obtener destino SCL + target_scl_name = get_target_scl_name(instruction, "out", network_id, default_to_temp=True) + + # Verificar dependencias + if sympy_en_expr is None or op1_sympy_or_const is None or op2_sympy_or_const is None or target_scl_name is None: return False - target_scl = get_target_scl_name( - instruction, "out", network_id, default_to_temp=True - ) - if target_scl is None: - print(f"Error: Sin destino MOD {instr_uid}") - instruction["scl"] = f"// ERROR: Mod {instr_uid} sin destino" - instruction["type"] += "_error" - return True + # Convertir operandos SymPy/Constante a SCL strings + op1_scl = sympy_expr_to_scl(op1_sympy_or_const, symbol_manager) + op2_scl = sympy_expr_to_scl(op2_sympy_or_const, symbol_manager) - # Formatear operandos si son variables - op1 = ( - format_variable_name(in1_scl) - if in1_info and in1_info.get("type") == "variable" - else in1_scl - ) - op2 = ( - format_variable_name(in2_scl) - if in2_info and in2_info.get("type") == "variable" - else in2_scl - ) + # Añadir paréntesis si contienen operadores + op1_scl_formatted = f"({op1_scl})" if re.search(r'[+\-*/ ]', op1_scl) else op1_scl + op2_scl_formatted = f"({op2_scl})" if re.search(r'[+\-*/ ]', op2_scl) else op2_scl - # Añadir paréntesis si es necesario (poco probable tras formatear) - op1 = f"({op1})" if " " in op1 and not op1.startswith("(") else op1 - op2 = f"({op2})" if " " in op2 and not op2.startswith("(") else op2 + # Generar SCL Core + scl_core = f"{target_scl_name} := {op1_scl_formatted} MOD {op2_scl_formatted};" - scl_core = f"{target_scl} := {op1} MOD {op2};" - scl_final = ( - f"IF {en_scl} THEN\n {scl_core}\nEND_IF;" if en_scl != "TRUE" else scl_core - ) + # Aplicar Condición EN (Simplificando EN) + scl_final = "" + if sympy_en_expr != sympy.true: + try: + #simplified_en_expr = sympy.simplify_logic(sympy_en_expr, force=True) + simplified_en_expr = sympy.logic.boolalg.to_dnf(sympy_en_expr, simplify=True) + except Exception as e: + print(f"Error simplifying EN for {instr_type_original} {instr_uid}: {e}") + simplified_en_expr = sympy_en_expr # Fallback + en_condition_scl = sympy_expr_to_scl(simplified_en_expr, symbol_manager) - instruction["scl"] = scl_final - instruction["type"] = instr_type + SCL_SUFFIX + indented_core = "\n".join([f" {line}" for line in scl_core.splitlines()]) + scl_final = f"IF {en_condition_scl} THEN\n{indented_core}\nEND_IF;" + else: + scl_final = scl_core + + # Actualizar instrucción y mapa + instruction["scl"] = scl_final # SCL final generado + instruction["type"] = instr_type_original + SCL_SUFFIX + + # Propagar valor de salida (nombre SCL del destino) y ENO (expresión SymPy) map_key_out = (network_id, instr_uid, "out") - scl_map[map_key_out] = target_scl + sympy_map[map_key_out] = target_scl_name # Guardar nombre del destino map_key_eno = (network_id, instr_uid, "eno") - scl_map[map_key_eno] = en_scl - return True + sympy_map[map_key_eno] = sympy_en_expr # Guardar la expresión SymPy para ENO -# --- Function code ends --- + return True # --- Processor Information Function --- def get_processor_info(): """Devuelve la información para la operación Modulo.""" - return {'type_name': 'mod', 'processor_func': process_mod, 'priority': 4} + return {'type_name': 'mod', 'processor_func': process_mod, 'priority': 4} \ No newline at end of file diff --git a/processors/process_move.py b/processors/process_move.py index 431c680..b950797 100644 --- a/processors/process_move.py +++ b/processors/process_move.py @@ -1,83 +1,74 @@ +# processors/process_move.py # -*- coding: utf-8 -*- -from .processor_utils import get_scl_representation, format_variable_name,get_target_scl_name +import sympy +import traceback +import re # Importar re +from .processor_utils import get_sympy_representation, sympy_expr_to_scl, get_target_scl_name, format_variable_name +from .symbol_manager import SymbolManager +SCL_SUFFIX = "_sympy_processed" -# TODO: Import necessary functions from processor_utils -# Example: from .processor_utils import get_scl_representation, format_variable_name -# Or: import processors.processor_utils as utils - -# TODO: Define constants if needed (e.g., SCL_SUFFIX) or import them -SCL_SUFFIX = "_scl" - -# --- Function code starts --- -def process_move(instruction, network_id, scl_map, access_map, data): +def process_move(instruction, network_id, sympy_map, symbol_manager: SymbolManager, data): + """Genera SCL para Move, simplificando la condición EN.""" instr_uid = instruction["instruction_uid"] - instr_type = instruction["type"] - if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + instr_type_original = instruction.get("type", "Move") + if instr_type_original.endswith(SCL_SUFFIX) or "_error" in instr_type_original: return False + # Obtener EN (SymPy) e IN (SymPy o Constante/String) en_input = instruction["inputs"].get("en") - en_scl = ( - get_scl_representation(en_input, network_id, scl_map, access_map) - if en_input - else "TRUE" - ) in_info = instruction["inputs"].get("in") - in_scl = get_scl_representation(in_info, network_id, scl_map, access_map) + sympy_en_expr = get_sympy_representation(en_input, network_id, sympy_map, symbol_manager) if en_input else sympy.true + input_sympy_or_const = get_sympy_representation(in_info, network_id, sympy_map, symbol_manager) - if en_scl is None or in_scl is None: + # Obtener destino SCL (requiere destino explícito para MOVE) + target_scl_name = get_target_scl_name(instruction, "out1", network_id, default_to_temp=False) + if target_scl_name is None: + target_scl_name = get_target_scl_name(instruction, "out", network_id, default_to_temp=False) + + # Verificar dependencias + if sympy_en_expr is None or input_sympy_or_const is None: return False + if target_scl_name is None: + print(f"Error: MOVE {instr_uid} sin destino claro en 'out' o 'out1'.") + instruction["scl"] = f"// ERROR: MOVE {instr_uid} sin destino claro." + instruction["type"] = instr_type_original + "_error" + return True # Procesado con error - # Intentar obtener el destino de 'out1' (o 'out' si es el estándar) - target_scl = get_target_scl_name( - instruction, "out1", network_id, default_to_temp=False - ) - if target_scl is None: - target_scl = get_target_scl_name( - instruction, "out", network_id, default_to_temp=False - ) + # Convertir la entrada (SymPy o Constante) a SCL string + input_scl = sympy_expr_to_scl(input_sympy_or_const, symbol_manager) - if target_scl is None: - # Si no hay destino explícito, podríamos usar una temp si la lógica lo requiere, - # pero MOVE generalmente necesita un destino claro. Marcar como advertencia/error. - print( - f"Advertencia/Error: MOVE {instr_uid} sin destino claro en 'out' o 'out1'. Se requiere destino explícito." - ) - # Decidir si generar error o simplemente no hacer nada. No hacer nada es más seguro. - # instruction["scl"] = f"// ERROR: MOVE {instr_uid} sin destino" - # instruction["type"] += "_error" - # return True - return False # No procesar si no hay destino claro + # Generar SCL Core + scl_core = f"{target_scl_name} := {input_scl};" - # Formatear entrada si es variable - in_scl_formatted = ( - format_variable_name(in_scl) - if in_info and in_info.get("type") == "variable" - else in_scl - ) + # Aplicar Condición EN (Simplificando EN) + scl_final = "" + if sympy_en_expr != sympy.true: + try: + #simplified_en_expr = sympy.simplify_logic(sympy_en_expr, force=True) + simplified_en_expr = sympy.logic.boolalg.to_dnf(sympy_en_expr, simplify=True) + except Exception as e: + print(f"Error simplifying EN for {instr_type_original} {instr_uid}: {e}") + simplified_en_expr = sympy_en_expr # Fallback + en_condition_scl = sympy_expr_to_scl(simplified_en_expr, symbol_manager) - scl_core = f"{target_scl} := {in_scl_formatted};" - scl_final = ( - f"IF {en_scl} THEN\n {scl_core}\nEND_IF;" if en_scl != "TRUE" else scl_core - ) + indented_core = "\n".join([f" {line}" for line in scl_core.splitlines()]) + scl_final = f"IF {en_condition_scl} THEN\n{indented_core}\nEND_IF;" + else: + scl_final = scl_core - instruction["scl"] = scl_final - instruction["type"] = instr_type + SCL_SUFFIX + # Actualizar instrucción y mapa + instruction["scl"] = scl_final # SCL final generado + instruction["type"] = instr_type_original + SCL_SUFFIX - # Propagar el valor movido a través de scl_map si se usa 'out' o 'out1' como fuente - map_key_out = (network_id, instr_uid, "out") # Asumir 'out' como estándar - scl_map[map_key_out] = target_scl # El valor es lo que está en el destino - map_key_out1 = (network_id, instr_uid, "out1") # Si existe out1 - scl_map[map_key_out1] = target_scl + # Propagar valor de salida (nombre SCL del destino) y ENO (expresión SymPy) + # Asumiendo que out y out1 deben propagar el mismo valor + sympy_map[(network_id, instr_uid, "out")] = target_scl_name + sympy_map[(network_id, instr_uid, "out1")] = target_scl_name + sympy_map[(network_id, instr_uid, "eno")] = sympy_en_expr - map_key_eno = (network_id, instr_uid, "eno") - scl_map[map_key_eno] = en_scl return True -# EN x2_process.py - -# --- Function code ends --- - # --- Processor Information Function --- def get_processor_info(): """Devuelve la información para la operación Move.""" diff --git a/processors/process_not.py b/processors/process_not.py index 8161dee..b721aee 100644 --- a/processors/process_not.py +++ b/processors/process_not.py @@ -1,47 +1,54 @@ +# processors/process_not.py # -*- coding: utf-8 -*- -from .processor_utils import get_scl_representation, format_variable_name,get_target_scl_name +import sympy +import traceback +# Usar las nuevas utilidades +from .processor_utils import get_sympy_representation +from .symbol_manager import SymbolManager +SCL_SUFFIX = "_sympy_processed" # Nuevo sufijo -# TODO: Import necessary functions from processor_utils -# Example: from .processor_utils import get_scl_representation, format_variable_name -# Or: import processors.processor_utils as utils - -# TODO: Define constants if needed (e.g., SCL_SUFFIX) or import them -SCL_SUFFIX = "_scl" - -# --- Function code starts --- -def process_not(instruction, network_id, scl_map, access_map, data): - """Genera la expresión SCL para la inversión lógica NOT.""" +def process_not(instruction, network_id, sympy_map, symbol_manager: SymbolManager, data): + """Genera la expresión SymPy para la inversión lógica NOT.""" instr_uid = instruction["instruction_uid"] - instr_type = instruction["type"] # Not - if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + instr_type_original = instruction.get("type", "Not") + if instr_type_original.endswith(SCL_SUFFIX) or "_error" in instr_type_original: return False + # Obtener entrada como expresión SymPy in_info = instruction["inputs"].get("in") - in_scl = get_scl_representation(in_info, network_id, scl_map, access_map) + sympy_expr_in = get_sympy_representation(in_info, network_id, sympy_map, symbol_manager) - if in_scl is None: - return False # Dependencia no lista + # Verificar dependencias + if sympy_expr_in is None: + # print(f"DEBUG Not {instr_uid}: Dependency not ready") + return False - # Formatear entrada (añadir paréntesis si es complejo) - in_scl_formatted = in_scl - if (" " in in_scl or "AND" in in_scl or "OR" in in_scl) and not (in_scl.startswith("(") and in_scl.endswith(")")): - in_scl_formatted = f"({in_scl})" + # Crear la expresión NOT de SymPy + try: + not_expr = sympy.Not(sympy_expr_in) + # ¿Simplificar aquí? NOT(NOT A) -> A; NOT(TRUE) -> FALSE, etc. + # simplify_logic podría hacer esto, pero puede ser costoso en cada paso. + # SymPy podría manejar simplificaciones básicas automáticamente. + # Opcional: not_expr = sympy.simplify_logic(not_expr) + except Exception as e: + print(f"Error creating SymPy Not for {instr_uid}: {e}") + instruction["scl"] = f"// ERROR creando expr SymPy NOT {instr_uid}: {e}" + instruction["type"] = instr_type_original + "_error" + return True - result_scl = f"NOT {in_scl_formatted}" - - # Guardar resultado en mapa para 'out' + # Guardar resultado (Expresión SymPy) en el mapa para 'out' map_key_out = (network_id, instr_uid, "out") - scl_map[map_key_out] = result_scl + sympy_map[map_key_out] = not_expr + + # Marcar como procesado, SCL principal es solo comentario + instruction["scl"] = f"// SymPy NOT: {not_expr}" # Comentario opcional + instruction["type"] = instr_type_original + SCL_SUFFIX + # NOT no tiene EN/ENO explícito en LAD, modifica el RLO ('out') - instruction["scl"] = f"// Logic NOT {instr_uid}: {result_scl}" - instruction["type"] = instr_type + SCL_SUFFIX - # NOT no tiene EN/ENO explícito en LAD, modifica el RLO return True -# --- Function code ends --- - # --- Processor Information Function --- def get_processor_info(): """Devuelve la información para la operación Not.""" - return {'type_name': 'not', 'processor_func': process_not, 'priority': 1} + return {'type_name': 'not', 'processor_func': process_not, 'priority': 1} \ No newline at end of file diff --git a/processors/process_o.py b/processors/process_o.py index 32abfb7..446817f 100644 --- a/processors/process_o.py +++ b/processors/process_o.py @@ -1,80 +1,69 @@ +# processors/process_o.py # -*- coding: utf-8 -*- -from .processor_utils import get_scl_representation, format_variable_name,get_target_scl_name +import sympy +import traceback +# Usar las nuevas utilidades +from .processor_utils import get_sympy_representation +from .symbol_manager import SymbolManager +SCL_SUFFIX = "_sympy_processed" # Nuevo sufijo -# TODO: Import necessary functions from processor_utils -# Example: from .processor_utils import get_scl_representation, format_variable_name -# Or: import processors.processor_utils as utils - -# TODO: Define constants if needed (e.g., SCL_SUFFIX) or import them -SCL_SUFFIX = "_scl" - -# --- Function code starts --- -def process_o(instruction, network_id, scl_map, access_map, data): +def process_o(instruction, network_id, sympy_map, symbol_manager: SymbolManager, data): + """Genera la expresión SymPy para la operación lógica O (OR).""" instr_uid = instruction["instruction_uid"] - instr_type = instruction["type"] - if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + instr_type_original = instruction.get("type", "O") + if instr_type_original.endswith(SCL_SUFFIX) or "_error" in instr_type_original: return False # Buscar todas las entradas 'in', 'in1', 'in2', ... - input_pins = sorted([pin for pin in instruction["inputs"] if pin.startswith("in")]) + input_pins = sorted([pin for pin in instruction.get("inputs", {}) if pin.startswith("in")]) if not input_pins: print(f"Error: O {instr_uid} sin pines de entrada (inX).") instruction["scl"] = f"// ERROR: O {instr_uid} sin pines inX" - instruction["type"] += "_error" - return True # Procesado con error + instruction["type"] = instr_type_original + "_error" + return True - scl_parts = [] + sympy_parts = [] all_resolved = True for pin in input_pins: - in_scl = get_scl_representation( - instruction["inputs"][pin], network_id, scl_map, access_map - ) - if in_scl is None: + input_info = instruction["inputs"][pin] + sympy_expr = get_sympy_representation(input_info, network_id, sympy_map, symbol_manager) + + if sympy_expr is None: all_resolved = False # print(f"DEBUG: O {instr_uid} esperando pin {pin}") - break # Salir del bucle for si una entrada no está lista + break # Salir si una dependencia no está lista - # Formatear término (añadir paréntesis si es necesario) - term = in_scl - if (" " in term or "AND" in term) and not ( - term.startswith("(") and term.endswith(")") - ): - term = f"({term})" - scl_parts.append(term) + # Optimización: No incluir FALSE en un OR + if sympy_expr != sympy.false: + sympy_parts.append(sympy_expr) if not all_resolved: - return False # Esperar a que todas las entradas estén resueltas + return False # Esperar dependencias - # Construir la expresión OR - result_scl = "FALSE" # Valor por defecto si no hay entradas válidas (raro) - if scl_parts: - result_scl = " OR ".join(scl_parts) - # Simplificar si solo hay un término - if len(scl_parts) == 1: - result_scl = scl_parts[0] - # Quitar paréntesis redundantes si solo hay un término y está entre paréntesis - if result_scl.startswith("(") and result_scl.endswith(")"): - # Comprobar si los paréntesis son necesarios (contienen operadores de menor precedencia) - # Simplificación: quitar siempre si solo hay un término. Podría ser incorrecto en casos complejos. - # result_scl = result_scl[1:-1] # Comentado por seguridad - pass + # Construir la expresión OR de SymPy + result_sympy_expr = sympy.false # Valor por defecto si no hay entradas válidas o todas son FALSE + if sympy_parts: + # Usar sympy.Or para construir la expresión + result_sympy_expr = sympy.Or(*sympy_parts) + # Simplificar casos obvios como OR(X) -> X, OR(X, TRUE) -> TRUE + # simplify_logic aquí puede ser prematuro, mejor al final. + # Pero Or() podría simplificar automáticamente OR(X) -> X. + # Opcional: result_sympy_expr = sympy.simplify_logic(result_sympy_expr) - # Actualizar mapa SCL y la instrucción + + # Guardar la expresión SymPy resultante en el mapa para 'out' map_key_out = (network_id, instr_uid, "out") - scl_map[map_key_out] = result_scl - instruction["scl"] = ( - f"// Logic O {instr_uid}: {result_scl}" # Comentario informativo - ) - instruction["type"] = instr_type + SCL_SUFFIX + sympy_map[map_key_out] = result_sympy_expr + # Marcar como procesado, SCL principal es solo comentario + instruction["scl"] = f"// SymPy O: {result_sympy_expr}" # Comentario opcional + instruction["type"] = instr_type_original + SCL_SUFFIX # La instrucción 'O' no tiene ENO propio, propaga el resultado por 'out' return True -# --- Function code ends --- - # --- Processor Information Function --- def get_processor_info(): """Devuelve la información para la operación lógica O (OR).""" - return {'type_name': 'o', 'processor_func': process_o, 'priority': 1} + return {'type_name': 'o', 'processor_func': process_o, 'priority': 1} \ No newline at end of file diff --git a/processors/process_rcoil.py b/processors/process_rcoil.py index 888f906..9824b83 100644 --- a/processors/process_rcoil.py +++ b/processors/process_rcoil.py @@ -1,59 +1,74 @@ +# processors/process_rcoil.py # -*- coding: utf-8 -*- -from .processor_utils import get_scl_representation, format_variable_name,get_target_scl_name +import sympy +import traceback +import re +from .processor_utils import get_sympy_representation, sympy_expr_to_scl, get_target_scl_name, format_variable_name +from .symbol_manager import SymbolManager +SCL_SUFFIX = "_sympy_processed" -# TODO: Import necessary functions from processor_utils -# Example: from .processor_utils import get_scl_representation, format_variable_name -# Or: import processors.processor_utils as utils - -# TODO: Define constants if needed (e.g., SCL_SUFFIX) or import them -SCL_SUFFIX = "_scl" - -# --- Function code starts --- -def process_rcoil(instruction, network_id, scl_map, access_map, data ): - """Genera SCL para Reset Coil (RCoil): IF condition THEN variable := FALSE; END_IF;""" +def process_rcoil(instruction, network_id, sympy_map, symbol_manager: SymbolManager, data ): + """Genera SCL para Reset Coil (RCoil), simplificando la condición.""" instr_uid = instruction["instruction_uid"] - instr_type = instruction["type"] - if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: - return False # Ya procesado o con error + instr_type_original = instruction.get("type", "RCoil") + if instr_type_original.endswith(SCL_SUFFIX) or "_error" in instr_type_original: + return False - # Obtener condición de entrada (RLO) + # Obtener condición de entrada (SymPy expr) in_info = instruction["inputs"].get("in") - condition_scl = get_scl_representation(in_info, network_id, scl_map, access_map) + sympy_expr_in = get_sympy_representation(in_info, network_id, sympy_map, symbol_manager) - # Obtener operando (variable a poner a FALSE) - operand_info = instruction["inputs"].get("operand") - variable_scl = get_scl_representation(operand_info, network_id, scl_map, access_map) + # Obtener operando (nombre SCL del destino) + target_scl_name = get_target_scl_name(instruction, "operand", network_id, default_to_temp=False) # RCoil necesita destino explícito # Verificar dependencias - if condition_scl is None or variable_scl is None: - return False # Dependencias no listas - - # Verificar que el operando sea una variable - if not (operand_info and operand_info.get("type") == "variable"): - print(f"Error: RCoil {instr_uid} operando no es variable o falta info (Tipo: {operand_info.get('type')}).") + if sympy_expr_in is None: return False + if target_scl_name is None: + print(f"Error: RCoil {instr_uid} operando no es variable o falta info.") instruction["scl"] = f"// ERROR: RCoil {instr_uid} operando no es variable." - instruction["type"] += "_error" - return True # Procesado con error + instruction["type"] = instr_type_original + "_error" + return True - # Formatear nombre de variable - variable_name_formatted = format_variable_name(variable_scl) + # No hacer nada si la condición es FALSE constante + if sympy_expr_in == sympy.false: + instruction["scl"] = f"// RCoil {instr_uid} con condición FALSE constante, optimizado." + instruction["type"] = instr_type_original + SCL_SUFFIX + return True - # Generar SCL - scl_core = f"{variable_name_formatted} := FALSE;" - scl_final = ( - f"IF {condition_scl} THEN\n {scl_core}\nEND_IF;" if condition_scl != "TRUE" else scl_core - ) + # Generar SCL Core (Reset) + scl_core = f"{target_scl_name} := FALSE;" + + # Aplicar Condición IF si no es TRUE constante + scl_final = "" + if sympy_expr_in != sympy.true: + # Simplificar la condición ANTES de convertirla a SCL + try: + #simplified_expr = sympy.simplify_logic(sympy_expr_in, force=True) + simplified_expr = sympy.logic.boolalg.to_dnf(sympy_expr_in, simplify=True) + except Exception as e: + print(f"Error simplifying condition for RCoil {instr_uid}: {e}") + simplified_expr = sympy_expr_in # Fallback + condition_scl = sympy_expr_to_scl(simplified_expr, symbol_manager) + + # Evitar IF TRUE THEN... + if condition_scl == "TRUE": + scl_final = scl_core + else: + indented_core = "\n".join([f" {line}" for line in scl_core.splitlines()]) + scl_final = f"IF {condition_scl} THEN\n{indented_core}\nEND_IF;" + else: + # Condición es TRUE constante + scl_final = scl_core # Actualizar instrucción - instruction["scl"] = scl_final - instruction["type"] = instr_type + SCL_SUFFIX - # RCoil no genera salida 'out' ni 'eno' significativas para propagar - return True + instruction["scl"] = scl_final # SCL final generado + instruction["type"] = instr_type_original + SCL_SUFFIX + # RCoil no tiene salida lógica para propagar en sympy_map -# --- Function code ends --- + return True # --- Processor Information Function --- def get_processor_info(): """Devuelve la información para la bobina Reset (RCoil).""" - return {'type_name': 'rcoil', 'processor_func': process_rcoil, 'priority': 3} + return {'type_name': 'rcoil', 'processor_func': process_rcoil, 'priority': 3} \ No newline at end of file diff --git a/processors/process_scoil.py b/processors/process_scoil.py index 104c9b8..4411f51 100644 --- a/processors/process_scoil.py +++ b/processors/process_scoil.py @@ -1,59 +1,74 @@ +# processors/process_scoil.py # -*- coding: utf-8 -*- -from .processor_utils import get_scl_representation, format_variable_name,get_target_scl_name +import sympy +import traceback +import re +from .processor_utils import get_sympy_representation, sympy_expr_to_scl, get_target_scl_name, format_variable_name +from .symbol_manager import SymbolManager +SCL_SUFFIX = "_sympy_processed" -# TODO: Import necessary functions from processor_utils -# Example: from .processor_utils import get_scl_representation, format_variable_name -# Or: import processors.processor_utils as utils - -# TODO: Define constants if needed (e.g., SCL_SUFFIX) or import them -SCL_SUFFIX = "_scl" - -# --- Function code starts --- -def process_scoil(instruction, network_id, scl_map, access_map, data): - """Genera SCL para Set Coil (SCoil): IF condition THEN variable := TRUE; END_IF;""" +def process_scoil(instruction, network_id, sympy_map, symbol_manager: SymbolManager, data): + """Genera SCL para Set Coil (SCoil), simplificando la condición.""" instr_uid = instruction["instruction_uid"] - instr_type = instruction["type"] - if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: - return False # Ya procesado o con error + instr_type_original = instruction.get("type", "SCoil") + if instr_type_original.endswith(SCL_SUFFIX) or "_error" in instr_type_original: + return False - # Obtener condición de entrada (RLO) + # Obtener condición de entrada (SymPy expr) in_info = instruction["inputs"].get("in") - condition_scl = get_scl_representation(in_info, network_id, scl_map, access_map) + sympy_expr_in = get_sympy_representation(in_info, network_id, sympy_map, symbol_manager) - # Obtener operando (variable a poner a TRUE) - operand_info = instruction["inputs"].get("operand") - variable_scl = get_scl_representation(operand_info, network_id, scl_map, access_map) + # Obtener operando (nombre SCL del destino) + target_scl_name = get_target_scl_name(instruction, "operand", network_id, default_to_temp=False) # SCoil necesita destino # Verificar dependencias - if condition_scl is None or variable_scl is None: - return False # Dependencias no listas - - # Verificar que el operando sea una variable - if not (operand_info and operand_info.get("type") == "variable"): - print(f"Error: SCoil {instr_uid} operando no es variable o falta info (Tipo: {operand_info.get('type')}).") + if sympy_expr_in is None: return False + if target_scl_name is None: + print(f"Error: SCoil {instr_uid} operando no es variable o falta info.") instruction["scl"] = f"// ERROR: SCoil {instr_uid} operando no es variable." - instruction["type"] += "_error" - return True # Procesado con error + instruction["type"] = instr_type_original + "_error" + return True - # Formatear nombre de variable - variable_name_formatted = format_variable_name(variable_scl) + # No hacer nada si la condición es FALSE constante + if sympy_expr_in == sympy.false: + instruction["scl"] = f"// SCoil {instr_uid} con condición FALSE constante, optimizado." + instruction["type"] = instr_type_original + SCL_SUFFIX + return True - # Generar SCL - scl_core = f"{variable_name_formatted} := TRUE;" - scl_final = ( - f"IF {condition_scl} THEN\n {scl_core}\nEND_IF;" if condition_scl != "TRUE" else scl_core - ) + # Generar SCL Core (Set) + scl_core = f"{target_scl_name} := TRUE;" + + # Aplicar Condición IF si no es TRUE constante + scl_final = "" + if sympy_expr_in != sympy.true: + # Simplificar la condición ANTES de convertirla a SCL + try: + #simplified_expr = sympy.simplify_logic(sympy_expr_in, force=True) + simplified_expr = sympy.logic.boolalg.to_dnf(sympy_expr_in, simplify=True) + except Exception as e: + print(f"Error simplifying condition for SCoil {instr_uid}: {e}") + simplified_expr = sympy_expr_in # Fallback + condition_scl = sympy_expr_to_scl(simplified_expr, symbol_manager) + + # Evitar IF TRUE THEN... + if condition_scl == "TRUE": + scl_final = scl_core + else: + indented_core = "\n".join([f" {line}" for line in scl_core.splitlines()]) + scl_final = f"IF {condition_scl} THEN\n{indented_core}\nEND_IF;" + else: + # Condición es TRUE constante + scl_final = scl_core # Actualizar instrucción - instruction["scl"] = scl_final - instruction["type"] = instr_type + SCL_SUFFIX - # SCoil no genera salida 'out' ni 'eno' significativas para propagar - return True + instruction["scl"] = scl_final # SCL final generado + instruction["type"] = instr_type_original + SCL_SUFFIX + # SCoil no tiene salida lógica para propagar en sympy_map -# --- Function code ends --- + return True # --- Processor Information Function --- def get_processor_info(): """Devuelve la información para la bobina Set (SCoil).""" - return {'type_name': 'scoil', 'processor_func': process_scoil, 'priority': 3} + return {'type_name': 'scoil', 'processor_func': process_scoil, 'priority': 3} \ No newline at end of file diff --git a/processors/process_sd.py b/processors/process_sd.py index e07206f..72d51eb 100644 --- a/processors/process_sd.py +++ b/processors/process_sd.py @@ -1,73 +1,77 @@ +# processors/process_sd.py # -*- coding: utf-8 -*- -from .processor_utils import get_scl_representation, format_variable_name,get_target_scl_name +import sympy +import traceback +# Usar las nuevas utilidades +from .processor_utils import get_sympy_representation, sympy_expr_to_scl, format_variable_name, get_target_scl_name +from .symbol_manager import SymbolManager, extract_plc_variable_name +SCL_SUFFIX = "_sympy_processed" -# TODO: Import necessary functions from processor_utils -# Example: from .processor_utils import get_scl_representation, format_variable_name -# Or: import processors.processor_utils as utils - -# TODO: Define constants if needed (e.g., SCL_SUFFIX) or import them -SCL_SUFFIX = "_scl" - -# --- Function code starts --- -def process_sd(instruction, network_id, scl_map, access_map, data): +def process_sd(instruction, network_id, sympy_map, symbol_manager: SymbolManager, data): """ Genera SCL para Temporizador On-Delay (Sd -> TON). Requiere datos de instancia (DB o STAT/TEMP). """ instr_uid = instruction["instruction_uid"] - instr_type = "Sd" # Tipo original LAD - if instruction["type"].endswith(SCL_SUFFIX) or "_error" in instruction["type"]: + instr_type_original = "Sd" # Tipo original LAD + if instruction.get("type","").endswith(SCL_SUFFIX) or "_error" in instruction.get("type",""): return False - # 1. Obtener Inputs: s (start), tv (time value) - # El pin 'r' (reset) no tiene equivalente directo en TON, se ignora aquí. + # 1. Obtener Inputs: s (start), tv (time value), timer (instance) s_info = instruction["inputs"].get("s") tv_info = instruction["inputs"].get("tv") - timer_instance_info = instruction["inputs"].get("timer") # Esperando que x1 lo extraiga + timer_instance_info = instruction["inputs"].get("timer") - scl_s = get_scl_representation(s_info, network_id, scl_map, access_map) - scl_tv = get_scl_representation(tv_info, network_id, scl_map, access_map) - scl_instance_name = get_scl_representation(timer_instance_info, network_id, scl_map, access_map) + sympy_s_expr = get_sympy_representation(s_info, network_id, sympy_map, symbol_manager) + # tv suele ser constante, pero lo obtenemos igual + sympy_or_const_tv = get_sympy_representation(tv_info, network_id, sympy_map, symbol_manager) + # Obtener el nombre de la INSTANCIA (no su valor) + instance_plc_name = extract_plc_variable_name(timer_instance_info) - if scl_s is None or scl_tv is None: - return False # Dependencias no listas + # Verificar dependencias + if sympy_s_expr is None or sympy_or_const_tv is None: return False + if instance_plc_name is None: + print(f"Error: Sd {instr_uid} sin variable de instancia 'timer'.") + instance_plc_name = f"#TON_INSTANCE_{instr_uid}" # Placeholder con error implícito + print(f"Advertencia: Usando placeholder '{instance_plc_name}'. ¡Declarar en SCL!") + # Podríamos marcar como error, pero intentamos generar algo + # instruction["type"] = instr_type_original + "_error" + # return True - # 2. Validar y obtener Nombre de Instancia - instance_name = None - if timer_instance_info and timer_instance_info.get("type") == "variable": - instance_name = scl_instance_name - elif timer_instance_info: - print(f"Advertencia: Pin 'timer' de {instr_type} UID {instr_uid} conectado a algo inesperado: {timer_instance_info.get('type')}") - instance_name = f"#TON_INSTANCE_{instr_uid}" - else: - instance_name = f"#TON_INSTANCE_{instr_uid}" - print(f"Advertencia: No se encontró conexión al pin 'timer' para {instr_type} UID {instr_uid}. Usando placeholder '{instance_name}'. ¡Revisar x1.py y XML!") + # Formatear nombre de instancia + instance_name_scl = format_variable_name(instance_plc_name) - # 3. Formatear entradas si son variables - scl_s_formatted = format_variable_name(scl_s) if s_info and s_info.get("type") == "variable" else scl_s - scl_tv_formatted = format_variable_name(scl_tv) if tv_info and tv_info.get("type") == "variable" else scl_tv + # Convertir entradas SymPy/Constante a SCL strings + s_scl = sympy_expr_to_scl(sympy_s_expr, symbol_manager) + tv_scl = sympy_expr_to_scl(sympy_or_const_tv, symbol_manager) - # 4. Generar la llamada SCL (TON usa IN, PT, Q, ET) - scl_call = f"{instance_name}(IN := {scl_s_formatted}, PT := {scl_tv_formatted}); // TODO: Declarar {instance_name} : TON; en VAR_STAT o VAR" + # Generar la llamada SCL (TON usa IN, PT) + # Ignoramos 'r' (reset) de Sd + scl_call = f"{instance_name_scl}(IN := {s_scl}, PT := {tv_scl}); // TODO: Declarar {instance_name_scl} : TON;" - instruction["scl"] = scl_call - instruction["type"] = instr_type + SCL_SUFFIX + # Actualizar instrucción + instruction["scl"] = scl_call # SCL final generado + instruction["type"] = instr_type_original + SCL_SUFFIX - # 5. Actualizar scl_map para las salidas Q y RT (mapeado a ET de TON) + # 7. Actualizar sympy_map para las salidas Q y RT map_key_q = (network_id, instr_uid, "q") - scl_map[map_key_q] = f"{instance_name}.Q" + q_output_scl_access = f"{instance_name_scl}.Q" # SCL string to access output + # *** GET/CREATE AND STORE SYMBOL for boolean output Q *** + sympy_q_symbol = symbol_manager.get_symbol(q_output_scl_access) + if sympy_q_symbol: + sympy_map[map_key_q] = sympy_q_symbol # STORE THE SYMBOL OBJECT + else: + print(f"Error: Could not create symbol for {q_output_scl_access} in Sd {instr_uid}") + sympy_map[map_key_q] = None # Indicate error/unresolved + map_key_rt = (network_id, instr_uid, "rt") - scl_map[map_key_rt] = f"{instance_name}.ET" + # ET is TIME, store SCL access string + sympy_map[map_key_rt] = f"{instance_name_scl}.ET" return True -# --- NUEVO: Procesador de Agrupación (Refinado) --- - -# --- Function code ends --- - # --- Processor Information Function --- def get_processor_info(): """Devuelve la información para el temporizador On-Delay (Sd -> TON).""" - # Asumiendo que el tipo en el JSON es 'Sd' - return {'type_name': 'sd', 'processor_func': process_sd, 'priority': 5} + return {'type_name': 'sd', 'processor_func': process_sd, 'priority': 5} \ No newline at end of file diff --git a/processors/process_se.py b/processors/process_se.py index e894898..cb44741 100644 --- a/processors/process_se.py +++ b/processors/process_se.py @@ -1,91 +1,112 @@ +# processors/process_se.py # -*- coding: utf-8 -*- -from .processor_utils import get_scl_representation, format_variable_name,get_target_scl_name +import sympy +import traceback +# Usar las nuevas utilidades +from .processor_utils import get_sympy_representation, sympy_expr_to_scl, format_variable_name, get_target_scl_name +from .symbol_manager import SymbolManager, extract_plc_variable_name +SCL_SUFFIX = "_sympy_processed" -# TODO: Import necessary functions from processor_utils -# Example: from .processor_utils import get_scl_representation, format_variable_name -# Or: import processors.processor_utils as utils - -# TODO: Define constants if needed (e.g., SCL_SUFFIX) or import them -SCL_SUFFIX = "_scl" - -# --- Function code starts --- -def process_se(instruction, network_id, scl_map, access_map, data): +def process_se(instruction, network_id, sympy_map, symbol_manager: SymbolManager, data): """ - Genera SCL para Temporizador de Pulso (Se -> TP). - Requiere datos de instancia (DB o STAT/TEMP). + Genera SCL para Temporizador de Pulso (Se -> TP) o SdCoil (-> TON). + Usa SymPy para entradas y almacena Symbol para salida Q. """ instr_uid = instruction["instruction_uid"] - instr_type = "Se" # Tipo original LAD - if instruction["type"].endswith(SCL_SUFFIX) or "_error" in instruction["type"]: + # Obtener tipo original (antes de añadir sufijo) para determinar comportamiento + instr_type_original = instruction.get("type", "").replace(SCL_SUFFIX,"").replace("_error","") # Se o SdCoil + current_type = instruction.get("type","") # Tipo actual para chequeo inicial + if current_type.endswith(SCL_SUFFIX) or "_error" in current_type: return False - # 1. Obtener Inputs: s (start), tv (time value) - # El pin 'r' (reset) no tiene equivalente directo en TP, se ignora aquí. - s_info = instruction["inputs"].get("s") - tv_info = instruction["inputs"].get("tv") - timer_instance_info = instruction["inputs"].get("timer") # Esperando que x1 lo extraiga + # Determinar el tipo de instrucción SCL y pines de entrada/salida correctos + scl_timer_type = "TP" + pin_in = "s" # Pin de entrada para Se + pin_time = "tv" # Pin de valor de tiempo para Se + pin_instance = "timer" # Pin donde se conecta la instancia para Se + pin_out_q = "q" # Pin de salida Q para Se + pin_out_time = "rt" # Pin de tiempo restante para Se -> TP.ET - scl_s = get_scl_representation(s_info, network_id, scl_map, access_map) - scl_tv = get_scl_representation(tv_info, network_id, scl_map, access_map) - # Obtenemos el nombre de la variable instancia, crucial! - scl_instance_name = get_scl_representation(timer_instance_info, network_id, scl_map, access_map) + # Ajustar pines si el tipo original era SdCoil + if instr_type_original == "SdCoil": + scl_timer_type = "TON" # SdCoil es funcionalmente un TON + pin_in = "in" # SdCoil usa 'in' + pin_time = "value" # SdCoil usa 'value' + pin_instance = "operand" # SdCoil usa 'operand' como instancia/variable de salida + pin_out_q = "out" # SdCoil usa 'out' como pin de salida Q + pin_out_time = None # SdCoil no tiene salida ET explícita - if scl_s is None or scl_tv is None: - return False # Dependencias no listas + # 1. Obtener Inputs usando los nombres de pin correctos + s_info = instruction["inputs"].get(pin_in) + tv_info = instruction["inputs"].get(pin_time) + timer_instance_info = instruction["inputs"].get(pin_instance) - # 2. Validar y obtener Nombre de Instancia - instance_name = None - if timer_instance_info and timer_instance_info.get("type") == "variable": - instance_name = scl_instance_name # Ya debería estar formateado por get_scl_repr - elif timer_instance_info: # Si está conectado pero no es variable directa? Raro. - print(f"Advertencia: Pin 'timer' de {instr_type} UID {instr_uid} conectado a algo inesperado: {timer_instance_info.get('type')}") - instance_name = f"#TP_INSTANCE_{instr_uid}" # Usar placeholder - else: # Si no hay pin 'timer' conectado (no debería pasar si x1 funciona) - instance_name = f"#TP_INSTANCE_{instr_uid}" # Usar placeholder - print(f"Advertencia: No se encontró conexión al pin 'timer' para {instr_type} UID {instr_uid}. Usando placeholder '{instance_name}'. ¡Revisar x1.py y XML!") + # Obtener representaciones (SymPy o Constante/String) + sympy_s_expr = get_sympy_representation(s_info, network_id, sympy_map, symbol_manager) + sympy_or_const_tv = get_sympy_representation(tv_info, network_id, sympy_map, symbol_manager) + # Obtener el nombre PLC original de la INSTANCIA + instance_plc_name = extract_plc_variable_name(timer_instance_info) - # 3. Formatear entradas si son variables (aunque get_scl_representation ya debería hacerlo) - scl_s_formatted = format_variable_name(scl_s) if s_info and s_info.get("type") == "variable" else scl_s - scl_tv_formatted = format_variable_name(scl_tv) if tv_info and tv_info.get("type") == "variable" else scl_tv + # 2. Verificar dependencias + if sympy_s_expr is None or sympy_or_const_tv is None: + # print(f"DEBUG {instr_type_original} {instr_uid}: Input/TV dependency not ready") + return False + if instance_plc_name is None: + print(f"Error: {instr_type_original} {instr_uid} sin variable de instancia en pin '{pin_instance}'.") + instance_plc_name = f"#{scl_timer_type}_INSTANCE_{instr_uid}" # Placeholder + print(f"Advertencia: Usando placeholder '{instance_plc_name}'. ¡Declarar en SCL!") - # 4. Generar la llamada SCL (TP usa IN, PT, Q, ET) - scl_call = f"{instance_name}(IN := {scl_s_formatted}, PT := {scl_tv_formatted}); // TODO: Declarar {instance_name} : TP; en VAR_STAT o VAR" + # 3. Formatear nombre de instancia para SCL + instance_name_scl = format_variable_name(instance_plc_name) + # 4. Convertir entradas SymPy/Constante a SCL strings (simplificando la entrada IN) + try: + # Simplificar la expresión de entrada booleana + simplified_s_expr = sympy.simplify_logic(sympy_s_expr, force=True) + simplified_s_expr = sympy.logic.boolalg.to_dnf(sympy_s_expr, simplify=True) + except Exception as e: + print(f"Error simplifying '{pin_in}' input for {instr_type_original} {instr_uid}: {e}") + simplified_s_expr = sympy_s_expr # Fallback + s_scl = sympy_expr_to_scl(simplified_s_expr, symbol_manager) + + # tv normalmente es constante, sympy_expr_to_scl debería manejarlo + tv_scl = sympy_expr_to_scl(sympy_or_const_tv, symbol_manager) + + # 5. Generar la llamada SCL + # Ignoramos 'r' (reset) de Se si existiera + scl_call = f"{instance_name_scl}(IN := {s_scl}, PT := {tv_scl}); // TODO: Declarar {instance_name_scl} : {scl_timer_type};" + + # 6. Actualizar instrucción con el SCL final instruction["scl"] = scl_call - instruction["type"] = instr_type + SCL_SUFFIX + instruction["type"] = instr_type_original + SCL_SUFFIX # Marcar como procesado - # 5. Actualizar scl_map usando los nombres de pin ORIGINALES mapeados si existen - output_pin_mapping_reverse = {v: k for k, v in instruction.get("_output_pin_mapping", {}).items()} # Necesitaríamos guardar el mapeo en x1 + # 7. Actualizar sympy_map para las salidas (Q y ET si aplica) + # Usar los nombres de pin originales determinados al principio + map_key_q = (network_id, instr_uid, pin_out_q) # pin_out_q es 'q' o 'out' + q_output_scl_access = f"{instance_name_scl}.Q" # Siempre accedemos a .Q del FB SCL + # *** OBTENER/CREAR Y ALMACENAR SYMBOL para la salida booleana Q *** + sympy_q_symbol = symbol_manager.get_symbol(q_output_scl_access) + if sympy_q_symbol: + sympy_map[map_key_q] = sympy_q_symbol # Almacenar el OBJETO SYMBOL + else: + # Manejar error si no se pudo crear el símbolo + print(f"Error: No se pudo crear símbolo para {q_output_scl_access} en {instr_type_original} {instr_uid}") + sympy_map[map_key_q] = None # Indicar error/irresoluble - q_original_pin = "q" # Default - rt_original_pin = "rt" # Default - - # Intentar encontrar los pines originales si x1 guardó el mapeo (MEJORA NECESARIA en x1) - # Por ahora, para SdCoil que mapeaba out->q, usaremos 'out' directamente - if instruction.get("type") == "Se_scl" and instruction.get("original_type") == "SdCoil": # Necesitamos guardar original_type en x1 - q_original_pin = "out" - # rt no existe en SdCoil - - map_key_q = (network_id, instr_uid, q_original_pin) - scl_map[map_key_q] = f"{instance_name}.Q" - - if rt_original_pin: # Solo añadir rt si corresponde - map_key_rt = (network_id, instr_uid, rt_original_pin) - scl_map[map_key_rt] = f"{instance_name}.ET" + # Almacenar ET solo si corresponde (para Se, no para SdCoil) + if pin_out_time: # pin_out_time es 'rt' o None + map_key_rt = (network_id, instr_uid, pin_out_time) + # ET es TIME, no booleano. Almacenar el string SCL de acceso está bien. + sympy_map[map_key_rt] = f"{instance_name_scl}.ET" # Salida ET del FB SCL return True -# --- Procesador para Sd (On-Delay Timer -> TON SCL) --- - -# --- Function code ends --- - # --- Processor Information Function --- def get_processor_info(): - """Devuelve la información para el temporizador de Pulso (Se -> TP) y maneja SdCoil.""" - # Asumiendo que el tipo en el JSON es 'Se' - # Y que SdCoil también se mapea aquí según el análisis previo + """Devuelve la info para Se (-> TP) y SdCoil (-> TON, manejado aquí).""" return [ {'type_name': 'se', 'processor_func': process_se, 'priority': 5}, - {'type_name': 'sdcoil', 'processor_func': process_se, 'priority': 5} # SdCoil también se procesa como TP - ] + # Asegurarse que x1.py mapea SdCoil a este procesador o a uno específico + {'type_name': 'sdcoil', 'processor_func': process_se, 'priority': 5} + ] \ No newline at end of file diff --git a/processors/process_timer.py b/processors/process_timer.py index dadb756..f6b3d40 100644 --- a/processors/process_timer.py +++ b/processors/process_timer.py @@ -1,70 +1,85 @@ +# processors/process_timer.py # -*- coding: utf-8 -*- -from .processor_utils import get_scl_representation, format_variable_name,get_target_scl_name +import sympy +import traceback +# Usar las nuevas utilidades +from .processor_utils import get_sympy_representation, sympy_expr_to_scl, format_variable_name, get_target_scl_name +from .symbol_manager import SymbolManager, extract_plc_variable_name +SCL_SUFFIX = "_sympy_processed" -# TODO: Import necessary functions from processor_utils -# Example: from .processor_utils import get_scl_representation, format_variable_name -# Or: import processors.processor_utils as utils - -# TODO: Define constants if needed (e.g., SCL_SUFFIX) or import them -SCL_SUFFIX = "_scl" - -# --- Function code starts --- -def process_timer(instruction, network_id, scl_map, access_map, data): +def process_timer(instruction, network_id, sympy_map, symbol_manager: SymbolManager, data): """ - Genera SCL para Temporizadores (TON, TOF). - Requiere datos de instancia (DB o STAT). + Genera SCL para Temporizadores (TON, TOF) directamente. + Requiere datos de instancia. """ instr_uid = instruction["instruction_uid"] - instr_type = instruction["type"] # Será "TON" o "TOF" - if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + instr_type_original = instruction.get("type", "").replace(SCL_SUFFIX,"").replace("_error","") # TON o TOF + if instruction.get("type","").endswith(SCL_SUFFIX) or "_error" in instruction.get("type",""): return False - # 1. Obtener Inputs - in_info = instruction["inputs"].get("IN") # Entrada booleana - pt_info = instruction["inputs"].get("PT") # Preset Time (Tipo TIME) - scl_in = get_scl_representation(in_info, network_id, scl_map, access_map) - scl_pt = get_scl_representation(pt_info, network_id, scl_map, access_map) + scl_timer_type = instr_type_original.upper() + if scl_timer_type not in ["TON", "TOF"]: + instruction["scl"] = f"// ERROR: Tipo de temporizador directo no soportado: {instr_type_original}" + instruction["type"] = instr_type_original + "_error" + return True - if scl_in is None or scl_pt is None: - return False # Dependencias no listas + # 1. Obtener Inputs: IN, PT, y nombre de instancia (implícito o explícito) + in_info = instruction["inputs"].get("IN") + pt_info = instruction["inputs"].get("PT") + # Buscar instancia: ¿está en inputs? ¿o como instance_db? + instance_plc_name = instruction.get("instance_db") # Buscar primero aquí + if not instance_plc_name: + # Si no, buscar un input llamado 'timer' o similar? No estándar. + # Asumir que debe estar declarado como STAT si no hay instance_db + instance_plc_name = instruction.get("instance_name") # Nombre directo? + if not instance_plc_name: + instance_plc_name = f"#{scl_timer_type}_INSTANCE_{instr_uid}" # Placeholder final + print(f"Advertencia: No se encontró nombre/instancia para {instr_type_original} UID {instr_uid}. Usando placeholder '{instance_plc_name}'.") - # 2. Obtener Nombre de Instancia (NECESITA MEJORA EN x1.py) - instance_name = instruction.get("instance_db") # Reutilizar campo si x1 lo llena - if not instance_name: - # Generar placeholder si x1 no extrajo la instancia para Part - instance_name = f"#TIMER_INSTANCE_{instr_uid}" # Placeholder para VAR_TEMP o VAR_STAT - print(f"Advertencia: No se encontró instancia para {instr_type} UID {instr_uid}. Usando placeholder '{instance_name}'. Ajustar x1.py y declarar en x3.py.") + + sympy_in_expr = get_sympy_representation(in_info, network_id, sympy_map, symbol_manager) + sympy_or_const_pt = get_sympy_representation(pt_info, network_id, sympy_map, symbol_manager) + + # Verificar dependencias + if sympy_in_expr is None or sympy_or_const_pt is None or instance_plc_name is None: + return False + + # Formatear nombre de instancia + instance_name_scl = format_variable_name(instance_plc_name) + + # Convertir entradas SymPy/Constante a SCL strings + in_scl = sympy_expr_to_scl(sympy_in_expr, symbol_manager) + pt_scl = sympy_expr_to_scl(sympy_or_const_pt, symbol_manager) + + # Generar la llamada SCL + scl_call = f"{instance_name_scl}(IN := {in_scl}, PT := {pt_scl}); // TODO: Declarar {instance_name_scl} : {scl_timer_type};" + + # Actualizar instrucción + instruction["scl"] = scl_call # SCL final generado + instruction["type"] = instr_type_original + SCL_SUFFIX + + # 7. Actualizar sympy_map para las salidas Q y ET + map_key_q = (network_id, instr_uid, "Q") # Pin estándar SCL + # *** Store SymPy Symbol for boolean output Q *** + q_output_scl_access = f"{instance_name_scl}.Q" # String for SCL access + sympy_q_symbol = symbol_manager.get_symbol(q_output_scl_access) # Get/Create Symbol + if sympy_q_symbol: + sympy_map[map_key_q] = sympy_q_symbol # Store the SYMBOL else: - instance_name = format_variable_name(instance_name) # Limpiar si viene de x1 + print(f"Error: Could not create symbol for {q_output_scl_access} in {instr_type_original} {instr_uid}") + sympy_map[map_key_q] = None - # 3. Formatear entradas si son variables - scl_in_formatted = format_variable_name(scl_in) if in_info and in_info.get("type") == "variable" else scl_in - scl_pt_formatted = format_variable_name(scl_pt) if pt_info and pt_info.get("type") == "variable" else scl_pt - - # 4. Generar la llamada SCL - # Nota: Las salidas Q y ET se acceden directamente desde la instancia. - scl_call = f"{instance_name}(IN := {scl_in_formatted}, PT := {scl_pt_formatted}); // TODO: Declarar {instance_name} : {instr_type}; en VAR_STAT o VAR" - - instruction["scl"] = scl_call - instruction["type"] = instr_type + SCL_SUFFIX - - # 5. Actualizar scl_map para las salidas Q y ET - map_key_q = (network_id, instr_uid, "Q") - scl_map[map_key_q] = f"{instance_name}.Q" - map_key_et = (network_id, instr_uid, "ET") - scl_map[map_key_et] = f"{instance_name}.ET" - # TON/TOF no tienen un pin ENO estándar en LAD/FBD que se mapee directamente + map_key_et = (network_id, instr_uid, "ET") # Pin estándar SCL + # ET is TIME, store SCL access string + sympy_map[map_key_et] = f"{instance_name_scl}.ET" return True # --- Processor Information Function --- def get_processor_info(): - """Devuelve la información para los temporizadores TON y TOF (si se usan genéricamente).""" - # Esta función manejaría tipos TON/TOF si aparecieran directamente en el JSON - # y no fueran manejados por process_sd/process_se (que es lo más común desde LAD). - # Incluir por si acaso o si la conversión inicial genera TON/TOF directamente. + """Devuelve info para TON y TOF directos.""" return [ {'type_name': 'ton', 'processor_func': process_timer, 'priority': 5}, {'type_name': 'tof', 'processor_func': process_timer, 'priority': 5} - ] + ] \ No newline at end of file diff --git a/processors/processor_utils.py b/processors/processor_utils.py index fb140a0..6d55415 100644 --- a/processors/processor_utils.py +++ b/processors/processor_utils.py @@ -1,15 +1,11 @@ # -*- coding: utf-8 -*- -# /processors/processor_utils.py -# Procesador de utilidades para el procesamiento de archivos XML de Simatic +# processors/processor_utils.py import re +import sympy +from .symbol_manager import SymbolManager, extract_plc_variable_name -# --- Copia aquí las funciones auxiliares --- -# get_scl_representation, format_variable_name, -# generate_temp_var_name, get_target_scl_name -# Asegúrate de que no dependen de variables globales de x2_process.py -# (como 'data' o 'network_access_maps' - esas se pasarán como argumentos) +SCL_SUFFIX = "_sympy_processed" # <<< AÑADE ESTA LÍNEA -# Ejemplo de una función (asegúrate de copiar todas las necesarias) def format_variable_name(name): """Limpia el nombre de la variable para SCL.""" if not name: @@ -25,8 +21,116 @@ def format_variable_name(name): name = re.sub(r"[^a-zA-Z0-9_]", "_", name) return prefix + name -# --- Helper Functions --- -# (get_scl_representation, format_variable_name, generate_temp_var_name, get_target_scl_name - sin cambios) +def get_sympy_representation(source_info, network_id, sympy_map, symbol_manager): + """Gets the SymPy expression object representing the source.""" + if not source_info: + print("Warning: get_sympy_representation called with None source_info.") + return None # Or raise error + + # Handle lists (OR branches) - Recursively call and combine with sympy.Or + if isinstance(source_info, list): + sympy_parts = [] + all_resolved = True + for sub_source in source_info: + sub_sympy = get_sympy_representation(sub_source, network_id, sympy_map, symbol_manager) + if sub_sympy is None: + all_resolved = False + break + sympy_parts.append(sub_sympy) + + if not all_resolved: + return None + if not sympy_parts: + return sympy.false # Empty OR is false + # Return sympy.Or only if there are multiple parts + return sympy.Or(*sympy_parts) if len(sympy_parts) > 1 else sympy_parts[0] + + # Handle single source dictionary + source_type = source_info.get("type") + + if source_type == "powerrail": + return sympy.true + elif source_type == "variable": + plc_name = extract_plc_variable_name(source_info) + if plc_name: + return symbol_manager.get_symbol(plc_name) + else: + print(f"Error: Variable source without name: {source_info}") + return None # Error case + elif source_type == "constant": + # Represent constants directly if possible, otherwise maybe as symbols? + # For boolean simplification, only TRUE/FALSE matter significantly. + dtype = str(source_info.get("datatype", "")).upper() + value = source_info.get("value") + if dtype == "BOOL": + return sympy.true if str(value).upper() == "TRUE" else sympy.false + else: + # For simplification, treat non-boolean constants as opaque symbols? + # Or just return their string representation if they won't be simplified anyway? + # Let's return their string value for now, processors will handle it. + # This might need refinement if constants need symbolic handling. + return str(value) # Or maybe symbol_manager.get_symbol(str(value))? + + elif source_type == "connection": + map_key = ( + network_id, + source_info.get("source_instruction_uid"), + source_info.get("source_pin"), + ) + # Return the SymPy object from the map + return sympy_map.get(map_key) # Returns None if not found (dependency not ready) + elif source_type == "unknown_source": + print(f"Warning: Referring to unknown source UID: {source_info.get('uid')}") + return None # Cannot resolve + else: + print(f"Warning: Unknown source type: {source_info}") + return None # Cannot resolve + +def sympy_expr_to_scl(expr, symbol_manager, format_prec=5): + """Converts a SymPy expression to an SCL string using the symbol map.""" + if expr is None: return "/* ERROR: None expression */" + if expr == sympy.true: return "TRUE" + if expr == sympy.false: return "FALSE" + + # Use sympy's string printer with custom settings if needed + # For boolean, standard printing might be okay, but need to substitute symbols + try: + # Get the inverse map (py_id -> plc_name) + inverse_map = symbol_manager.get_inverse_map() + + # Substitute symbols back to their py_id strings first + # Need to handle the structure (And, Or, Not) + scl_str = sympy.sstr(expr, order=None) # Basic string representation + + # Now, carefully replace py_id back to PLC names using regex + # Sort keys by length descending to replace longer IDs first + for py_id in sorted(inverse_map.keys(), key=len, reverse=True): + # Use word boundaries to avoid replacing parts of other IDs + scl_str = re.sub(r'\b' + re.escape(py_id) + r'\b', inverse_map[py_id], scl_str) + + # Replace SymPy operators/functions with SCL equivalents + scl_str = scl_str.replace('&', ' AND ') + scl_str = scl_str.replace('|', ' OR ') + scl_str = scl_str.replace('^', ' XOR ') # If XOR is used + scl_str = scl_str.replace('~', 'NOT ') + # Add spaces around operators if needed after substitution + scl_str = re.sub(r'AND', ' AND ', scl_str) + scl_str = re.sub(r'OR', ' OR ', scl_str) + scl_str = re.sub(r'XOR', ' XOR ', scl_str) + scl_str = re.sub(r'NOT', 'NOT ', scl_str) # Space after NOT + + # Clean up potential double spaces, etc. + scl_str = re.sub(r'\s+', ' ', scl_str).strip() + # Handle parentheses potentially added by sstr - maybe remove redundant ones? + # Be careful not to break operator precedence. + + return scl_str + + except Exception as e: + print(f"Error converting SymPy expr '{expr}' to SCL: {e}") + traceback.print_exc() + return f"/* ERROR converting SymPy: {expr} */" + def get_scl_representation(source_info, network_id, scl_map, access_map): if not source_info: return None @@ -154,56 +258,53 @@ def generate_temp_var_name(network_id, instr_uid, pin_name): # Usar # para variables temporales SCL estándar return f"#_temp_{net_id_clean}_{instr_uid_clean}_{pin_name_clean}" -def get_target_scl_name(instruction, output_pin_name, network_id, default_to_temp=True): +def get_target_scl_name(instruction, pin_name, network_id, default_to_temp=True): + """Gets the SCL formatted name for a target variable. + Handles instruction outputs AND specific inputs like Coil operand. + """ instr_uid = instruction["instruction_uid"] - output_pin_data = instruction["outputs"].get(output_pin_name) + # Ahora SCL_SUFFIX está definido en este módulo + instr_type_upper = instruction.get("type", "").upper().replace(SCL_SUFFIX.upper(), "").replace("_ERROR", "") # Check original type + target_info = None + + # Special handling for inputs that represent the target variable + if instr_type_upper in ["COIL", "SCOIL", "RCOIL"] and pin_name == "operand": + target_info = instruction.get("inputs", {}).get("operand") + # Add other instructions where input pin == target if necessary + # elif instr_type_upper == "XYZ" and pin_name == "some_input_target_pin": + # target_info = instruction.get("inputs", {}).get(pin_name) + else: + # Default: Assume pin_name refers to an output pin + output_pin_data = instruction.get("outputs", {}).get(pin_name) + # Check if it's a list and has one connection (standard case) + if (output_pin_data and isinstance(output_pin_data, list) and len(output_pin_data) == 1): + target_info = output_pin_data[0] + # Add handling for direct output assignment if your JSON structure supports it + target_scl = None - if ( - output_pin_data - and isinstance(output_pin_data, list) - and len(output_pin_data) == 1 - ): - dest_access = output_pin_data[0] - if dest_access.get("type") == "variable": - target_scl = dest_access.get("name") - if target_scl: - target_scl = format_variable_name(target_scl) # Formatear nombre + if target_info: + if target_info.get("type") == "variable": + plc_name = target_info.get("name") + if plc_name: + target_scl = format_variable_name(plc_name) # Use existing util else: - print( - f"Error: Var destino {instr_uid}.{output_pin_name} sin nombre (UID: {dest_access.get('uid')}). {'Usando temp.' if default_to_temp else 'Ignorando.'}" - ) - target_scl = ( - generate_temp_var_name(network_id, instr_uid, output_pin_name) - if default_to_temp - else None - ) - elif dest_access.get("type") == "constant": - print( - f"Advertencia: Instr {instr_uid} escribe en const UID {dest_access.get('uid')}. {'Usando temp.' if default_to_temp else 'Ignorando.'}" - ) - target_scl = ( - generate_temp_var_name(network_id, instr_uid, output_pin_name) - if default_to_temp - else None - ) - else: - print( - f"Advertencia: Destino {instr_uid}.{output_pin_name} no es var/const: {dest_access.get('type')}. {'Usando temp.' if default_to_temp else 'Ignorando.'}" - ) - target_scl = ( - generate_temp_var_name(network_id, instr_uid, output_pin_name) - if default_to_temp - else None - ) + print(f"Error: Target variable for {instr_uid}.{pin_name} has no name (UID: {target_info.get('uid')}).") + elif target_info.get("type") == "constant": + print(f"Advertencia: Attempt to write to constant target {instr_uid}.{pin_name} (UID: {target_info.get('uid')}).") + # else: # Handle other target types if needed + # print(f"Advertencia: Target {instr_uid}.{pin_name} is not a variable: {target_info.get('type')}.") + # else: # No target info found for the specified pin + # print(f"DEBUG: No target info found for {instr_uid}.{pin_name}") + pass + + + # Handle default_to_temp logic + if target_scl: + return target_scl elif default_to_temp: - target_scl = generate_temp_var_name(network_id, instr_uid, output_pin_name) - - # Si target_scl sigue siendo None y no se debe usar temp, devolver None - if target_scl is None and not default_to_temp: + # Generate temp only if no explicit target was found AND default is allowed + print(f"INFO: Generating temp var for {instr_uid}.{pin_name}") # Be informative + return generate_temp_var_name(network_id, instr_uid, pin_name) + else: + # No target found and default temps not allowed return None - - # Si target_scl es None pero sí se permite temp, generar uno ahora - if target_scl is None and default_to_temp: - target_scl = generate_temp_var_name(network_id, instr_uid, output_pin_name) - - return target_scl diff --git a/processors/symbol_manager.py b/processors/symbol_manager.py new file mode 100644 index 0000000..ed271d2 --- /dev/null +++ b/processors/symbol_manager.py @@ -0,0 +1,58 @@ +# processors/symbol_manager.py +import sympy +import re + +class SymbolManager: + def __init__(self): + # plc_name -> py_id (e.g., '"DB".Var' -> 'v0_') + self.plc_to_py_id = {} + # py_id -> Symbol object (e.g., 'v0_' -> sympy.Symbol('v0_')) + self.py_id_to_symbol = {} + # py_id -> plc_name (e.g., 'v0_' -> '"DB".Var') - Inverse mapping + self.py_id_to_plc = {} + self.counter = 0 + # Pre-define common keywords/constants to avoid mapping them + self.reserved_names = {"TRUE", "FALSE"} # Add others if needed + + def _generate_py_id(self): + py_id = f"v{self.counter}_" + self.counter += 1 + # Extremely unlikely collision, but check anyway + while py_id in self.py_id_to_symbol: + py_id = f"v{self.counter}_" + self.counter += 1 + return py_id + + def get_symbol(self, plc_var_name): + """Gets/Creates a SymPy Symbol for a PLC variable name.""" + if plc_var_name is None: + print("Warning: Attempted to get symbol for None PLC name.") + return None # Or handle error appropriately + if plc_var_name.upper() in self.reserved_names: + print(f"Warning: Attempted to create symbol for reserved name: {plc_var_name}") + return None # Or handle differently (e.g., return sympy.true/false?) + + if plc_var_name not in self.plc_to_py_id: + py_id = self._generate_py_id() + self.plc_to_py_id[plc_var_name] = py_id + self.py_id_to_plc[py_id] = plc_var_name + self.py_id_to_symbol[py_id] = sympy.symbols(py_id) + # print(f"DEBUG SymbolManager: Created {py_id} -> {plc_var_name}") # Debug + else: + py_id = self.plc_to_py_id[plc_var_name] + + return self.py_id_to_symbol.get(py_id) + + def get_plc_name(self, py_id): + """Gets the original PLC name from a py_id.""" + return self.py_id_to_plc.get(py_id) + + def get_inverse_map(self): + """Returns the map needed for postprocessing (py_id -> plc_name).""" + return self.py_id_to_plc.copy() + +# Helper function to extract PLC variable name from JSON operand info +def extract_plc_variable_name(operand_info): + if operand_info and operand_info.get("type") == "variable": + return operand_info.get("name") + return None # Not a variable or info missing \ No newline at end of file diff --git a/x2_process.py b/x2_process.py index 7c41482..d7a10a1 100644 --- a/x2_process.py +++ b/x2_process.py @@ -7,167 +7,141 @@ import traceback import re import importlib import sys +import sympy # Import sympy + +# Import necessary components from processors directory +from processors.processor_utils import ( + format_variable_name, # Keep if used outside processors + sympy_expr_to_scl, # Needed for IF grouping and maybe others + # get_target_scl_name might be used here? Unlikely. +) +from processors.symbol_manager import SymbolManager # Import the manager # --- Constantes y Configuración --- -SCL_SUFFIX = "_scl" +# SCL_SUFFIX = "_scl" # Old suffix +SCL_SUFFIX = "_sympy_processed" # New suffix to indicate processing method GROUPED_COMMENT = "// Logic included in grouped IF" +SIMPLIFIED_IF_COMMENT = "// Simplified IF condition by script" # May still be useful + # Global data variable data = {} -def process_group_ifs(instruction, network_id, scl_map, access_map, data): +def process_group_ifs(instruction, network_id, sympy_map, symbol_manager, data): """ - Busca instrucciones que generan condiciones (Contact, O, Eq, PBox, etc.) ya procesadas - y, si habilitan un grupo (>1) de bloques funcionales (Move, Add, Call, etc.), - construye el bloque IF agrupado. + Busca condiciones (ya procesadas -> tienen expr SymPy en sympy_map) + y, si habilitan un grupo (>1) de bloques funcionales (con SCL ya generado), + construye el bloque IF agrupado CON LA CONDICIÓN SIMPLIFICADA. Modifica el campo 'scl' de la instrucción generadora de condición. """ instr_uid = instruction["instruction_uid"] - instr_type = instruction["type"] - instr_type_original = instr_type.replace("_scl", "").replace("_error", "") + instr_type_original = instruction.get("type", "").replace(SCL_SUFFIX, "").replace("_error", "") made_change = False - # Solo actuar sobre generadores de condición ya procesados (_scl) - # y que no sean ellos mismos errores o ya agrupados por otro IF + # Check if this instruction *could* generate a condition suitable for grouping + # It must have been processed by the new SymPy method if ( - not instr_type.endswith("_scl") - or "_error" in instr_type + not instruction.get("type", "").endswith(SCL_SUFFIX) # Check if processed by new method + or "_error" in instruction.get("type", "") or instruction.get("grouped", False) - or instr_type_original - not in [ - "Contact", - "O", - "Eq", - "Ne", - "Gt", - "Lt", - "Ge", - "Le", - "PBox", - "And", - "Xor", + or instr_type_original 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 ] - ): # Añadir más si es necesario + ): return False - # Evitar reagrupar si ya se hizo (comprobando si SCL ya es un IF complejo) + # Avoid reagruping if SCL already contains a complex IF (less likely now) current_scl = instruction.get("scl", "") - if current_scl.strip().startswith("IF") and "END_IF;" in current_scl: - # print(f"DEBUG Group: {instr_uid} ya tiene IF complejo, saltando agrupación.") - return False - # Ignorar comentarios simples que empiezan por IF - if current_scl.strip().startswith("//") and "IF" in current_scl: + if current_scl.strip().startswith("IF") and "END_IF;" in current_scl and GROUPED_COMMENT not in current_scl: return False - # Obtener la condición generada por esta instrucción (debería estar en scl_map['out']) + # *** Get the SymPy expression for the condition *** map_key_out = (network_id, instr_uid, "out") - condition_scl = scl_map.get(map_key_out) + sympy_condition_expr = sympy_map.get(map_key_out) - # No agrupar para condiciones triviales, no encontradas o ya agrupadas - if condition_scl is None or condition_scl in ["TRUE", "FALSE"]: + # No SymPy expression found or trivial conditions + if sympy_condition_expr is None or sympy_condition_expr in [sympy.true, sympy.false]: return False - # Encontrar todos los bloques funcionales habilitados DIRECTAMENTE por esta condición - grouped_instructions_cores = [] # Lista de SCL 'core' de los consumidores - consumer_instr_list = [] # Lista de instrucciones consumidoras - network_logic = next( - (net["logic"] for net in data["networks"] if net["id"] == network_id), [] - ) - if not network_logic: - return False + # --- Find consumer instructions (logic similar to before) --- + grouped_instructions_cores = [] + consumer_instr_list = [] + network_logic = next((net["logic"] for net in data["networks"] if net["id"] == network_id), []) + if not network_logic: return False - # Identificar los tipos de instrucciones que queremos agrupar (bloques funcionales) - groupable_types = [ - "Move", - "Add", - "Sub", - "Mul", - "Div", - "Mod", - "Convert", - "Call_FC", - "Call_FB", - ] # Añadir más si es necesario + groupable_types = [ # Types whose *final SCL* we want to group + "Move", "Add", "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" + ] for consumer_instr in network_logic: consumer_uid = consumer_instr["instruction_uid"] - # Saltar si ya está agrupado por otra condición o es él mismo if consumer_instr.get("grouped", False) or consumer_uid == instr_uid: continue consumer_en = consumer_instr.get("inputs", {}).get("en") - consumer_type = consumer_instr.get("type", "") # Tipo actual (_scl o no) - consumer_type_original = consumer_type.replace("_scl", "").replace("_error", "") + consumer_type = consumer_instr.get("type", "") # Current type suffix matters + consumer_type_original = consumer_type.replace(SCL_SUFFIX, "").replace("_error", "") - # ¿Está la entrada 'en' del consumidor conectada a nuestra salida 'out'? is_enabled_by_us = False - if ( - isinstance(consumer_en, dict) - and consumer_en.get("type") == "connection" - and consumer_en.get("source_instruction_uid") == instr_uid - and consumer_en.get("source_pin") - == "out" # Condición viene de 'out' del generador - ): + if ( isinstance(consumer_en, dict) and consumer_en.get("type") == "connection" and + consumer_en.get("source_instruction_uid") == instr_uid and + consumer_en.get("source_pin") == "out"): is_enabled_by_us = True - # ¿Es un tipo de instrucción agrupable y ya procesado (tiene SCL)? - if ( - is_enabled_by_us - and consumer_type.endswith("_scl") - and consumer_type_original in groupable_types - ): + # Check if consumer is groupable AND has its final SCL generated + # 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. + if ( is_enabled_by_us and consumer_type.endswith(SCL_SUFFIX) and # Or a specific "final_scl" suffix + consumer_type_original in groupable_types ): + consumer_scl = consumer_instr.get("scl", "") - # Extraer el SCL core (la parte DENTRO del IF o la línea única si no había IF) + # Extract core SCL (logic is similar, maybe simpler if SCL is cleaner now) core_scl = None - if consumer_scl.strip().startswith("IF"): - # Extraer todo entre THEN y END_IF; - match = re.search( - r"IF\s+.*\s+THEN\s*(.*?)\s*END_IF;", - consumer_scl, - re.DOTALL | re.IGNORECASE, - ) - if match: - core_scl = match.group(1).strip() - elif consumer_scl and not consumer_scl.strip().startswith("//"): - # Si no es IF y no es solo comentario, es el core - core_scl = consumer_scl.strip() + if consumer_scl: + # If consumer SCL itself is an IF generated by EN, take the body + if consumer_scl.strip().startswith("IF"): + match = re.search(r"THEN\s*(.*?)\s*END_IF;", consumer_scl, re.DOTALL | re.IGNORECASE) + 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: grouped_instructions_cores.append(core_scl) - consumer_instr_list.append(consumer_instr) # Guardar referencia - # else: # Debug - # print(f"DEBUG Group: Consumidor {consumer_uid} ({consumer_type}) habilitado por {instr_uid} no tenía SCL core extraíble. SCL: '{consumer_scl}'") + consumer_instr_list.append(consumer_instr) - # Si encontramos más de un consumidor agrupable + # --- If groupable consumers found --- if len(grouped_instructions_cores) > 1: - print( - f"INFO: Agrupando {len(grouped_instructions_cores)} instrucciones bajo condición de {instr_type_original} UID {instr_uid} (Cond: {condition_scl})" - ) + print(f"INFO: Agrupando {len(grouped_instructions_cores)} instr. bajo condición de {instr_type_original} UID {instr_uid}") - # Construir el bloque IF agrupado - scl_grouped = [f"IF {condition_scl} THEN"] + # *** Simplify the SymPy condition *** + try: + #simplified_expr = sympy.simplify_logic(sympy_condition_expr, force=True) + simplified_expr = sympy.logic.boolalg.to_dnf(sympy_condition_expr, simplify=True) + except Exception as e: + print(f"Error simplifying condition for grouping UID {instr_uid}: {e}") + simplified_expr = sympy_condition_expr # Fallback + + # *** Convert simplified condition to SCL string *** + condition_scl_simplified = sympy_expr_to_scl(simplified_expr, symbol_manager) + + # *** Build the grouped IF SCL *** + scl_grouped_lines = [f"IF {condition_scl_simplified} THEN"] for core_line in grouped_instructions_cores: - # Añadir indentación adecuada (2 espacios) - indented_core = "\n".join( - [f" {line.strip()}" for line in core_line.splitlines()] - ) - scl_grouped.append(indented_core) - scl_grouped.append("END_IF;") - final_grouped_scl = "\n".join(scl_grouped) + indented_core = "\n".join([f" {line.strip()}" for line in core_line.splitlines()]) + scl_grouped_lines.append(indented_core) + scl_grouped_lines.append("END_IF;") + final_grouped_scl = "\n".join(scl_grouped_lines) - # Sobrescribir 'scl' de la instrucción generadora de condición + # Update the generator instruction's SCL instruction["scl"] = final_grouped_scl - # Marcar los consumidores como agrupados y limpiar su SCL original + # Mark consumers as grouped for consumer_instr in consumer_instr_list: consumer_instr["scl"] = f"{GROUPED_COMMENT} (by UID {instr_uid})" - consumer_instr["grouped"] = True # Marcar como agrupado + consumer_instr["grouped"] = True made_change = True - # else: # Debug - # if len(grouped_instructions_cores) == 1: - # print(f"DEBUG Group: Solo 1 consumidor ({consumer_instr_list[0]['instruction_uid']}) para {instr_uid}. No se agrupa.") - # elif len(grouped_instructions_cores) == 0 and condition_scl not in ['TRUE', 'FALSE']: - # # Solo mostrar si la condición no era trivial - # pass # print(f"DEBUG Group: Ningún consumidor agrupable encontrado para {instr_uid} (Cond: {condition_scl}).") return made_change @@ -254,30 +228,20 @@ def process_json_to_scl(json_filepath): # 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): - print(f"Error: JSON no encontrado: {json_filepath}") - return + if not os.path.exists(json_filepath): print(f"Error: JSON no encontrado: {json_filepath}"); return print(f"Cargando JSON desde: {json_filepath}") try: - # Cargar datos en una variable local de esta función - with open(json_filepath, "r", encoding="utf-8") as f: - data = json.load(f) - except Exception as e: - print(f"Error al cargar JSON: {e}") - traceback.print_exc() - return + with open(json_filepath, "r", encoding="utf-8") as f: data = json.load(f) + except Exception as e: print(f"Error al cargar JSON: {e}"); traceback.print_exc(); return - # --- Carga dinámica de procesadores (Obtiene mapa y lista ordenada) --- - script_dir = os.path.dirname(__file__) - processors_dir_path = os.path.join(script_dir, 'processors') + # --- Carga dinámica de procesadores (sin cambios) --- + script_dir = os.path.dirname(__file__); processors_dir_path = os.path.join(script_dir, 'processors') processor_map, sorted_processors = load_processors(processors_dir_path) + if not processor_map: print("Error crítico: No se cargaron procesadores. Abortando."); return - if not processor_map: # O verificar sorted_processors - print("Error crítico: No se cargaron procesadores. Abortando.") - return - - # --- Crear mapas de acceso por red --- + # --- Crear mapas de acceso por red (sin cambios) --- network_access_maps = {} + # ... (logic to populate network_access_maps remains the same) ... for network in data.get("networks", []): net_id = network["id"] current_access_map = {} @@ -297,30 +261,35 @@ def process_json_to_scl(json_filepath): current_access_map[dest["uid"]] = dest network_access_maps[net_id] = current_access_map - # --- Inicializar mapa SCL y bucle --- - scl_map = {} # Mapa para resultados SCL intermedios + # --- 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() + sympy_map = {} # Mapa para resultados SymPy intermedios (expresiones) + max_passes = 30 passes = 0 processing_complete = False - print("\n--- Iniciando Bucle de Procesamiento Iterativo (con prioridad) ---") + print("\n--- Iniciando Bucle de Procesamiento Iterativo (con SymPy y prioridad) ---") while passes < max_passes and not processing_complete: passes += 1 - made_change_in_base_pass = False + made_change_in_base_pass = False # Renombrar: made_change_in_sympy_pass made_change_in_group_pass = False + # made_change_in_simplify_pass = False # Ya no existe Fase 3 print(f"\n--- Pase {passes} ---") - num_processed_this_pass = 0 + num_processed_this_pass = 0 # Renombrar: num_sympy_processed_this_pass num_grouped_this_pass = 0 + # num_simplified_this_pass = 0 # Ya no existe Fase 3 - # --- FASE 1: Procesadores Base (Itera según la lista ordenada por prioridad) --- - print(f" Fase 1 (Base - Orden por Prioridad):") - for processor_info in sorted_processors: # Iterar sobre la lista ordenada por prioridad + # --- FASE 1: Procesadores Base (Ahora usan SymPy) --- + print(f" Fase 1 (SymPy Base - Orden por Prioridad):") + num_sympy_processed_this_pass = 0 # Contador específico + for processor_info in sorted_processors: current_type_name = processor_info['type_name'] func_to_call = processor_info['func'] - # Descomentar para depuración muy detallada: - # print(f" Intentando procesar tipo: {current_type_name} (Prio: {processor_info['priority']})") - # Buscar instrucciones de este tipo en todas las redes for network in data.get("networks", []): network_id = network["id"] access_map = network_access_maps.get(network_id, {}) @@ -330,82 +299,84 @@ def process_json_to_scl(json_filepath): instr_uid = instruction.get("instruction_uid") instr_type_original = instruction.get("type", "Unknown") - # Saltar si ya está procesado, es un error o ya fue agrupado por otro - 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 instruction.get("grouped", False)): continue - # Determinar el tipo efectivo de la instrucción para la comparación - # (Manejo especial para 'Call') + # Determinar tipo efectivo (como antes) lookup_key = instr_type_original.lower() 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" - # Nota: Si es un tipo de bloque desconocido, effective_type_name será 'call' + if instr_type_original == "Call": # ... (manejo Call FC/FB) ... + 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" - # Si el tipo efectivo de la instrucción coincide con el tipo que estamos procesando en este ciclo... if effective_type_name == current_type_name: try: - # Llamar a la función del procesador, pasando 'data' - changed = func_to_call(instruction, network_id, scl_map, access_map, data) # Pasar data + # *** Llamar al procesador refactorizado *** + # Pasa sympy_map y symbol_manager, no scl_map + changed = func_to_call(instruction, network_id, sympy_map, symbol_manager, data) # Pasamos SymbolManager if changed: made_change_in_base_pass = True - num_processed_this_pass += 1 - # La función llamada debe añadir _scl o _error al tipo de la instrucción - # Descomentar para depuración: - # print(f" Procesado: {instr_type_original} UID {instr_uid}") + num_sympy_processed_this_pass += 1 except Exception as e: - print(f"ERROR(Base) al procesar {instr_type_original} UID {instr_uid} con {func_to_call.__name__}: {e}") + print(f"ERROR(SymPy Base) al procesar {instr_type_original} UID {instr_uid}: {e}") traceback.print_exc() - # Marcar como error para no reintentar - instruction["scl"] = f"// ERROR en procesador base: {e}" + instruction["scl"] = f"// ERROR en SymPy procesador base: {e}" instruction["type"] = instr_type_original + "_error" - made_change_in_base_pass = True # Considerar error como cambio + made_change_in_base_pass = True + print(f" -> {num_sympy_processed_this_pass} instrucciones procesadas con SymPy.") - # --- FASE 2: Procesador de Agrupación (Se ejecuta después de toda la Fase 1) --- - # Ejecutar solo si hubo cambios en la fase base (o en el primer pase) + + # --- FASE 2: Agrupación IF (Ahora usa SymPy para simplificar) --- + # Ejecutar si hubo cambios en base o es el primer pase if made_change_in_base_pass or passes == 1: - print(f" Fase 2 (Agrupación IF):") + print(f" Fase 2 (Agrupación IF con Simplificación):") + num_grouped_this_pass = 0 # Reiniciar contador for network in data.get("networks", []): network_id = network["id"] - access_map = network_access_maps.get(network_id, {}) + # access_map = network_access_maps.get(network_id, {}) # No usado directamente por group_ifs network_logic = network.get("logic", []) - # Iterar sobre instrucciones ya procesadas que podrían generar condiciones + # Iterar sobre instrucciones que *pueden* generar condiciones booleanas for instruction in network_logic: - # Intentar agrupar solo si está procesado (_scl) y no previamente agrupado - if instruction["type"].endswith("_scl") and not instruction.get("grouped", False): - try: - # Llamar a la función de agrupación, pasando 'data' - group_changed = process_group_ifs(instruction, network_id, scl_map, access_map, data) - if group_changed: - made_change_in_group_pass = True - num_grouped_this_pass += 1 - except Exception as e: - print(f"ERROR(Group) al intentar agrupar desde UID {instruction.get('instruction_uid')}: {e}") - traceback.print_exc() - # No marcamos la instrucción origen como error, solo falló la agrupación + # process_group_ifs ahora verifica internamente si la instr. fue procesada + try: + # *** Llamar a process_group_ifs adaptado *** + 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.") + + # --- FASE 3 Eliminada --- # --- Comprobar si se completó el procesamiento --- + # Solo considera Fase 1 (SymPy Base) y Fase 2 (Grouping) if not made_change_in_base_pass and not made_change_in_group_pass: print(f"\n--- No se hicieron más cambios en el pase {passes}. Proceso iterativo completado. ---") processing_complete = True else: - print(f"--- Fin Pase {passes}: {num_processed_this_pass} procesados, {num_grouped_this_pass} agrupados. Continuando...") + # Mensaje de fin de pase actualizado + print(f"--- Fin Pase {passes}: {num_sympy_processed_this_pass} proc SymPy, {num_grouped_this_pass} agrup. Continuando...") # --- Comprobar límite de pases --- if passes == max_passes and not processing_complete: - print(f"\n--- ADVERTENCIA: Límite de {max_passes} pases alcanzado. Puede haber dependencias no resueltas. ---") + print(f"\n--- ADVERTENCIA: Límite de {max_passes} pases alcanzado...") # --- FIN BUCLE ITERATIVO --- - # --- Verificación Final de Instrucciones No Procesadas --- + # --- Verificación Final --- + # La lógica aquí podría necesitar ajustes si el sufijo cambió o si el SCL final + # solo se genera en instrucciones terminales. print("\n--- Verificación Final de Instrucciones No Procesadas ---") unprocessed_count = 0 unprocessed_details = [] - ignored_types = ['raw_scl_chunk', 'unsupported_lang'] # Tipos que esperamos no procesar + ignored_types = ['raw_scl_chunk', 'unsupported_lang'] for network in data.get("networks", []): network_id = network.get("id", "Unknown ID") @@ -414,8 +385,11 @@ def process_json_to_scl(json_filepath): 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("//") - # Comprobar si NO está procesada, NO es error, NO está agrupada Y NO es un tipo ignorado + # 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 @@ -425,24 +399,21 @@ def process_json_to_scl(json_filepath): 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 (y no son tipos ignorados):") - if unprocessed_details: - for detail in unprocessed_details: - print(detail) - print(">>> Estos tipos podrían necesitar un procesador en el directorio 'processors' o tener dependencias irresolubles.") - # else: # No debería pasar si unprocessed_count > 0 y la lógica es correcta - # print("...") + 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 fueron procesadas a SCL, marcadas como error o agrupadas exitosamente.") + print("INFO: Todas las instrucciones relevantes parecen haber sido procesadas o agrupadas.") - # --- Guardar JSON Final --- + # --- Guardar JSON Final (sin cambios) --- output_filename = json_filepath.replace("_simplified.json", "_simplified_processed.json") print(f"\nGuardando JSON procesado en: {output_filename}") try: with open(output_filename, "w", encoding="utf-8") as f: - # Usamos la 'data' local que hemos estado modificando json.dump(data, f, indent=4, ensure_ascii=False) print("Guardado completado.") except Exception as e: diff --git a/x3_generate_scl.py b/x3_generate_scl.py index 50df658..66207c4 100644 --- a/x3_generate_scl.py +++ b/x3_generate_scl.py @@ -1,28 +1,39 @@ +# x3_generate_scl.py # -*- coding: utf-8 -*- import json import os import re import argparse +import sys +import traceback # Importar traceback para errores -# --- Helper Functions --- +# --- Importar Utilidades y Constantes (Asumiendo ubicación) --- +try: + # Intenta importar desde el paquete de procesadores si está estructurado así + from processors.processor_utils import format_variable_name + # Definir SCL_SUFFIX aquí o importarlo si está centralizado + SCL_SUFFIX = "_sympy_processed" # Asegúrate que coincida con x2_process.py + GROUPED_COMMENT = "// Logic included in grouped IF" # Opcional, si se usa para filtrar +except ImportError: + print("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!).") + # Implementación local BÁSICA como fallback (MENOS RECOMENDADA) + def format_variable_name(name): + if not name: return "_INVALID_NAME_" + if name.startswith('"') and name.endswith('"'): return name # Mantener comillas + prefix = "#" if name.startswith("#") else "" + if prefix: name = name[1:] + if name and name[0].isdigit(): name = "_" + name + name = re.sub(r"[^a-zA-Z0-9_]", "_", name) + return prefix + name + SCL_SUFFIX = "_sympy_processed" + GROUPED_COMMENT = "// Logic included in grouped IF" -def format_variable_name(name): - """Limpia el nombre de la variable quitando comillas y espacios.""" - if not name: - return "_INVALID_NAME_" - # Quita comillas dobles iniciales/finales - name = name.strip('"') - # Reemplaza comillas dobles internas y puntos por guión bajo - name = name.replace('"."', '_').replace('.', '_') - # Quita comillas restantes (si las hubiera) - name = name.replace('"', '') - # Asegurarse de que no empiece con número (aunque raro con comillas iniciales) - if name and name[0].isdigit(): - name = "_" + name - return name + +# --- Función Principal de Generación SCL --- def generate_scl(processed_json_filepath, output_scl_filepath): - """Genera un archivo SCL a partir del JSON procesado.""" + """Genera un archivo SCL a partir del JSON procesado por x2_process (versión SymPy).""" if not os.path.exists(processed_json_filepath): print(f"Error: Archivo JSON procesado no encontrado en '{processed_json_filepath}'") @@ -34,117 +45,153 @@ def generate_scl(processed_json_filepath, output_scl_filepath): data = json.load(f) except Exception as e: print(f"Error al cargar o parsear JSON: {e}") + traceback.print_exc() return # --- Extracción de Información del Bloque --- block_name = data.get('block_name', 'UnknownBlock') block_number = data.get('block_number') - block_lang = data.get('language', 'LAD') # Lenguaje original + block_lang_original = data.get('language', 'LAD') # Lenguaje original + # Determinar tipo de bloque SCL (Asumir FB si no se especifica) + # Idealmente, x1_to_json.py guardaría esto en data['block_type_scl'] = 'FC' o 'FB' + block_type_scl = data.get('block_type_scl', 'FUNCTION_BLOCK') block_comment = data.get('block_comment', '') - # Limpiar nombre del bloque para usarlo en SCL + # Usar format_variable_name para el nombre del bloque en SCL scl_block_name = format_variable_name(block_name) - print(f"Generando SCL para el bloque: {scl_block_name} (Original: {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() # Para flancos, si se implementan completamente - # Usar regex para encontrar variables _temp_... y stat_... - temp_pattern = re.compile(r'"?(_temp_[a-zA-Z0-9_]+)"?') - stat_pattern = re.compile(r'"?(stat_[a-zA-Z0-9_]+)"?') + 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', '') - if scl_code: - # Buscar temporales en el código SCL generado - found_temps = temp_pattern.findall(scl_code) - for temp_name in found_temps: - temp_vars.add(temp_name) # Añadir al set (evita duplicados) - # Buscar estáticas (para flancos) - found_stats = stat_pattern.findall(scl_code) - for stat_name in found_stats: - stat_vars.add(stat_name) + # 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 '') - print(f"Variables temporales detectadas: {len(temp_vars)}") - # print(f"Variables estáticas detectadas (para flancos): {len(stat_vars)}") + 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 = [] # Cabecera del Bloque 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}") - if block_comment: - scl_output.append(f"// Block Comment: {block_comment}") + 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("") - scl_output.append(f"FUNCTION_BLOCK \"{scl_block_name}\"") # Asumir FB por variables Temp/Stat - scl_output.append("{ S7_Optimized_Access := 'TRUE' }") # Opcional, común - scl_output.append("VERSION : 0.1") # Opcional + scl_output.append(f"{block_type_scl} \"{scl_block_name}\"") + scl_output.append("{ S7_Optimized_Access := 'TRUE' }") + scl_output.append("VERSION : 0.1") scl_output.append("") - # Declaraciones de Interfaz - scl_output.append("VAR_INPUT") - # Iterar sobre data['interface']['Input'] si existe - # for var in data.get('interface', {}).get('Input', []): - # scl_output.append(f" {format_variable_name(var['name'])} : {var['datatype']};") - scl_output.append("END_VAR") - scl_output.append("") + # Declaraciones de Interfaz (Implementación básica) + interface_sections = ["Input", "Output", "InOut", "Static", "Temp", "Constant", "Return"] + interface_data = data.get('interface', {}) - scl_output.append("VAR_OUTPUT") - # Iterar sobre data['interface']['Output'] si existe - # for var in data.get('interface', {}).get('Output', []): - # scl_output.append(f" {format_variable_name(var['name'])} : {var['datatype']};") - scl_output.append("END_VAR") - scl_output.append("") + for section_name in interface_sections: + scl_section_name = section_name + # Ajustar nombres de sección para SCL (Static -> STAT, Temp -> TEMP) + 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("VAR_IN_OUT") - # Iterar sobre data['interface']['InOut'] si existe - # for var in data.get('interface', {}).get('InOut', []): - # scl_output.append(f" {format_variable_name(var['name'])} : {var['datatype']};") - scl_output.append("END_VAR") - scl_output.append("") + vars_in_section = interface_data.get(section_name, []) + # No declarar VAR_TEMP aquí, se hará después con las detectadas/originales + if section_name == "Temp": continue - # Declaraciones Estáticas (para flancos) - if stat_vars: - scl_output.append("VAR_STAT") - # Asumir Bool para flancos, se podría inferir mejor si PBox lo indicara - for var_name in sorted(list(stat_vars)): - scl_output.append(f" \"{var_name}\" : Bool; // Memory for edge detection") - scl_output.append("END_VAR") - scl_output.append("") + # No declarar VAR_STAT aquí si ya lo hacemos abajo con las detectadas + if section_name == "Static" and stat_vars: continue - # Declaraciones Temporales - # Incluir las variables de la sección Temp del JSON original - # y las generadas automáticamente (_temp_...) + + if vars_in_section or (section_name == "Static" and stat_vars): # Incluir STAT si hay detectadas + # Usar VAR para Input/Output/InOut/Constant/Return + var_keyword = "VAR" if section_name != "Static" else "VAR_STAT" + scl_output.append(f"{var_keyword}_{section_name.upper()}") + + for var in vars_in_section: + var_name = var.get('name') + var_dtype = var.get('datatype', 'VARIANT') # Default a VARIANT + if var_name: + # Usar format_variable_name CORRECTO + scl_name = format_variable_name(var_name) + scl_output.append(f" {scl_name} : {var_dtype};") + + # Declarar stat_vars detectadas si esta es la sección STAT + if section_name == "Static" and stat_vars: + for var_name in sorted(list(stat_vars)): + # Asumir Bool para stat_, podría necesitar inferencia + scl_output.append(f" {format_variable_name(var_name)} : Bool; // Auto-detected STAT") + + scl_output.append("END_VAR") + scl_output.append("") + + # Declaraciones Estáticas (Si no estaban en la interfaz y se detectaron) + # Esto es redundante si la sección VAR_STAT ya se generó arriba + # 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 = data.get('interface', {}).get('Temp', []) + interface_temps = interface_data.get('Temp', []) if interface_temps: for var in interface_temps: - formatted_name = format_variable_name(var['name']) - # Añadir comillas si el nombre original las tenía o si contiene caracteres especiales - scl_name = f'"{formatted_name}"' if '"' in var['name'] or '.' in var['name'] else formatted_name - scl_output.append(f" {scl_name} : {var['datatype']};") - declared_temps.add(scl_name) # Marcar como declarada + var_name = var.get('name') + var_dtype = var.get('datatype', 'VARIANT') + if var_name: + scl_name = format_variable_name(var_name) + scl_output.append(f" {scl_name} : {var_dtype};") + declared_temps.add(scl_name) # Marcar como declarada # Declarar las _temp_ generadas si no estaban ya en la interfaz Temp if temp_vars: - # Intentar inferir tipo (difícil sin más info), por ahora usar Variant o Bool/DInt for var_name in sorted(list(temp_vars)): - scl_name = f'"{var_name}"' # Asegurar comillas para _temp_ + scl_name = format_variable_name(var_name) # #_temp_... if scl_name not in declared_temps: - # Inferencia básica de tipo por nombre de pin (muy heurístico) - inferred_type = "Variant" # Tipo seguro por defecto - if var_name.endswith("_out"): # Salida de bloque lógico/comparación? - inferred_type = "Bool" - elif var_name.endswith("_out_num"): # Salida de bloque numérico? - inferred_type = "DInt" # O Real? O Int? Difícil saber + # 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) # Marcar como declarada + declared_temps.add(scl_name) scl_output.append("END_VAR") scl_output.append("") @@ -156,75 +203,61 @@ def generate_scl(processed_json_filepath, output_scl_filepath): for i, network in enumerate(data.get('networks', [])): network_title = network.get('title', f'Network {network.get("id")}') network_comment = network.get('comment', '') - # Obtener lenguaje original de la red, default a LAD si no está - network_lang = network.get('language', 'LAD') + 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("") # Línea en blanco antes del código de la red + scl_output.append("") network_has_code = False # Iterar sobre la 'logica' de la red for instruction in network.get('logic', []): instruction_type = instruction.get("type", "") - scl_code = instruction.get('scl') + scl_code = instruction.get('scl', "") # Obtener SCL generado por x2 - # --- INICIO: Manejar RAW_SCL_CHUNK y otros tipos --- - if instruction_type == "RAW_SCL_CHUNK" and scl_code: - network_has_code = True - # Imprimir el SCL reconstruido directamente - for line in scl_code.splitlines(): - scl_output.append(f" {line}") # Añadir indentación - elif instruction_type == "UNSUPPORTED_LANG" and scl_code: - network_has_code = True - # Imprimir comentario para lenguajes no soportados - for line in scl_code.splitlines(): - scl_output.append(f" {line}") - elif instruction_type.endswith("_scl") and scl_code: - # Código SCL generado por x2_process.py para LAD/FBD - if instruction.get("grouped", False): # Ignorar si fue agrupado - continue + # Saltar instrucciones agrupadas + if instruction.get("grouped", False): + continue - # Lógica mejorada para omitir comentarios internos si no aportan - lines = scl_code.splitlines() - is_internal_comment_only = (len(lines) == 1 and - (lines[0].strip().startswith("// RLO") or - lines[0].strip().startswith("// Comparison") or - lines[0].strip().startswith("// Logic O") or - lines[0].strip().startswith("// Logic included in grouped IF") or # Usar GROUPED_COMMENT si lo importas - lines[0].strip().startswith("// P_TRIG") or - lines[0].strip().startswith("// N_TRIG") )) + # 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()) - if not is_internal_comment_only: + + # 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 lines: - clean_line = line.strip() - # Omitir comentarios autogenerados específicos - if not (clean_line.startswith("// RLO:") or \ - clean_line.startswith("// Comparison") or \ - clean_line.startswith("// Logic O") or \ - clean_line == "// Logic included in grouped IF" or \ - clean_line.startswith("// P_TRIG(") or \ - clean_line.startswith("// N_TRIG(")): - scl_output.append(f" {line}") # Indentación - # Ignorar instrucciones no procesadas (sin _scl) o con error + 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: - # scl_output.append(f" // Error processing instruction {instruction.get('instruction_uid')}: {scl_code}") - # network_has_code = True + # network_has_code = True + # scl_output.append(f" // ERROR processing instruction UID {instruction.get('instruction_uid')}: {instruction.get('scl', 'No details')}") - # --- FIN: Manejar RAW_SCL_CHUNK y otros tipos --- - if network_has_code: - scl_output.append("") # Añadir línea en blanco después del código de la red si hubo algo + scl_output.append("") # Línea en blanco después del código de la red else: - # Añadir comentario si la red estaba vacía o no generó código imprimible scl_output.append(f" // Network did not produce printable SCL code.") scl_output.append("") - scl_output.append("END_FUNCTION_BLOCK") + # 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}") @@ -235,16 +268,12 @@ def generate_scl(processed_json_filepath, output_scl_filepath): print("Generación de SCL completada.") except Exception as e: print(f"Error al escribir el archivo SCL: {e}") + traceback.print_exc() + # --- Ejecución --- if __name__ == "__main__": - # Imports necesarios solo para la ejecución como script principal - import argparse - import os - import sys - - parser = argparse.ArgumentParser(description="Generate final SCL file from processed JSON.") - # Acepta el nombre del XML original como referencia para derivar nombres + parser = argparse.ArgumentParser(description="Generate final SCL file from processed JSON (SymPy version).") parser.add_argument( "source_xml_filepath", nargs="?", @@ -253,20 +282,17 @@ if __name__ == "__main__": ) args = parser.parse_args() - # Derivar nombres de archivos de entrada y salida xml_filename_base = os.path.splitext(os.path.basename(args.source_xml_filepath))[0] - input_dir = os.path.dirname(args.source_xml_filepath) # Directorio del XML original + # 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__) - # Nombre del JSON procesado (entrada para este script) - input_json_file = os.path.join(input_dir, f"{xml_filename_base}_simplified_processed.json") - # Nombre del SCL final (salida de este script) - output_scl_file = os.path.join(input_dir, f"{xml_filename_base}_simplified_processed.scl") + 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") - # Verificar si el archivo JSON procesado de entrada existe if not os.path.exists(input_json_file): print(f"Error: Processed JSON file not found: '{input_json_file}'") print(f"Ensure 'x2_process.py' ran successfully for '{args.source_xml_filepath}'.") - sys.exit(1) # Salir si el archivo de entrada no existe + sys.exit(1) else: - # Llamar a la función principal con los nombres derivados generate_scl(input_json_file, output_scl_file) \ No newline at end of file