246 pou.updateElementName(old_name, new_name) |
262 pou.updateElementName(old_name, new_name) |
247 for configuration in self.instances.configurations.getconfiguration(): |
263 for configuration in self.instances.configurations.getconfiguration(): |
248 configuration.updateElementName(old_name, new_name) |
264 configuration.updateElementName(old_name, new_name) |
249 setattr(cls, "updateElementName", updateElementName) |
265 setattr(cls, "updateElementName", updateElementName) |
250 |
266 |
|
267 def RefreshDataTypeHierarchy(self): |
|
268 self.EnumeratedDataTypeValues = {} |
|
269 self.CustomDataTypeRange = {} |
|
270 self.CustomTypeHierarchy = {} |
|
271 for datatype in self.getdataTypes(): |
|
272 self.AddCustomDataType(datatype) |
|
273 setattr(cls, "RefreshDataTypeHierarchy", RefreshDataTypeHierarchy) |
|
274 |
|
275 def AddCustomDataType(self, datatype): |
|
276 name = datatype.getname() |
|
277 basetype_content = datatype.getbaseType().getcontent() |
|
278 if basetype_content["value"] is None: |
|
279 self.CustomTypeHierarchy[name] = basetype_content["name"] |
|
280 elif basetype_content["name"] in ["string", "wstring"]: |
|
281 self.CustomTypeHierarchy[name] = basetype_content["name"].upper() |
|
282 elif basetype_content["name"] == "derived": |
|
283 self.CustomTypeHierarchy[name] = basetype_content["value"].getname() |
|
284 elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned"]: |
|
285 range = (basetype_content["value"].range.getlower(), |
|
286 basetype_content["value"].range.getupper()) |
|
287 self.CustomDataTypeRange[name] = range |
|
288 base_type = basetype_content["value"].baseType.getcontent() |
|
289 if base_type["value"] is None: |
|
290 self.CustomTypeHierarchy[name] = base_type["name"] |
|
291 else: |
|
292 self.CustomTypeHierarchy[name] = base_type["value"].getname() |
|
293 else: |
|
294 if basetype_content["name"] == "enum": |
|
295 values = [] |
|
296 for value in basetype_content["value"].values.getvalue(): |
|
297 values.append(value.getname()) |
|
298 self.EnumeratedDataTypeValues[name] = values |
|
299 self.CustomTypeHierarchy[name] = "ANY_DERIVED" |
|
300 setattr(cls, "AddCustomDataType", AddCustomDataType) |
|
301 |
|
302 # Update Block types with user-defined pou added |
|
303 def RefreshCustomBlockTypes(self): |
|
304 # Reset the tree of user-defined pou cross-use |
|
305 self.CustomBlockTypes = [] |
|
306 for pou in self.getpous(): |
|
307 self.AddCustomBlockType(pou) |
|
308 setattr(cls, "RefreshCustomBlockTypes", RefreshCustomBlockTypes) |
|
309 |
|
310 def AddCustomBlockType(self, pou): |
|
311 pou_name = pou.getname() |
|
312 pou_type = pou.getpouType() |
|
313 if pou_type != "program": |
|
314 block_infos = {"name" : pou_name, "type" : pou_type, "extensible" : False, |
|
315 "inputs" : [], "outputs" : [], "comment" : "", |
|
316 "generate" : generate_block, "initialise" : initialise_block } |
|
317 if pou.getinterface(): |
|
318 for type, varlist in pou.getvars(): |
|
319 if type == "InOut": |
|
320 for var in varlist.getvariable(): |
|
321 var_type = var.type.getcontent() |
|
322 if var_type["name"] == "derived": |
|
323 block_infos["inputs"].append((var.getname(), var_type["value"].getname(), "none")) |
|
324 block_infos["outputs"].append((var.getname(), var_type["value"].getname(), "none")) |
|
325 elif var_type["name"] in ["string", "wstring"]: |
|
326 block_infos["inputs"].append((var.getname(), var_type["name"].upper(), "none")) |
|
327 block_infos["outputs"].append((var.getname(), var_type["name"].upper(), "none")) |
|
328 else: |
|
329 block_infos["inputs"].append((var.getname(), var_type["name"], "none")) |
|
330 block_infos["outputs"].append((var.getname(), var_type["name"], "none")) |
|
331 elif type == "Input": |
|
332 for var in varlist.getvariable(): |
|
333 var_type = var.type.getcontent() |
|
334 if var_type["name"] == "derived": |
|
335 block_infos["inputs"].append((var.getname(), var_type["value"].getname(), "none")) |
|
336 elif var_type["name"] in ["string", "wstring"]: |
|
337 block_infos["inputs"].append((var.getname(), var_type["name"].upper(), "none")) |
|
338 else: |
|
339 block_infos["inputs"].append((var.getname(), var_type["name"], "none")) |
|
340 elif type == "Output": |
|
341 for var in varlist.getvariable(): |
|
342 var_type = var.type.getcontent() |
|
343 if var_type["name"] == "derived": |
|
344 block_infos["outputs"].append((var.getname(), var_type["value"].getname(), "none")) |
|
345 elif var_type["name"] in ["string", "wstring"]: |
|
346 block_infos["outputs"].append((var.getname(), var_type["name"].upper(), "none")) |
|
347 else: |
|
348 block_infos["outputs"].append((var.getname(), var_type["name"], "none")) |
|
349 return_type = pou.interface.getreturnType() |
|
350 if return_type: |
|
351 var_type = return_type.getcontent() |
|
352 if var_type["name"] == "derived": |
|
353 block_infos["outputs"].append(("", var_type["value"].getname(), "none")) |
|
354 elif var_type["name"] in ["string", "wstring"]: |
|
355 block_infos["outputs"].append(("", var_type["name"].upper(), "none")) |
|
356 else: |
|
357 block_infos["outputs"].append(("", var_type["name"], "none")) |
|
358 if pou.getbodyType() in ["FBD","LD","SFC"]: |
|
359 for instance in pou.getinstances(): |
|
360 if isinstance(instance, PLCOpenClasses.get("commonObjects_comment", None)): |
|
361 block_infos["comment"] = instance.getcontentText() |
|
362 self.CustomBlockTypes.append(block_infos) |
|
363 setattr(cls, "AddCustomBlockType", AddCustomBlockType) |
|
364 |
|
365 def RefreshElementUsingTree(self): |
|
366 # Reset the tree of user-defined element cross-use |
|
367 self.ElementUsingTree = {} |
|
368 pous = self.getpous() |
|
369 # Reference all the user-defined elementu names and initialize the tree of |
|
370 # user-defined elemnt cross-use |
|
371 pounames = [pou.getname() for pou in pous] |
|
372 for name in pounames: |
|
373 self.ElementUsingTree[name] = [] |
|
374 # Analyze each pou |
|
375 for pou in pous: |
|
376 name = pou.getname() |
|
377 if pou.interface: |
|
378 # Extract variables from every varLists |
|
379 for type, varlist in pou.getvars(): |
|
380 for var in varlist.getvariable(): |
|
381 vartype_content = var.gettype().getcontent() |
|
382 if vartype_content["name"] == "derived": |
|
383 typename = vartype_content["value"].getname() |
|
384 if typename in pounames and name not in self.ElementUsingTree[typename]: |
|
385 self.ElementUsingTree[typename].append(name) |
|
386 setattr(cls, "RefreshElementUsingTree", RefreshElementUsingTree) |
|
387 |
|
388 def GetParentType(self, type): |
|
389 if type in self.CustomTypeHierarchy: |
|
390 return self.CustomTypeHierarchy[type] |
|
391 elif type in TypeHierarchy: |
|
392 return TypeHierarchy[type] |
|
393 return None |
|
394 setattr(cls, "GetParentType", GetParentType) |
|
395 |
|
396 def GetBaseType(self, type): |
|
397 parent_type = self.GetParentType(type) |
|
398 if parent_type is not None: |
|
399 if parent_type.startswith("ANY"): |
|
400 return type |
|
401 else: |
|
402 return self.GetBaseType(parent_type) |
|
403 return None |
|
404 setattr(cls, "GetBaseType", GetBaseType) |
|
405 |
|
406 def GetSubrangeBaseTypes(self, exclude): |
|
407 derived = [] |
|
408 for type in self.CustomTypeHierarchy.keys(): |
|
409 for base_type in DataTypeRange.keys(): |
|
410 if self.IsOfType(type, base_type) and not self.IsOfType(type, exclude): |
|
411 derived.append(type) |
|
412 break |
|
413 return DataTypeRange.keys() + derived |
|
414 setattr(cls, "GetSubrangeBaseTypes", GetSubrangeBaseTypes) |
|
415 |
|
416 """ |
|
417 returns true if the given data type is the same that "reference" meta-type or one of its types. |
|
418 """ |
|
419 def IsOfType(self, type, reference): |
|
420 if reference is None: |
|
421 return True |
|
422 elif type == reference: |
|
423 return True |
|
424 else: |
|
425 parent_type = self.GetParentType(type) |
|
426 if parent_type is not None: |
|
427 return self.IsOfType(parent_type, reference) |
|
428 return False |
|
429 setattr(cls, "IsOfType", IsOfType) |
|
430 |
|
431 # Return if pou given by name is used by another pou |
|
432 def ElementIsUsed(self, name): |
|
433 if name in self.ElementUsingTree: |
|
434 return len(self.ElementUsingTree[name]) > 0 |
|
435 return False |
|
436 setattr(cls, "ElementIsUsed", ElementIsUsed) |
|
437 |
|
438 def DataTypeIsDerived(self, name): |
|
439 return name in self.CustomTypeHierarchy.values() |
|
440 setattr(cls, "DataTypeIsDerived", DataTypeIsDerived) |
|
441 |
|
442 # Return if pou given by name is directly or undirectly used by the reference pou |
|
443 def ElementIsUsedBy(self, name, reference): |
|
444 if name in self.ElementUsingTree: |
|
445 list = self.ElementUsingTree[name] |
|
446 # Test if pou is directly used by reference |
|
447 if reference in list: |
|
448 return True |
|
449 else: |
|
450 # Test if pou is undirectly used by reference, by testing if pous |
|
451 # that directly use pou is directly or undirectly used by reference |
|
452 used = False |
|
453 for element in list: |
|
454 used |= self.ElementIsUsedBy(element, reference) |
|
455 return used |
|
456 return False |
|
457 setattr(cls, "ElementIsUsedBy", ElementIsUsedBy) |
|
458 |
|
459 def GetDataTypeRange(self, type): |
|
460 if type in self.CustomDataTypeRange: |
|
461 return self.CustomDataTypeRange[type] |
|
462 elif type in DataTypeRange: |
|
463 return DataTypeRange[type] |
|
464 else: |
|
465 parent_type = self.GetParentType(type) |
|
466 if parent_type is not None: |
|
467 return self.GetDataTypeRange(parent_type) |
|
468 return None |
|
469 setattr(cls, "GetDataTypeRange", GetDataTypeRange) |
|
470 |
|
471 def GetEnumeratedDataTypeValues(self, type = None): |
|
472 if type is None: |
|
473 all_values = [] |
|
474 for values in self.EnumeratedDataTypeValues.values(): |
|
475 all_values.extend(values) |
|
476 return all_values |
|
477 elif type in self.EnumeratedDataTypeValues: |
|
478 return self.EnumeratedDataTypeValues(type) |
|
479 return [] |
|
480 setattr(cls, "GetEnumeratedDataTypeValues", GetEnumeratedDataTypeValues) |
|
481 |
|
482 # Function that returns the block definition associated to the block type given |
|
483 def GetCustomBlockType(self, type, inputs = None): |
|
484 for customblocktype in self.CustomBlockTypes: |
|
485 if inputs: |
|
486 customblock_inputs = tuple([var_type for name, var_type, modifier in customblocktype["inputs"]]) |
|
487 same_inputs = inputs == customblock_inputs |
|
488 else: |
|
489 same_inputs = True |
|
490 if customblocktype["name"] == type and same_inputs: |
|
491 return customblocktype |
|
492 return None |
|
493 setattr(cls, "GetCustomBlockType", GetCustomBlockType) |
|
494 |
|
495 # Return Block types checking for recursion |
|
496 def GetCustomBlockTypes(self, exclude = ""): |
|
497 pou = self.getpou(exclude) |
|
498 type = pou.getpouType() |
|
499 customblocktypes = [] |
|
500 for customblocktype in self.CustomBlockTypes: |
|
501 if customblocktype["name"] != exclude and not self.ElementIsUsedBy(exclude, customblocktype["name"]) and not (type == "function" and customblocktype["type"] != "function"): |
|
502 customblocktypes.append(customblocktype) |
|
503 return customblocktypes |
|
504 setattr(cls, "GetCustomBlockTypes", GetCustomBlockTypes) |
|
505 |
|
506 # Return Function Block types checking for recursion |
|
507 def GetCustomFunctionBlockTypes(self, exclude = ""): |
|
508 pou = self.getpou(exclude) |
|
509 type = pou.getpouType() |
|
510 customblocktypes = [] |
|
511 for customblocktype in self.CustomBlockTypes: |
|
512 if customblocktype["name"] != exclude and not self.ElementIsUsedBy(exclude, customblocktype["name"]) and not (type == "function" and customblocktype["type"] != "function"): |
|
513 customblocktypes.appendcustom(customblocktype["name"]) |
|
514 return customblocktypes |
|
515 setattr(cls, "GetCustomFunctionBlockTypes", GetCustomFunctionBlockTypes) |
|
516 |
|
517 # Return Block types checking for recursion |
|
518 def GetCustomBlockResource(self): |
|
519 customblocktypes = [] |
|
520 for customblocktype in self.CustomBlockTypes: |
|
521 if customblocktype["type"] == "program": |
|
522 customblocktypes.append(customblocktype["name"]) |
|
523 return customblocktypes |
|
524 setattr(cls, "GetCustomBlockResource", GetCustomBlockResource) |
|
525 |
|
526 # Return Data Types checking for recursion |
|
527 def GetCustomDataTypes(self, exclude = ""): |
|
528 customdatatypes = [] |
|
529 for customdatatype in self.getdataTypes(): |
|
530 customdatatype_name = customdatatype.getname() |
|
531 if customdatatype_name != exclude and not self.ElementIsUsedBy(exclude, customdatatype_name): |
|
532 customdatatypes.append(customdatatype_name) |
|
533 return customdatatypes |
|
534 setattr(cls, "GetCustomDataTypes", GetCustomDataTypes) |
|
535 |
251 cls = PLCOpenClasses.get("project_fileHeader", None) |
536 cls = PLCOpenClasses.get("project_fileHeader", None) |
252 if cls: |
537 if cls: |
253 cls.singleLineAttributes = False |
538 cls.singleLineAttributes = False |
254 |
539 |
255 cls = PLCOpenClasses.get("project_contentHeader", None) |
540 cls = PLCOpenClasses.get("project_contentHeader", None) |