diff --git a/BlenderCtrl_ProdModeInit_simplified.json b/BlenderCtrl_ProdModeInit_simplified.json deleted file mode 100644 index c9c59bd..0000000 --- a/BlenderCtrl_ProdModeInit_simplified.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "block_name": "BlenderCtrl_ProdModeInit", - "block_number": 2012, - "language": "LAD", - "block_comment": "", - "interface": { - "Return": [ - { - "name": "Ret_Val", - "datatype": "Void" - } - ] - }, - "networks": [ - { - "id": "9", - "title": "PID Reset Integral", - "comment": "", - "logic": [ - { - "instruction_uid": "21", - "uid": "21", - "type": "Call", - "block_name": "BlenderPID_PIDResInteg", - "block_type": "FC", - "inputs": { - "en": { - "type": "powerrail" - } - }, - "outputs": {} - } - ] - }, - { - "id": "1A", - "title": "Ctrl Init Errors", - "comment": "", - "logic": [ - { - "instruction_uid": "21", - "uid": "21", - "type": "Call", - "block_name": "BlenderCtrl_InitErrors", - "block_type": "FC", - "inputs": { - "en": { - "type": "powerrail" - } - }, - "outputs": {} - } - ] - }, - { - "id": "2B", - "title": "RunOut Counter", - "comment": "", - "logic": [ - { - "instruction_uid": "23", - "uid": "23", - "type": "Move", - "template_values": { - "Card": "Cardinality" - }, - "inputs": { - "en": { - "type": "powerrail" - }, - "in": { - "uid": "21", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Real", - "value": 0.0 - } - }, - "outputs": { - "out1": [ - { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"HMI_Variables_Status\".\"Analog_Values\".\"TP301RunOutCount\"" - } - ] - } - } - ] - } - ] -} \ No newline at end of file diff --git a/BlenderCtrl_ProdModeInit_simplified_processed.json b/BlenderCtrl_ProdModeInit_simplified_processed.json deleted file mode 100644 index 25721a0..0000000 --- a/BlenderCtrl_ProdModeInit_simplified_processed.json +++ /dev/null @@ -1,96 +0,0 @@ -{ - "block_name": "BlenderCtrl_ProdModeInit", - "block_number": 2012, - "language": "LAD", - "block_comment": "", - "interface": { - "Return": [ - { - "name": "Ret_Val", - "datatype": "Void" - } - ] - }, - "networks": [ - { - "id": "9", - "title": "PID Reset Integral", - "comment": "", - "logic": [ - { - "instruction_uid": "21", - "uid": "21", - "type": "Call_FC_scl", - "block_name": "BlenderPID_PIDResInteg", - "block_type": "FC", - "inputs": { - "en": { - "type": "powerrail" - } - }, - "outputs": {}, - "scl": "BlenderPID_PIDResInteg();" - } - ] - }, - { - "id": "1A", - "title": "Ctrl Init Errors", - "comment": "", - "logic": [ - { - "instruction_uid": "21", - "uid": "21", - "type": "Call_FC_scl", - "block_name": "BlenderCtrl_InitErrors", - "block_type": "FC", - "inputs": { - "en": { - "type": "powerrail" - } - }, - "outputs": {}, - "scl": "BlenderCtrl_InitErrors();" - } - ] - }, - { - "id": "2B", - "title": "RunOut Counter", - "comment": "", - "logic": [ - { - "instruction_uid": "23", - "uid": "23", - "type": "Move_scl", - "template_values": { - "Card": "Cardinality" - }, - "inputs": { - "en": { - "type": "powerrail" - }, - "in": { - "uid": "21", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Real", - "value": 0.0 - } - }, - "outputs": { - "out1": [ - { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"HMI_Variables_Status\".\"Analog_Values\".\"TP301RunOutCount\"" - } - ] - }, - "scl": "\"HMI_Variables_Status\".\"Analog_Values\".\"TP301RunOutCount\" := 0.0;" - } - ] - } - ] -} \ No newline at end of file diff --git a/BlenderCtrl_ProdModeInit_simplified_processed.scl b/BlenderCtrl_ProdModeInit_simplified_processed.scl deleted file mode 100644 index 427db6f..0000000 --- a/BlenderCtrl_ProdModeInit_simplified_processed.scl +++ /dev/null @@ -1,35 +0,0 @@ -// Block Name (Original): BlenderCtrl_ProdModeInit -// Block Number: 2012 -// Original Language: LAD - -FUNCTION_BLOCK "BlenderCtrl_ProdModeInit" -{ S7_Optimized_Access := 'TRUE' } -VERSION : 0.1 - -VAR_INPUT -END_VAR - -VAR_OUTPUT -END_VAR - -VAR_IN_OUT -END_VAR - -VAR_TEMP -END_VAR - -BEGIN - - // Network 1: PID Reset Integral - - BlenderPID_PIDResInteg(); - - // Network 2: Ctrl Init Errors - - BlenderCtrl_InitErrors(); - - // Network 3: RunOut Counter - - "HMI_Variables_Status"."Analog_Values"."TP301RunOutCount" := 0.0; - -END_FUNCTION_BLOCK diff --git a/BlenderCtrl__Main_simplified.json b/BlenderCtrl__Main_simplified.json index 67f545b..3241dd5 100644 --- a/BlenderCtrl__Main_simplified.json +++ b/BlenderCtrl__Main_simplified.json @@ -157,17 +157,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "bit": { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"M19000\"" - }, "in": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "24", "source_pin": "out" + }, + "bit": { + "uid": "22", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"M19000\"" } }, "outputs": {} @@ -293,17 +293,17 @@ }, "negated_pins": {}, "inputs": { - "in2": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "32", - "source_pin": "out" - }, "in1": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "29", "source_pin": "out" + }, + "in2": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "32", + "source_pin": "out" } }, "outputs": {} @@ -357,17 +357,17 @@ }, "negated_pins": {}, "inputs": { - "in2": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "35", - "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": "35", + "source_pin": "out" } }, "outputs": {} @@ -844,17 +844,17 @@ }, "negated_pins": {}, "inputs": { - "in2": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "29", - "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": "29", + "source_pin": "out" } }, "outputs": {} @@ -1232,17 +1232,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": {} @@ -1361,13 +1361,6 @@ }, "negated_pins": {}, "inputs": { - "in2": { - "uid": "23", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 6 - }, "in1": { "uid": "22", "scope": "GlobalVariable", @@ -1379,6 +1372,13 @@ "source_instruction_type": "Contact", "source_instruction_uid": "24", "source_pin": "out" + }, + "in2": { + "uid": "23", + "scope": "LiteralConstant", + "type": "constant", + "datatype": "Int", + "value": 6 } }, "outputs": {} @@ -1434,13 +1434,6 @@ }, "negated_pins": {}, "inputs": { - "in2": { - "uid": "23", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 5 - }, "in1": { "uid": "22", "scope": "GlobalVariable", @@ -1452,6 +1445,13 @@ "source_instruction_type": "Contact", "source_instruction_uid": "24", "source_pin": "out" + }, + "in2": { + "uid": "23", + "scope": "LiteralConstant", + "type": "constant", + "datatype": "Int", + "value": 5 } }, "outputs": {} @@ -1549,13 +1549,6 @@ }, "negated_pins": {}, "inputs": { - "in2": { - "uid": "23", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 3 - }, "in1": { "uid": "22", "scope": "GlobalVariable", @@ -1567,6 +1560,13 @@ "source_instruction_type": "Contact", "source_instruction_uid": "24", "source_pin": "out" + }, + "in2": { + "uid": "23", + "scope": "LiteralConstant", + "type": "constant", + "datatype": "Int", + "value": 3 } }, "outputs": {} @@ -1743,17 +1743,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "bit": { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"M19001\"" - }, "in": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "25", "source_pin": "out" + }, + "bit": { + "uid": "22", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"M19001\"" } }, "outputs": {} @@ -1855,17 +1855,17 @@ }, "negated_pins": {}, "inputs": { - "in2": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "25", - "source_pin": "out" - }, "in1": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "24", "source_pin": "out" + }, + "in2": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "25", + "source_pin": "out" } }, "outputs": {} @@ -1943,17 +1943,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "bit": { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"M19002\"" - }, "in": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "25", "source_pin": "out" + }, + "bit": { + "uid": "22", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"M19002\"" } }, "outputs": {} @@ -2037,17 +2037,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "bit": { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"M19003\"" - }, "in": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "25", "source_pin": "out" + }, + "bit": { + "uid": "22", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"M19003\"" } }, "outputs": {} @@ -2674,17 +2674,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": {} @@ -2819,17 +2819,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": {} @@ -2986,17 +2986,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": {} @@ -3131,17 +3131,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": {} @@ -3432,17 +3432,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "bit": { - "uid": "23", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"M19011\"" - }, "in": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "26", "source_pin": "out" + }, + "bit": { + "uid": "23", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"M19011\"" } }, "outputs": {} diff --git a/BlenderCtrl__Main_simplified_processed.json b/BlenderCtrl__Main_simplified_processed.json index 4adeb1e..8f11f95 100644 --- a/BlenderCtrl__Main_simplified_processed.json +++ b/BlenderCtrl__Main_simplified_processed.json @@ -161,17 +161,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "bit": { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"M19000\"" - }, "in": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "24", "source_pin": "out" + }, + "bit": { + "uid": "22", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"M19000\"" } }, "outputs": {} @@ -301,17 +301,17 @@ }, "negated_pins": {}, "inputs": { - "in2": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "32", - "source_pin": "out" - }, "in1": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "29", "source_pin": "out" + }, + "in2": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "32", + "source_pin": "out" } }, "outputs": {}, @@ -368,17 +368,17 @@ }, "negated_pins": {}, "inputs": { - "in2": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "35", - "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": "35", + "source_pin": "out" } }, "outputs": {}, @@ -871,17 +871,17 @@ }, "negated_pins": {}, "inputs": { - "in2": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "29", - "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": "29", + "source_pin": "out" } }, "outputs": {}, @@ -1276,17 +1276,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": {}, @@ -1409,13 +1409,6 @@ }, "negated_pins": {}, "inputs": { - "in2": { - "uid": "23", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 6 - }, "in1": { "uid": "22", "scope": "GlobalVariable", @@ -1427,6 +1420,13 @@ "source_instruction_type": "Contact", "source_instruction_uid": "24", "source_pin": "out" + }, + "in2": { + "uid": "23", + "scope": "LiteralConstant", + "type": "constant", + "datatype": "Int", + "value": 6 } }, "outputs": {}, @@ -1485,13 +1485,6 @@ }, "negated_pins": {}, "inputs": { - "in2": { - "uid": "23", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 5 - }, "in1": { "uid": "22", "scope": "GlobalVariable", @@ -1503,6 +1496,13 @@ "source_instruction_type": "Contact", "source_instruction_uid": "24", "source_pin": "out" + }, + "in2": { + "uid": "23", + "scope": "LiteralConstant", + "type": "constant", + "datatype": "Int", + "value": 5 } }, "outputs": {}, @@ -1605,13 +1605,6 @@ }, "negated_pins": {}, "inputs": { - "in2": { - "uid": "23", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 3 - }, "in1": { "uid": "22", "scope": "GlobalVariable", @@ -1623,6 +1616,13 @@ "source_instruction_type": "Contact", "source_instruction_uid": "24", "source_pin": "out" + }, + "in2": { + "uid": "23", + "scope": "LiteralConstant", + "type": "constant", + "datatype": "Int", + "value": 3 } }, "outputs": {}, @@ -1808,17 +1808,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "bit": { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"M19001\"" - }, "in": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "25", "source_pin": "out" + }, + "bit": { + "uid": "22", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"M19001\"" } }, "outputs": {}, @@ -1925,17 +1925,17 @@ }, "negated_pins": {}, "inputs": { - "in2": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "25", - "source_pin": "out" - }, "in1": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "24", "source_pin": "out" + }, + "in2": { + "type": "connection", + "source_instruction_type": "Contact", + "source_instruction_uid": "25", + "source_pin": "out" } }, "outputs": {}, @@ -2017,17 +2017,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "bit": { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"M19002\"" - }, "in": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "25", "source_pin": "out" + }, + "bit": { + "uid": "22", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"M19002\"" } }, "outputs": {}, @@ -2115,17 +2115,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "bit": { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"M19003\"" - }, "in": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "25", "source_pin": "out" + }, + "bit": { + "uid": "22", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"M19003\"" } }, "outputs": {}, @@ -2782,17 +2782,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": {}, @@ -2931,17 +2931,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": {}, @@ -3102,17 +3102,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": {}, @@ -3251,17 +3251,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": {}, @@ -3562,17 +3562,17 @@ "template_values": {}, "negated_pins": {}, "inputs": { - "bit": { - "uid": "23", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"M19011\"" - }, "in": { "type": "connection", "source_instruction_type": "Contact", "source_instruction_uid": "26", "source_pin": "out" + }, + "bit": { + "uid": "23", + "scope": "GlobalVariable", + "type": "variable", + "name": "\"M19011\"" } }, "outputs": {} diff --git a/BlenderCtrl__Main_simplified_processed.scl b/BlenderCtrl__Main_simplified_processed.scl.txt similarity index 64% rename from BlenderCtrl__Main_simplified_processed.scl rename to BlenderCtrl__Main_simplified_processed.scl.txt index babaa13..f3e79d1 100644 --- a/BlenderCtrl__Main_simplified_processed.scl +++ b/BlenderCtrl__Main_simplified_processed.scl.txt @@ -29,7 +29,7 @@ BEGIN // Network 1: Clock Generation - Clock Signal(); + Clock_Signal(); // Network 2: Machine Init @@ -47,12 +47,12 @@ BEGIN // RLO: "gIN_LinePressCO2Ok" // RLO: "gWorkshopTest" - // RLO: "gWorkshopTest" AND "gWorkshop_Co2_Presence" - // RLO: ("gWorkshopTest" AND "gWorkshop_Co2_Presence") AND "gWorkshop_CIP_Signals" - // RLO: ("gIN_LinePressCO2Ok" OR (("gWorkshopTest" AND "gWorkshop_Co2_Presence") AND "gWorkshop_CIP_Signals")) AND "HMI_Digital"."_PAL_S11"."Filtered" - // RLO: "Disable_Bit" - // RLO: ((("gIN_LinePressCO2Ok" OR (("gWorkshopTest" AND "gWorkshop_Co2_Presence") AND "gWorkshop_CIP_Signals")) AND "HMI_Digital"."_PAL_S11"."Filtered") OR "Disable_Bit") AND "gIN_VoltageOk" - "gBlenderSuppliesOk" := ((("gIN_LinePressCO2Ok" OR (("gWorkshopTest" AND "gWorkshop_Co2_Presence") AND "gWorkshop_CIP_Signals")) AND "HMI_Digital"."_PAL_S11"."Filtered") OR "Disable_Bit") AND "gIN_VoltageOk"; + // RLO: "gWorkshopTest" AND (NOT "gWorkshop_Co2_Presence") + // RLO: ("gWorkshopTest" AND (NOT "gWorkshop_Co2_Presence")) AND (NOT "gWorkshop_CIP_Signals") + // RLO: ("gIN_LinePressCO2Ok" OR ("gWorkshopTest" AND (NOT "gWorkshop_Co2_Presence")) AND (NOT "gWorkshop_CIP_Signals")) AND "HMI_Digital"."_PAL_S11"."Filtered" + // RLO: (NOT "Disable_Bit") + // RLO: (("gIN_LinePressCO2Ok" OR ("gWorkshopTest" AND (NOT "gWorkshop_Co2_Presence")) AND (NOT "gWorkshop_CIP_Signals")) AND "HMI_Digital"."_PAL_S11"."Filtered") OR (NOT "Disable_Bit") AND "gIN_VoltageOk" + "gBlenderSuppliesOk" := (("gIN_LinePressCO2Ok" OR ("gWorkshopTest" AND (NOT "gWorkshop_Co2_Presence")) AND (NOT "gWorkshop_CIP_Signals")) AND "HMI_Digital"."_PAL_S11"."Filtered") OR (NOT "Disable_Bit") AND "gIN_VoltageOk"; // Network 6: Blender State Num @@ -69,49 +69,49 @@ BEGIN // Network 9: CIp Mode - // RLO: "HMI_Variables_Status"."System"."Blender_Prod_CIP" - "gBlenderCIPMode" := "HMI_Variables_Status"."System"."Blender_Prod_CIP"; - IF "HMI_Variables_Status"."System"."Blender_Prod_CIP" THEN + // RLO: (NOT "HMI_Variables_Status"."System"."Blender_Prod_CIP") + "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 - // RLO: "AUX FALSE" + // RLO: (NOT "AUX FALSE") // Network 11: Filler Bottle Count Used to push Product - // RLO: "System_RunOut_Variables"."ProdPipeRunOutWaterCount" - "System_RunOut_Variables"."ProdPipeRunOutFillerBott" := "System_RunOut_Variables"."ProdPipeRunOutWaterCount"; + // RLO: (NOT "System_RunOut_Variables"."ProdPipeRunOutWaterCount") + "System_RunOut_Variables"."ProdPipeRunOutFillerBott" := (NOT "System_RunOut_Variables"."ProdPipeRunOutWaterCount"); // Network 12: Water Bypass Enable // RLO: "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_StillWaterByPass" // RLO: "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_ByPassDeair" - // RLO: "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_ByPassDeair" AND "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_Deaireation" - // RLO: ("HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_StillWaterByPass" OR ("HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_ByPassDeair" AND "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_Deaireation")) AND "Blender_Variables_Pers"."gWaterRecipe" - // RLO: (("HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_StillWaterByPass" OR ("HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_ByPassDeair" AND "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_Deaireation")) AND "Blender_Variables_Pers"."gWaterRecipe") AND "Blender_Variables_Pers"."gCarboStillRecipe" - "gStillWaterByPassEn" := (("HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_StillWaterByPass" OR ("HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_ByPassDeair" AND "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_Deaireation")) AND "Blender_Variables_Pers"."gWaterRecipe") AND "Blender_Variables_Pers"."gCarboStillRecipe"; + // RLO: "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_ByPassDeair" AND (NOT "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_Deaireation") + // 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" + // 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") + "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"); // Network 13: Still Water Bypass // RLO: "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_BlendFillSystem" // RLO: "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_BlendFillSystem" AND "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_StillWaterByPass" // RLO: ("HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_BlendFillSystem" AND "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_StillWaterByPass") AND "Blender_Variables_Pers"."gWaterRecipe" - // RLO: (("HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_BlendFillSystem" AND "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_StillWaterByPass") AND "Blender_Variables_Pers"."gWaterRecipe") AND "Blender_Variables_Pers"."gCarboStillRecipe" - "gBlendFiStillWaterByPass" := (("HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_BlendFillSystem" AND "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_StillWaterByPass") AND "Blender_Variables_Pers"."gWaterRecipe") AND "Blender_Variables_Pers"."gCarboStillRecipe"; + // 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") + "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"); // Network 14: Manual Syrup Drain Valve Open - Operator Alarm // RLO: "gSyrupRoomEn" - // RLO: "gSyrupRoomEn" AND "gIN_HVP301_Aux" - // RLO: ("gSyrupRoomEn" AND "gIN_HVP301_Aux") AND "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_FastChangeOverEnabled" - // RLO: (("gSyrupRoomEn" AND "gIN_HVP301_Aux") AND "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_FastChangeOverEnabled") AND "Procedure_Variables"."FTP302Line_Preparation"."Done" - // RLO: ((("gSyrupRoomEn" AND "gIN_HVP301_Aux") AND "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_FastChangeOverEnabled") AND "Procedure_Variables"."FTP302Line_Preparation"."Done") AND "Procedure_Variables"."Syr_RunOut"."Done" + // RLO: "gSyrupRoomEn" AND (NOT "gIN_HVP301_Aux") + // RLO: ("gSyrupRoomEn" AND (NOT "gIN_HVP301_Aux")) AND (NOT "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_FastChangeOverEnabled") + // RLO: ("gSyrupRoomEn" AND (NOT "gIN_HVP301_Aux")) AND (NOT "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_FastChangeOverEnabled") AND "Procedure_Variables"."FTP302Line_Preparation"."Done" + // 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") // RLO: "gBlenderCIPMode" // RLO: "gBlenderCIPMode" AND "gIN_CIP_CIPRunning" // RLO: ("gBlenderCIPMode" AND "gIN_CIP_CIPRunning") AND "Procedure_Variables"."Blender_Run"."Running" - "gHVP301_Open" := (((("gSyrupRoomEn" AND "gIN_HVP301_Aux") AND "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_FastChangeOverEnabled") AND "Procedure_Variables"."FTP302Line_Preparation"."Done") AND "Procedure_Variables"."Syr_RunOut"."Done") OR (("gBlenderCIPMode" AND "gIN_CIP_CIPRunning") AND "Procedure_Variables"."Blender_Run"."Running"); + "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 (("gBlenderCIPMode" AND "gIN_CIP_CIPRunning") AND "Procedure_Variables"."Blender_Run"."Running"); // Network 15: Manual Syrup Drain Valve Open - Operator Alarm @@ -120,7 +120,6 @@ BEGIN // Network 16: Maselli Control // RLO: "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_BrixMeter" - // Cond: "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_MeterType" = 6 IF "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_MeterType" = 6 THEN Maselli_PA_Control(); END_IF; @@ -128,7 +127,6 @@ BEGIN // Network 17: mPDS Control // RLO: "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_BrixMeter" - // Cond: "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_MeterType" = 5 IF "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_MeterType" = 5 THEN mPDS_PA_Control(); END_IF; @@ -146,7 +144,6 @@ BEGIN // NOP 0 // RLO: "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_BrixMeter" - // Cond: "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_MeterType" = 3 IF "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_MeterType" = 3 THEN GetProdBrixCO2_Anal_Inpt(); END_IF; @@ -157,7 +154,7 @@ BEGIN // Network 21: Input Data - // ERROR: Call a bloque no soportado: Input + // ERROR: FB Call Input sin instancia // Network 22: Sel Brix Source Check @@ -177,32 +174,32 @@ BEGIN // Network 25: Production ONS // RLO: "gBlenderProdMode" - // PBox 26 - Passing bit: "M19001" - // RLO: "M19001" AND "mDelayPowerOnTmr" - "gProductionONS" := "M19001" AND "mDelayPowerOnTmr"; + // // PBox 26 - Passing memory bit: "M19001" + // RLO: "M19001" AND (NOT "mDelayPowerOnTmr") + "gProductionONS" := "M19001" AND (NOT "mDelayPowerOnTmr"); // Network 26: Blender Prod Mode Init // RLO: "gProductionONS" // RLO: "Procedure_Variables"."Blender_Rinse"."ONS_Done" - // RLO: ("gProductionONS" OR "Procedure_Variables"."Blender_Rinse"."ONS_Done") AND "Blender_Variables_Pers"."gBlenderStarted" - IF ("gProductionONS" OR "Procedure_Variables"."Blender_Rinse"."ONS_Done") AND "Blender_Variables_Pers"."gBlenderStarted" THEN + // RLO: ("gProductionONS" OR "Procedure_Variables"."Blender_Rinse"."ONS_Done") AND (NOT "Blender_Variables_Pers"."gBlenderStarted") + IF ("gProductionONS" OR "Procedure_Variables"."Blender_Rinse"."ONS_Done") AND (NOT "Blender_Variables_Pers"."gBlenderStarted") THEN BlenderCtrl_ProdModeInit(); END_IF; // Network 27: Rinse ONS // RLO: "HMI_Variables_Status"."System"."Blender_Prod_CIP" - // PBox 26 - Passing bit: "M19002" - // RLO: "M19002" AND "mDelayPowerOnTmr" - "gRinseONS" := "M19002" AND "mDelayPowerOnTmr"; + // // PBox 26 - Passing memory bit: "M19002" + // RLO: "M19002" AND (NOT "mDelayPowerOnTmr") + "gRinseONS" := "M19002" AND (NOT "mDelayPowerOnTmr"); // Network 28: CIP ONS // RLO: "gBlenderCIPMode" - // PBox 26 - Passing bit: "M19003" - // RLO: "M19003" AND "mDelayPowerOnTmr" - "gCIPONS" := "M19003" AND "mDelayPowerOnTmr"; + // // PBox 26 - Passing memory bit: "M19003" + // RLO: "M19003" AND (NOT "mDelayPowerOnTmr") + "gCIPONS" := "M19003" AND (NOT "mDelayPowerOnTmr"); // Network 29: CIp Mode Init @@ -221,7 +218,7 @@ BEGIN // Network 32: Tank Pressure Control - Prod Tank PressCtrl(); + Prod_Tank_PressCtrl(); // Network 33: Balaiage @@ -229,7 +226,7 @@ BEGIN // Network 34: First Production - // ERROR: Call a bloque no soportado: ProcedureFirstProduction + // ERROR: FB Call ProcedureFirstProduction sin instancia // Network 35: CIP MAIN Calling @@ -257,14 +254,12 @@ BEGIN // Network 41: Blend Procedure Data - // RLO: "mDelayPowerOnTmr" - IF "mDelayPowerOnTmr" THEN - // ERROR: Call a bloque no soportado: Procedure - END_IF; + // RLO: (NOT "mDelayPowerOnTmr") + // ERROR: FB Call Procedure sin instancia // Network 42: Pneumatic Valve Control - Pneumatic Valve Ctrl(); + Pneumatic_Valve_Ctrl(); // Network 43: Pumps Control @@ -343,18 +338,18 @@ BEGIN // Network 60: Blender Ctrl Command - // RLO: "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_Simulation" - IF "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_Simulation" THEN - BlenderCtrl_MFM Command(); + // RLO: (NOT "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_Simulation") + IF (NOT "HMI_Blender_Parameters"."Processor_Options"."Blender_OPT"."_Simulation") THEN + BlenderCtrl_MFM_Command(); END_IF; // Network 61: DP Global Diag - CPU_DP Global Diag(); + CPU_DP_Global_Diag(); // Network 62: Profibus - Profibus Network(); + Profibus_Network(); // Network 63: Valve Fault @@ -372,8 +367,8 @@ BEGIN // Network 66: Mod Copy Recipe // RLO: "HMI_Variables_Cmd"."Recipe"."Main_Page" - // RLO: "HMI_Variables_Cmd"."Recipe"."Main_Page" AND "mFP_Recip_Main_Page" - "mAux_FP_M700_1" := "HMI_Variables_Cmd"."Recipe"."Main_Page" AND "mFP_Recip_Main_Page"; + // RLO: "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"); // RLO: "HMI_Variables_Cmd"."Recipe"."Main_Page" // RLO: "HMI_Variables_Cmd"."Recipe"."Main_Page" AND "HMI_Variables_Cmd"."Recipe"."Edit" // RLO: "mAux_FP_M700_1" @@ -381,9 +376,7 @@ BEGIN // Network 67: to HMI - Recipe Management // RLO: "AUX TRUE" - IF "AUX TRUE" THEN - // ERROR: Call a bloque no soportado: RecipeManagement - Prod - END_IF; + // ERROR: FB Call RecipeManagement___Prod sin instancia // Network 68: Recipe Calculation diff --git a/BlenderRun_ProdTime_simplified.json b/BlenderRun_ProdTime_simplified.json deleted file mode 100644 index 01f75a0..0000000 --- a/BlenderRun_ProdTime_simplified.json +++ /dev/null @@ -1,1317 +0,0 @@ -{ - "block_name": "BlenderRun_ProdTime", - "block_number": 2040, - "language": "LAD", - "block_comment": "", - "interface": { - "Temp": [ - { - "name": "m1MinONS", - "datatype": "Bool" - }, - { - "name": "m1HourONS", - "datatype": "Bool" - }, - { - "name": "Buffer", - "datatype": "Bool" - }, - { - "name": "mRunMin", - "datatype": "Bool" - }, - { - "name": "mRunHr", - "datatype": "Bool" - }, - { - "name": "I_DIRunning_sec", - "datatype": "DInt" - }, - { - "name": "I_DIRunning_min", - "datatype": "DInt" - }, - { - "name": "MOD60", - "datatype": "DInt" - } - ], - "Return": [ - { - "name": "Ret_Val", - "datatype": "Void" - } - ] - }, - "networks": [ - { - "id": "9", - "title": "Seconds", - "comment": "", - "logic": [ - { - "instruction_uid": "26", - "uid": "26", - "type": "Contact", - "template_values": {}, - "inputs": { - "operand": { - "uid": "21", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Procedure_Variables\".\"Blender_Run\".\"Running\"" - }, - "in": { - "type": "powerrail" - } - }, - "outputs": {} - }, - { - "instruction_uid": "27", - "uid": "27", - "type": "Contact", - "template_values": {}, - "inputs": { - "operand": { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"CLK_1.0S\"" - }, - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "26", - "source_pin": "out" - } - }, - "outputs": {} - }, - { - "instruction_uid": "28", - "uid": "28", - "type": "Add", - "template_values": { - "Card": "Cardinality", - "SrcType": "Type" - }, - "inputs": { - "in2": { - "uid": "24", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 1 - }, - "en": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "27", - "source_pin": "out" - }, - "in1": { - "uid": "23", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gSLIM_Sec\"" - } - }, - "outputs": { - "out": [ - { - "uid": "25", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gSLIM_Sec\"" - } - ] - } - } - ] - }, - { - "id": "1A", - "title": "Reset Hours", - "comment": "", - "logic": [ - { - "instruction_uid": "24", - "uid": "24", - "type": "Contact", - "template_values": {}, - "inputs": { - "operand": { - "uid": "21", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"SLIM_Variables\".\"ResetHour\"" - }, - "in": { - "type": "powerrail" - } - }, - "outputs": {} - }, - { - "instruction_uid": "25", - "uid": "25", - "type": "Move", - "template_values": { - "Card": "Cardinality" - }, - "inputs": { - "in": { - "uid": "22", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 0 - }, - "en": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "24", - "source_pin": "out" - } - }, - "outputs": { - "out1": [ - { - "uid": "23", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gSLIM_Sec\"" - } - ] - } - } - ] - }, - { - "id": "2B", - "title": "Seconds Counter", - "comment": "", - "logic": [ - { - "instruction_uid": "26", - "uid": "26", - "type": "Contact", - "template_values": {}, - "inputs": { - "operand": { - "uid": "21", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"gBlenderBlending\"" - }, - "in": { - "type": "powerrail" - } - }, - "outputs": {} - }, - { - "instruction_uid": "27", - "uid": "27", - "type": "Contact", - "template_values": {}, - "inputs": { - "operand": { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"CLK_1.0S\"" - }, - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "26", - "source_pin": "out" - } - }, - "outputs": {} - }, - { - "instruction_uid": "28", - "uid": "28", - "type": "Add", - "template_values": { - "Card": "Cardinality", - "SrcType": "Type" - }, - "inputs": { - "in2": { - "uid": "24", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 1 - }, - "en": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "27", - "source_pin": "out" - }, - "in1": { - "uid": "23", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdSec\"" - } - }, - "outputs": { - "out": [ - { - "uid": "25", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdSec\"" - } - ] - } - } - ] - }, - { - "id": "3C", - "title": "Minute", - "comment": "", - "logic": [ - { - "instruction_uid": "24", - "uid": "24", - "type": "Eq", - "template_values": { - "SrcType": "Type" - }, - "inputs": { - "pre": { - "type": "powerrail" - }, - "in2": { - "uid": "22", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 60 - }, - "in1": { - "uid": "21", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdSec\"" - } - }, - "outputs": {} - }, - { - "instruction_uid": "25", - "uid": "25", - "type": "Coil", - "template_values": {}, - "inputs": { - "operand": { - "uid": "23", - "scope": "LocalVariable", - "type": "variable", - "name": "\"m1MinONS\"" - }, - "in": { - "type": "connection", - "source_instruction_type": "Eq", - "source_instruction_uid": "24", - "source_pin": "out" - } - }, - "outputs": {} - } - ] - }, - { - "id": "4D", - "title": "Minute Counter", - "comment": "", - "logic": [ - { - "instruction_uid": "27", - "uid": "27", - "type": "Contact", - "template_values": {}, - "inputs": { - "operand": { - "uid": "21", - "scope": "LocalVariable", - "type": "variable", - "name": "\"m1MinONS\"" - }, - "in": { - "type": "powerrail" - } - }, - "outputs": {} - }, - { - "instruction_uid": "28", - "uid": "28", - "type": "Move", - "template_values": { - "Card": "Cardinality" - }, - "inputs": { - "in": { - "uid": "22", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 0 - }, - "en": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "27", - "source_pin": "out" - } - }, - "outputs": { - "out1": [ - { - "uid": "23", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdSec\"" - } - ] - } - }, - { - "instruction_uid": "29", - "uid": "29", - "type": "Add", - "template_values": { - "Card": "Cardinality", - "SrcType": "Type" - }, - "inputs": { - "in2": { - "uid": "25", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 1 - }, - "in1": { - "uid": "24", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdMin\"" - }, - "en": { - "type": "connection", - "source_instruction_uid": "27", - "source_instruction_type": "Contact", - "source_pin": "out" - } - }, - "outputs": { - "out": [ - { - "uid": "26", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdMin\"" - } - ] - } - } - ] - }, - { - "id": "5E", - "title": "Hour", - "comment": "", - "logic": [ - { - "instruction_uid": "24", - "uid": "24", - "type": "Eq", - "template_values": { - "SrcType": "Type" - }, - "inputs": { - "pre": { - "type": "powerrail" - }, - "in2": { - "uid": "22", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 60 - }, - "in1": { - "uid": "21", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdMin\"" - } - }, - "outputs": {} - }, - { - "instruction_uid": "25", - "uid": "25", - "type": "Coil", - "template_values": {}, - "inputs": { - "operand": { - "uid": "23", - "scope": "LocalVariable", - "type": "variable", - "name": "\"m1HourONS\"" - }, - "in": { - "type": "connection", - "source_instruction_type": "Eq", - "source_instruction_uid": "24", - "source_pin": "out" - } - }, - "outputs": {} - } - ] - }, - { - "id": "6F", - "title": "Hour Counter", - "comment": "", - "logic": [ - { - "instruction_uid": "30", - "uid": "30", - "type": "Contact", - "template_values": {}, - "inputs": { - "operand": { - "uid": "21", - "scope": "LocalVariable", - "type": "variable", - "name": "\"m1HourONS\"" - }, - "in": { - "type": "powerrail" - } - }, - "outputs": {} - }, - { - "instruction_uid": "31", - "uid": "31", - "type": "Move", - "template_values": { - "Card": "Cardinality" - }, - "inputs": { - "in": { - "uid": "22", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 0 - }, - "en": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "30", - "source_pin": "out" - } - }, - "outputs": { - "out1": [ - { - "uid": "23", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdMin\"" - } - ] - } - }, - { - "instruction_uid": "32", - "uid": "32", - "type": "Add", - "template_values": { - "Card": "Cardinality", - "SrcType": "Type" - }, - "inputs": { - "in2": { - "uid": "25", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 1 - }, - "in1": { - "uid": "24", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdHour\"" - }, - "en": { - "type": "connection", - "source_instruction_uid": "30", - "source_instruction_type": "Contact", - "source_pin": "out" - } - }, - "outputs": { - "out": [ - { - "uid": "26", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdHour\"" - } - ] - } - }, - { - "instruction_uid": "33", - "uid": "33", - "type": "Add", - "template_values": { - "Card": "Cardinality", - "SrcType": "Type" - }, - "inputs": { - "in2": { - "uid": "28", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 1 - }, - "in1": { - "uid": "27", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gBlendingMaintHour\"" - }, - "en": { - "type": "connection", - "source_instruction_uid": "30", - "source_instruction_type": "Contact", - "source_pin": "out" - } - }, - "outputs": { - "out": [ - { - "uid": "29", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gBlendingMaintHour\"" - } - ] - } - } - ] - }, - { - "id": "80", - "title": "Counter reset", - "comment": "", - "logic": [ - { - "instruction_uid": "29", - "uid": "29", - "type": "Contact", - "template_values": {}, - "inputs": { - "operand": { - "uid": "21", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"gBlenderCIPMode\"" - }, - "in": { - "type": "powerrail" - } - }, - "outputs": {} - }, - { - "instruction_uid": "30", - "uid": "30", - "type": "Contact", - "template_values": {}, - "inputs": { - "operand": { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"gBlenderRinseMode\"" - } - }, - "outputs": {} - }, - { - "instruction_uid": "31", - "uid": "31", - "type": "O", - "template_values": { - "Card": "Cardinality" - }, - "inputs": { - "in2": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "30", - "source_pin": "out" - }, - "in1": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "29", - "source_pin": "out" - } - }, - "outputs": {} - }, - { - "instruction_uid": "32", - "uid": "32", - "type": "Move", - "template_values": { - "Card": "Cardinality" - }, - "inputs": { - "in": { - "uid": "23", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 0 - }, - "en": { - "type": "connection", - "source_instruction_type": "O", - "source_instruction_uid": "31", - "source_pin": "out" - } - }, - "outputs": { - "out1": [ - { - "uid": "24", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdSec\"" - } - ] - } - }, - { - "instruction_uid": "33", - "uid": "33", - "type": "Move", - "template_values": { - "Card": "Cardinality" - }, - "inputs": { - "in": { - "uid": "25", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 0 - }, - "en": { - "type": "connection", - "source_instruction_uid": "31", - "source_instruction_type": "O", - "source_pin": "out" - } - }, - "outputs": { - "out1": [ - { - "uid": "26", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdMin\"" - } - ] - } - }, - { - "instruction_uid": "34", - "uid": "34", - "type": "Move", - "template_values": { - "Card": "Cardinality" - }, - "inputs": { - "in": { - "uid": "27", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 0 - }, - "en": { - "type": "connection", - "source_instruction_uid": "31", - "source_instruction_type": "O", - "source_pin": "out" - } - }, - "outputs": { - "out1": [ - { - "uid": "28", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdHour\"" - } - ] - } - } - ] - }, - { - "id": "91", - "title": "Running Seconds", - "comment": "", - "logic": [ - { - "instruction_uid": "26", - "uid": "26", - "type": "Contact", - "template_values": {}, - "inputs": { - "operand": { - "uid": "21", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Procedure_Variables\".\"Blender_Run\".\"Running\"" - }, - "in": { - "type": "powerrail" - } - }, - "outputs": {} - }, - { - "instruction_uid": "27", - "uid": "27", - "type": "Contact", - "template_values": {}, - "inputs": { - "operand": { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"CLK_1.0S\"" - }, - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "26", - "source_pin": "out" - } - }, - "outputs": {} - }, - { - "instruction_uid": "28", - "uid": "28", - "type": "Add", - "template_values": { - "Card": "Cardinality", - "SrcType": "Type" - }, - "inputs": { - "in2": { - "uid": "24", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 1 - }, - "en": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "27", - "source_pin": "out" - }, - "in1": { - "uid": "23", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gRunningSeconds\"" - } - }, - "outputs": { - "out": [ - { - "uid": "25", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gRunningSeconds\"" - } - ] - } - } - ] - }, - { - "id": "A2", - "title": "Running Minutes", - "comment": "", - "logic": [ - { - "instruction_uid": "35", - "uid": "35", - "type": "Convert", - "template_values": { - "SrcType": "Type", - "DestType": "Type" - }, - "inputs": { - "in": { - "uid": "21", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gRunningSeconds\"" - }, - "en": { - "type": "powerrail" - } - }, - "outputs": { - "out": [ - { - "uid": "22", - "scope": "LocalVariable", - "type": "variable", - "name": "\"I_DIRunning_sec\"" - } - ] - } - }, - { - "instruction_uid": "36", - "uid": "36", - "type": "Mod", - "template_values": { - "SrcType": "Type" - }, - "inputs": { - "in2": { - "uid": "24", - "scope": "TypedConstant", - "type": "constant", - "datatype": "TypedConstant", - "value": "DINT#60" - }, - "en": { - "type": "connection", - "source_instruction_type": "Convert", - "source_instruction_uid": "35", - "source_pin": "eno" - }, - "in1": { - "uid": "23", - "scope": "LocalVariable", - "type": "variable", - "name": "\"I_DIRunning_sec\"" - } - }, - "outputs": { - "out": [ - { - "uid": "25", - "scope": "LocalVariable", - "type": "variable", - "name": "\"MOD60\"" - } - ] - }, - "eno_logic": [ - { - "target_pin": "pre", - "target_type": "instruction", - "target_uid": "37", - "target_name": "Eq" - } - ] - }, - { - "instruction_uid": "37", - "uid": "37", - "type": "Eq", - "template_values": { - "SrcType": "Type" - }, - "inputs": { - "pre": { - "type": "connection", - "source_instruction_type": "Mod", - "source_instruction_uid": "36", - "source_pin": "eno" - }, - "in2": { - "uid": "27", - "scope": "TypedConstant", - "type": "constant", - "datatype": "TypedConstant", - "value": "DINT#0" - }, - "in1": { - "uid": "26", - "scope": "LocalVariable", - "type": "variable", - "name": "\"MOD60\"" - } - }, - "outputs": {} - }, - { - "instruction_uid": "38", - "uid": "38", - "type": "Contact", - "template_values": {}, - "inputs": { - "operand": { - "uid": "28", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Procedure_Variables\".\"Blender_Run\".\"Running\"" - }, - "in": { - "type": "connection", - "source_instruction_type": "Eq", - "source_instruction_uid": "37", - "source_pin": "out" - } - }, - "outputs": {} - }, - { - "instruction_uid": "39", - "uid": "39", - "type": "Contact", - "template_values": {}, - "inputs": { - "operand": { - "uid": "29", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"CLK_1.0S\"" - }, - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "38", - "source_pin": "out" - } - }, - "outputs": {} - }, - { - "instruction_uid": "40", - "uid": "40", - "type": "Add", - "template_values": { - "Card": "Cardinality", - "SrcType": "Type" - }, - "inputs": { - "in2": { - "uid": "31", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 1 - }, - "en": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "39", - "source_pin": "out" - }, - "in1": { - "uid": "30", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gRunningMinutes\"" - } - }, - "outputs": { - "out": [ - { - "uid": "32", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gRunningMinutes\"" - } - ] - } - }, - { - "instruction_uid": "41", - "uid": "41", - "type": "PBox", - "template_values": {}, - "inputs": { - "bit": { - "uid": "33", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"M19012\"" - } - }, - "outputs": {} - }, - { - "instruction_uid": "42", - "uid": "42", - "type": "Coil", - "template_values": {}, - "inputs": { - "operand": { - "uid": "34", - "scope": "LocalVariable", - "type": "variable", - "name": "\"mRunMin\"" - }, - "in": { - "type": "connection", - "source_instruction_type": "PBox", - "source_instruction_uid": "41", - "source_pin": "out" - } - }, - "outputs": {} - } - ] - }, - { - "id": "B3", - "title": "Running Hours for Maintenance", - "comment": "", - "logic": [ - { - "instruction_uid": "32", - "uid": "32", - "type": "Contact", - "template_values": {}, - "inputs": { - "operand": { - "uid": "21", - "scope": "LocalVariable", - "type": "variable", - "name": "\"mRunMin\"" - }, - "in": { - "type": "powerrail" - } - }, - "outputs": {} - }, - { - "instruction_uid": "33", - "uid": "33", - "type": "Convert", - "template_values": { - "SrcType": "Type", - "DestType": "Type" - }, - "inputs": { - "in": { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gRunningMinutes\"" - }, - "en": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "32", - "source_pin": "out" - } - }, - "outputs": { - "out": [ - { - "uid": "23", - "scope": "LocalVariable", - "type": "variable", - "name": "\"I_DIRunning_min\"" - } - ] - } - }, - { - "instruction_uid": "34", - "uid": "34", - "type": "Mod", - "template_values": { - "SrcType": "Type" - }, - "inputs": { - "in2": { - "uid": "25", - "scope": "TypedConstant", - "type": "constant", - "datatype": "TypedConstant", - "value": "DINT#60" - }, - "en": { - "type": "connection", - "source_instruction_type": "Convert", - "source_instruction_uid": "33", - "source_pin": "eno" - }, - "in1": { - "uid": "24", - "scope": "LocalVariable", - "type": "variable", - "name": "\"I_DIRunning_min\"" - } - }, - "outputs": { - "out": [ - { - "uid": "26", - "scope": "LocalVariable", - "type": "variable", - "name": "\"MOD60\"" - } - ] - }, - "eno_logic": [ - { - "target_pin": "pre", - "target_type": "instruction", - "target_uid": "35", - "target_name": "Eq" - } - ] - }, - { - "instruction_uid": "35", - "uid": "35", - "type": "Eq", - "template_values": { - "SrcType": "Type" - }, - "inputs": { - "pre": { - "type": "connection", - "source_instruction_type": "Mod", - "source_instruction_uid": "34", - "source_pin": "eno" - }, - "in2": { - "uid": "28", - "scope": "TypedConstant", - "type": "constant", - "datatype": "TypedConstant", - "value": "DINT#0" - }, - "in1": { - "uid": "27", - "scope": "LocalVariable", - "type": "variable", - "name": "\"MOD60\"" - } - }, - "outputs": {} - }, - { - "instruction_uid": "36", - "uid": "36", - "type": "Add", - "template_values": { - "Card": "Cardinality", - "SrcType": "Type" - }, - "inputs": { - "in2": { - "uid": "30", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 1 - }, - "en": { - "type": "connection", - "source_instruction_type": "Eq", - "source_instruction_uid": "35", - "source_pin": "out" - }, - "in1": { - "uid": "29", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gRunningMaintHour\"" - } - }, - "outputs": { - "out": [ - { - "uid": "31", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gRunningMaintHour\"" - } - ] - } - } - ] - }, - { - "id": "C4", - "title": "Running Hours for Maintenance", - "comment": "", - "logic": [ - { - "instruction_uid": "23", - "uid": "23", - "type": "Move", - "template_values": { - "Card": "Cardinality" - }, - "inputs": { - "in": { - "uid": "21", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gRunningMaintHour\"" - }, - "en": { - "type": "powerrail" - } - }, - "outputs": { - "out1": [ - { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"HMI_Variables_Status\".\"System\".\"BlendingMaintHour\"" - } - ] - } - } - ] - } - ] -} \ No newline at end of file diff --git a/BlenderRun_ProdTime_simplified_processed.json b/BlenderRun_ProdTime_simplified_processed.json deleted file mode 100644 index 93ec292..0000000 --- a/BlenderRun_ProdTime_simplified_processed.json +++ /dev/null @@ -1,1367 +0,0 @@ -{ - "block_name": "BlenderRun_ProdTime", - "block_number": 2040, - "language": "LAD", - "block_comment": "", - "interface": { - "Temp": [ - { - "name": "m1MinONS", - "datatype": "Bool" - }, - { - "name": "m1HourONS", - "datatype": "Bool" - }, - { - "name": "Buffer", - "datatype": "Bool" - }, - { - "name": "mRunMin", - "datatype": "Bool" - }, - { - "name": "mRunHr", - "datatype": "Bool" - }, - { - "name": "I_DIRunning_sec", - "datatype": "DInt" - }, - { - "name": "I_DIRunning_min", - "datatype": "DInt" - }, - { - "name": "MOD60", - "datatype": "DInt" - } - ], - "Return": [ - { - "name": "Ret_Val", - "datatype": "Void" - } - ] - }, - "networks": [ - { - "id": "9", - "title": "Seconds", - "comment": "", - "logic": [ - { - "instruction_uid": "26", - "uid": "26", - "type": "Contact_scl", - "template_values": {}, - "inputs": { - "operand": { - "uid": "21", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Procedure_Variables\".\"Blender_Run\".\"Running\"" - }, - "in": { - "type": "powerrail" - } - }, - "outputs": {}, - "scl": "// RLO updated by Contact 26: \"Procedure_Variables\".\"Blender_Run\".\"Running\"" - }, - { - "instruction_uid": "27", - "uid": "27", - "type": "Contact_scl", - "template_values": {}, - "inputs": { - "operand": { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"CLK_1.0S\"" - }, - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "26", - "source_pin": "out" - } - }, - "outputs": {}, - "scl": "// RLO updated by Contact 27: \"Procedure_Variables\".\"Blender_Run\".\"Running\" AND \"CLK_1.0S\"" - }, - { - "instruction_uid": "28", - "uid": "28", - "type": "Add_scl", - "template_values": { - "Card": "Cardinality", - "SrcType": "Type" - }, - "inputs": { - "in2": { - "uid": "24", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 1 - }, - "en": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "27", - "source_pin": "out" - }, - "in1": { - "uid": "23", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gSLIM_Sec\"" - } - }, - "outputs": { - "out": [ - { - "uid": "25", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gSLIM_Sec\"" - } - ] - }, - "scl": "IF \"Procedure_Variables\".\"Blender_Run\".\"Running\" AND \"CLK_1.0S\" THEN\n \"Blender_Variables_Pers\".\"gSLIM_Sec\" := \"Blender_Variables_Pers\".\"gSLIM_Sec\" + 1;\nEND_IF;" - } - ] - }, - { - "id": "1A", - "title": "Reset Hours", - "comment": "", - "logic": [ - { - "instruction_uid": "24", - "uid": "24", - "type": "Contact_scl", - "template_values": {}, - "inputs": { - "operand": { - "uid": "21", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"SLIM_Variables\".\"ResetHour\"" - }, - "in": { - "type": "powerrail" - } - }, - "outputs": {}, - "scl": "// RLO updated by Contact 24: \"SLIM_Variables\".\"ResetHour\"" - }, - { - "instruction_uid": "25", - "uid": "25", - "type": "Move_scl", - "template_values": { - "Card": "Cardinality" - }, - "inputs": { - "in": { - "uid": "22", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 0 - }, - "en": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "24", - "source_pin": "out" - } - }, - "outputs": { - "out1": [ - { - "uid": "23", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gSLIM_Sec\"" - } - ] - }, - "scl": "IF \"SLIM_Variables\".\"ResetHour\" THEN\n \"Blender_Variables_Pers\".\"gSLIM_Sec\" := 0;\nEND_IF;" - } - ] - }, - { - "id": "2B", - "title": "Seconds Counter", - "comment": "", - "logic": [ - { - "instruction_uid": "26", - "uid": "26", - "type": "Contact_scl", - "template_values": {}, - "inputs": { - "operand": { - "uid": "21", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"gBlenderBlending\"" - }, - "in": { - "type": "powerrail" - } - }, - "outputs": {}, - "scl": "// RLO updated by Contact 26: \"gBlenderBlending\"" - }, - { - "instruction_uid": "27", - "uid": "27", - "type": "Contact_scl", - "template_values": {}, - "inputs": { - "operand": { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"CLK_1.0S\"" - }, - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "26", - "source_pin": "out" - } - }, - "outputs": {}, - "scl": "// RLO updated by Contact 27: \"gBlenderBlending\" AND \"CLK_1.0S\"" - }, - { - "instruction_uid": "28", - "uid": "28", - "type": "Add_scl", - "template_values": { - "Card": "Cardinality", - "SrcType": "Type" - }, - "inputs": { - "in2": { - "uid": "24", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 1 - }, - "en": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "27", - "source_pin": "out" - }, - "in1": { - "uid": "23", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdSec\"" - } - }, - "outputs": { - "out": [ - { - "uid": "25", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdSec\"" - } - ] - }, - "scl": "IF \"gBlenderBlending\" AND \"CLK_1.0S\" THEN\n \"Blender_Variables_Pers\".\"gProdSec\" := \"Blender_Variables_Pers\".\"gProdSec\" + 1;\nEND_IF;" - } - ] - }, - { - "id": "3C", - "title": "Minute", - "comment": "", - "logic": [ - { - "instruction_uid": "24", - "uid": "24", - "type": "Eq_scl", - "template_values": { - "SrcType": "Type" - }, - "inputs": { - "pre": { - "type": "powerrail" - }, - "in2": { - "uid": "22", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 60 - }, - "in1": { - "uid": "21", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdSec\"" - } - }, - "outputs": {}, - "scl": "// Comparison Eq 24: \"Blender_Variables_Pers\".\"gProdSec\" = 60" - }, - { - "instruction_uid": "25", - "uid": "25", - "type": "Coil_scl", - "template_values": {}, - "inputs": { - "operand": { - "uid": "23", - "scope": "LocalVariable", - "type": "variable", - "name": "\"m1MinONS\"" - }, - "in": { - "type": "connection", - "source_instruction_type": "Eq", - "source_instruction_uid": "24", - "source_pin": "out" - } - }, - "outputs": {}, - "scl": "\"m1MinONS\" := \"Blender_Variables_Pers\".\"gProdSec\" = 60;" - } - ] - }, - { - "id": "4D", - "title": "Minute Counter", - "comment": "", - "logic": [ - { - "instruction_uid": "27", - "uid": "27", - "type": "Contact_scl", - "template_values": {}, - "inputs": { - "operand": { - "uid": "21", - "scope": "LocalVariable", - "type": "variable", - "name": "\"m1MinONS\"" - }, - "in": { - "type": "powerrail" - } - }, - "outputs": {}, - "scl": "IF \"m1MinONS\" THEN\n \"Blender_Variables_Pers\".\"gProdSec\" := 0;\n \"Blender_Variables_Pers\".\"gProdMin\" := \"Blender_Variables_Pers\".\"gProdMin\" + 1;\nEND_IF;" - }, - { - "instruction_uid": "28", - "uid": "28", - "type": "Move_scl", - "template_values": { - "Card": "Cardinality" - }, - "inputs": { - "in": { - "uid": "22", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 0 - }, - "en": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "27", - "source_pin": "out" - } - }, - "outputs": { - "out1": [ - { - "uid": "23", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdSec\"" - } - ] - }, - "scl": "// Logic included in grouped IF (by UID 27)", - "grouped": true - }, - { - "instruction_uid": "29", - "uid": "29", - "type": "Add_scl", - "template_values": { - "Card": "Cardinality", - "SrcType": "Type" - }, - "inputs": { - "in2": { - "uid": "25", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 1 - }, - "in1": { - "uid": "24", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdMin\"" - }, - "en": { - "type": "connection", - "source_instruction_uid": "27", - "source_instruction_type": "Contact", - "source_pin": "out" - } - }, - "outputs": { - "out": [ - { - "uid": "26", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdMin\"" - } - ] - }, - "scl": "// Logic included in grouped IF (by UID 27)", - "grouped": true - } - ] - }, - { - "id": "5E", - "title": "Hour", - "comment": "", - "logic": [ - { - "instruction_uid": "24", - "uid": "24", - "type": "Eq_scl", - "template_values": { - "SrcType": "Type" - }, - "inputs": { - "pre": { - "type": "powerrail" - }, - "in2": { - "uid": "22", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 60 - }, - "in1": { - "uid": "21", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdMin\"" - } - }, - "outputs": {}, - "scl": "// Comparison Eq 24: \"Blender_Variables_Pers\".\"gProdMin\" = 60" - }, - { - "instruction_uid": "25", - "uid": "25", - "type": "Coil_scl", - "template_values": {}, - "inputs": { - "operand": { - "uid": "23", - "scope": "LocalVariable", - "type": "variable", - "name": "\"m1HourONS\"" - }, - "in": { - "type": "connection", - "source_instruction_type": "Eq", - "source_instruction_uid": "24", - "source_pin": "out" - } - }, - "outputs": {}, - "scl": "\"m1HourONS\" := \"Blender_Variables_Pers\".\"gProdMin\" = 60;" - } - ] - }, - { - "id": "6F", - "title": "Hour Counter", - "comment": "", - "logic": [ - { - "instruction_uid": "30", - "uid": "30", - "type": "Contact_scl", - "template_values": {}, - "inputs": { - "operand": { - "uid": "21", - "scope": "LocalVariable", - "type": "variable", - "name": "\"m1HourONS\"" - }, - "in": { - "type": "powerrail" - } - }, - "outputs": {}, - "scl": "IF \"m1HourONS\" THEN\n \"Blender_Variables_Pers\".\"gProdMin\" := 0;\n \"Blender_Variables_Pers\".\"gProdHour\" := \"Blender_Variables_Pers\".\"gProdHour\" + 1;\n \"Blender_Variables_Pers\".\"gBlendingMaintHour\" := \"Blender_Variables_Pers\".\"gBlendingMaintHour\" + 1;\nEND_IF;" - }, - { - "instruction_uid": "31", - "uid": "31", - "type": "Move_scl", - "template_values": { - "Card": "Cardinality" - }, - "inputs": { - "in": { - "uid": "22", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 0 - }, - "en": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "30", - "source_pin": "out" - } - }, - "outputs": { - "out1": [ - { - "uid": "23", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdMin\"" - } - ] - }, - "scl": "// Logic included in grouped IF (by UID 30)", - "grouped": true - }, - { - "instruction_uid": "32", - "uid": "32", - "type": "Add_scl", - "template_values": { - "Card": "Cardinality", - "SrcType": "Type" - }, - "inputs": { - "in2": { - "uid": "25", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 1 - }, - "in1": { - "uid": "24", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdHour\"" - }, - "en": { - "type": "connection", - "source_instruction_uid": "30", - "source_instruction_type": "Contact", - "source_pin": "out" - } - }, - "outputs": { - "out": [ - { - "uid": "26", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdHour\"" - } - ] - }, - "scl": "// Logic included in grouped IF (by UID 30)", - "grouped": true - }, - { - "instruction_uid": "33", - "uid": "33", - "type": "Add_scl", - "template_values": { - "Card": "Cardinality", - "SrcType": "Type" - }, - "inputs": { - "in2": { - "uid": "28", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 1 - }, - "in1": { - "uid": "27", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gBlendingMaintHour\"" - }, - "en": { - "type": "connection", - "source_instruction_uid": "30", - "source_instruction_type": "Contact", - "source_pin": "out" - } - }, - "outputs": { - "out": [ - { - "uid": "29", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gBlendingMaintHour\"" - } - ] - }, - "scl": "// Logic included in grouped IF (by UID 30)", - "grouped": true - } - ] - }, - { - "id": "80", - "title": "Counter reset", - "comment": "", - "logic": [ - { - "instruction_uid": "29", - "uid": "29", - "type": "Contact_scl", - "template_values": {}, - "inputs": { - "operand": { - "uid": "21", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"gBlenderCIPMode\"" - }, - "in": { - "type": "powerrail" - } - }, - "outputs": {}, - "scl": "// RLO updated by Contact 29: \"gBlenderCIPMode\"" - }, - { - "instruction_uid": "30", - "uid": "30", - "type": "Contact_scl", - "template_values": {}, - "inputs": { - "operand": { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"gBlenderRinseMode\"" - } - }, - "outputs": {}, - "scl": "// RLO updated by Contact 30: \"gBlenderRinseMode\"" - }, - { - "instruction_uid": "31", - "uid": "31", - "type": "O_scl", - "template_values": { - "Card": "Cardinality" - }, - "inputs": { - "in2": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "30", - "source_pin": "out" - }, - "in1": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "29", - "source_pin": "out" - } - }, - "outputs": {}, - "scl": "IF \"gBlenderCIPMode\" OR \"gBlenderRinseMode\" THEN\n \"Blender_Variables_Pers\".\"gProdSec\" := 0;\n \"Blender_Variables_Pers\".\"gProdMin\" := 0;\n \"Blender_Variables_Pers\".\"gProdHour\" := 0;\nEND_IF;" - }, - { - "instruction_uid": "32", - "uid": "32", - "type": "Move_scl", - "template_values": { - "Card": "Cardinality" - }, - "inputs": { - "in": { - "uid": "23", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 0 - }, - "en": { - "type": "connection", - "source_instruction_type": "O", - "source_instruction_uid": "31", - "source_pin": "out" - } - }, - "outputs": { - "out1": [ - { - "uid": "24", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdSec\"" - } - ] - }, - "scl": "// Logic included in grouped IF (by UID 31)", - "grouped": true - }, - { - "instruction_uid": "33", - "uid": "33", - "type": "Move_scl", - "template_values": { - "Card": "Cardinality" - }, - "inputs": { - "in": { - "uid": "25", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 0 - }, - "en": { - "type": "connection", - "source_instruction_uid": "31", - "source_instruction_type": "O", - "source_pin": "out" - } - }, - "outputs": { - "out1": [ - { - "uid": "26", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdMin\"" - } - ] - }, - "scl": "// Logic included in grouped IF (by UID 31)", - "grouped": true - }, - { - "instruction_uid": "34", - "uid": "34", - "type": "Move_scl", - "template_values": { - "Card": "Cardinality" - }, - "inputs": { - "in": { - "uid": "27", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 0 - }, - "en": { - "type": "connection", - "source_instruction_uid": "31", - "source_instruction_type": "O", - "source_pin": "out" - } - }, - "outputs": { - "out1": [ - { - "uid": "28", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gProdHour\"" - } - ] - }, - "scl": "// Logic included in grouped IF (by UID 31)", - "grouped": true - } - ] - }, - { - "id": "91", - "title": "Running Seconds", - "comment": "", - "logic": [ - { - "instruction_uid": "26", - "uid": "26", - "type": "Contact_scl", - "template_values": {}, - "inputs": { - "operand": { - "uid": "21", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Procedure_Variables\".\"Blender_Run\".\"Running\"" - }, - "in": { - "type": "powerrail" - } - }, - "outputs": {}, - "scl": "// RLO updated by Contact 26: \"Procedure_Variables\".\"Blender_Run\".\"Running\"" - }, - { - "instruction_uid": "27", - "uid": "27", - "type": "Contact_scl", - "template_values": {}, - "inputs": { - "operand": { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"CLK_1.0S\"" - }, - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "26", - "source_pin": "out" - } - }, - "outputs": {}, - "scl": "// RLO updated by Contact 27: \"Procedure_Variables\".\"Blender_Run\".\"Running\" AND \"CLK_1.0S\"" - }, - { - "instruction_uid": "28", - "uid": "28", - "type": "Add_scl", - "template_values": { - "Card": "Cardinality", - "SrcType": "Type" - }, - "inputs": { - "in2": { - "uid": "24", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 1 - }, - "en": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "27", - "source_pin": "out" - }, - "in1": { - "uid": "23", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gRunningSeconds\"" - } - }, - "outputs": { - "out": [ - { - "uid": "25", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gRunningSeconds\"" - } - ] - }, - "scl": "IF \"Procedure_Variables\".\"Blender_Run\".\"Running\" AND \"CLK_1.0S\" THEN\n \"Blender_Variables_Pers\".\"gRunningSeconds\" := \"Blender_Variables_Pers\".\"gRunningSeconds\" + 1;\nEND_IF;" - } - ] - }, - { - "id": "A2", - "title": "Running Minutes", - "comment": "", - "logic": [ - { - "instruction_uid": "35", - "uid": "35", - "type": "Convert_scl", - "template_values": { - "SrcType": "Type", - "DestType": "Type" - }, - "inputs": { - "in": { - "uid": "21", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gRunningSeconds\"" - }, - "en": { - "type": "powerrail" - } - }, - "outputs": { - "out": [ - { - "uid": "22", - "scope": "LocalVariable", - "type": "variable", - "name": "\"I_DIRunning_sec\"" - } - ] - }, - "scl": "\"I_DIRunning_sec\" := \"Blender_Variables_Pers\".\"gRunningSeconds\";" - }, - { - "instruction_uid": "36", - "uid": "36", - "type": "Mod_scl", - "template_values": { - "SrcType": "Type" - }, - "inputs": { - "in2": { - "uid": "24", - "scope": "TypedConstant", - "type": "constant", - "datatype": "TypedConstant", - "value": "DINT#60" - }, - "en": { - "type": "connection", - "source_instruction_type": "Convert", - "source_instruction_uid": "35", - "source_pin": "eno" - }, - "in1": { - "uid": "23", - "scope": "LocalVariable", - "type": "variable", - "name": "\"I_DIRunning_sec\"" - } - }, - "outputs": { - "out": [ - { - "uid": "25", - "scope": "LocalVariable", - "type": "variable", - "name": "\"MOD60\"" - } - ] - }, - "eno_logic": [ - { - "target_pin": "pre", - "target_type": "instruction", - "target_uid": "37", - "target_name": "Eq" - } - ], - "scl": "\"MOD60\" := \"I_DIRunning_sec\" MOD DINT#60;" - }, - { - "instruction_uid": "37", - "uid": "37", - "type": "Eq_scl", - "template_values": { - "SrcType": "Type" - }, - "inputs": { - "pre": { - "type": "connection", - "source_instruction_type": "Mod", - "source_instruction_uid": "36", - "source_pin": "eno" - }, - "in2": { - "uid": "27", - "scope": "TypedConstant", - "type": "constant", - "datatype": "TypedConstant", - "value": "DINT#0" - }, - "in1": { - "uid": "26", - "scope": "LocalVariable", - "type": "variable", - "name": "\"MOD60\"" - } - }, - "outputs": {}, - "scl": "// Comparison Eq 37: \"MOD60\" = DINT#0" - }, - { - "instruction_uid": "38", - "uid": "38", - "type": "Contact_scl", - "template_values": {}, - "inputs": { - "operand": { - "uid": "28", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Procedure_Variables\".\"Blender_Run\".\"Running\"" - }, - "in": { - "type": "connection", - "source_instruction_type": "Eq", - "source_instruction_uid": "37", - "source_pin": "out" - } - }, - "outputs": {}, - "scl": "// RLO updated by Contact 38: \"MOD60\" = DINT#0 AND \"Procedure_Variables\".\"Blender_Run\".\"Running\"" - }, - { - "instruction_uid": "39", - "uid": "39", - "type": "Contact_scl", - "template_values": {}, - "inputs": { - "operand": { - "uid": "29", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"CLK_1.0S\"" - }, - "in": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "38", - "source_pin": "out" - } - }, - "outputs": {}, - "scl": "// RLO updated by Contact 39: (\"MOD60\" = DINT#0 AND \"Procedure_Variables\".\"Blender_Run\".\"Running\") AND \"CLK_1.0S\"" - }, - { - "instruction_uid": "40", - "uid": "40", - "type": "Add_scl", - "template_values": { - "Card": "Cardinality", - "SrcType": "Type" - }, - "inputs": { - "in2": { - "uid": "31", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 1 - }, - "en": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "39", - "source_pin": "out" - }, - "in1": { - "uid": "30", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gRunningMinutes\"" - } - }, - "outputs": { - "out": [ - { - "uid": "32", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gRunningMinutes\"" - } - ] - }, - "scl": "IF (\"MOD60\" = DINT#0 AND \"Procedure_Variables\".\"Blender_Run\".\"Running\") AND \"CLK_1.0S\" THEN\n \"Blender_Variables_Pers\".\"gRunningMinutes\" := \"Blender_Variables_Pers\".\"gRunningMinutes\" + 1;\nEND_IF;" - }, - { - "instruction_uid": "41", - "uid": "41", - "type": "PBox_scl", - "template_values": {}, - "inputs": { - "bit": { - "uid": "33", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"M19012\"" - } - }, - "outputs": {}, - "scl": "\"M19012\" := ((\"MOD60\" = DINT#0 AND \"Procedure_Variables\".\"Blender_Run\".\"Running\") AND \"CLK_1.0S\"); // Update edge memory bit" - }, - { - "instruction_uid": "42", - "uid": "42", - "type": "Coil_scl", - "template_values": {}, - "inputs": { - "operand": { - "uid": "34", - "scope": "LocalVariable", - "type": "variable", - "name": "\"mRunMin\"" - }, - "in": { - "type": "connection", - "source_instruction_type": "PBox", - "source_instruction_uid": "41", - "source_pin": "out" - } - }, - "outputs": {}, - "scl": "\"mRunMin\" := ((\"MOD60\" = DINT#0 AND \"Procedure_Variables\".\"Blender_Run\".\"Running\") AND \"CLK_1.0S\") AND NOT \"M19012\";" - } - ] - }, - { - "id": "B3", - "title": "Running Hours for Maintenance", - "comment": "", - "logic": [ - { - "instruction_uid": "32", - "uid": "32", - "type": "Contact_scl", - "template_values": {}, - "inputs": { - "operand": { - "uid": "21", - "scope": "LocalVariable", - "type": "variable", - "name": "\"mRunMin\"" - }, - "in": { - "type": "powerrail" - } - }, - "outputs": {}, - "scl": "// RLO updated by Contact 32: \"mRunMin\"" - }, - { - "instruction_uid": "33", - "uid": "33", - "type": "Convert_scl", - "template_values": { - "SrcType": "Type", - "DestType": "Type" - }, - "inputs": { - "in": { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gRunningMinutes\"" - }, - "en": { - "type": "connection", - "source_instruction_type": "Contact", - "source_instruction_uid": "32", - "source_pin": "out" - } - }, - "outputs": { - "out": [ - { - "uid": "23", - "scope": "LocalVariable", - "type": "variable", - "name": "\"I_DIRunning_min\"" - } - ] - }, - "scl": "IF \"mRunMin\" THEN\n \"I_DIRunning_min\" := \"Blender_Variables_Pers\".\"gRunningMinutes\";\nEND_IF;" - }, - { - "instruction_uid": "34", - "uid": "34", - "type": "Mod_scl", - "template_values": { - "SrcType": "Type" - }, - "inputs": { - "in2": { - "uid": "25", - "scope": "TypedConstant", - "type": "constant", - "datatype": "TypedConstant", - "value": "DINT#60" - }, - "en": { - "type": "connection", - "source_instruction_type": "Convert", - "source_instruction_uid": "33", - "source_pin": "eno" - }, - "in1": { - "uid": "24", - "scope": "LocalVariable", - "type": "variable", - "name": "\"I_DIRunning_min\"" - } - }, - "outputs": { - "out": [ - { - "uid": "26", - "scope": "LocalVariable", - "type": "variable", - "name": "\"MOD60\"" - } - ] - }, - "eno_logic": [ - { - "target_pin": "pre", - "target_type": "instruction", - "target_uid": "35", - "target_name": "Eq" - } - ], - "scl": "IF \"mRunMin\" THEN\n \"MOD60\" := \"I_DIRunning_min\" MOD DINT#60;\nEND_IF;" - }, - { - "instruction_uid": "35", - "uid": "35", - "type": "Eq_scl", - "template_values": { - "SrcType": "Type" - }, - "inputs": { - "pre": { - "type": "connection", - "source_instruction_type": "Mod", - "source_instruction_uid": "34", - "source_pin": "eno" - }, - "in2": { - "uid": "28", - "scope": "TypedConstant", - "type": "constant", - "datatype": "TypedConstant", - "value": "DINT#0" - }, - "in1": { - "uid": "27", - "scope": "LocalVariable", - "type": "variable", - "name": "\"MOD60\"" - } - }, - "outputs": {}, - "scl": "// Comparison Eq 35: \"MOD60\" = DINT#0" - }, - { - "instruction_uid": "36", - "uid": "36", - "type": "Add_scl", - "template_values": { - "Card": "Cardinality", - "SrcType": "Type" - }, - "inputs": { - "in2": { - "uid": "30", - "scope": "LiteralConstant", - "type": "constant", - "datatype": "Int", - "value": 1 - }, - "en": { - "type": "connection", - "source_instruction_type": "Eq", - "source_instruction_uid": "35", - "source_pin": "out" - }, - "in1": { - "uid": "29", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gRunningMaintHour\"" - } - }, - "outputs": { - "out": [ - { - "uid": "31", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gRunningMaintHour\"" - } - ] - }, - "scl": "IF \"MOD60\" = DINT#0 THEN\n \"Blender_Variables_Pers\".\"gRunningMaintHour\" := \"Blender_Variables_Pers\".\"gRunningMaintHour\" + 1;\nEND_IF;" - } - ] - }, - { - "id": "C4", - "title": "Running Hours for Maintenance", - "comment": "", - "logic": [ - { - "instruction_uid": "23", - "uid": "23", - "type": "Move_scl", - "template_values": { - "Card": "Cardinality" - }, - "inputs": { - "in": { - "uid": "21", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"Blender_Variables_Pers\".\"gRunningMaintHour\"" - }, - "en": { - "type": "powerrail" - } - }, - "outputs": { - "out1": [ - { - "uid": "22", - "scope": "GlobalVariable", - "type": "variable", - "name": "\"HMI_Variables_Status\".\"System\".\"BlendingMaintHour\"" - } - ] - }, - "scl": "\"HMI_Variables_Status\".\"System\".\"BlendingMaintHour\" := \"Blender_Variables_Pers\".\"gRunningMaintHour\";" - } - ] - } - ] -} \ No newline at end of file diff --git a/BlenderRun_ProdTime_simplified_processed.scl b/BlenderRun_ProdTime_simplified_processed.scl deleted file mode 100644 index 7af1511..0000000 --- a/BlenderRun_ProdTime_simplified_processed.scl +++ /dev/null @@ -1,120 +0,0 @@ -// Block Name (Original): BlenderRun_ProdTime -// Block Number: 2040 -// Original Language: LAD - -FUNCTION_BLOCK "BlenderRun_ProdTime" -{ S7_Optimized_Access := 'TRUE' } -VERSION : 0.1 - -VAR_INPUT -END_VAR - -VAR_OUTPUT -END_VAR - -VAR_IN_OUT -END_VAR - -VAR_TEMP - m1MinONS : Bool; - m1HourONS : Bool; - Buffer : Bool; - mRunMin : Bool; - mRunHr : Bool; - I_DIRunning_sec : DInt; - I_DIRunning_min : DInt; - MOD60 : DInt; -END_VAR - -BEGIN - - // Network 1: Seconds - - IF "Procedure_Variables"."Blender_Run"."Running" AND "CLK_1.0S" THEN - "Blender_Variables_Pers"."gSLIM_Sec" := "Blender_Variables_Pers"."gSLIM_Sec" + 1; - END_IF; - - // Network 2: Reset Hours - - IF "SLIM_Variables"."ResetHour" THEN - "Blender_Variables_Pers"."gSLIM_Sec" := 0; - END_IF; - - // Network 3: Seconds Counter - - IF "gBlenderBlending" AND "CLK_1.0S" THEN - "Blender_Variables_Pers"."gProdSec" := "Blender_Variables_Pers"."gProdSec" + 1; - END_IF; - - // Network 4: Minute - - "m1MinONS" := "Blender_Variables_Pers"."gProdSec" = 60; - - // Network 5: Minute Counter - - IF "m1MinONS" THEN - "Blender_Variables_Pers"."gProdSec" := 0; - "Blender_Variables_Pers"."gProdMin" := "Blender_Variables_Pers"."gProdMin" + 1; - END_IF; - // Logic included in grouped IF (by UID 27) - // Logic included in grouped IF (by UID 27) - - // Network 6: Hour - - "m1HourONS" := "Blender_Variables_Pers"."gProdMin" = 60; - - // Network 7: Hour Counter - - IF "m1HourONS" THEN - "Blender_Variables_Pers"."gProdMin" := 0; - "Blender_Variables_Pers"."gProdHour" := "Blender_Variables_Pers"."gProdHour" + 1; - "Blender_Variables_Pers"."gBlendingMaintHour" := "Blender_Variables_Pers"."gBlendingMaintHour" + 1; - END_IF; - // Logic included in grouped IF (by UID 30) - // Logic included in grouped IF (by UID 30) - // Logic included in grouped IF (by UID 30) - - // Network 8: Counter reset - - IF "gBlenderCIPMode" OR "gBlenderRinseMode" THEN - "Blender_Variables_Pers"."gProdSec" := 0; - "Blender_Variables_Pers"."gProdMin" := 0; - "Blender_Variables_Pers"."gProdHour" := 0; - END_IF; - // Logic included in grouped IF (by UID 31) - // Logic included in grouped IF (by UID 31) - // Logic included in grouped IF (by UID 31) - - // Network 9: Running Seconds - - IF "Procedure_Variables"."Blender_Run"."Running" AND "CLK_1.0S" THEN - "Blender_Variables_Pers"."gRunningSeconds" := "Blender_Variables_Pers"."gRunningSeconds" + 1; - END_IF; - - // Network 10: Running Minutes - - "I_DIRunning_sec" := "Blender_Variables_Pers"."gRunningSeconds"; - "MOD60" := "I_DIRunning_sec" MOD DINT#60; - IF ("MOD60" = DINT#0 AND "Procedure_Variables"."Blender_Run"."Running") AND "CLK_1.0S" THEN - "Blender_Variables_Pers"."gRunningMinutes" := "Blender_Variables_Pers"."gRunningMinutes" + 1; - END_IF; - "M19012" := (("MOD60" = DINT#0 AND "Procedure_Variables"."Blender_Run"."Running") AND "CLK_1.0S"); // Update edge memory bit - "mRunMin" := (("MOD60" = DINT#0 AND "Procedure_Variables"."Blender_Run"."Running") AND "CLK_1.0S") AND NOT "M19012"; - - // Network 11: Running Hours for Maintenance - - IF "mRunMin" THEN - "I_DIRunning_min" := "Blender_Variables_Pers"."gRunningMinutes"; - END_IF; - IF "mRunMin" THEN - "MOD60" := "I_DIRunning_min" MOD DINT#60; - END_IF; - IF "MOD60" = DINT#0 THEN - "Blender_Variables_Pers"."gRunningMaintHour" := "Blender_Variables_Pers"."gRunningMaintHour" + 1; - END_IF; - - // Network 12: Running Hours for Maintenance - - "HMI_Variables_Status"."System"."BlendingMaintHour" := "Blender_Variables_Pers"."gRunningMaintHour"; - -END_FUNCTION_BLOCK diff --git a/TestLAD_simplified_processed.scl.txt b/TestLAD_simplified_processed.scl.txt deleted file mode 100644 index 93e785e..0000000 --- a/TestLAD_simplified_processed.scl.txt +++ /dev/null @@ -1,33 +0,0 @@ -// Block Name (Original): TestLAD -// Block Number: 2 -// Original Language: LAD - -FUNCTION_BLOCK "TestLAD" -{ S7_Optimized_Access := 'TRUE' } -VERSION : 0.1 - -VAR_INPUT -END_VAR - -VAR_OUTPUT -END_VAR - -VAR_IN_OUT -END_VAR - -VAR_TEMP -END_VAR - -BEGIN - - // Network 1: Clock Bit - - "Clock_5Hz" := "Clock_10Hz"; - - // Network 2: Clock Bit - - "Clock_5Hz" := "Clock_10Hz"; - - // Network 3: - -END_FUNCTION_BLOCK diff --git a/VersionNoFuncionante/readme.md b/VersionNoFuncionante/readme.md new file mode 100644 index 0000000..c7c6d4b --- /dev/null +++ b/VersionNoFuncionante/readme.md @@ -0,0 +1,170 @@ +# LAD-to-SCL Conversion Pipeline: Documentación de Referencia + +## 1. Visión General + +Este documento describe un pipeline de scripts de Python diseñado para convertir bloques de función o funciones (FC/FB) escritos en Ladder Logic (LAD) desde archivos XML de TIA Portal Openness a un código SCL (Structured Control Language) semánticamente equivalente. + +El proceso se divide en tres etapas principales, cada una manejada por un script específico: + +1. **XML a JSON Enriquecido (`x1_to_json.py`):** Parsea el XML de Openness, extrae la estructura lógica (incluyendo llamadas a FC/FB y temporizadores S5), conexiones explícitas e **infiere conexiones implícitas** (especialmente las habilitaciones EN) para crear un archivo JSON detallado. Mapea tipos de instrucción LAD/FBD (p.ej., `Se`, `NBox`) a nombres internos consistentes (p.ej., `TON_S5`, `N_TRIG`). +2. **Procesamiento Semántico (`x2_process.py`):** Lee el JSON enriquecido y, de forma iterativa, traduce cada instrucción (usando los tipos mapeados) a su equivalente SCL, manejando dependencias, propagando el estado lógico (RLO), traduciendo temporizadores S5 a IEC, generando lógica de flancos y agrupando lógica paralela bajo bloques `IF`. El SCL generado se almacena *dentro* del propio JSON. +3. **Generación de SCL Final (`x3_generate_scl.py`):** Lee el JSON completamente procesado y ensambla el código SCL final en un archivo `.scl` formateado, incluyendo declaraciones de variables (Input, Output, InOut, Temp, Stat - incluyendo instancias de temporizadores y bits de memoria de flancos) y el cuerpo del programa (`FUNCTION` o `FUNCTION_BLOCK`). + +## 2. Etapas del Pipeline + +### Etapa 1: XML a JSON Enriquecido (`x1_to_json.py`) + +* **Propósito:** Transformar la compleja y a veces ambigua estructura XML de Openness en un formato JSON estructurado y más fácil de procesar, añadiendo información clave que está implícita en el LAD visual pero no siempre explícita en el XML. +* **Entrada:** Archivo `.xml` exportado desde TIA Portal Openness para un FC o FB. +* **Salida:** Archivo `_simplified.json`. +* **Proceso Clave:** + 1. **Parseo XML:** Utiliza `lxml` para leer el archivo XML. + 2. **Extracción de Metadatos:** Obtiene nombre del bloque, número, lenguaje original, comentario del bloque. Detecta si es `SW.Blocks.FC` o `SW.Blocks.FB`. + 3. **Extracción de Interfaz:** Parsea las secciones `Input`, `Output`, `InOut`, `Temp`, `Constant`, `Return` para obtener la declaración de variables. + 4. **Parseo de Redes (`CompileUnit`):** Itera sobre cada red lógica. + * **`parse_network`:** + * **Parseo de Componentes:** + * `Access`: Identifica variables globales/locales, constantes literales y tipadas (`parse_access`). Utiliza `get_symbol_name` para formatear nombres simbólicos con comillas (`"DB"."Var"`). + * `Part`: Identifica instrucciones estándar LAD/FBD (`parse_part`). **Importante:** Detecta pines negados (``) y los almacena en `negated_pins`. **Mapea** nombres XML (`Se`, `Sd`, `PBox`, `NBox`, `RCoil`, `SCoil`, `SdCoil`) a tipos internos (`TON_S5`, `TONR_S5`, `P_TRIG`, `N_TRIG`, `R`, `S`, `SR`). + * `Call`: Identifica llamadas a otros FCs o FBs (`parse_call`), extrayendo el nombre del bloque llamado, tipo (FC/FB) e información de instancia DB (`instance_db`) si aplica (formateado con comillas). + * Crea `access_map` y `parts_and_calls_map` para referencia rápida por UID. + * **Parseo de Conexiones (`Wire`):** + * Construye `wire_connections`: Un mapa `(dest_uid, dest_pin) -> [(src_uid, src_pin), ...]`. + * Construye `source_connections`: Un mapa `(src_uid, src_pin) -> [(dest_uid, dest_pin), ...]`. + * **Construcción Lógica Inicial:** Crea una lista de diccionarios (`all_logic_steps`), uno por cada `Part` o `Call`, rellenando `inputs` y `outputs` **solo con las conexiones explícitas** encontradas en los `Wire`. + * **Inferencia de Conexión `EN` (¡Paso Crucial!):** + * Itera sobre los bloques funcionales (`Move`, `Add`, `Call`, `BLKMOV`, etc.) que *no* tienen una entrada `en` explícita definida después del paso anterior. + * Utiliza una **heurística de búsqueda lineal hacia atrás** para encontrar la fuente de RLO más probable que precede a este bloque (la salida `out` de un bloque lógico como `Contact`/`O`/`Eq`/`P_TRIG`/`N_TRIG` o la salida `eno` de un bloque funcional anterior). + * Si se encuentra una fuente inferida, **añade la conexión `en`** al diccionario `inputs` del bloque funcional actual. Esto enriquece el JSON con la dependencia lógica implícita. + * **Ordenamiento:** Ordena las instrucciones en la lista `logic` final (generalmente por UID). + 5. **Escritura JSON:** Guarda la estructura de datos completa en el archivo `_simplified.json`. + +### Etapa 2: Procesamiento Semántico (`x2_process.py`) + +* **Propósito:** Traducir la lógica LAD/FBD (representada en el JSON enriquecido) a código SCL embebido, resolviendo dependencias entre instrucciones, generando lógica SCL equivalente (incluyendo manejo de flancos y temporizadores), y aplicando optimizaciones de agrupación `IF`. +* **Entrada:** Archivo `_simplified.json` (generado por la Etapa 1). +* **Salida:** Archivo `_simplified_processed.json`. +* **Proceso Clave:** + 1. **Carga de JSON y Preparación:** Lee el JSON de entrada y reconstruye mapas de acceso por red. Inicializa el `scl_map` global (o por red). + 2. **Bucle Iterativo:** Repite los siguientes pasos hasta que no se realicen cambios en un pase completo o se alcance un límite máximo de pases (`max_passes`). + * **Fase 1: Procesadores Base:** + * Itera sobre cada instrucción en cada red. + * Si la instrucción no ha sido procesada (`_scl` o `_error`) ni agrupada (`grouped`), busca el procesador adecuado (`process_xxx`) basado en su `type` (usando los tipos mapeados como `TON_S5`, `P_TRIG`, etc.). + * **`process_xxx` (Ejecución):** + * Llama a `get_scl_representation` para obtener el SCL de sus pines de entrada, buscándolos en `scl_map` o directamente en `access_map`. `get_scl_representation` ahora **convierte constantes S5T# a T#**. + * Si alguna dependencia no está resuelta (devuelve `None`), el procesador retorna `False`. + * Si las dependencias están resueltas: + * **Generadores RLO (`Contact`, `O`, `Eq`, `P_TRIG`, `N_TRIG`):** Calculan la expresión booleana SCL resultante y la almacenan en `scl_map` bajo la clave `(network_id, instr_uid, 'out')`. `P_TRIG`/`N_TRIG` generan lógica explícita de flancos y la llamada para actualizar el bit de memoria (`stat_... := CLK;`). Guardan comentarios/lógica en `instruction['scl']`. + * **Bloques Funcionales (`Move`, `Add`, `Convert`, `Mod`, `BLKMOV`, `Call`):** + * Obtienen la condición `EN` (explícita o inferida). + * Generan el código SCL *core* (la asignación, cálculo o llamada). `process_call` ahora usa correctamente `instance_db` para FBs. `process_blkmov` traduce a `DST := SRC;` (con advertencia sobre tipos). + * Generan el SCL final, **envolviendo el core en `IF en_scl THEN ... END_IF;`** si `en_scl` no es `"TRUE"`. + * Almacenan el SCL final en `instruction['scl']`. + * Almacenan el nombre de la variable de salida/temporal (prefijado con `#` si es temporal) en `scl_map` para `out`/`out1`/`RET_VAL`. + * Almacenan el `en_scl` en `scl_map` para `eno`. + * **Bobinas (`Coil`, `R`, `S`, `SR`):** Obtienen el RLO de entrada (`in`, o `S`/`R1` para `SR`), obtienen el operando destino, generan la asignación (`:= TRUE`/`:= FALSE`) o lógica `IF/ELSIF` envuelta en `IF RLO THEN ...` si aplica, y la guardan en `instruction['scl']`. + * **Temporizadores (`TON_S5`, `TONR_S5`):** Generan una llamada a un bloque IEC (`TON`/`TONR`) usando un nombre de instancia (`stat_timer_...`). Parsean el valor `PT` (T#...). Mapean `Q` y `ET` a la instancia (`Instance.Q`, `Instance.ET`) en `scl_map`. Almacenan la llamada en `instruction['scl']`. + * Marcan la instrucción como procesada añadiendo `_scl` a `instruction['type']`. + * Retornan `True`. + * Se registra si hubo algún cambio en esta fase (`made_change_in_base_pass`). + * **Fase 2: Agrupación de IFs (`process_group_ifs`):** + * Itera sobre las instrucciones *ya procesadas* (`_scl`) que son generadoras de condición (`Contact`, `O`, `Eq`, `P_TRIG`, `N_TRIG`, etc.). + * Obtiene la `condition_scl` de `scl_map`. + * Busca todos los bloques funcionales, bobinas o temporizadores (`Move_scl`, `Add_scl`, `Coil_scl`, `TON_S5_scl`, etc.) cuyo pin de habilitación (`en`, `in`, `s`) esté conectado a la salida `out` de esta instrucción generadora. + * Si encuentra **más de uno**: + * Extrae el código *core* (lo que está dentro del `IF...END_IF;` si existe, o el código completo si no) de cada consumidor. + * Construye un **único bloque `IF condition_scl THEN ... END_IF;`** que contiene todos los cores extraídos, indentados. + * **Sobrescribe** el campo `scl` de la instrucción *generadora de condición* con este nuevo bloque `IF` agrupado. + * Marca cada instrucción consumidora con `grouped = True` y cambia su `scl` a un comentario (`GROUPED_COMMENT`) para evitar que `x3_generate_scl.py` lo use. + * Se registra si hubo algún cambio en esta fase (`made_change_in_group_pass`). + * **Condición de Salida:** El bucle termina si `made_change_in_base_pass` y `made_change_in_group_pass` son ambos `False`. + 3. **Verificación Final:** Comprueba si quedaron instrucciones sin procesar, sin agrupar y sin errores, e informa al usuario. + 4. **Escritura JSON:** Guarda el JSON modificado (con SCL embebido y marcas de agrupación) en el archivo `_simplified_processed.json`. + +### Etapa 3: Generación de SCL Final (`x3_generate_scl.py`) + +* **Propósito:** Ensamblar un archivo `.scl` completo y formateado a partir del JSON procesado. +* **Entrada:** Archivo `_simplified_processed.json` (generado por la Etapa 2). +* **Salida:** Archivo `.scl`. +* **Proceso Clave:** + 1. **Carga de JSON:** Lee el archivo JSON procesado. + 2. **Detección de Variables y Tipo de Bloque:** + * Escanea el SCL generado en busca de variables `#_temp_...` y `stat_...`. + * Identifica los tipos de las variables `stat_...` (Bool, TON, TONR) según sus nombres (`stat_nbox_mem...`, `stat_timer_Se...`, etc.). + * Determina si el bloque debe ser `FUNCTION_BLOCK` (si hay variables `STAT` o `TEMP`) o `FUNCTION`. + 3. **Generación de Cabecera:** Escribe el encabezado del bloque (`FUNCTION_BLOCK name` o `FUNCTION name`, `VERSION`, etc.). Utiliza `format_variable_name` (la versión corregida) para el nombre del bloque. + 4. **Generación de Declaraciones VAR:** + * Escribe las secciones `VAR_INPUT`, `VAR_OUTPUT`, `VAR_IN_OUT` usando `format_variable_name` para los nombres de las variables de la interfaz. + * **Escribe `VAR_STAT`:** Declara las variables `stat_...` detectadas con sus tipos inferidos (Bool, TON, TONR) y nombres entre comillas. + * **Escribe `VAR_TEMP`:** Declara las variables `#_temp_...` detectadas (declaradas como `"_temp_..."` sin el `#` pero con comillas) y las variables de la sección `Temp` de la interfaz. Utiliza inferencia de tipo básica para las variables `#_temp_...`. + 5. **Generación del Cuerpo (`BEGIN`/`END_FUNCTION_BLOCK` o `END_FUNCTION`):** + * Itera sobre las `networks` en el JSON. + * Añade comentarios de red. + * Itera sobre la `logic` de cada red. + * Para cada `instruction`: + * **Verifica el flag `grouped`:** Si `instruction.get('grouped', False)` es `True`, **ignora** esta instrucción. + * Si no está agrupada, obtiene el valor del campo `scl`. + * **Limpia comentarios internos:** Elimina comentarios informativos específicos (`// RLO:`, `// Comparison:`, `// Logic O:`, `// N/P_TRIG Output Logic:`) si son la única parte de la línea, pero conserva los comentarios de actualización de memoria de flancos, errores y agrupación. + * Indenta y añade las líneas del SCL resultante al output. + * Añade líneas en blanco entre redes si contienen código. + 6. **Escritura de Archivo:** Escribe el string SCL completo al archivo `.scl`. + +## 3. Cómo Extender para Nuevas Instrucciones LAD/FBD + +Añadir soporte para un nuevo tipo de instrucción (p.ej., un comparador `GT`, una función matemática `SQRT`, o un temporizador IEC `TP`) requiere modificar los scripts `x1_to_json.py` y `x2_process.py`. + +**Pasos:** + +1. **Analizar el XML:** Exporta un bloque simple que use la nueva instrucción y examina el XML de Openness. Identifica: + * Si se representa como `` o ``. + * Sus pines de entrada y salida (`NameCon`/`IdentCon` en los `Wire`). + * Cualquier atributo o `TemplateValue` relevante. + * Si tiene pines negados (``). + +2. **Modificar `x1_to_json.py` (`parse_part` o `parse_call` y `parse_network`):** + * **Parseo:** Asegúrate de que `parse_part` o `parse_call` capture correctamente la nueva instrucción. + * **Mapeo de Tipo:** Si el nombre XML no es ideal (como `Se`), mapéalo a un nombre interno consistente en `parse_part` (p.ej., si fuera un temporizador IEC TP, podrías mapear `TPartName` -> `TP_IEC`). + * **Clasificación:** Decide si la nueva instrucción es un `functional_block_type` (necesita inferencia EN?) o un `rlo_generator`. Actualiza estas listas en `parse_network` si es necesario. + * **Inferencia EN:** Revisa si la lógica de inferencia EN en `parse_network` necesita ajustes. + * **Pines:** Asegúrate de que sus pines de entrada/salida esperados estén en `possible_input_pins` / `possible_output_pins` en `parse_network`. + +3. **Modificar `x2_process.py` (continuación):** + * **Lógica SCL (continuación):** + * ... + * Almacena el SCL final en `instruction['scl']`. + * Actualiza `instruction['type']` con el sufijo `_scl`. + * **Actualiza `scl_map`:** Añade entradas para los pines de salida (`out`, `Q`, etc.) con su representación SCL (puede ser un nombre de variable temporal prefijado con `#`, el resultado de una expresión, o el acceso a un miembro de instancia como `"Instance".Q`). Añade la entrada para `eno` si el bloque lo tiene (generalmente `scl_map[key_eno] = en_scl`). + * Retorna `True`. + * **Añadir a la Lista:** Inserta la nueva función `process_nombre_instruccion` en la lista `base_processors_list` en el orden de prioridad correcto (generalmente, generadores de valores/condiciones antes que consumidores, y las llamadas (`process_call`) al final o cerca del final). Actualiza el `processor_map` si es necesario (especialmente si manejas tipos como `Call_FC`, `Call_FB`). + * **Agrupación:** Considera si este nuevo bloque debería ser parte de la lógica de agrupación (¿es un bloque funcional, bobina o temporizador que puede ser habilitado en paralelo?). Si es así, añádelo a la lista `groupable_types_original` en `process_group_ifs`. El código de agrupación existente debería funcionar si el procesador del nuevo bloque genera correctamente la estructura `IF EN THEN ... END_IF;` (o código simple si EN=TRUE). + +4. **Modificar `x3_generate_scl.py`:** + * **Declaraciones STAT:** Si la nueva instrucción introduce la necesidad de un nuevo tipo de variable estática (p.ej., un tipo de datos específico para un contador, o un nuevo tipo de instancia de FB IEC), necesitarás: + * Añadir una nueva expresión regular (`stat_pattern_xxx`) para detectar el nombre de la instancia/variable estática generada por tu nuevo procesador en `x2_process.py`. + * Actualizar el bucle de detección para que use esta nueva regex y almacene el nombre y el tipo SCL correcto (`MyCounterType`, `IEC_Counter`, etc.) en el diccionario `stat_vars`. + * La lógica existente en `generate_scl` que escribe la sección `VAR_STAT` usará esta información para declarar la variable correctamente. + * **Declaraciones TEMP:** Si la nueva instrucción genera variables temporales con un patrón específico o requiere un tipo de dato específico que pueda ser inferido, puedes mejorar la lógica de inferencia de tipo en la sección `VAR_TEMP`. + * **Limpieza de Comentarios:** Si el nuevo procesador genera comentarios internos específicos que no quieres en el SCL final, ajusta la lógica de filtrado en la sección de generación del cuerpo del bloque. + +5. **Probar:** + * Crea un archivo XML de prueba simple que use la nueva instrucción en diferentes contextos (con entradas/salidas conectadas, con EN explícito/implícito, negaciones si aplica). + * Ejecuta el pipeline completo (`x1_to_json.py`, `x2_process.py`, `x3_generate_scl.py`). + * **Verifica `_simplified.json`:** Asegúrate de que `x1` parseó correctamente la instrucción, mapeó su tipo, identificó sus conexiones y realizó la inferencia EN si era necesario. + * **Verifica `_simplified_processed.json`:** Comprueba que `x2` ejecutó tu nuevo procesador, generó el SCL esperado en el campo `scl`, marcó el tipo con `_scl`, y actualizó el `scl_map` correctamente para sus salidas. Verifica si la agrupación `IF` funcionó como se esperaba si la instrucción era parte de lógica paralela. + * **Verifica el archivo `.scl`:** Confirma que `x3` generó el SCL final correctamente, incluyendo las declaraciones necesarias (STAT/TEMP) y el código SCL de la instrucción (indentado y sin comentarios no deseados). Asegúrate de que no haya errores de sintaxis SCL obvios. + * **Importar en TIA Portal (Opcional pero Recomendado):** Intenta importar el archivo SCL generado en un proyecto de TIA Portal para validar la sintaxis y la estructura del bloque. + +## 4. Futuras Mejoras y Consideraciones + +* **Manejo de Tipos de Datos:** Implementar un seguimiento y conversión de tipos más robusto. Inferir tipos para variables temporales de forma más precisa. Usar funciones de conversión SCL explícitas (`INT_TO_DINT`, etc.) donde sea necesario, posiblemente requiriendo información de tipo adicional en el JSON. +* **Lógica de Flancos/Temporizadores:** Asegurar que la traducción de temporizadores S5 y la lógica de flancos generada sea completamente compatible con los bloques IEC estándar (`TON`, `TOF`, `TP`, `TONR`, `R_TRIG`, `F_TRIG`). Considerar la necesidad de declarar instancias de `R_TRIG`/`F_TRIG` en `VAR_STAT` en lugar de generar lógica explícita. +* **Soporte para FBs:** Mejorar el manejo de parámetros InOut y Return para llamadas a FC/FB. Potencialmente, requerir información de la interfaz del bloque llamado (parseando su propio XML o desde una biblioteca) para generar llamadas SCL más precisas. +* **Optimización SCL:** Explorar más optimizaciones SCL más allá de la agrupación de IFs (p.ej., simplificación de expresiones booleanas complejas, propagación de constantes). +* **Estructuras LAD Complejas:** La inferencia de EN actual (búsqueda lineal hacia atrás) es simple. Para manejar bifurcaciones (`Branch`), uniones (`Merge`) y saltos (`JMP`) complejos de forma robusta, `x1_to_json.py` necesitaría realizar un análisis de flujo de datos/control más sofisticado para determinar las dependencias lógicas correctas antes de generar el JSON. +* **Manejo de Errores:** Mejorar el reporte de errores con más contexto (nombre de red, UID, tipo de instrucción). Añadir más validaciones en cada etapa. +* **Interfaz Gráfica/Configuración:** Crear una interfaz más amigable o archivos de configuración para gestionar el proceso, seleccionar archivos y configurar opciones (p.ej., idioma por defecto, nivel de log). +* **Soporte para otros lenguajes (FBD/STL):** Extender el parser `x1_to_json.py` y los procesadores en `x2_process.py` para manejar otros lenguajes de origen, lo cual requeriría entender sus respectivas representaciones XML en Openness. + +## 5. Conclusión + +Este pipeline proporciona una base funcional para la conversión automática de LAD a SCL desde archivos TIA Portal Openness XML. La clave de su funcionamiento es la **separación de responsabilidades**: `x1` enriquece el modelo de datos con información implícita, `x2` realiza la traducción semántica iterativa y la optimización de agrupación, y `x3` ensambla el archivo SCL final. Al añadir procesadores específicos para cada tipo de instrucción LAD/FBD y refinar la lógica de inferencia y generación, la cobertura y calidad de la conversión pueden ser extendidas significativamente. La estructura modular facilita la incorporación de soporte para nuevas instrucciones y futuras mejoras. \ No newline at end of file diff --git a/VersionNoFuncionante/x1_to_json.py b/VersionNoFuncionante/x1_to_json.py new file mode 100644 index 0000000..06c3126 --- /dev/null +++ b/VersionNoFuncionante/x1_to_json.py @@ -0,0 +1,687 @@ +# -*- coding: utf-8 -*- +import json +import os +from lxml import etree +import traceback +from collections import defaultdict + +# --- Namespaces --- +ns = { + "iface": "http://www.siemens.com/automation/Openness/SW/Interface/v5", + "flg": "http://www.siemens.com/automation/Openness/SW/NetworkSource/FlgNet/v4", +} + + +# --- Helper Functions --- +# get_multilingual_text, get_symbol_name, parse_access - No changes needed from previous corrected version +def get_multilingual_text(element, default_lang="en-US", fallback_lang="it-IT"): + if element is None: + return "" + try: + # Try default language first + xpath_expr_default = ( + f".//iface:MultilingualTextItem[iface:Culture='{default_lang}']/iface:Text" + ) + text_items = element.xpath(xpath_expr_default, namespaces=ns) + if text_items and text_items[0].text is not None: + return text_items[0].text.strip() + + # Try fallback language + xpath_expr_fallback = ( + f".//iface:MultilingualTextItem[iface:Culture='{fallback_lang}']/iface:Text" + ) + text_items = element.xpath(xpath_expr_fallback, namespaces=ns) + if text_items and text_items[0].text is not None: + return text_items[0].text.strip() + + # Try any language if specific ones fail + xpath_expr_any = ".//iface:MultilingualTextItem/iface:Text" + text_items = element.xpath(xpath_expr_any, namespaces=ns) + if text_items and text_items[0].text is not None: + return text_items[0].text.strip() + + return "" # No text found + except Exception as e: + # print(f"Advertencia: Error extrayendo MultilingualText: {e}") # Reduced verbosity + return "" + + +def get_symbol_name(symbol_element): + """Extracts the full symbolic name, adding quotes around each component.""" + if symbol_element is None: + return None + try: + # Namespace might be missing on Component, use local-name() + components = symbol_element.xpath("./*[local-name()='Component']/@Name") + # Ensure quotes are added correctly + return ".".join(f'"{c}"' for c in components) if components else None + except Exception as e: + print(f"Advertencia: Excepción en get_symbol_name: {e}") + return None + + +def parse_access(access_element): + """Parses Access elements (variables, constants).""" + if access_element is None: + return None + uid = access_element.get("UId") + scope = access_element.get( + "Scope" + ) # GlobalVariable, LocalVariable, LiteralConstant, TypedConstant etc. + info = {"uid": uid, "scope": scope, "type": "unknown_access"} # Default type + + symbol = access_element.xpath("./*[local-name()='Symbol']") + constant = access_element.xpath("./*[local-name()='Constant']") + # Add check for ConstantValue tag directly under Access (sometimes happens for literals) + const_val_direct = access_element.xpath("./*[local-name()='ConstantValue']/text()") + + if symbol: + info["type"] = "variable" + info["name"] = get_symbol_name(symbol[0]) + if info["name"] is None: + info["type"] = "error_parsing_symbol" + print(f"Error: No se pudo parsear nombre símbolo Access UID={uid}") + elif constant: + info["type"] = "constant" + const_type_elem = constant[0].xpath("./*[local-name()='ConstantType']") + const_val_elem = constant[0].xpath("./*[local-name()='ConstantValue']") + info["datatype"] = ( + const_type_elem[0].text.strip() + if const_type_elem and const_type_elem[0].text + else "Unknown" + ) + info["value"] = ( + const_val_elem[0].text.strip() + if const_val_elem and const_val_elem[0].text + else None + ) + + if info["value"] is None: + info["type"] = "error_parsing_constant" + print(f"Error: Constante sin valor Access UID={uid}") + # Handle S5Time specifically - store its original format + elif info["datatype"] == "Unknown" and scope == "TypedConstant": + if info["value"].upper().startswith("S5T#"): + info["datatype"] = "S5Time" # Mark as S5Time, value remains S5T#... + # Add other typed constant checks if necessary (e.g., C#, P#) + + elif const_val_direct and scope == "LiteralConstant": + info["type"] = "constant" + info["value"] = const_val_direct[0].strip() + # Infer datatype for literals + val_lower = info["value"].lower() + if val_lower in ["true", "false"]: + info["datatype"] = "Bool" + elif info["value"].isdigit() or ( + info["value"].startswith("-") and info["value"][1:].isdigit() + ): + info["datatype"] = "Int" # Could be DInt etc, Int is safe default + elif "." in info["value"] or "e" in val_lower: + try: + float(info["value"]) + info["datatype"] = "Real" # Could be LReal + except ValueError: + info["datatype"] = "String" # If float conversion fails + else: + info["datatype"] = "String" # Default literal type + + # If still unknown, log warning + if info["type"] == "unknown_access": + # Don't warn for Constant scope as it might be handled later + if scope != "Constant": + print( + f"Advertencia: Access UID={uid} scope={scope} no es Symbol ni Constant reconocible." + ) + + # Ensure variable has a name + if info["type"] == "variable" and not info.get("name"): + print(f"Error Interno: parse_access var sin nombre UID {uid}.") + info["type"] = "error_no_name" + + return info + + +def parse_part(part_element): + """Parses Part elements (standard instructions), extracting UID, name, template values, and negated pins.""" + if part_element is None: + return None + uid = part_element.get("UId") + name_orig = part_element.get("Name") # Instruction type (e.g., Contact, Coil, Move) + if not uid or not name_orig: + print( + f"Error: Part sin UID o Name: {etree.tostring(part_element, encoding='unicode')}" + ) + return None + + template_values = {} + try: + for tv in part_element.xpath("./*[local-name()='TemplateValue']"): + tv_name = tv.get("Name") + tv_type = tv.get("Type") + if tv_name and tv_type: + template_values[tv_name] = tv_type + except Exception as e: + print(f"Advertencia: Error extrayendo TemplateValues Part UID={uid}: {e}") + + negated_pins = {} + try: + for negated_elem in part_element.xpath("./*[local-name()='Negated']"): + negated_pin_name = negated_elem.get("Name") + if negated_pin_name: + negated_pins[negated_pin_name] = True + except Exception as e: + print(f"Advertencia: Error extrayendo Negated Pins Part UID={uid}: {e}") + + version = part_element.get("Version") + # Map XML names to internal types used by x2_process + name_mapped = name_orig + if name_orig == "Se": + name_mapped = "TON_S5" + elif name_orig == "Sd": + name_mapped = "TONR_S5" + elif name_orig == "PBox": + name_mapped = "P_TRIG" + elif name_orig == "NBox": + name_mapped = "N_TRIG" + elif name_orig == "RCoil": + name_mapped = "R" + elif name_orig == "SCoil": + name_mapped = "S" + elif name_orig == "SdCoil": + name_mapped = "SR" # Map S5 Set-Dominant to SR internal type + elif name_orig == "BLKMOV": + name_mapped = "BLKMOV" # Keep as is + # Add other mappings if necessary (e.g., RsCoil -> RS) + + part_data = { + "uid": uid, + "type": name_mapped, # Use the mapped type + "original_type": name_orig, # Store original name for reference if needed + "template_values": template_values, + "negated_pins": negated_pins, + } + if version: + part_data["version"] = version + + return part_data + + +# parse_call - No changes needed from previous corrected version +def parse_call(call_element): + """Parses Call elements (FC/FB calls).""" + if call_element is None: + return None + uid = call_element.get("UId") + if not uid: + print( + f"Error: Call encontrado sin UID: {etree.tostring(call_element, encoding='unicode')}" + ) + return None + + # Use local-name() for CallInfo + call_info_elem = call_element.xpath("./*[local-name()='CallInfo']") + if not call_info_elem: + print(f"Error: Call UID {uid} sin elemento CallInfo.") + return None + call_info = call_info_elem[0] + + block_name = call_info.get("Name") + block_type = call_info.get("BlockType") # FC, FB + + if not block_name or not block_type: + print(f"Error: CallInfo para UID {uid} sin Name o BlockType.") + return None + + call_data = { + "uid": uid, + "type": "Call", # Generic type for our JSON + "block_name": block_name, + "block_type": block_type, + "template_values": {}, # Add fields for consistency with parse_part + "negated_pins": {}, + } + + # Instance info for FBs + instance_name = None + if block_type == "FB": + # Use local-name() for Instance and Symbol + instance_elem = call_info.xpath("./*[local-name()='Instance']") + if instance_elem: + symbol_elem = instance_elem[0].xpath("./*[local-name()='Symbol']") + if symbol_elem: + instance_name = get_symbol_name(symbol_elem[0]) + if instance_name: + call_data["instance_db"] = ( + instance_name # Store the formatted name directly + ) + + return call_data + + +# --- Function parse_network (Main logic per network) --- +def parse_network(network_element): + if network_element is None: + return { + "id": "ERROR", + "title": "Invalid Network Element", + "logic": [], + "error": "Input element was None", + } + network_id = network_element.get("ID") + + title_node = network_element.xpath( + ".//*[local-name()='MultilingualText'][@CompositionName='Title']" + ) + network_title = ( + get_multilingual_text(title_node[0]) if title_node else f"Network {network_id}" + ) + + comment_node = network_element.xpath( + ".//*[local-name()='MultilingualText'][@CompositionName='Comment']" + ) + network_comment = get_multilingual_text(comment_node[0]) if comment_node else "" + + flgnet_list = network_element.xpath(".//flg:FlgNet", namespaces=ns) + if not flgnet_list: + return { + "id": network_id, + "title": network_title, + "comment": network_comment, + "logic": [], + "error": "FlgNet not found", + } + flgnet = flgnet_list[0] + + # 1. Parse Access, Parts, and Calls + access_map = {} + for acc in flgnet.xpath(".//flg:Access", namespaces=ns): + if acc_info := parse_access(acc): + access_map[acc_info["uid"]] = acc_info + + parts_and_calls_map = {} + instruction_elements = flgnet.xpath(".//flg:Part | .//flg:Call", namespaces=ns) + for element in instruction_elements: + parsed_info = None + if element.tag == etree.QName(ns["flg"], "Part"): + parsed_info = parse_part(element) + elif element.tag == etree.QName(ns["flg"], "Call"): + parsed_info = parse_call(element) + + if parsed_info and "uid" in parsed_info: + parts_and_calls_map[parsed_info["uid"]] = parsed_info + + # 2. Parse Wires + wire_connections = defaultdict(list) + source_connections = defaultdict(list) + flg_ns_uri = ns["flg"] + for wire in flgnet.xpath(".//flg:Wire", namespaces=ns): + source_uid, source_pin, dest_uid, dest_pin = None, None, None, None + source_elem = wire.xpath("./*[1]")[0] + dest_elem = wire.xpath("./*[2]")[0] + + if source_elem.tag == etree.QName(flg_ns_uri, "Powerrail"): + source_uid, source_pin = "POWERRAIL", "out" + elif source_elem.tag == etree.QName(flg_ns_uri, "IdentCon"): + source_uid, source_pin = source_elem.get("UId"), "value" + elif source_elem.tag == etree.QName(flg_ns_uri, "NameCon"): + source_uid, source_pin = source_elem.get("UId"), source_elem.get("Name") + + if dest_elem.tag == etree.QName(flg_ns_uri, "IdentCon"): + dest_uid, dest_pin = dest_elem.get("UId"), "value" + elif dest_elem.tag == etree.QName(flg_ns_uri, "NameCon"): + dest_uid, dest_pin = dest_elem.get("UId"), dest_elem.get("Name") + elif dest_elem.tag == etree.QName(flg_ns_uri, "OpenCon"): + dest_uid, dest_pin = "OPEN", "in" + + if dest_uid and dest_pin and source_uid is not None and source_pin is not None: + if dest_uid != "OPEN": + dest_key = (dest_uid, dest_pin) + source_info = (source_uid, source_pin) + if source_info not in wire_connections[dest_key]: + wire_connections[dest_key].append(source_info) + source_key = (source_uid, source_pin) + dest_info = (dest_uid, dest_pin) + if dest_info not in source_connections[source_key]: + source_connections[source_key].append(dest_info) + + # 3. Build Initial Logic Representation + all_logic_steps = {} + for instr_uid, instr_info in parts_and_calls_map.items(): + instruction_repr = { + "instruction_uid": instr_uid, + **instr_info, + "inputs": {}, + "outputs": {}, + } + + # *** ADD DSTBLK to possible inputs *** + possible_input_pins = { + "en", + "in", + "in1", + "in2", + "in3", + "in4", + "operand", + "bit", + "pre", + "clk", + "s", + "tv", + "r", + "S", + "R1", + "SRCBLK", + "DSTBLK", + } + + for dest_pin_name in possible_input_pins: + dest_key = (instr_uid, dest_pin_name) + if dest_key in wire_connections: + sources_list = wire_connections[dest_key] + input_sources_repr = [] + for source_uid, source_pin in sources_list: + if source_uid == "POWERRAIL": + input_sources_repr.append({"type": "powerrail"}) + elif source_uid in access_map: + input_sources_repr.append(access_map[source_uid]) + elif source_uid in parts_and_calls_map: + input_sources_repr.append( + { + "type": "connection", + "source_instruction_type": parts_and_calls_map[ + source_uid + ]["type"], + "source_instruction_uid": source_uid, + "source_pin": source_pin, + } + ) + else: + input_sources_repr.append( + {"type": "unknown_source", "uid": source_uid} + ) + if len(input_sources_repr) == 1: + instruction_repr["inputs"][dest_pin_name] = input_sources_repr[0] + elif len(input_sources_repr) > 1: + instruction_repr["inputs"][dest_pin_name] = input_sources_repr + + possible_output_pins = {"out", "out1", "Q", "eno", "RET_VAL", "q", "et"} + for src_pin_name in possible_output_pins: + source_key = (instr_uid, src_pin_name) + if source_key in source_connections: + dest_access_list = [] + for dest_uid, dest_pin in source_connections[source_key]: + if dest_uid in access_map: + if access_map[dest_uid] not in dest_access_list: + dest_access_list.append(access_map[dest_uid]) + if dest_access_list: + instruction_repr["outputs"][src_pin_name] = dest_access_list + + all_logic_steps[instr_uid] = instruction_repr + + # 4. EN Connection Inference + functional_block_types = { + "Move", + "Add", + "Sub", + "Mul", + "Div", + "Mod", + "Convert", + "Call", + "BLKMOV", + } + # Use MAPPED types for RLO generators + rlo_generators = { + "Contact", + "O", + "Eq", + "Ne", + "Gt", + "Lt", + "Ge", + "Le", + "And", + "Xor", + "P_TRIG", + "N_TRIG", + } + + try: + sorted_uids = sorted(all_logic_steps.keys(), key=lambda x: int(x)) + except ValueError: + sorted_uids = sorted(all_logic_steps.keys()) + + processed_for_en_inference = set() + current_logic_list_for_en = [all_logic_steps[uid] for uid in sorted_uids] + + for i, instruction in enumerate(current_logic_list_for_en): + instr_uid = instruction["instruction_uid"] + instr_type = instruction["type"] # Use the mapped type + + if ( + instr_type in functional_block_types + and "en" not in instruction["inputs"] + and instr_uid not in processed_for_en_inference + ): + inferred_en_source = None + if i > 0: + # Simple lookback to previous instruction + prev_instr = current_logic_list_for_en[i - 1] + prev_uid = prev_instr["instruction_uid"] + prev_type = prev_instr["type"] + # Check if previous instruction has a mappable 'out' or 'eno' + # We check source_connections map for actual wire existence + prev_has_out_wire = any( + dest[0] != "OPEN" + for dest in source_connections.get((prev_uid, "out"), []) + ) + prev_has_eno_wire = any( + dest[0] != "OPEN" + for dest in source_connections.get((prev_uid, "eno"), []) + ) + + if prev_type in rlo_generators and prev_has_out_wire: + inferred_en_source = { + "type": "connection", + "source_instruction_uid": prev_uid, + "source_instruction_type": prev_type, + "source_pin": "out", + } + elif prev_type in functional_block_types and prev_has_eno_wire: + inferred_en_source = { + "type": "connection", + "source_instruction_uid": prev_uid, + "source_instruction_type": prev_type, + "source_pin": "eno", + } + + if inferred_en_source: + all_logic_steps[instr_uid]["inputs"]["en"] = inferred_en_source + processed_for_en_inference.add(instr_uid) + + # 5. Final Logic Ordering + network_logic = [all_logic_steps[uid] for uid in sorted_uids] + + return { + "id": network_id, + "title": network_title, + "comment": network_comment, + "logic": network_logic, + } + + +# --- Main XML to JSON Conversion Function --- +# convert_xml_to_json - No significant changes needed from previous version +def convert_xml_to_json(xml_filepath, json_filepath): + print(f"Iniciando conversión de '{xml_filepath}' a '{json_filepath}'...") + if not os.path.exists(xml_filepath): + print(f"Error Crítico: Archivo XML no encontrado: '{xml_filepath}'") + return + try: + print("Paso 1: Parseando archivo XML...") + # Disable DTD loading for security and compatibility + parser = etree.XMLParser( + remove_blank_text=True, load_dtd=False, resolve_entities=False + ) + tree = etree.parse(xml_filepath, parser) + root = tree.getroot() + print("Paso 1: Parseo XML completado.") + + # Detect block type (FC or FB) - Look for SW.Blocks.FC or SW.Blocks.FB + block_node = None + block_xpath = ".//*[local-name()='SW.Blocks.FC' or local-name()='SW.Blocks.FB']" + block_list = root.xpath(block_xpath) + + if not block_list: + print("Error Crítico: No se encontró o .") + return + block_node = block_list[0] + block_tag_name = etree.QName( + block_node.tag + ).localname # SW.Blocks.FC or SW.Blocks.FB + print( + f"Paso 2: Bloque {block_tag_name} encontrado (ID={block_node.get('ID')})." + ) + + print("Paso 3: Extrayendo atributos del bloque...") + attribute_list_node = block_node.xpath("./*[local-name()='AttributeList']") + block_name_val, block_number_val, block_lang_val = "Unknown", None, "Unknown" + if attribute_list_node: + attr_list = attribute_list_node[0] + name_node = attr_list.xpath("./*[local-name()='Name']/text()") + block_name_val = name_node[0].strip() if name_node else block_name_val + num_node = attr_list.xpath("./*[local-name()='Number']/text()") + try: + block_number_val = int(num_node[0]) if num_node else None + except ValueError: + block_number_val = None # Handle non-integer Number + lang_node = attr_list.xpath( + "./*[local-name()='ProgrammingLanguage']/text()" + ) + block_lang_val = lang_node[0].strip() if lang_node else block_lang_val + print( + f"Paso 3: Atributos: Nombre='{block_name_val}', Número={block_number_val}, Lenguaje='{block_lang_val}'" + ) + else: + print("Advertencia: No se encontró AttributeList para el bloque.") + + # Get block comment + block_comment_val = "" + comment_node_list = block_node.xpath( + "./*[local-name()='ObjectList']/*[local-name()='MultilingualText'][@CompositionName='Comment']" + ) + if comment_node_list: + block_comment_val = get_multilingual_text(comment_node_list[0]) + + # Initialize result dictionary + result = { + "block_name": block_name_val, + "block_number": block_number_val, + "language": block_lang_val, + "block_comment": block_comment_val, + "interface": {}, + "networks": [], + } + + print("Paso 4: Extrayendo la interfaz del bloque...") + if attribute_list_node: + interface_node = attribute_list_node[0].xpath( + "./*[local-name()='Interface']" + ) + if interface_node: + print("Paso 4: Nodo Interface encontrado.") + # Iterate through sections using the correct namespace prefix 'iface' + for section in interface_node[0].xpath( + ".//iface:Section", namespaces=ns + ): + section_name = section.get( + "Name" + ) # Input, Output, InOut, Temp, Constant, Return + members = [] + for member in section.xpath("./iface:Member", namespaces=ns): + member_name = member.get("Name") + member_dtype = member.get("Datatype") + if member_name and member_dtype: + member_info = { + "name": member_name, + "datatype": member_dtype, + } + members.append(member_info) + if members: + result["interface"][section_name] = members + if not result["interface"]: + print("Advertencia: Interface sin secciones iface:Section válidas.") + else: + print( + "Advertencia: No se encontró DENTRO de ." + ) + if not result["interface"]: + print("Advertencia: No se pudo extraer información de la interfaz.") + + print("Paso 5: Extrayendo y PROCESANDO lógica de redes (CompileUnits)...") + networks_processed_count = 0 + object_list_node = block_node.xpath("./*[local-name()='ObjectList']") + if object_list_node: + compile_units = object_list_node[0].xpath( + "./*[local-name()='SW.Blocks.CompileUnit']" + ) + print( + f"Paso 5: Se encontraron {len(compile_units)} elementos SW.Blocks.CompileUnit." + ) + for network_elem in compile_units: + networks_processed_count += 1 + parsed_network = parse_network(network_elem) + if parsed_network and parsed_network.get("error") is None: + result["networks"].append(parsed_network) + elif parsed_network: + print( + f"Error: Falló parseo red ID={parsed_network.get('id')}: {parsed_network.get('error')}" + ) + result["networks"].append( + parsed_network + ) # Include network with error marker + else: + print( + f"Error Crítico: parse_network devolvió None para CompileUnit (ID={network_elem.get('ID')})." + ) + + if networks_processed_count == 0: + print("Advertencia: ObjectList sin SW.Blocks.CompileUnit.") + else: + print("Advertencia: No se encontró ObjectList.") + + print("Paso 6: Escribiendo el resultado en el archivo JSON...") + if not result["interface"]: + print("ADVERTENCIA FINAL: 'interface' está vacía.") + if not result["networks"]: + print("ADVERTENCIA FINAL: 'networks' está vacía.") + + try: + with open(json_filepath, "w", encoding="utf-8") as f: + json.dump( + result, f, indent=4, ensure_ascii=False + ) # ensure_ascii=False is important + print(f"Paso 6: Escritura completada.") + print(f"Conversión finalizada. JSON guardado en: '{json_filepath}'") + except IOError as e: + print( + f"Error Crítico: No se pudo escribir JSON en '{json_filepath}'. Error: {e}" + ) + except TypeError as e: + print(f"Error Crítico: Problema al serializar a JSON. Error: {e}") + + except etree.XMLSyntaxError as e: + print(f"Error Crítico: Sintaxis XML en '{xml_filepath}'. Detalles: {e}") + except Exception as e: + print(f"Error Crítico: Error inesperado durante la conversión: {e}") + print("--- Traceback ---") + traceback.print_exc() + print("--- Fin Traceback ---") + + +# --- Punto de Entrada Principal --- +if __name__ == "__main__": + xml_file = "BlenderCtrl__Main.xml" + json_file = xml_file.replace(".xml", "_simplified.json") + convert_xml_to_json(xml_file, json_file) diff --git a/VersionNoFuncionante/x2_process.py b/VersionNoFuncionante/x2_process.py new file mode 100644 index 0000000..e892024 --- /dev/null +++ b/VersionNoFuncionante/x2_process.py @@ -0,0 +1,1309 @@ +# -*- coding: utf-8 -*- +import json +import os +import copy +import traceback +import re +from collections import defaultdict + +# --- Constantes y Configuración --- +SCL_SUFFIX = "_scl" +GROUPED_COMMENT = "// Logic included in grouped IF" + +# Global data variable +data = {} + + +# --- Helper Functions --- +# Updated get_scl_representation +def get_scl_representation(source_info, network_id, scl_map, access_map): + """ + Obtiene la representación SCL para una fuente de datos (variable, constante, conexión). + Handles S5Time constants by converting them to TIME literals. + """ + if not source_info: + return None + if isinstance(source_info, list): # Handle OR merges + scl_parts = [] + all_resolved = True + for sub_source in source_info: + sub_scl = get_scl_representation( + sub_source, network_id, scl_map, access_map + ) + if sub_scl is None: + all_resolved = False + break + if ( + sub_scl in ["TRUE", "FALSE"] + or (sub_scl.startswith('"') and sub_scl.endswith('"')) + or (sub_scl.startswith("'") and sub_scl.endswith("'")) + or ( + sub_scl.upper().startswith("T#") + ) # Check T# prefix case-insensitive + or (sub_scl.upper().startswith("W#")) + or (sub_scl.upper().startswith("B#")) + or sub_scl.isdigit() + or (sub_scl.startswith("-") and sub_scl[1:].isdigit()) + or (sub_scl.startswith("(") and sub_scl.endswith(")")) + ): + scl_parts.append(sub_scl) + else: + scl_parts.append(f"({sub_scl})") # Parenthesize complex terms in OR + return ( + ( + " OR ".join(scl_parts) + if len(scl_parts) > 1 + else (scl_parts[0] if scl_parts else "FALSE") + ) + if all_resolved + else None + ) + + source_type = source_info.get("type") + if source_type == "powerrail": + return "TRUE" + elif source_type == "variable": + name = source_info.get("name") + return ( + format_variable_name(name) + if name + else f"#_ERR_VAR_NO_NAME_{source_info.get('uid')}_" + ) + elif source_type == "constant": + dtype = str(source_info.get("datatype", "")).upper() + value = source_info.get("value") + uid = source_info.get("uid", "UnknownUID") + try: + # S5Time conversion (Example: S5T#2S -> T#2s) + if ( + dtype == "S5TIME" + and value + and isinstance(value, str) + and value.upper().startswith("S5T#") + ): + time_str = value.upper().split("#")[-1] + time_str = time_str.replace("_", "") + match = re.match(r"(\d+)(MS|S|M|H)?", time_str, re.IGNORECASE) + if match: + num_val = match.group(1) + unit = (match.group(2) or "S").lower() # Default to seconds + return f"T#{num_val}{unit}" + else: + print( + f"Advertencia: Formato S5Time no reconocido '{value}' UID={uid}. Usando T#0s." + ) + return "T#0s" + # Standard constants + elif dtype == "BOOL": + return str(value).upper() + elif dtype in [ + "INT", + "DINT", + "SINT", + "USINT", + "UINT", + "UDINT", + "LINT", + "ULINT", + "WORD", + "DWORD", + "LWORD", + "BYTE", + ]: + return str(int(value)) + elif dtype in ["REAL", "LREAL"]: + s_val = str(float(value)) + return s_val if "." in s_val or "e" in s_val.lower() else s_val + ".0" + elif dtype == "STRING": + # Escapar comillas simples dentro del string si es necesario + str_val = str(value).replace("'", "''") + return f"'{str_val}'" + elif dtype == "TIME": + return f"T#{str(value)}" + elif dtype == "DATE": + return f"D#{str(value)}" + # Add other types like TOD, DT, DTL if needed + else: + # Fallback: treat as potentially numeric or string + try: + return str(int(value)) + except ValueError: + try: + return str(float(value)) + except ValueError: + escaped_value = str(value).replace("'", "''") + return f"'{escaped_value}'" # Treat as string if not numeric + except Exception as e: + print(f"Advertencia: Error formateando constante {source_info}: {e}") + return f"#_ERR_CONST_FORMAT_{uid}_" + elif source_type == "connection": + map_key = ( + network_id, + source_info.get("source_instruction_uid"), + source_info.get("source_pin"), + ) + return scl_map.get(map_key) + elif source_type == "unknown_source": + return f"#_ERR_UNKNOWN_SRC_{source_info.get('uid')}_" + else: + return f"#_ERR_INVALID_SRC_TYPE_" + + +# format_variable_name - no change needed +def format_variable_name(name): + """Formats variable names for SCL, preserving quotes for structured names.""" + if not name: + return "_INVALID_NAME_" + if name.startswith('"') and name.endswith('"'): + return name + prefix = "" + if name.startswith("#"): + prefix = "#" + name = name[1:] + if not name: + return "_INVALID_NAME_" # Handle case "#" + if not re.match(r"^[a-zA-Z_]", name[0]): + name = "_" + name + name = re.sub(r"[^a-zA-Z0-9_]", "_", name) + return prefix + name + + +# generate_temp_var_name - returns base name WITHOUT # +def generate_temp_var_name(network_id, instr_uid, pin_name): + """Generates a base name for temporary variables (without the leading #).""" + net_id_clean = str(network_id).replace("-", "_") + instr_uid_clean = str(instr_uid).replace("-", "_") + pin_name_clean = str(pin_name).replace("-", "_").lower() + return f"_temp_{net_id_clean}_{instr_uid_clean}_{pin_name_clean}" + + +# get_target_scl_name - adds # for temps when needed for SCL usage +def get_target_scl_name(instruction, output_pin_name, network_id, default_to_temp=True): + """Gets the SCL name for an output target, using temps if necessary. Adds # prefix for temp usage.""" + instr_uid = instruction["instruction_uid"] + output_pin_data = instruction["outputs"].get(output_pin_name) + target_scl_base = 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_name = dest_access.get("name") + if target_name: + target_scl_base = format_variable_name(target_name) + elif default_to_temp: + target_scl_base = generate_temp_var_name( + network_id, instr_uid, output_pin_name + ) + 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: + target_scl_base = generate_temp_var_name( + network_id, instr_uid, output_pin_name + ) + elif default_to_temp: # Connection or other types + target_scl_base = generate_temp_var_name( + network_id, instr_uid, output_pin_name + ) + elif default_to_temp: # No explicit target, use temp if allowed + target_scl_base = generate_temp_var_name(network_id, instr_uid, output_pin_name) + + if target_scl_base is None: + return None + + # Add # prefix for temps + if target_scl_base.startswith("_temp_"): + return f"#{target_scl_base}" + else: + return target_scl_base # Standard variable + + + +# Timer/Edge name helpers +def get_s5_timer_instance_name(network_id, instr_uid, timer_type="Se"): + type_prefix = ( + "TON" + if timer_type.upper() == "TON_S5" + else "TONR" if timer_type.upper() == "TONR_S5" else "IEC_TIMER" + ) + base_name = f"stat_{type_prefix}_{network_id}_{instr_uid}" + return format_variable_name(f'"{base_name}"') + + +def get_edge_mem_bit_name(network_id, instr_uid, edge_type="P_TRIG"): + type_prefix = ( + "ptrig" + if edge_type.upper() == "P_TRIG" + else "ntrig" if edge_type.upper() == "N_TRIG" else "edge" + ) + base_name = f"stat_{type_prefix}_mem_{network_id}_{instr_uid}" + return format_variable_name(f'"{base_name}"') + + +# --- Procesadores de Instrucciones --- +# process_contact, process_eq, process_o, process_convert, process_mod, process_add, process_move - Minor refinements if needed, but largely okay + + +def process_contact(instruction, network_id, scl_map, access_map): + instr_uid = instruction["instruction_uid"] + instr_type = instruction["type"] + if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + return False + is_negated = instruction.get("negated_pins", {}).get("operand", False) + in_rlo_scl = ( + get_scl_representation( + instruction["inputs"].get("in"), network_id, scl_map, access_map + ) + or "TRUE" + ) + operand_scl = get_scl_representation( + instruction["inputs"].get("operand"), network_id, scl_map, access_map + ) + if operand_scl is None: + return False + term = f"(NOT {operand_scl})" if is_negated else operand_scl + if ( + " " in operand_scl or "AND" in operand_scl or "OR" in operand_scl + ) and not is_negated: + term = f"({operand_scl})" # Parenthesize operand if complex + if is_negated and not operand_scl.startswith("("): + term = f"NOT ({operand_scl})" # Ensure NOT applies correctly + if in_rlo_scl == "TRUE": + new_rlo_scl = term + else: + in_rlo_formatted = ( + f"({in_rlo_scl})" + if (" " in in_rlo_scl or "AND" in in_rlo_scl or "OR" in in_rlo_scl) + and not (in_rlo_scl.startswith("(") and in_rlo_scl.endswith(")")) + else in_rlo_scl + ) + new_rlo_scl = f"{in_rlo_formatted} AND {term}" + scl_map[(network_id, instr_uid, "out")] = new_rlo_scl + instruction["scl"] = f"// RLO: {new_rlo_scl}" + instruction["type"] = instr_type + SCL_SUFFIX + return True + +# --- Add this function definition back into x2_process.py --- +def process_add(instruction, network_id, scl_map, access_map): + instr_uid = instruction["instruction_uid"]; instr_type = instruction["type"] + if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: return False + + en_scl = get_scl_representation(instruction["inputs"].get("en"), network_id, scl_map, access_map) or "TRUE" + in1_scl = get_scl_representation(instruction["inputs"].get("in1"), network_id, scl_map, access_map) + in2_scl = get_scl_representation(instruction["inputs"].get("in2"), network_id, scl_map, access_map) + + if in1_scl is None or in2_scl is None: return False # Wait for operands + + target_scl = get_target_scl_name(instruction, "out", network_id, default_to_temp=True) # Add usually outputs to 'out' + if target_scl is None: + instruction["scl"] = f"// ERROR: ADD {instr_uid} sin destino" + instruction["type"] += "_error" + return True + + # Parenthesize inputs if they are complex + op1 = f"({in1_scl})" if ' ' in in1_scl else in1_scl + op2 = f"({in2_scl})" if ' ' in in2_scl else in2_scl + + scl_core = f"{target_scl} := {op1} + {op2};" + instruction["scl"] = f"IF {en_scl} THEN\n {scl_core}\nEND_IF;" if en_scl != "TRUE" else scl_core + instruction["type"] = instr_type + SCL_SUFFIX + + scl_map[(network_id, instr_uid, "out")] = target_scl # The result is the value in the target + scl_map[(network_id, instr_uid, "eno")] = en_scl + return True +# --- End of function to add --- + +def process_mod(instruction, network_id, scl_map, access_map): + instr_uid = instruction["instruction_uid"] + instr_type = instruction["type"] + if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + return False + + 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) + + if en_scl is None or in1_scl is None or in2_scl 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 + + # 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 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 + + 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 + ) + + instruction["scl"] = scl_final + instruction["type"] = instr_type + SCL_SUFFIX + map_key_out = (network_id, instr_uid, "out") + scl_map[map_key_out] = target_scl + map_key_eno = (network_id, instr_uid, "eno") + scl_map[map_key_eno] = en_scl + return True + +def process_convert(instruction, network_id, scl_map, access_map): + instr_uid = instruction["instruction_uid"] + instr_type = instruction["type"] + if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + return False + + 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) + + if en_scl is None or in_scl is None: + return False # Esperar si dependencias no listas + + 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 + + # 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 + ) + + # 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. + + # 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};" + + # 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 + ) + + instruction["scl"] = scl_final + instruction["type"] = instr_type + SCL_SUFFIX + map_key_out = (network_id, instr_uid, "out") + scl_map[map_key_out] = target_scl # El valor de salida es el contenido del destino + map_key_eno = (network_id, instr_uid, "eno") + scl_map[map_key_eno] = en_scl # ENO sigue a EN + return True + + +def process_eq(instruction, network_id, scl_map, access_map): + instr_uid = instruction["instruction_uid"] + instr_type = instruction["type"] + if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + return False + in1_scl = get_scl_representation( + instruction["inputs"].get("in1"), network_id, scl_map, access_map + ) + in2_scl = get_scl_representation( + instruction["inputs"].get("in2"), network_id, scl_map, access_map + ) + pre_scl = ( + get_scl_representation( + instruction["inputs"].get("pre"), network_id, scl_map, access_map + ) + or "TRUE" + ) + if in1_scl is None or in2_scl is None: + return False + op1 = f"({in1_scl})" if " " in in1_scl else in1_scl + op2 = f"({in2_scl})" if " " in in2_scl else in2_scl + comparison_scl = f"{op1} = {op2}" + if pre_scl == "TRUE": + result_rlo = f"({comparison_scl})" + else: + pre_formatted = ( + f"({pre_scl})" + if (" " in pre_scl or "AND" in pre_scl or "OR" in pre_scl) + and not (pre_scl.startswith("(") and pre_scl.endswith(")")) + else pre_scl + ) + result_rlo = f"{pre_formatted} AND ({comparison_scl})" + scl_map[(network_id, instr_uid, "out")] = result_rlo + scl_map[(network_id, instr_uid, "eno")] = pre_scl + instruction["scl"] = f"// Comparison Eq {instr_uid}: {comparison_scl}" + instruction["type"] = instr_type + SCL_SUFFIX + return True + + +def process_o(instruction, network_id, scl_map, access_map): + instr_uid = instruction["instruction_uid"] + instr_type = instruction["type"] + if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + return False + input_pins = sorted([pin for pin in instruction["inputs"] if pin.startswith("in")]) + if not input_pins: + instruction["scl"] = f"// ERROR: O {instr_uid} sin pines inX" + instruction["type"] += "_error" + return True + scl_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: + all_resolved = False + break + term = ( + f"({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(")")) + else in_scl + ) + scl_parts.append(term) + if not all_resolved: + return False + result_scl = ( + " OR ".join(scl_parts) + if len(scl_parts) > 1 + else (scl_parts[0] if scl_parts else "FALSE") + ) + scl_map[(network_id, instr_uid, "out")] = result_scl + instruction["scl"] = f"// Logic O {instr_uid}: {result_scl}" + instruction["type"] = instr_type + SCL_SUFFIX + return True + + +def process_move(instruction, network_id, scl_map, access_map): + instr_uid = instruction["instruction_uid"] + instr_type = instruction["type"] + if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + return False + en_scl = ( + get_scl_representation( + instruction["inputs"].get("en"), network_id, scl_map, access_map + ) + or "TRUE" + ) + in_scl = get_scl_representation( + instruction["inputs"].get("in"), network_id, scl_map, access_map + ) + if in_scl is None: + return False + 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=True + ) + if target_scl is None: + instruction["scl"] = f"// ERROR: MOVE {instr_uid} sin destino" + instruction["type"] += "_error" + return True + scl_core = f"{target_scl} := {in_scl};" + instruction["scl"] = ( + f"IF {en_scl} THEN\n {scl_core}\nEND_IF;" if en_scl != "TRUE" else scl_core + ) + instruction["type"] = instr_type + SCL_SUFFIX + scl_map[(network_id, instr_uid, "out")] = target_scl + scl_map[(network_id, instr_uid, "out1")] = target_scl + scl_map[(network_id, instr_uid, "eno")] = en_scl + return True + + +# --- Processors for Coils (Coil, R, S, SR) --- +def process_coil(instruction, network_id, scl_map, access_map): # Standard Coil (=) + instr_uid = instruction["instruction_uid"] + instr_type = instruction["type"] + if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + return False + in_rlo_scl = get_scl_representation( + instruction["inputs"].get("in"), network_id, scl_map, access_map + ) + operand_info = instruction["inputs"].get("operand") + operand_scl = get_scl_representation(operand_info, network_id, scl_map, access_map) + if in_rlo_scl is None or operand_scl is None: + return False + if not (operand_info and operand_info.get("type") == "variable"): + instruction["scl"] = f"// ERROR: Coil {instr_uid} operando no valido" + instruction["type"] += "_error" + return True + instruction["scl"] = ( + f"{operand_scl} := {in_rlo_scl};" # Direct assignment based on RLO + ) + instruction["type"] = instr_type + SCL_SUFFIX + return True + + +def process_r(instruction, network_id, scl_map, access_map): # Reset Coil (R) + instr_uid = instruction["instruction_uid"] + instr_type = instruction["type"] + if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + return False + in_rlo_scl = get_scl_representation( + instruction["inputs"].get("in"), network_id, scl_map, access_map + ) + operand_info = instruction["inputs"].get("operand") + operand_scl = get_scl_representation(operand_info, network_id, scl_map, access_map) + if in_rlo_scl is None or operand_scl is None: + return False + if not (operand_info and operand_info.get("type") == "variable"): + instruction["scl"] = f"// ERROR: R Coil {instr_uid} operando no valido" + instruction["type"] += "_error" + return True + scl_core = f"{operand_scl} := FALSE;" + instruction["scl"] = ( + f"IF {in_rlo_scl} THEN\n {scl_core}\nEND_IF;" + if in_rlo_scl != "FALSE" + else f"// R Coil {instr_uid} disabled" + ) + instruction["type"] = instr_type + SCL_SUFFIX + return True + + +def process_s(instruction, network_id, scl_map, access_map): # Set Coil (S) + instr_uid = instruction["instruction_uid"] + instr_type = instruction["type"] + if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + return False + in_rlo_scl = get_scl_representation( + instruction["inputs"].get("in"), network_id, scl_map, access_map + ) + operand_info = instruction["inputs"].get("operand") + operand_scl = get_scl_representation(operand_info, network_id, scl_map, access_map) + if in_rlo_scl is None or operand_scl is None: + return False + if not (operand_info and operand_info.get("type") == "variable"): + instruction["scl"] = f"// ERROR: S Coil {instr_uid} operando no valido" + instruction["type"] += "_error" + return True + scl_core = f"{operand_scl} := TRUE;" + instruction["scl"] = ( + f"IF {in_rlo_scl} THEN\n {scl_core}\nEND_IF;" + if in_rlo_scl != "FALSE" + else f"// S Coil {instr_uid} disabled" + ) + instruction["type"] = instr_type + SCL_SUFFIX + return True + + +def process_sr( + instruction, network_id, scl_map, access_map +): # Set-Dominant SR FlipFlop (mapped from SdCoil) + # Assumes separate S and R coils target the same operand in the original LAD. + # This processor handles the SET part. process_r handles the RESET part. + return process_s( + instruction, network_id, scl_map, access_map + ) # Treat SR essentially as S coil + + +# --- Processors for Edges (P_TRIG, N_TRIG) --- +def process_p_trig( + instruction, network_id, scl_map, access_map, network_logic_list=None +): + instr_uid = instruction["instruction_uid"] + instr_type = instruction["type"] + if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + return False + clk_scl = ( + get_scl_representation( + instruction["inputs"].get("in"), network_id, scl_map, access_map + ) + or "FALSE" + ) # Default clk to FALSE if not connected + mem_bit_info = instruction["inputs"].get("bit") + if clk_scl is None: + return False + if not (mem_bit_info and mem_bit_info.get("type") == "variable"): + stat_mem_bit_scl = get_edge_mem_bit_name(network_id, instr_uid, "P_TRIG") + print( + f"Advertencia: P_TRIG {instr_uid} sin 'bit' variable conectado. Usando STAT {stat_mem_bit_scl}." + ) + else: + stat_mem_bit_scl_raw = get_scl_representation( + mem_bit_info, network_id, scl_map, access_map + ) + if stat_mem_bit_scl_raw is None: + return False + stat_mem_bit_scl = format_variable_name(stat_mem_bit_scl_raw) + + result_scl = f"({clk_scl}) AND (NOT {stat_mem_bit_scl})" + scl_update_mem = f"{stat_mem_bit_scl} := {clk_scl};" + scl_map[(network_id, instr_uid, "out")] = result_scl + instruction["scl"] = ( + f"{scl_update_mem} // P_TRIG Edge Memory Update for UID {instr_uid}" + ) + # Output logic isn't placed here, it's propagated via scl_map + instruction["type"] = instr_type + SCL_SUFFIX + return True + + +def process_n_trig( + instruction, network_id, scl_map, access_map, network_logic_list=None +): + instr_uid = instruction["instruction_uid"] + instr_type = instruction["type"] + if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + return False + clk_scl = ( + get_scl_representation( + instruction["inputs"].get("in"), network_id, scl_map, access_map + ) + or "FALSE" + ) + mem_bit_info = instruction["inputs"].get("bit") + if clk_scl is None: + return False + if not (mem_bit_info and mem_bit_info.get("type") == "variable"): + stat_mem_bit_scl = get_edge_mem_bit_name(network_id, instr_uid, "N_TRIG") + print( + f"Advertencia: N_TRIG {instr_uid} sin 'bit' variable conectado. Usando STAT {stat_mem_bit_scl}." + ) + else: + stat_mem_bit_scl_raw = get_scl_representation( + mem_bit_info, network_id, scl_map, access_map + ) + if stat_mem_bit_scl_raw is None: + return False + stat_mem_bit_scl = format_variable_name(stat_mem_bit_scl_raw) + + result_scl = f"(NOT ({clk_scl})) AND {stat_mem_bit_scl}" + scl_update_mem = f"{stat_mem_bit_scl} := {clk_scl};" + scl_map[(network_id, instr_uid, "out")] = result_scl + instruction["scl"] = ( + f"{scl_update_mem} // N_TRIG Edge Memory Update for UID {instr_uid}" + ) + instruction["type"] = instr_type + SCL_SUFFIX + return True + + +# --- Processors for Timers (TON_S5 -> TON, TONR_S5 -> TONR) --- +def process_ton_s5(instruction, network_id, scl_map, access_map): # Mapped from Se + instr_uid = instruction["instruction_uid"] + instr_type = instruction["type"] # Type is TON_S5 + if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + return False + start_scl = get_scl_representation( + instruction["inputs"].get("s"), network_id, scl_map, access_map + ) + pt_scl = get_scl_representation( + instruction["inputs"].get("tv"), network_id, scl_map, access_map + ) + reset_scl = ( + get_scl_representation( + instruction["inputs"].get("r"), network_id, scl_map, access_map + ) + or "FALSE" + ) # Assume FALSE if R not connected + if start_scl is None or pt_scl is None: + return False + timer_instance_scl = get_s5_timer_instance_name(network_id, instr_uid, "TON_S5") + scl_call = f"{timer_instance_scl}(IN := {start_scl}, PT := {pt_scl}, RESET := {reset_scl}); // TON from S5 Se" + scl_map[(network_id, instr_uid, "q")] = ( + f"{timer_instance_scl}.Q" # Map S5 'q' to TON 'Q' + ) + scl_map[(network_id, instr_uid, "et")] = ( + f"{timer_instance_scl}.ET" # Map ET if needed + ) + instruction["scl"] = scl_call + instruction["type"] = instr_type + SCL_SUFFIX + return True + + +def process_tonr_s5(instruction, network_id, scl_map, access_map): # Mapped from Sd + instr_uid = instruction["instruction_uid"] + instr_type = instruction["type"] # Type is TONR_S5 + if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + return False + start_scl = get_scl_representation( + instruction["inputs"].get("s"), network_id, scl_map, access_map + ) + pt_scl = get_scl_representation( + instruction["inputs"].get("tv"), network_id, scl_map, access_map + ) + reset_scl = ( + get_scl_representation( + instruction["inputs"].get("r"), network_id, scl_map, access_map + ) + or "FALSE" + ) # Reset essential for TONR + if start_scl is None or pt_scl is None: + return False + timer_instance_scl = get_s5_timer_instance_name(network_id, instr_uid, "TONR_S5") + scl_call = f"{timer_instance_scl}(IN := {start_scl}, PT := {pt_scl}, RESET := {reset_scl}); // TONR from S5 Sd" + scl_map[(network_id, instr_uid, "q")] = f"{timer_instance_scl}.Q" + scl_map[(network_id, instr_uid, "et")] = f"{timer_instance_scl}.ET" + instruction["scl"] = scl_call + instruction["type"] = instr_type + SCL_SUFFIX + return True + + +# --- Processor for BLKMOV --- +def process_blkmov(instruction, network_id, scl_map, access_map): + instr_uid = instruction["instruction_uid"] + instr_type = instruction["type"] + if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + return False + en_scl = ( + get_scl_representation( + instruction["inputs"].get("en"), network_id, scl_map, access_map + ) + or "TRUE" + ) + src_scl = get_scl_representation( + instruction["inputs"].get("SRCBLK"), network_id, scl_map, access_map + ) + # DSTBLK is parsed as input by corrected x1 + dst_scl = get_scl_representation( + instruction["inputs"].get("DSTBLK"), network_id, scl_map, access_map + ) + ret_val_target = get_target_scl_name( + instruction, "RET_VAL", network_id, default_to_temp=True + ) # Name includes # if temp + + if src_scl is None or dst_scl is None: + return False + print( + f"Advertencia: BLKMOV {instr_uid} traducido como asignación simple (:=). Verificar compatibilidad de tipos/tamaños entre {src_scl} y {dst_scl}." + ) + scl_core = f"{dst_scl} := {src_scl};" + if ret_val_target: + scl_core += ( + f"\n {ret_val_target} := 0; // Assuming success" # Assign 0=OK to RET_VAL + ) + instruction["scl"] = ( + f"IF {en_scl} THEN\n {scl_core}\nEND_IF;" if en_scl != "TRUE" else scl_core + ) + instruction["type"] = instr_type + SCL_SUFFIX + scl_map[(network_id, instr_uid, "eno")] = en_scl + if ret_val_target: + scl_map[(network_id, instr_uid, "RET_VAL")] = ret_val_target + return True + + +# --- Processor for Call --- +def process_call(instruction, network_id, scl_map, access_map): + instr_uid = instruction["instruction_uid"] + instr_type = instruction.get("type", "") + if instr_type.endswith(SCL_SUFFIX) or "_error" in instr_type: + return False + block_name = instruction.get("block_name", f"UnknownCall_{instr_uid}") + block_type = instruction.get("block_type") + instance_db_name = instruction.get("instance_db") # Provided by x1 + en_scl = ( + get_scl_representation( + instruction["inputs"].get("en"), network_id, scl_map, access_map + ) + or "TRUE" + ) + + block_name_scl = format_variable_name(block_name) + instance_db_scl = ( + format_variable_name(instance_db_name) if instance_db_name else None + ) + # DEBUG PRINT for FB calls: + # if block_type == "FB": print(f"DEBUG process_call FB: UID={instr_uid}, Instance DB from JSON: {instance_db_name}, Formatted: {instance_db_scl}") + + scl_call_params = [] + output_assignments = [] + inout_assignments = [] + all_params_resolved = True + processed_inputs = {"en"} + + # Inputs + for pin_name, source_info in instruction.get("inputs", {}).items(): + 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: + all_params_resolved = False + break + param_name_scl = format_variable_name(pin_name) + scl_call_params.append(f"{param_name_scl} := {param_scl}") + processed_inputs.add(pin_name) + if not all_params_resolved: + return False + + # Outputs (=> assignments) + for pin_name, dest_list in instruction.get("outputs", {}).items(): + if pin_name == "eno": + continue + if isinstance(dest_list, list): + for dest_info in dest_list: + if dest_info.get("type") == "variable": + dest_var_name = dest_info.get("name") + if dest_var_name: + dest_scl = format_variable_name(dest_var_name) + param_name_scl = format_variable_name(pin_name) + # Assume Output (=>). Could be InOut (:=) - needs interface info to be sure. + output_assignments.append(f"{param_name_scl} => {dest_scl}") + # else: print(f"Warn: Call {instr_uid} output '{pin_name}' to unnamed var UID {dest_info.get('uid')}") + + all_params_str = ", ".join(scl_call_params + output_assignments + inout_assignments) + scl_call_body = "" + + if block_type == "FB": + if not instance_db_scl: # Check the formatted name + error_msg = f"// ERROR: FB Call '{block_name_scl}' UID {instr_uid} sin DB de instancia válido." + print(error_msg.replace("// ", "")) + instruction["scl"] = error_msg + instruction["type"] = "Call_FB_error" + return True + scl_call_body = f"{instance_db_scl}({all_params_str});" + elif block_type == "FC": + if output_assignments: + print( + f"Advertencia: FC Call {instr_uid} '{block_name_scl}' usa sintaxis '=>' para salidas. Verificar." + ) + scl_call_body = f"{block_name_scl}({all_params_str});" + else: + error_msg = ( + f"// ERROR: Tipo bloque no soportado Call UID {instr_uid}: {block_type}" + ) + print(error_msg.replace("// ", "")) + instruction["scl"] = error_msg + instruction["type"] = f"Call_{block_type}_error" + return True + + instruction["scl"] = ( + f"IF {en_scl} THEN\n {scl_call_body}\nEND_IF;" + if en_scl != "TRUE" + else scl_call_body + ) + instruction["type"] = ( + f"Call_{block_type}_scl" + if "_error" not in instruction["type"] + else instruction["type"] + ) + scl_map[(network_id, instr_uid, "eno")] = en_scl + if block_type == "FB" and instance_db_scl: + for pin_name in instruction.get("outputs", {}).keys(): + if pin_name != "eno": + scl_map[(network_id, instr_uid, pin_name)] = ( + f"{instance_db_scl}.{format_variable_name(pin_name)}" + ) + return True + + +# process_group_ifs - No significant changes needed from previous version +def process_group_ifs(instruction, network_id, scl_map, access_map): + """ + Groups instructions enabled by the same condition into a single IF block. + """ + instr_uid = instruction["instruction_uid"] + instr_type = instruction["type"] + instr_type_original = instr_type.replace("_scl", "").replace("_error", "") + made_change = False + + if ( + not instr_type.endswith("_scl") + or "_error" in instr_type + or instruction.get("grouped", False) + ): + return False + + is_condition_generator = instr_type_original in [ + "Contact", + "O", + "Eq", + "Ne", + "Gt", + "Lt", + "Ge", + "Le", + "P_TRIG", + "N_TRIG", + "And", + "Xor", + ] + if not is_condition_generator: + return False + + current_scl = instruction.get("scl", "").strip() + if ( + current_scl.startswith("IF") + and "END_IF;" in current_scl + and "\n" in current_scl + ) or current_scl.startswith("//"): + return False + + map_key_out = (network_id, instr_uid, "out") + condition_scl = scl_map.get(map_key_out) + if condition_scl is None or condition_scl in ["TRUE", "FALSE"]: + return False + + 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 + + groupable_types_original = [ + "Move", + "Add", + "Sub", + "Mul", + "Div", + "Mod", + "Convert", + "Call_FC", + "Call_FB", + "Coil", + "R", + "S", + "SR", + "TON_S5", + "TONR_S5", + "BLKMOV", + "P_TRIG", + "N_TRIG", + ] + + for consumer_instr in network_logic: + consumer_uid = consumer_instr["instruction_uid"] + if consumer_instr.get("grouped", False) or consumer_uid == instr_uid: + continue + consumer_type = consumer_instr.get("type", "") + consumer_type_original = consumer_type.replace("_scl", "").replace("_error", "") + consumer_scl = consumer_instr.get("scl", "") + + is_enabled_by_us = False + # Determine enabling pin based on consumer type + enabling_pin = "en" # Default for functional blocks + if consumer_type_original in ["Coil", "R", "S", "SR"]: + enabling_pin = "in" + elif consumer_type_original in ["TON_S5", "TONR_S5"]: + enabling_pin = "s" + elif consumer_type_original in ["P_TRIG", "N_TRIG"]: + enabling_pin = "in" # Clock input + + consumer_input = consumer_instr.get("inputs", {}).get(enabling_pin) + if ( + isinstance(consumer_input, dict) + and consumer_input.get("type") == "connection" + and consumer_input.get("source_instruction_uid") == instr_uid + and consumer_input.get("source_pin") == "out" + ): + is_enabled_by_us = True + + if ( + is_enabled_by_us + and consumer_type.endswith("_scl") + and consumer_type_original in groupable_types_original + and consumer_scl + ): + core_scl = None + if consumer_scl.strip().startswith("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 not consumer_scl.strip().startswith("//"): + core_scl = consumer_scl.strip() + if core_scl: + grouped_instructions_cores.append(core_scl) + consumer_instr_list.append(consumer_instr) + + 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}") + scl_grouped = [f"IF {condition_scl} THEN"] + for core_line in grouped_instructions_cores: + indented_core = "\n".join( + [f" {line.strip()}" for line in core_line.splitlines() if line.strip()] + ) + scl_grouped.append(indented_core) + scl_grouped.append("END_IF;") + instruction["scl"] = "\n".join(scl_grouped) + for consumer_instr in consumer_instr_list: + consumer_instr["scl"] = f"{GROUPED_COMMENT} (by UID {instr_uid})" + consumer_instr["grouped"] = True + made_change = True + return made_change + + +# --- Bucle Principal de Procesamiento --- +def process_json_to_scl(json_filepath): + if not os.path.exists(json_filepath): + print(f"Error: JSON no encontrado: {json_filepath}") + return + print(f"Cargando JSON desde: {json_filepath}") + try: + with open(json_filepath, "r", encoding="utf-8") as f: + global data + data = json.load(f) + except Exception as e: + print(f"Error al cargar JSON: {e}") + traceback.print_exc() + return + + network_access_maps = {} + for network in data.get("networks", []): + net_id = network["id"] + current_access_map = {} + network_logic = network.get("logic", []) + for instr in network_logic: + for source in list(instr.get("inputs", {}).values()) + [ + item + for sublist in instr.get("outputs", {}).values() + for item in sublist + ]: + sources_to_check = ( + source + if isinstance(source, list) + else ([source] if isinstance(source, dict) else []) + ) + for src in sources_to_check: + if ( + isinstance(src, dict) + and src.get("uid") + and src.get("type") in ["variable", "constant"] + ): + current_access_map[src["uid"]] = src + network_access_maps[net_id] = current_access_map + + scl_map = {} + max_passes = 50 + passes = 0 + processing_complete = False + + # Define processor functions and map + base_processors_list = [ + process_contact, + process_eq, + process_o, + process_p_trig, + process_n_trig, # Edges before coils + process_ton_s5, + process_tonr_s5, # Timers before coils + process_move, + process_add, + process_mod, + process_convert, + process_blkmov, + process_coil, + process_r, + process_s, + process_sr, # Coils + process_call, # Calls last + ] + grouping_processor = process_group_ifs + processor_map = {} + for func in base_processors_list: + match = re.match(r"process_(\w+)", func.__name__) + if match: + type_name = match.group(1).lower() + processor_map[type_name] = func + if type_name == "call": + processor_map["call_fc"] = func + processor_map["call_fb"] = func + # Map mapped types directly + if type_name == "ton_s5": + processor_map["ton_s5"] = func + if type_name == "tonr_s5": + processor_map["tonr_s5"] = func + if type_name == "p_trig": + processor_map["p_trig"] = func + if type_name == "n_trig": + processor_map["n_trig"] = func + if type_name == "r": + processor_map["r"] = func + if type_name == "s": + processor_map["s"] = func + if type_name == "sr": + processor_map["sr"] = func + + print("\n--- Iniciando Bucle de Procesamiento Iterativo ---") + while passes < max_passes and not processing_complete: + passes += 1 + made_change_in_base_pass = False + made_change_in_group_pass = False + print(f"\n--- Pase {passes} ---") + num_processed_this_pass = 0 + num_grouped_this_pass = 0 + + # --- FASE 1: Base Processors --- + for network in data.get("networks", []): + network_id = network["id"] + access_map = network_access_maps.get(network_id, {}) + network_logic = network.get("logic", []) + for instruction in network_logic: + instr_uid = instruction.get("instruction_uid") + instr_type = instruction.get("type", "Unknown") + if ( + instr_type.endswith(SCL_SUFFIX) + or "_error" in instr_type + or instruction.get("grouped", False) + ): + continue + + lookup_key = ( + instr_type.lower() + ) # Use the mapped type from x1 (e.g., ton_s5) + if instr_type == "Call": # Still need to handle FC/FB for Call type + block_type = instruction.get("block_type", "").upper() + if block_type == "FC": + lookup_key = "call_fc" + elif block_type == "FB": + lookup_key = "call_fb" + + func_to_call = processor_map.get(lookup_key) + if func_to_call: + try: + # Pass network_logic only if needed (currently not used by edge detectors) + changed = func_to_call( + instruction, network_id, scl_map, access_map + ) + if changed: + made_change_in_base_pass = True + num_processed_this_pass += 1 + except Exception as e: + print( + f"ERROR(Base) al procesar {instr_type} UID {instr_uid}: {e}" + ) + traceback.print_exc() + instruction["scl"] = f"// ERROR en procesador base: {e}" + instruction["type"] = instr_type + "_error" + made_change_in_base_pass = True + # else: # Debug missing + # if not lookup_key.endswith(SCL_SUFFIX) and lookup_key not in ['unknown_access', 'unknown', 'contact']: # Example ignore list + # print(f"DEBUG: No processor for type '{instr_type}' (lookup: '{lookup_key}') UID {instr_uid}") + + # --- FASE 2: Grouping Processor --- + if made_change_in_base_pass or passes == 1: + for network in data.get("networks", []): + network_id = network["id"] + access_map = network_access_maps.get(network_id, {}) + network_logic = network.get("logic", []) + for instruction in network_logic: + if instruction["type"].endswith("_scl") and not instruction.get( + "grouped", False + ): + try: + if grouping_processor( + instruction, network_id, scl_map, access_map + ): + made_change_in_group_pass = True + num_grouped_this_pass += 1 + except Exception as e: + print( + f"ERROR(Group) UID {instruction.get('instruction_uid')}: {e}" + ) + traceback.print_exc() + + # --- Check Completion --- + if not made_change_in_base_pass and not made_change_in_group_pass: + print(f"\n--- No cambios en pase {passes}. Proceso iterativo COMPLETO. ---") + processing_complete = True + else: + print( + f"--- Fin Pase {passes}: {num_processed_this_pass} procesados, {num_grouped_this_pass} agrupados. Continuando..." + ) + if passes == max_passes and not processing_complete: + print(f"\n--- ADVERTENCIA: Límite {max_passes} pases alcanzado. ---") + + # --- Final Verification --- (No changes needed) + print("\n--- Verificación Final de Instrucciones No Procesadas ---") + unprocessed_count = 0 + unprocessed_details = [] + for network in data.get("networks", []): + network_id = network.get("id", "N/A") + network_title = network.get("title", f"Red {network_id}") + for instruction in network.get("logic", []): + instr_uid = instruction.get("instruction_uid", "N/A") + instr_type = instruction.get("type", "N/A") + is_grouped = instruction.get("grouped", False) + if ( + not instr_type.endswith(SCL_SUFFIX) + and "_error" not in instr_type + and not is_grouped + ): + unprocessed_count += 1 + orig_type = instruction.get( + "original_type", instr_type + ) # Show original type if available + unprocessed_details.append( + f" - Red '{network_title}' (ID: {network_id}), UID: {instr_uid}, Tipo: '{orig_type}' (Mapped: '{instr_type}')" + ) + if unprocessed_count > 0: + print(f"ADVERTENCIA: {unprocessed_count} instrucciones no procesadas:") + [print(d) for d in unprocessed_details] + print(">>> Verificar dependencias o procesadores faltantes.") + else: + print( + "INFO: Todas las instrucciones fueron procesadas, marcadas como error o agrupadas." + ) + + # --- Guardar JSON Final --- (No changes needed) + 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: + json.dump(data, f, indent=4, ensure_ascii=False) + print("Guardado completado.") + except Exception as e: + print(f"Error Crítico al guardar JSON: {e}") + traceback.print_exc() + + +# --- Ejecución --- +if __name__ == "__main__": + xml_filename_base = "BlenderCtrl__Main" + input_json_file = f"{xml_filename_base}_simplified.json" + if not os.path.exists(input_json_file): + print(f"Error Fatal: Archivo JSON '{input_json_file}' no existe.") + print(f"Ejecuta 'x1_to_json.py' sobre '{xml_filename_base}.xml' primero.") + else: + process_json_to_scl(input_json_file) diff --git a/VersionNoFuncionante/x3_generate_scl.py b/VersionNoFuncionante/x3_generate_scl.py new file mode 100644 index 0000000..4dba521 --- /dev/null +++ b/VersionNoFuncionante/x3_generate_scl.py @@ -0,0 +1,218 @@ +# -*- coding: utf-8 -*- +import json +import os +import re + + +# --- Helper Functions --- +# Use the CORRECT version from x2_process.py +def format_variable_name(name): + """Formats variable names for SCL, preserving quotes for structured names.""" + if not name: + return "_INVALID_NAME_" + if name.startswith('"') and name.endswith('"'): + return name + prefix = "" + if name.startswith("#"): + prefix = "#" + name = name[1:] + if not name: + return "_INVALID_NAME_" + if not re.match(r"^[a-zA-Z_]", name[0]): + name = "_" + name + name = re.sub(r"[^a-zA-Z0-9_]", "_", name) + return prefix + name + + +def generate_scl(processed_json_filepath, output_scl_filepath): + """Genera un archivo SCL a partir del JSON procesado.""" + if not os.path.exists(processed_json_filepath): + print( + f"Error: Archivo JSON procesado no encontrado en '{processed_json_filepath}'" + ) + return + print(f"Cargando JSON procesado desde: {processed_json_filepath}") + try: + with open(processed_json_filepath, "r", encoding="utf-8") as f: + data = json.load(f) + except Exception as e: + print(f"Error al cargar JSON: {e}") + return + + # --- Block Info --- + block_name_orig = data.get("block_name", "UnknownBlock") + block_number = data.get("block_number") + block_lang = data.get("language", "LAD") + block_comment = data.get("block_comment", "") + + # --- Variable Detection --- + temp_vars_base = set() # Base names like _temp_... + stat_vars = {} # Quoted Name -> TYPE (Bool, TON, TONR) + + temp_pattern = re.compile(r"#(_temp_[a-zA-Z0-9_]+)") # Capture base name after # + # Regex needs to capture the QUOTED name from SCL + stat_pattern_bool = re.compile( + r'("stat_(?:ptrig|ntrig|sr)_mem_[a-zA-Z0-9_]+")' + ) # Edge/SR mem bits + stat_pattern_ton = re.compile(r'("stat_TON_[a-zA-Z0-9_]+")') # TON instances + stat_pattern_tonr = re.compile(r'("stat_TONR_[a-zA-Z0-9_]+")') # TONR instances + + for network in data.get("networks", []): + for instruction in network.get("logic", []): + scl_code = instruction.get("scl", "") + if scl_code: + temp_vars_base.update(temp_pattern.findall(scl_code)) + for name in stat_pattern_bool.findall(scl_code): + stat_vars[name] = "Bool" + for name in stat_pattern_ton.findall(scl_code): + stat_vars[name] = "TON" + for name in stat_pattern_tonr.findall(scl_code): + stat_vars[name] = "TONR" + + has_stat = bool(stat_vars) + interface_temps_list = data.get("interface", {}).get("Temp", []) + has_temp = bool(temp_vars_base or interface_temps_list) + block_type_keyword = "FUNCTION_BLOCK" if has_stat or has_temp else "FUNCTION" + scl_block_name = format_variable_name(block_name_orig) # Format name correctly + + print(f"Generando SCL para bloque: {scl_block_name} como {block_type_keyword}") + print(f"Variables temporales (#_temp_...) detectadas: {len(temp_vars_base)}") + print(f"Variables estáticas (stat_...) detectadas: {len(stat_vars)}") + + # --- Build SCL Output --- + scl_output = [] + scl_output.append(f"// Block Name (Original): {block_name_orig}") + 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}") + scl_output.append("") + scl_output.append(f"{block_type_keyword} {scl_block_name}") + scl_output.append("{ S7_Optimized_Access := 'TRUE' }") + scl_output.append("VERSION : 0.1") + scl_output.append("") + + # --- VAR Sections --- + def add_var_section(section_name, members_list): + if not members_list: + return + scl_output.append(f"VAR_{section_name}") + for member in members_list: + scl_name = format_variable_name( + member["name"] + ) # Format interface var names + scl_output.append(f" {scl_name} : {member['datatype']};") + scl_output.append("END_VAR") + scl_output.append("") + + interface_data = data.get("interface", {}) + add_var_section("INPUT", interface_data.get("Input", [])) + add_var_section("OUTPUT", interface_data.get("Output", [])) + add_var_section("IN_OUT", interface_data.get("InOut", [])) + + if stat_vars: + scl_output.append("VAR_STAT") + for var_name_quoted in sorted(stat_vars.keys()): + var_type = stat_vars[var_name_quoted] + comment = ( + f"// Instance for {var_type}" + if var_type in ["TON", "TONR"] + else "// Memory Bit" + ) + scl_output.append(f" {var_name_quoted} : {var_type}; {comment}") + scl_output.append("END_VAR") + scl_output.append("") + + declared_temps_formatted = set() + temp_declarations = [] + if interface_temps_list: + for var in interface_temps_list: + scl_name = format_variable_name(var["name"]) + temp_declarations.append( + f" {scl_name} : {var['datatype']}; // From Interface" + ) + declared_temps_formatted.add(scl_name) + if temp_vars_base: + for base_name in sorted(list(temp_vars_base)): + # Declare using the base name, quoted + scl_name_declare = format_variable_name(f'"{base_name}"') + if scl_name_declare not in declared_temps_formatted: + # Simple inference based on common pin names in the base name + inferred_type = "Bool" # Default + if "ret_val" in base_name: + inferred_type = "Int" + elif "_et" in base_name: + inferred_type = "Time" + temp_declarations.append( + f" {scl_name_declare} : {inferred_type}; // Auto-generated temporary" + ) + declared_temps_formatted.add(scl_name_declare) + if temp_declarations: + scl_output.append("VAR_TEMP") + scl_output.extend(temp_declarations) + scl_output.append("END_VAR") + scl_output.append("") + + # --- Block Body --- + scl_output.append("BEGIN") + scl_output.append("") + for i, network in enumerate(data.get("networks", [])): + network_title = network.get("title", f'Network {network.get("id")}') + network_comment = network.get("comment", "") + scl_output.append(f" // Network {i+1}: {network_title}") + if network_comment: + for line in network_comment.splitlines(): + scl_output.append(f" // {line}") + scl_output.append("") + network_has_code = False + for instruction in network.get("logic", []): + if instruction.get("grouped", False): + continue + scl_code = instruction.get("scl") + if scl_code: + lines_to_add = [] + for line in scl_code.splitlines(): + line_strip = line.strip() + is_simple_info_comment = line_strip.startswith( + ("// RLO:", "// Comparison Eq", "// Logic O") + ) + # Keep essential comments (Errors, Grouping, Memory Updates) and actual SCL + if ( + not is_simple_info_comment + or line_strip.startswith("// ERROR") + or line_strip.startswith(GROUPED_COMMENT) + or "Edge Memory Update" in line_strip + ): + lines_to_add.append(line) + if lines_to_add: + network_has_code = True + for line in lines_to_add: + scl_output.append(f" {line}") + if network_has_code: + scl_output.append("") + + end_keyword = ( + "END_FUNCTION_BLOCK" + if block_type_keyword == "FUNCTION_BLOCK" + else "END_FUNCTION" + ) + scl_output.append(end_keyword) + + # --- Write File --- + print(f"Escribiendo archivo SCL en: {output_scl_filepath}") + try: + with open(output_scl_filepath, "w", encoding="utf-8") as f: + for line in scl_output: + f.write(line + "\n") + print("Generación de SCL completada.") + except Exception as e: + print(f"Error al escribir el archivo SCL: {e}") + + +# --- Ejecución --- +if __name__ == "__main__": + xml_filename_base = "BlenderCtrl__Main" + input_json_file = f"{xml_filename_base}_simplified_processed.json" + output_scl_file = input_json_file.replace("_simplified_processed.json", ".scl") + generate_scl(input_json_file, output_scl_file) diff --git a/x1_to_json.py b/x1_to_json.py index 94ccf15..c3c5423 100644 --- a/x1_to_json.py +++ b/x1_to_json.py @@ -713,7 +713,7 @@ def convert_xml_to_json(xml_filepath, json_filepath): # --- Punto de Entrada Principal --- if __name__ == "__main__": - xml_file = "BlenderCtrl__Main.xml" # CAMBIAR AL NUEVO ARCHIVO XML + xml_file = "TestLAD.xml" # CAMBIAR AL NUEVO ARCHIVO XML json_file = xml_file.replace( ".xml", "_simplified.json" ) # Nombre de salida dinámico diff --git a/x2_process.py b/x2_process.py index f8119bf..e8c8f6a 100644 --- a/x2_process.py +++ b/x2_process.py @@ -1447,7 +1447,7 @@ def process_json_to_scl(json_filepath): # --- Ejecución --- if __name__ == "__main__": # Asegúrate de que el nombre base del archivo XML sea correcto - xml_filename_base = "BlenderCtrl__Main" # Cambia esto si tu XML se llama diferente + xml_filename_base = "TestLAD" # Cambia esto si tu XML se llama diferente input_json_file = f"{xml_filename_base}_simplified.json" if not os.path.exists(input_json_file): diff --git a/x3_generate_scl.py b/x3_generate_scl.py index 2c986a5..726ebdf 100644 --- a/x3_generate_scl.py +++ b/x3_generate_scl.py @@ -197,7 +197,7 @@ def generate_scl(processed_json_filepath, output_scl_filepath): # --- Ejecución --- if __name__ == "__main__": - xml_file = "BlenderCtrl__Main.xml" # CAMBIAR AL NUEVO ARCHIVO XML + xml_file = "TestLAD.xml" # CAMBIAR AL NUEVO ARCHIVO XML input_json_file = xml_file.replace( ".xml", "_simplified_processed.json" ) # Nombre de salida dinámico