Modular Application Creator Use Case Based Documentation
Loading...
Searching...
No Matches
GenericBlockCreation.cs
1using System;
2using System.IO;
3using System.Linq;
4using System.Runtime.CompilerServices;
5using MAC_use_cases.TiaImports;
6using Siemens.Automation.ModularApplicationCreator.Tia.Helper;
7using Siemens.Automation.ModularApplicationCreator.Tia.Helper.Create_XML_Block;
8using Siemens.Automation.ModularApplicationCreator.Tia.Helper.Create_XML_Block.XmlBlocks.BlockFrames;
9using Siemens.Automation.ModularApplicationCreator.Tia.Openness;
10using Siemens.Automation.ModularApplicationCreator.Tia.Openness.SoftwareUnit;
11using Siemens.Automation.ModularApplicationCreator.Tia.TiaAttributeFuncs;
12using ProgrammingLanguage =
13 Siemens.Automation.ModularApplicationCreator.Tia.Helper.Create_XML_Block.ProgrammingLanguage;
14
16
21{
25 public static string ParameterName = "myParameterName";
26
53
54 // TODO expand for sw-units
55 public static void CreateFunctionBlock(string blockName, string instanceDbName,
56 ProgrammingLanguage programmingLanguage,
57 PlcDevice plcDevice)
58 {
59 // Input validation
60 if (string.IsNullOrEmpty(blockName))
61 {
62 throw new ArgumentNullException(nameof(blockName));
63 }
64
65 if (string.IsNullOrEmpty(instanceDbName))
66 {
67 throw new ArgumentNullException(nameof(instanceDbName));
68 }
69
70 if (plcDevice == null)
71 {
72 throw new ArgumentNullException(nameof(plcDevice));
73 }
74
75 if (programmingLanguage != ProgrammingLanguage.LAD && programmingLanguage != ProgrammingLanguage.FBD &&
76 programmingLanguage != ProgrammingLanguage.SCL)
77 {
78 throw new ArgumentException(nameof(programmingLanguage));
79 }
80
81 // Create block call with default values
82 var fbCall = new BlockCall(instanceDbName, plcDevice) { ["Input1"] = "1", ["Input2"] = "0" };
83
84 // Create and configure network
85 var fbNetwork = new BlockNetwork { NetworkTitles = { [TypeMapper.BaseCulture.Name] = "myFB Network Title" } };
86 fbNetwork.Blocks.Add(fbCall);
87
88 // Create and Configure FB properties
89 var fb = new XmlFB(blockName);
90 fb.Networks.Add(fbNetwork);
91 fb.BlockAttributes.ProgrammingLanguage = programmingLanguage;
92 fb.BlockComments[TypeMapper.BaseCulture.Name] = "myFB Block Comment";
93 fb.BlockTitles[TypeMapper.BaseCulture.Name] = "myFB Block Title";
94
95 // Generate the block in appropriate format
96 if (programmingLanguage == ProgrammingLanguage.SCL)
97 {
98 fb.GenerateSclBlock(plcDevice);
99 }
100 else
101 {
102 fb.GenerateXmlBlock(plcDevice);
103 }
104 }
105
131 public static void CreateFailSafeFunctionBlock(string blockName, string instanceDbName,
132 ProgrammingLanguage programmingLanguage,
133 PlcDevice plcDevice)
134 {
135 // Input validation
136 if (string.IsNullOrEmpty(blockName))
137 {
138 throw new ArgumentNullException(nameof(blockName));
139 }
140
141 if (string.IsNullOrEmpty(instanceDbName))
142 {
143 throw new ArgumentNullException(nameof(instanceDbName));
144 }
145
146 if (plcDevice == null)
147 {
148 throw new ArgumentNullException(nameof(plcDevice));
149 }
150
151 if (programmingLanguage != ProgrammingLanguage.F_LAD && programmingLanguage != ProgrammingLanguage.F_FBD)
152 {
153 throw new ArgumentException(nameof(programmingLanguage));
154 }
155
156 // Create block call with default values
157 var fbCall = new BlockCall(instanceDbName, plcDevice) { ["Input1"] = "1", ["Input2"] = "0" };
158
159 // Create and configure network
160 var fbNetwork = new BlockNetwork { NetworkTitles = { [TypeMapper.BaseCulture.Name] = "myFB Network Title" } };
161 fbNetwork.Blocks.Add(fbCall);
162
163 //Create and configure FB properties
164 var failSafeBlock = new XmlFailSafeFB(blockName);
165 failSafeBlock.Networks.Add(fbNetwork);
166 failSafeBlock.BlockAttributes.ProgrammingLanguage = programmingLanguage;
167 failSafeBlock.BlockComments[TypeMapper.BaseCulture.Name] = "myFB Block Comment";
168 failSafeBlock.BlockTitles[TypeMapper.BaseCulture.Name] = "myFB Block Title";
169
170 // Generate the block in appropriate format
171 failSafeBlock.GenerateXmlBlock(plcDevice, programmingLanguage);
172 }
173
174
183 public static XmlGlobalDB GenerateGlobalDataBlock(string dbName, PlcDevice plcDevice, MAC_use_casesEM module)
184 {
185 var dataBlock = new XmlGlobalDB(dbName);
186 var itf = dataBlock.Interface[InterfaceSections.Static];
187
188 //Create new parameters. The custom parameter means you are using your own user defined data type.
189 var standardParam = new InterfaceParameter(ParameterName, "Int");
190 var customParam1 = new InterfaceParameter("var_struct", "Struct");
191 customParam1.SubParameter.Add(new InterfaceParameter("Var1", "Bool"));
192 customParam1.SubParameter.Add(new InterfaceParameter("Var2", "Int"));
193 var customParam2 = new InterfaceParameter("datatyp_from_lib", "\"" + "myDataType" + "\"");
194
195 //Add your parameters
196 itf.Add(standardParam);
197 itf.Add(customParam1);
198 itf.Add(customParam2);
199
200 dataBlock.GenerateXmlBlock(plcDevice);
201 return dataBlock;
202 }
203
225 public static void CreateFunctionBlockInSoftwareUnit(ISoftwareUnitBase softwareUnitBase, string fbName,
226 ProgrammingLanguage programmingLanguage, PlcDevice plcDevice)
227 {
228 var fb = new XmlFB(fbName);
229
230 fb.Interface[InterfaceSections.Input].Add(new InterfaceParameter("Input_1", "Bool")
231 {
232 Remanence = RemanenceSettings.IgnoreRemanence
233 });
234 fb.Interface[InterfaceSections.Input].Add(new InterfaceParameter("Input_2", "Bool")
235 {
236 Remanence = RemanenceSettings.IgnoreRemanence
237 });
238 fb.Interface[InterfaceSections.Output].Add(new InterfaceParameter("Output", "Bool")
239 {
240 Remanence = RemanenceSettings.IgnoreRemanence
241 });
242
243 //here an example how to create a multi instance call in the function block
244 if (programmingLanguage == ProgrammingLanguage.SCL)
245 {
246 fb.GenerateSclBlock(softwareUnitBase);
247 }
248 else
249 {
250 fb.GenerateXmlBlock(softwareUnitBase, programmingLanguage);
251 }
252 var block = softwareUnitBase.Blocks.ToList().FirstOrDefault(b => b.Value.Name == fbName);
253 block.Value.Namespace = "Namespace_Block";
254 }
255
263 private static void GenerateBlock(string code, PlcDevice targetDevice, ITarget targetContainer = null,
264 bool isScl = true)
265 {
266 //Get the right file extension depending on the block language
267 var extension = ".scl";
268 if (!isScl)
269 {
270 extension = ".xml";
271 }
272
273 //Create a temporary file
274 var filePath = Path.ChangeExtension(Path.GetTempFileName(), extension);
275
276 //Write the code to this file
277 File.WriteAllText(filePath, code);
278
279 //Create the block on the plc using the file
280 var block = OpennessFuncs.ImportBlockToPlc(filePath, targetDevice, targetContainer);
281
282 //Delete the file
283 File.Delete(filePath);
284 }
285
295 public static void SetDefaultValue(string dbName, string parameterName, TIATYPE dataType, string value,
296 MAC_use_casesEM parent)
297 {
298 var myParameterNameAttribute = TiaAttributeProvider.CreateAttribute(dataType, SOURCETYPE.BLOCKVAR,
299 dbName, parameterName, parent);
300 myParameterNameAttribute.Value = value;
301 }
302
310 public static void GenerateMultiInstanceFB(PlcDevice plcDevice, string languageSettings, MAC_use_casesEM module)
311 {
312 var myFb = new XmlFB("MyFunctionBlock_MultiInstance")
313 {
314 BlockAttributes = { ProgrammingLanguage = ProgrammingLanguage.LAD }
315 };
316
317 var multiInstanceDataBlockName = myFb.Name + "_Instance";
318 var myMultiInstanceFbCall =
319 new MultiInstanceCall(multiInstanceDataBlockName, module.ResourceManagement.MyFunctionBlock.Name, plcDevice)
320 {
321 ["Input1"] = "1", // inputVariable1
322 ["Input2"] = "0" // inputVariable1
323 };
324
325 //manipulate interface
326 var interfaceParameters = myFb.Interface[InterfaceSections.Static];
327
328 //Create new parameters. The custom parameter means you are using your own user defined data type.
329 var customParam =
330 new InterfaceParameter(multiInstanceDataBlockName,
331 module.ResourceManagement.MyFunctionBlock.Name) { Remanence = RemanenceSettings.IgnoreRemanence };
332
333 //Add your parameters
334 interfaceParameters.Add(customParam);
335
336 var networkMultiInstance = new BlockNetwork();
337 networkMultiInstance.Blocks.Add(myMultiInstanceFbCall);
338 networkMultiInstance.GenerationLabel =
339 new GenerationLabel(module.Name, "Generated by MAC", module.ModuleID.ToString());
340 myFb.Networks.Add(networkMultiInstance);
341 AddCodeBlockToOB(myFb, module.ResourceManagement, languageSettings, plcDevice);
342 }
343
352 public static void GenerateOB_Main(string instanceDbName, MAC_use_casesEM module, string languageSettings,
353 PlcDevice plcDevice)
354 {
355 var mainOb = new XmlOB("Main");
356 mainOb.BlockAttributes.ProgrammingLanguage = ProgrammingLanguage.LAD;
357 ((OB_BlockAttributes)mainOb.BlockAttributes).BlockSecondaryType = "ProgramCycle";
358
359 var itf = mainOb.Interface[InterfaceSections.Temp];
360 var temp = new InterfaceParameter("Temp", "Bool");
361 var tempInt = new InterfaceParameter("TempInt", "Int");
362 itf.Add(temp);
363 itf.Add(tempInt);
364
365 //create block call of instance DB
366 var myFBCall = new BlockCall(instanceDbName, plcDevice)
367 {
368 ["Input1"] = "#Temp", // inputVariable1
369 ["Input2"] = "0" // inputVariable1
370 //["Input2"] = "inputVariable1",
371
372 //["Output1"] = "outputVariable1",
373 };
374 var blockNetwork = new BlockNetwork();
375 blockNetwork.Blocks.Add(myFBCall);
376 blockNetwork.GenerationLabel =
377 new GenerationLabel(module.Name, "Generated by MAC", module.ModuleID.ToString());
378 mainOb.Networks.Add(blockNetwork);
379
381 var content = "\"MyDataBlock_Global\".myParameterName := 100;\n";
382 content += "IF #Temp THEN\n";
383 content += "#TempInt := 5;\n";
384 content += "ELSE\n";
385 content += "TempInt := 1;\n";
386 content += "END_IF;\n\n";
387 var sclContent = content;
388 var sclcode_network = ParseSingleSCLCall(sclContent, plcDevice, mainOb);
389 sclcode_network.GenerationLabel =
390 new GenerationLabel(module.Name, "Virtual_Master_scl_code", module.ModuleID.ToString());
391 mainOb.Networks.Add(sclcode_network);
392
393 AddCodeBlockToOB(mainOb, module.ResourceManagement, languageSettings, plcDevice);
394 }
395
404 public static void AddCodeBlockToOB(XmlLogicalBlock codeBlock, ResourceManagement resourceManagement,
405 string languageSettings, PlcDevice plcDevice)
406 {
407 var existingOB = OpennessFuncs.TryGetOBFromPlcDevice(plcDevice, codeBlock.Name);
408 //Create new OB in SCL with calling code
409 if (existingOB == null)
410 {
411 if (codeBlock.BlockAttributes.ProgrammingLanguage == ProgrammingLanguage.SCL)
412 {
413 codeBlock.GenerateSclBlock(plcDevice);
414 }
415 else //insert networks to KOP/FUP
416 {
417 codeBlock.GenerateXmlBlock(plcDevice, null, languageSettings);
418 }
419 }
420 else
421 //Insert Code to existing OB
422 {
423 var blockAsDoc =
424 OpennessFuncs.ExportBlockAsXml(existingOB.Name, plcDevice, OpennessFuncs.CachingOptions.DISABLED);
425 var parser = new Parser();
426 var xmlOB = parser.ParseXml(blockAsDoc);
427 xmlOB.MergeBlock(codeBlock);
428 //add SCL-Code
429 if (xmlOB.BlockAttributes.ProgrammingLanguage == ProgrammingLanguage.SCL)
430 {
431 xmlOB.GenerateSclBlock(plcDevice);
432 }
433 else //insert networks to KOP/FUP
434 {
435 xmlOB.GenerateXmlBlock(plcDevice, null, languageSettings);
436 }
437 }
438 }
439
449 public static void GenerateOBWithMultipleCalls(string name, int numberOfCalls, string languageSettings,
450 PlcDevice plcDevice, MAC_use_casesEM module)
451 {
452 var myOb = new XmlOB(name);
453 myOb.BlockAttributes.BlockAutoNumber = false;
454 myOb.BlockAttributes.BlockNumber = 555.ToString();
455
456 for (var i = 1; i <= numberOfCalls; i++)
457 {
458 var blockName = $"{nameof(module.ResourceManagement.MyFunctionBlock)}DB" + i;
459 IntegrateLibraries.CreateInstanceDataBlock(module, module.ResourceManagement.MyFunctionBlock,
460 blockName, module.ResourceManagement.ModuleBlocksRootGroup);
461 var myOBCall = new BlockCall(blockName, plcDevice)
462 {
463 ["Input1"] = "1", // inputVariable1
464 ["Input2"] = "0" // inputVariable1
465 };
466
467 var myObBlockNetwork = new BlockNetwork();
468 myObBlockNetwork.Blocks.Add(myOBCall);
469 myObBlockNetwork.GenerationLabel = new GenerationLabel(blockName,
470 "Generated by MAC. Blockname: \"" + blockName + "\"", module.ModuleID.ToString());
471 myOb.Networks.Add(myObBlockNetwork);
472 }
473
474 AddCodeBlockToOB(myOb, module.ResourceManagement, languageSettings, plcDevice);
475 }
476
477 private static INetwork ParseSingleSCLCall(string sclCall, PlcDevice plc, XmlBlock xmlBlock)
478 {
479 var parsed = new Parser().ParseSclSnippet(sclCall, xmlBlock, plc, GroupBlockCalls.NOGROUPING)
480 .FirstOrDefault();
481 if (parsed is BlockNetwork blockNetwork)
482 {
483 return blockNetwork;
484 }
485
486 if (parsed is FixNetwork fixNetwork)
487 {
488 return fixNetwork;
489 }
490
491 return null;
492 }
493}
This is the main class in which the workflow starts. Here are all sections for creating or generating...
All the functions to configure and generate Blocks are defined here.
static XmlGlobalDB GenerateGlobalDataBlock(string dbName, PlcDevice plcDevice, MAC_use_casesEM module)
This function creates a Data Block with interface (sub-)parameters in a desired folder....
static void GenerateMultiInstanceFB(PlcDevice plcDevice, string languageSettings, MAC_use_casesEM module)
This function creates an multiInstanceFB.
static void SetDefaultValue(string dbName, string parameterName, TIATYPE dataType, string value, MAC_use_casesEM parent)
This function sets the default value of a parameter in a DB.
static void GenerateOB_Main(string instanceDbName, MAC_use_casesEM module, string languageSettings, PlcDevice plcDevice)
This function generates an OB and creates a block call in FBD and SCL.
static string ParameterName
This is the name of the generated parameter.
static void CreateFailSafeFunctionBlock(string blockName, string instanceDbName, ProgrammingLanguage programmingLanguage, PlcDevice plcDevice)
Creates a Fail-Safe Function Block (F-FB) in the target PLC's program blocks folder.
static void GenerateOBWithMultipleCalls(string name, int numberOfCalls, string languageSettings, PlcDevice plcDevice, MAC_use_casesEM module)
This function Generates the OB with the given number of calls.
static void CreateFunctionBlock(string blockName, string instanceDbName, ProgrammingLanguage programmingLanguage, PlcDevice plcDevice)
Creates a Function Block (FB) in the target PLC's program blocks folder.
static void AddCodeBlockToOB(XmlLogicalBlock codeBlock, ResourceManagement resourceManagement, string languageSettings, PlcDevice plcDevice)
This function checks if OB is already in TIA Project and merge the new one into the existing one depe...
static void CreateFunctionBlockInSoftwareUnit(ISoftwareUnitBase softwareUnitBase, string fbName, ProgrammingLanguage programmingLanguage, PlcDevice plcDevice)
Creates a new Function Block (FB) within the specified software unit with predefined interface parame...
static void GenerateBlock(string code, PlcDevice targetDevice, ITarget targetContainer=null, bool isScl=true)
This function creates a Block on the targetDevice in the targetContainer (folder under program blocks...
All the functions to configure and generate parts of the library are defined here.
static DataBlock CreateInstanceDataBlock(MAC_use_casesEM module, FBMasterCopy masterCopy, string instanceName, BlockGroup target)
This function creates an instance DB in the target folder (folder under program blocks)