PLCControler.py
changeset 125 394d9f168258
parent 121 40b91ba978db
child 128 d16a8df4d322
equal deleted inserted replaced
124:635d0817508c 125:394d9f168258
    35 from PLCGenerator import *
    35 from PLCGenerator import *
    36 
    36 
    37 duration_model = re.compile("(?:([0-9]{1,2})h)?(?:([0-9]{1,2})m(?!s))?(?:([0-9]{1,2})s)?(?:([0-9]{1,3}(?:.[0-9]*)?)ms)?")
    37 duration_model = re.compile("(?:([0-9]{1,2})h)?(?:([0-9]{1,2})m(?!s))?(?:([0-9]{1,2})s)?(?:([0-9]{1,3}(?:.[0-9]*)?)ms)?")
    38 
    38 
    39 [ITEM_UNEDITABLE, ITEM_PROJECT, ITEM_POU, ITEM_CLASS, ITEM_VARIABLE,
    39 [ITEM_UNEDITABLE, ITEM_PROJECT, ITEM_POU, ITEM_CLASS, ITEM_VARIABLE,
    40  ITEM_TRANSITION, ITEM_ACTION, ITEM_CONFIGURATION, ITEM_RESOURCE] = range(9)
    40  ITEM_TRANSITION, ITEM_ACTION, ITEM_CONFIGURATION, ITEM_RESOURCE, 
       
    41  ITEM_DATATYPE] = range(10)
       
    42 
       
    43 ScriptDirectory = os.path.split(os.path.realpath(__file__))[0]
    41 
    44 
    42 """
    45 """
    43 pyxsval is not complete and the parts that are not supported print some error
    46 pyxsval is not complete and the parts that are not supported print some error
    44 reports. This class is used for not displaying them
    47 reports. This class is used for not displaying them
    45 """
    48 """
   165         self.ProjectBuffer = None
   168         self.ProjectBuffer = None
   166         self.Buffering = False
   169         self.Buffering = False
   167         self.FilePath = ""
   170         self.FilePath = ""
   168         self.FileName = ""
   171         self.FileName = ""
   169         self.ProgramFilePath = ""
   172         self.ProgramFilePath = ""
       
   173         self.RefreshDataTypeUsingTree()
       
   174         self.RefreshDataTypes()
   170         self.RefreshPouUsingTree()
   175         self.RefreshPouUsingTree()
   171         self.RefreshBlockTypes()
   176         self.RefreshBlockTypes()
   172 
   177 
   173     def GetQualifierTypes(self):
   178     def GetQualifierTypes(self):
   174         return plcopen.QualifierList
   179         return plcopen.QualifierList
   189         self.Project.setName(name)
   194         self.Project.setName(name)
   190         self.SetFilePath("")
   195         self.SetFilePath("")
   191         # Initialize the project buffer
   196         # Initialize the project buffer
   192         self.ProjectBuffer = UndoBuffer(self.Copy(self.Project), False)
   197         self.ProjectBuffer = UndoBuffer(self.Copy(self.Project), False)
   193         self.Buffering = False
   198         self.Buffering = False
       
   199     
       
   200     # Return project data type names
       
   201     def GetProjectDataTypeNames(self):
       
   202         if self.Project:
       
   203             return [datatype.getName() for datatype in self.Project.getDataTypes()]
       
   204         return []
   194     
   205     
   195     # Return project pou names
   206     # Return project pou names
   196     def GetProjectPouNames(self):
   207     def GetProjectPouNames(self):
   197         if self.Project:
   208         if self.Project:
   198             return [pou.getName() for pou in self.Project.getPous()]
   209             return [pou.getName() for pou in self.Project.getPous()]
   261     
   272     
   262     # Return project informations
   273     # Return project informations
   263     def GetProjectInfos(self):
   274     def GetProjectInfos(self):
   264         if self.Project:
   275         if self.Project:
   265             infos = {"name": self.Project.getName(), "type": ITEM_PROJECT}
   276             infos = {"name": self.Project.getName(), "type": ITEM_PROJECT}
       
   277             datatypes = {"name": "Data Types", "type": ITEM_UNEDITABLE, "values":[]}
       
   278             for datatype in self.Project.getDataTypes():
       
   279                 datatypes["values"].append({"name": datatype.getName(), "type": ITEM_DATATYPE, "values": []})
   266             pou_types = {"function": {"name": "Functions", "type": ITEM_UNEDITABLE, "values":[]},
   280             pou_types = {"function": {"name": "Functions", "type": ITEM_UNEDITABLE, "values":[]},
   267                          "functionBlock": {"name": "Function Blocks", "type": ITEM_UNEDITABLE, "values":[]},
   281                          "functionBlock": {"name": "Function Blocks", "type": ITEM_UNEDITABLE, "values":[]},
   268                          "program": {"name": "Programs", "type": ITEM_UNEDITABLE, "values":[]}}
   282                          "program": {"name": "Programs", "type": ITEM_UNEDITABLE, "values":[]}}
   269             for pou in self.Project.getPous():
   283             for pou in self.Project.getPous():
   270                 pou_type = pou.getPouType().getValue()
   284                 pou_type = pou.getPouType().getValue()
   292                     resource_infos = {"name": resource_name, "type": ITEM_RESOURCE, "values": []}
   306                     resource_infos = {"name": resource_name, "type": ITEM_RESOURCE, "values": []}
   293                     resources["values"].append(resource_infos)
   307                     resources["values"].append(resource_infos)
   294                 config_infos["values"] = [resources]
   308                 config_infos["values"] = [resources]
   295                 configurations["values"].append(config_infos)
   309                 configurations["values"].append(config_infos)
   296             infos["values"] = [{"name": "Properties", "type": ITEM_UNEDITABLE, "values": []},
   310             infos["values"] = [{"name": "Properties", "type": ITEM_UNEDITABLE, "values": []},
   297                                pou_types["function"], pou_types["functionBlock"], 
   311                                datatypes, pou_types["function"], pou_types["functionBlock"], 
   298                                pou_types["program"], configurations]
   312                                pou_types["program"], configurations]
   299             return infos
   313             return infos
   300         return None
   314         return None
   301 
   315 
       
   316     # Refresh the tree of user-defined data type cross-use
       
   317     def RefreshDataTypeUsingTree(self):
       
   318         # Reset the tree of user-defined pou cross-use
       
   319         self.DataTypeUsingTree = {}
       
   320         if self.Project:
       
   321             datatypes = self.Project.getDataTypes()
       
   322             # Reference all the user-defined data type names and initialize the tree of 
       
   323             # user-defined data type cross-use
       
   324             datatypenames = [datatype.getName() for datatype in datatypes]
       
   325             for name in datatypenames:
       
   326                 self.DataTypeUsingTree[name] = []
       
   327             # Analyze each data type
       
   328             for datatype in datatypes:
       
   329                 name = datatype.getName()
       
   330                 basetype_content = datatype.getBaseType().getContent()
       
   331                 if basetype_content["value"] is not None:
       
   332                     if basetype_content["name"] == "derived":
       
   333                         basetype_name = basetype_content["value"].getName()
       
   334                         if basetype_name in datatypenames and name not in self.DataTypeUsingTree[basetype_name]:
       
   335                             self.DataTypeUsingTree[basetype_name].append(name)
       
   336                     elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned", "array"]:
       
   337                         base_type = basetype_content["value"].baseType.getContent()
       
   338                         if base_type["value"] is not None:
       
   339                             basetype_name = base_type["value"].getName()
       
   340                             if basetype_name in datatypenames and name not in self.DataTypeUsingTree[basetype_name]:
       
   341                                 self.DataTypeUsingTree[basetype_name].append(name)
       
   342     
   302     # Refresh the tree of user-defined pou cross-use
   343     # Refresh the tree of user-defined pou cross-use
   303     def RefreshPouUsingTree(self):
   344     def RefreshPouUsingTree(self):
   304         # Reset the tree of user-defined pou cross-use
   345         # Reset the tree of user-defined pou cross-use
   305         self.PouUsingTree = {}
   346         self.PouUsingTree = {}
   306         if self.Project:
   347         if self.Project:
   315                 name = pou.getName()
   356                 name = pou.getName()
   316                 if pou.interface:
   357                 if pou.interface:
   317                     # Extract variables from every varLists
   358                     # Extract variables from every varLists
   318                     for type, varlist in pou.getVars():
   359                     for type, varlist in pou.getVars():
   319                         for var in varlist.getVariable():
   360                         for var in varlist.getVariable():
   320                             var_type = var.getType().getValue()
   361                             vartype_content = var.getType().getContent()
   321                             if not isinstance(var_type, (StringType, UnicodeType)):
   362                             if vartype_content["value"] is not None:
   322                                 typename = var_type.getName()
   363                                 typename = vartype_content["value"].getName()
   323                                 if typename in pounames and name not in self.PouUsingTree[typename]:
   364                                 if typename in pounames and name not in self.PouUsingTree[typename]:
   324                                     self.PouUsingTree[typename].append(name)
   365                                     self.PouUsingTree[typename].append(name)
   325                 bodytype = pou.getBodyType()
   366                 bodytype = pou.getBodyType()
   326                 # If pou is written in a graphical language
   367                 # If pou is written in a graphical language
   327                 if bodytype in ["FBD","LD","SFC"]:
   368                 if bodytype in ["FBD","LD","SFC"]:
   340                         typename_model = re.compile("[ \t\n]%s[ \t\n]"%typename)
   381                         typename_model = re.compile("[ \t\n]%s[ \t\n]"%typename)
   341                         # Update tree if there is a cross-use
   382                         # Update tree if there is a cross-use
   342                         if typename != name and typename_model.search(text):
   383                         if typename != name and typename_model.search(text):
   343                             self.PouUsingTree[typename].append(name)
   384                             self.PouUsingTree[typename].append(name)
   344 
   385 
       
   386     # Return if data type given by name is used by another data type or pou
       
   387     def DataTypeIsUsed(self, name):
       
   388         if name in self.DataTypeUsingTree:
       
   389             return len(self.DataTypeUsingTree[name]) > 0
       
   390         return False
       
   391 
   345     # Return if pou given by name is used by another pou
   392     # Return if pou given by name is used by another pou
   346     def PouIsUsed(self, name):
   393     def PouIsUsed(self, name):
   347         if name in self.PouUsingTree:
   394         if name in self.PouUsingTree:
   348             return len(self.PouUsingTree[name]) > 0
   395             return len(self.PouUsingTree[name]) > 0
       
   396         return False
       
   397 
       
   398     # Return if data type given by name is directly or undirectly used by the reference data type
       
   399     def DataTypeIsUsedBy(self, name, reference):
       
   400         if name in self.DataTypeUsingTree:
       
   401             list = self.DataTypeUsingTree[name]
       
   402             # Test if data type is directly used by reference
       
   403             if reference in list:
       
   404                 return True
       
   405             else:
       
   406                 # Test if data type is undirectly used by reference, by testing if data types 
       
   407                 # that directly use data type is directly or undirectly used by reference
       
   408                 used = False
       
   409                 for element in list:
       
   410                     used |= self.DataTypeIsUsedBy(element, reference)
       
   411                 return used
   349         return False
   412         return False
   350 
   413 
   351     # Return if pou given by name is directly or undirectly used by the reference pou
   414     # Return if pou given by name is directly or undirectly used by the reference pou
   352     def PouIsUsedBy(self, name, reference):
   415     def PouIsUsedBy(self, name, reference):
   353         if name in self.PouUsingTree:
   416         if name in self.PouUsingTree:
   378         return False
   441         return False
   379 
   442 
   380 #-------------------------------------------------------------------------------
   443 #-------------------------------------------------------------------------------
   381 #                        Project Pous management functions
   444 #                        Project Pous management functions
   382 #-------------------------------------------------------------------------------
   445 #-------------------------------------------------------------------------------
   383         
   446     
       
   447     # Add a Data Type to Project
       
   448     def ProjectAddDataType(self, datatype_name):
       
   449         # Add the pou to project
       
   450         self.Project.appendDataType(datatype_name)
       
   451         self.RefreshDataTypeUsingTree()
       
   452         self.RefreshDataTypes()
       
   453         self.BufferProject()
       
   454     
       
   455     # Remove a Data Type from project
       
   456     def ProjectRemoveDataType(self, datatype_name):
       
   457         self.Project.removeDataType(datatype_name)
       
   458         self.RefreshDataTypeUsingTree()
       
   459         self.RefreshDataTypes()
       
   460         self.BufferProject()
       
   461     
   384     # Add a Pou to Project
   462     # Add a Pou to Project
   385     def ProjectAddPou(self, pou_name, pou_type, body_type):
   463     def ProjectAddPou(self, pou_name, pou_type, body_type):
   386         # Add the pou to project
   464         # Add the pou to project
   387         self.Project.appendPou(pou_name, pou_type, body_type)
   465         self.Project.appendPou(pou_name, pou_type, body_type)
   388         if pou_type == "function":
   466         if pou_type == "function":
   389             self.SetPouInterfaceReturnType(pou_name, "BOOL")
   467             self.SetPouInterfaceReturnType(pou_name, "BOOL")
   390         self.RefreshPouUsingTree()
   468         self.RefreshPouUsingTree()
   391         self.RefreshBlockTypes()
   469         self.RefreshBlockTypes()
   392         self.BufferProject()
   470         self.BufferProject()
   393     
   471     
   394     # Remove a pou from project
   472     # Remove a Pou from project
   395     def ProjectRemovePou(self, pou_name):
   473     def ProjectRemovePou(self, pou_name):
   396         self.Project.removePou(pou_name)
   474         self.Project.removePou(pou_name)
   397         self.RefreshPouUsingTree()
   475         self.RefreshPouUsingTree()
   398         self.RefreshBlockTypes()
   476         self.RefreshBlockTypes()
   399         self.BufferProject()
   477         self.BufferProject()
   400     
   478     
   401     # Add a configuration to Project
   479     # Add a configuration to Project
   402     def ProjectAddConfiguration(self, config_name):
   480     def ProjectAddConfiguration(self, config_name):
   403         self.Project.addConfiguration(config_name)
   481         self.Project.addConfiguration(config_name)
   404         self.RefreshPouUsingTree()
       
   405         self.RefreshBlockTypes()
       
   406         self.BufferProject()
   482         self.BufferProject()
   407     
   483     
   408     # Remove a configuration from project
   484     # Remove a configuration from project
   409     def ProjectRemoveConfiguration(self, config_name):
   485     def ProjectRemoveConfiguration(self, config_name):
   410         self.Project.removeConfiguration(config_name)
   486         self.Project.removeConfiguration(config_name)
   411         self.BufferProject()
   487         self.BufferProject()
   412     
   488     
   413     # Add a resource to a configuration of the Project
   489     # Add a resource to a configuration of the Project
   414     def ProjectAddConfigurationResource(self, config_name, resource_name):
   490     def ProjectAddConfigurationResource(self, config_name, resource_name):
   415         self.Project.addConfigurationResource(config_name, resource_name)
   491         self.Project.addConfigurationResource(config_name, resource_name)
   416         self.RefreshPouUsingTree()
       
   417         self.RefreshBlockTypes()
       
   418         self.BufferProject()
   492         self.BufferProject()
   419     
   493     
   420     # Remove a resource from a configuration of the project
   494     # Remove a resource from a configuration of the project
   421     def ProjectRemoveConfigurationResource(self, config_name, resource_name):
   495     def ProjectRemoveConfigurationResource(self, config_name, resource_name):
   422         self.Project.removeConfigurationResource(config_name, resource_name)
   496         self.Project.removeConfigurationResource(config_name, resource_name)
   448             if words[0] == "A" and words[1] == pou_name and words[2] == action_name:
   522             if words[0] == "A" and words[1] == pou_name and words[2] == action_name:
   449                 self.RemoveElementEditing(i)
   523                 self.RemoveElementEditing(i)
   450         pou = self.Project.getPou(pou_name)
   524         pou = self.Project.getPou(pou_name)
   451         pou.removeAction(action_name)
   525         pou.removeAction(action_name)
   452         self.BufferProject()
   526         self.BufferProject()
   453         
   527     
       
   528     # Change the name of a pou
       
   529     def ChangeDataTypeName(self, old_name, new_name):
       
   530         # Found the pou corresponding to old name and change its name to new name
       
   531         datatype = self.Project.getDataType(old_name)
       
   532         datatype.setName(new_name)
       
   533         self.Project.updateElementName(old_name, new_name)
       
   534         self.BufferProject()
       
   535     
   454     # Change the name of a pou
   536     # Change the name of a pou
   455     def ChangePouName(self, old_name, new_name):
   537     def ChangePouName(self, old_name, new_name):
   456         # Found the pou corresponding to old name and change its name to new name
   538         # Found the pou corresponding to old name and change its name to new name
   457         pou = self.Project.getPou(old_name)
   539         pou = self.Project.getPou(old_name)
   458         pou.setName(new_name)
   540         pou.setName(new_name)
   573                     varlist.setConstant(True)
   655                     varlist.setConstant(True)
   574             # Create variable and change its properties
   656             # Create variable and change its properties
   575             tempvar = plcopen.varListPlain_variable()
   657             tempvar = plcopen.varListPlain_variable()
   576             tempvar.setName(var["Name"])
   658             tempvar.setName(var["Name"])
   577             var_type = plcopen.dataType()
   659             var_type = plcopen.dataType()
   578             if GetBlockType(var["Type"]) != None:
   660             if var["Type"] not in var_type.getChoices():
   579                 derived_type = plcopen.derived()
   661                 derived_type = plcopen.derived()
   580                 derived_type.setName(var["Type"])
   662                 derived_type.setName(var["Type"])
   581                 var_type.setValue(derived_type)
   663                 var_type.setContent("derived", derived_type)
   582             else:
   664             else:
   583                 var_type.setValue(var["Type"])
   665                 var_type.setContent(var["Type"], None)
   584             tempvar.setType(var_type)
   666             tempvar.setType(var_type)
   585             if var["Initial Value"] != "":
   667             if var["Initial Value"] != "":
   586                 value = plcopen.value()
   668                 value = plcopen.value()
   587                 value.setValue(var["Initial Value"])
   669                 value.setValue(var["Initial Value"])
   588                 tempvar.setInitialValue(value)
   670                 tempvar.setInitialValue(value)
   613         if configuration:
   695         if configuration:
   614             # Extract variables from every varLists
   696             # Extract variables from every varLists
   615             for varlist in configuration.getGlobalVars():
   697             for varlist in configuration.getGlobalVars():
   616                 for var in varlist.getVariable():
   698                 for var in varlist.getVariable():
   617                     tempvar = {"Name":var.getName(),"Class":"Global"}
   699                     tempvar = {"Name":var.getName(),"Class":"Global"}
   618                     var_type = var.getType().getValue()
   700                     vartype_content = var.getType().getContent()
   619                     if isinstance(var_type, (StringType, UnicodeType)):
   701                     if vartype_content["value"] is None:
   620                         tempvar["Type"] = var_type
   702                         tempvar["Type"] = vartype_content["name"]
   621                     else:
   703                     else:
   622                         tempvar["Type"] = var_type.getName()
   704                         tempvar["Type"] = vartype_content["value"].getName()
   623                     tempvar["Edit"] = True
   705                     tempvar["Edit"] = True
   624                     initial = var.getInitialValue()
   706                     initial = var.getInitialValue()
   625                     if initial:
   707                     if initial:
   626                         tempvar["Initial Value"] = initial.getValue()
   708                         tempvar["Initial Value"] = initial.getValue()
   627                     else:
   709                     else:
   661         if resource:
   743         if resource:
   662             # Extract variables from every varLists
   744             # Extract variables from every varLists
   663             for varlist in resource.getGlobalVars():
   745             for varlist in resource.getGlobalVars():
   664                 for var in varlist.getVariable():
   746                 for var in varlist.getVariable():
   665                     tempvar = {"Name":var.getName(),"Class":"Global"}
   747                     tempvar = {"Name":var.getName(),"Class":"Global"}
   666                     var_type = var.getType().getValue()
   748                     vartype_content = var.getType().getContent()
   667                     if isinstance(var_type, (StringType, UnicodeType)):
   749                     if vartype_content["value"] is None:
   668                         tempvar["Type"] = var_type
   750                         tempvar["Type"] = vartype_content["name"]
   669                     else:
   751                     else:
   670                         tempvar["Type"] = var_type.getName()
   752                         tempvar["Type"] = vartype_content["value"].getName()
   671                     tempvar["Edit"] = True
   753                     tempvar["Edit"] = True
   672                     initial = var.getInitialValue()
   754                     initial = var.getInitialValue()
   673                     if initial:
   755                     if initial:
   674                         tempvar["Initial Value"] = initial.getValue()
   756                         tempvar["Initial Value"] = initial.getValue()
   675                     else:
   757                     else:
   702         if pou.interface:
   784         if pou.interface:
   703             # Extract variables from every varLists
   785             # Extract variables from every varLists
   704             for type, varlist in pou.getVars():
   786             for type, varlist in pou.getVars():
   705                 for var in varlist.getVariable():
   787                 for var in varlist.getVariable():
   706                     tempvar = {"Name":var.getName(),"Class":type}
   788                     tempvar = {"Name":var.getName(),"Class":type}
   707                     var_type = var.getType().getValue()
   789                     vartype_content = var.getType().getContent()
   708                     if isinstance(var_type, (StringType, UnicodeType)):
   790                     if vartype_content["value"] is None:
   709                         tempvar["Type"] = var_type
   791                         tempvar["Type"] = vartype_content["name"]
   710                         tempvar["Edit"] = True
   792                         tempvar["Edit"] = True
   711                     else:
   793                     else:
   712                         tempvar["Type"] = var_type.getName()
   794                         tempvar["Type"] = vartype_content["value"].getName()
   713                         tempvar["Edit"] = not pou.hasBlock(tempvar["Name"])
   795                         tempvar["Edit"] = not pou.hasBlock(tempvar["Name"])
   714                     initial = var.getInitialValue()
   796                     initial = var.getInitialValue()
   715                     if initial:
   797                     if initial:
   716                         tempvar["Initial Value"] = initial.getValue()
   798                         tempvar["Initial Value"] = initial.getValue()
   717                     else:
   799                     else:
   752         return_type = pou.interface.getReturnType()
   834         return_type = pou.interface.getReturnType()
   753         if not return_type:
   835         if not return_type:
   754             return_type = plcopen.dataType()
   836             return_type = plcopen.dataType()
   755             pou.interface.setReturnType(return_type)
   837             pou.interface.setReturnType(return_type)
   756         # Change return type
   838         # Change return type
   757         return_type.setValue(type)
   839         if type in self.GetBaseTypes():
       
   840             return_type.setContent(type, None)
       
   841         else:
       
   842             derived_type = plcopen.derived()
       
   843             derived_type.setName(type)
       
   844             return_type.setContent("derived", derived_type)
   758         self.RefreshBlockTypes()
   845         self.RefreshBlockTypes()
   759     
   846     
   760     def UpdateProjectUsedPous(self, old_name, new_name):
   847     def UpdateProjectUsedPous(self, old_name, new_name):
   761         if self.Project:
   848         if self.Project:
   762             self.Project.updateElementName(old_name, new_name)
   849             self.Project.updateElementName(old_name, new_name)
   776         # Verify that the pou has an interface
   863         # Verify that the pou has an interface
   777         if pou.interface:
   864         if pou.interface:
   778             # Return the return type if there is one
   865             # Return the return type if there is one
   779             return_type = pou.interface.getReturnType()
   866             return_type = pou.interface.getReturnType()
   780             if return_type:
   867             if return_type:
   781                 return return_type.getValue()
   868                 returntype_content = return_type.getContent()
       
   869                 if returntype_content["value"] is None:
       
   870                     return returntype_content["name"]
       
   871                 else:
       
   872                     return returntype_content["value"].getName()
   782         return None
   873         return None
   783 
   874     
       
   875     # Update data types with user-defined data types added
       
   876     def RefreshDataTypes(self):
       
   877         ResetTypeHierarchy()
       
   878         ResetEnumeratedDataValues()
       
   879         if self.Project:
       
   880             for datatype in self.Project.getDataTypes():
       
   881                 name = datatype.getName()
       
   882                 basetype_content = datatype.getBaseType().getContent()
       
   883                 if basetype_content["value"] is None:
       
   884                     AddDataTypeHierarchy(name, basetype_content["name"])
       
   885                 elif basetype_content["name"] == "derived":
       
   886                     AddDataTypeHierarchy(name, basetype_content["value"].getName())
       
   887                 elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned"]:
       
   888                     base_type = basetype_content["value"].baseType.getContent()
       
   889                     if base_type["value"] is None:
       
   890                         AddDataTypeHierarchy(name, base_type["name"])
       
   891                     else:
       
   892                         AddDataTypeHierarchy(name, base_type["value"].getName())
       
   893                 else:
       
   894                     if basetype_content["name"] == "enum":
       
   895                         values = []
       
   896                         for value in basetype_content["value"].values.getValue():
       
   897                             values.append(value.getName())
       
   898                         AddEnumeratedDataValues(values)
       
   899                     AddDataTypeHierarchy(name, "ANY_DERIVED")
       
   900     
   784     # Update Block types with user-defined pou added
   901     # Update Block types with user-defined pou added
   785     def RefreshBlockTypes(self):
   902     def RefreshBlockTypes(self):
   786         if BlockTypes[-1]["name"] == "User-defined POUs":
   903         if BlockTypes[-1]["name"] == "User-defined POUs":
   787             BlockTypes[-1]["list"] = []
   904             BlockTypes[-1]["list"] = []
   788         else:
   905         else:
   797                                    "generate" : generate_block, "initialise" : initialise_block }
   914                                    "generate" : generate_block, "initialise" : initialise_block }
   798                     if pou.getInterface():
   915                     if pou.getInterface():
   799                         for type, varlist in pou.getVars():
   916                         for type, varlist in pou.getVars():
   800                             if type == "InOut":
   917                             if type == "InOut":
   801                                 for var in varlist.getVariable():
   918                                 for var in varlist.getVariable():
   802                                     block_infos["inputs"].append((var.getName(),var.getType().getValue(),"none"))
   919                                     var_type = var.type.getContent()
   803                                     block_infos["outputs"].append((var.getName(),var.getType().getValue(),"none"))
   920                                     if var_type["value"] is None:
       
   921                                         block_infos["inputs"].append((var.getName(),var_type["name"],"none"))
       
   922                                         block_infos["outputs"].append((var.getName(),var_type["name"],"none"))
       
   923                                     else:
       
   924                                         block_infos["inputs"].append((var.getName(),var_type["value"].getName(),"none"))
       
   925                                         block_infos["outputs"].append((var.getName(),var_type["value"].getName(),"none"))
   804                             elif type == "Input":
   926                             elif type == "Input":
   805                                 for var in varlist.getVariable():
   927                                 for var in varlist.getVariable():
   806                                     block_infos["inputs"].append((var.getName(),var.getType().getValue(),"none"))
   928                                     var_type = var.type.getContent()
       
   929                                     if var_type["value"] is None:
       
   930                                         block_infos["inputs"].append((var.getName(),var_type["name"],"none"))
       
   931                                     else:
       
   932                                         block_infos["inputs"].append((var.getName(),var_type["value"].getName(),"none"))
   807                             elif type == "Output":
   933                             elif type == "Output":
   808                                 for var in varlist.getVariable():
   934                                 for var in varlist.getVariable():
   809                                     block_infos["outputs"].append((var.getName(),var.getType().getValue(),"none"))
   935                                     var_type = var.type.getContent()
       
   936                                     if var_type["value"] is None:
       
   937                                         block_infos["outputs"].append((var.getName(),var_type["name"],"none"))
       
   938                                     else:
       
   939                                         block_infos["outputs"].append((var.getName(),var_type["value"].getName(),"none"))
   810                         return_type = pou.interface.getReturnType()
   940                         return_type = pou.interface.getReturnType()
   811                         if return_type:
   941                         if return_type:
   812                             block_infos["outputs"].append(("",return_type.getValue(),"none"))
   942                             var_type = return_type.getContent()
       
   943                             if var_type["value"] is None:
       
   944                                 block_infos["outputs"].append(("",var_type["name"],"none"))
       
   945                             else:
       
   946                                 block_infos["outputs"].append(("",var_type["value"].getName(),"none"))
   813                     if pou.getBodyType() in ["FBD","LD","SFC"]:
   947                     if pou.getBodyType() in ["FBD","LD","SFC"]:
   814                         for instance in pou.getInstances():
   948                         for instance in pou.getInstances():
   815                             if isinstance(instance, plcopen.comment):
   949                             if isinstance(instance, plcopen.comment):
   816                                 block_infos["comment"] = instance.getContentText()
   950                                 block_infos["comment"] = instance.getContentText()
   817                     BlockTypes[-1]["list"].append(block_infos)
   951                     BlockTypes[-1]["list"].append(block_infos)
   818     
   952     
   819     # Return Block types checking for recursion
   953     # Return Block types checking for recursion
   820     def GetBlockTypes(self, tagname = ""):
   954     def GetBlockTypes(self, tagname = ""):
       
   955         name = ""
       
   956         type = None
   821         if self.Project:
   957         if self.Project:
   822             words = tagname.split("::")
   958             words = tagname.split("::")
   823             if len(words) == 1:
   959             if words[0] in ["P","T","A"]:
   824                 name = current_name
       
   825             else:
       
   826                 name = words[1]
   960                 name = words[1]
   827             type = self.GetPouType(name)
   961                 type = self.GetPouType(name)
   828         else:
       
   829             name = ""
       
   830             type = None
       
   831         if type == "function":
   962         if type == "function":
   832             blocktypes = []
   963             blocktypes = []
   833             for category in BlockTypes[:-1] + PluginTypes:
   964             for category in BlockTypes[:-1] + PluginTypes:
   834                 cat = {"name" : category["name"], "list" : []}
   965                 cat = {"name" : category["name"], "list" : []}
   835                 for block in category["list"]:
   966                 for block in category["list"]:
   851         name = ""
   982         name = ""
   852         type = None
   983         type = None
   853         if self.Project:
   984         if self.Project:
   854             words = tagname.split("::")
   985             words = tagname.split("::")
   855             if words[0] in ["P","T","A"]:
   986             if words[0] in ["P","T","A"]:
   856                 if len(words) == 1:
   987                 name = words[1]
   857                     name = current_name
       
   858                 else:
       
   859                     name = words[1]
       
   860                 type = self.GetPouType(name)
   988                 type = self.GetPouType(name)
   861         blocktypes = []
   989         blocktypes = []
   862         for category in BlockTypes[:-1]:
   990         for category in BlockTypes[:-1]:
   863             for block in category["list"]:
   991             for block in category["list"]:
   864                 if block["type"] != "function":
   992                 if block["type"] != "function":
   880             for pou in self.Project.getPous():
  1008             for pou in self.Project.getPous():
   881                 if pou.pouType.getValue() == "program":
  1009                 if pou.pouType.getValue() == "program":
   882                     blocktypes.append(pou.getName())
  1010                     blocktypes.append(pou.getName())
   883         return blocktypes
  1011         return blocktypes
   884 
  1012 
       
  1013     # Return Data Types checking for recursion
       
  1014     def GetDataTypes(self, tagname = "", basetypes = True):
       
  1015         if basetypes:
       
  1016             datatypes = self.GetBaseTypes()
       
  1017         else:
       
  1018             datatypes = []
       
  1019         if self.Project:
       
  1020             words = tagname.split("::")
       
  1021             if words[0] in ["D"]:
       
  1022                 name = words[1]
       
  1023             else:
       
  1024                 name = ""
       
  1025             for datatype in self.Project.getDataTypes():
       
  1026                 datatype_name = datatype.getName()
       
  1027                 if datatype_name != name and not self.DataTypeIsUsedBy(name, datatype_name):
       
  1028                     datatypes.append(datatype_name)
       
  1029         return datatypes
       
  1030 
       
  1031     # Return Base Types
       
  1032     def GetBaseTypes(self):
       
  1033         return [value for value, parent in TypeHierarchy_list if not value.startswith("ANY")]
       
  1034 
       
  1035     # Return Subrange types
       
  1036     def GetSubrangeTypes(self):
       
  1037         return [value for value, range in DataTypeRange_list]
       
  1038 
       
  1039     # Return Enumerated Values
       
  1040     def GetEnumeratedDataValues(self):
       
  1041         return EnumeratedDataValues
       
  1042 
   885 #-------------------------------------------------------------------------------
  1043 #-------------------------------------------------------------------------------
   886 #                   Project Element tag name computation functions
  1044 #                   Project Element tag name computation functions
   887 #-------------------------------------------------------------------------------
  1045 #-------------------------------------------------------------------------------
   888     
  1046     
   889     # Compute a pou transition name
  1047     # Compute a data type name
       
  1048     def ComputeDataTypeName(self, datatype):
       
  1049         return "D::%s" % datatype
       
  1050     
       
  1051     # Compute a pou name
   890     def ComputePouName(self, pou):
  1052     def ComputePouName(self, pou):
   891         return "P::%s" % pou
  1053         return "P::%s" % pou
   892     
  1054     
   893     # Compute a pou transition name
  1055     # Compute a pou transition name
   894     def ComputePouTransitionName(self, pou, transition):
  1056     def ComputePouTransitionName(self, pou, transition):
   903         return "C::%s" % config
  1065         return "C::%s" % config
   904 
  1066 
   905     # Compute a pou  name
  1067     # Compute a pou  name
   906     def ComputeConfigurationResourceName(self, config, resource):
  1068     def ComputeConfigurationResourceName(self, config, resource):
   907         return "R::%s::%s" % (config, resource)
  1069         return "R::%s::%s" % (config, resource)
       
  1070 
       
  1071 #-------------------------------------------------------------------------------
       
  1072 #                    Project opened Data types management functions
       
  1073 #-------------------------------------------------------------------------------
       
  1074 
       
  1075     # Return the data type informations
       
  1076     def GetDataTypeInfos(self, tagname):
       
  1077         words = tagname.split("::")
       
  1078         if words[0] == "D":
       
  1079             infos = {}
       
  1080             datatype = self.Project.getDataType(words[1])
       
  1081             basetype_content = datatype.baseType.getContent()
       
  1082             if basetype_content["value"] is None:
       
  1083                 infos["type"] = "Directly"
       
  1084                 infos["base_type"] = basetype_content["name"]
       
  1085             elif basetype_content["name"] == "derived":
       
  1086                 infos["type"] = "Directly"
       
  1087                 infos["base_type"] = basetype_content["value"].getName()
       
  1088             elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned"]:
       
  1089                 infos["type"] = "Subrange"
       
  1090                 infos["min"] = basetype_content["value"].range.getLower()
       
  1091                 infos["max"] = basetype_content["value"].range.getUpper()
       
  1092                 base_type = basetype_content["value"].baseType.getContent()
       
  1093                 if base_type["value"] is None:
       
  1094                     infos["base_type"] = base_type["name"]
       
  1095                 else:
       
  1096                     infos["base_type"] = base_type["value"].getName()
       
  1097             elif basetype_content["name"] == "enum":
       
  1098                 infos["type"] = "Enumerated"
       
  1099                 infos["values"] = []
       
  1100                 for value in basetype_content["value"].values.getValue():
       
  1101                     infos["values"].append(value.getName())
       
  1102             elif basetype_content["name"] == "array":
       
  1103                 infos["type"] = "Array"
       
  1104                 infos["dimensions"] = []
       
  1105                 for dimension in basetype_content["value"].getDimension():
       
  1106                     infos["dimensions"].append(str(dimension.getUpper()))
       
  1107                 base_type = basetype_content["value"].baseType.getContent()
       
  1108                 if base_type["value"] is None:
       
  1109                     infos["base_type"] = base_type["name"]
       
  1110                 else:
       
  1111                     infos["base_type"] = base_type["value"].getName()
       
  1112             if datatype.initialValue is not None:
       
  1113                 infos["initial"] = str(datatype.initialValue.getValue())
       
  1114             else:
       
  1115                 infos["initial"] = ""
       
  1116             return infos
       
  1117         return None
       
  1118     
       
  1119     # Change the data type informations
       
  1120     def SetDataTypeInfos(self, tagname, infos):
       
  1121         words = tagname.split("::")
       
  1122         if words[0] == "D":
       
  1123             datatype = self.Project.getDataType(words[1])
       
  1124             if infos["type"] == "Directly":
       
  1125                 if infos["base_type"] in self.GetBaseTypes():
       
  1126                     datatype.baseType.setContent(infos["base_type"], None)
       
  1127                 else:
       
  1128                     derived_datatype = plcopen.derived()
       
  1129                     derived_datatype.setName(infos["base_type"])
       
  1130                     datatype.baseType.setContent("derived", derived_datatype)
       
  1131             elif infos["type"] == "Subrange":
       
  1132                 if infos["base_type"] in GetSubTypes("ANY_UINT"):
       
  1133                     subrange = plcopen.subrangeUnsigned()
       
  1134                     datatype.baseType.setContent("subrangeUnsigned", subrange)
       
  1135                 else:
       
  1136                     subrange = plcopen.subrangeSigned()
       
  1137                     datatype.baseType.setContent("subrangeSigned", subrange)
       
  1138                 subrange.range.setLower(infos["min"])
       
  1139                 subrange.range.setUpper(infos["max"])
       
  1140                 if infos["base_type"] in self.GetBaseTypes():
       
  1141                     subrange.baseType.setContent(infos["base_type"], None)
       
  1142                 else:
       
  1143                     derived_datatype = plcopen.derived()
       
  1144                     derived_datatype.setName(infos["base_type"])
       
  1145                     subrange.baseType.setContent("derived", derived_datatype)
       
  1146             elif infos["type"] == "Enumerated":
       
  1147                 enumerated = plcopen.enum()
       
  1148                 for enum_value in infos["values"]:
       
  1149                     value = plcopen.values_value()
       
  1150                     value.setName(enum_value)
       
  1151                     enumerated.values.appendValue(value)
       
  1152                 datatype.baseType.setContent("enum", enumerated)
       
  1153             elif infos["type"] == "Array":
       
  1154                 array = plcopen.array()
       
  1155                 for dimension in infos["dimensions"]:
       
  1156                     dimension_range = plcopen.rangeSigned()
       
  1157                     dimension_range.setLower(1)
       
  1158                     dimension_range.setUpper(int(dimension))
       
  1159                     array.appendDimension(dimension_range)
       
  1160                 if infos["base_type"] in self.GetBaseTypes():
       
  1161                     array.baseType.setContent(infos["base_type"], None)
       
  1162                 else:
       
  1163                     derived_datatype = plcopen.derived()
       
  1164                     derived_datatype.setName(infos["base_type"])
       
  1165                     array.baseType.setContent("derived", derived_datatype)
       
  1166                 datatype.baseType.setContent("array", array)
       
  1167             if infos["initial"] != "":
       
  1168                 if datatype.initialValue is None:
       
  1169                     datatype.initialValue = plcopen.value()
       
  1170                 datatype.initialValue.setValue(infos["initial"])
       
  1171             else:
       
  1172                 datatype.initialValue = None
       
  1173             self.RefreshDataTypeUsingTree()
       
  1174             self.RefreshDataTypes()
       
  1175             self.BufferProject()
   908     
  1176     
   909 #-------------------------------------------------------------------------------
  1177 #-------------------------------------------------------------------------------
   910 #                       Project opened Pous management functions
  1178 #                       Project opened Pous management functions
   911 #-------------------------------------------------------------------------------
  1179 #-------------------------------------------------------------------------------
   912 
  1180 
   970             return self.GetPouInterfaceReturnType(pou)
  1238             return self.GetPouInterfaceReturnType(pou)
   971         elif words[0] == 'T':
  1239         elif words[0] == 'T':
   972             return "BOOL"
  1240             return "BOOL"
   973         return None
  1241         return None
   974     
  1242     
   975     # Change the edited element taxt
  1243     # Change the edited element text
   976     def SetEditedElementText(self, tagname, text):
  1244     def SetEditedElementText(self, tagname, text):
   977         element = self.GetEditedElement(tagname)
  1245         element = self.GetEditedElement(tagname)
   978         if element != None:
  1246         if element != None:
   979             element.setText(text)
  1247             element.setText(text)
   980             self.RefreshPouUsingTree()
  1248             self.RefreshPouUsingTree()
  1329         if words[0] in ["P","T","A"]:
  1597         if words[0] in ["P","T","A"]:
  1330             pou = self.Project.getPou(words[1])
  1598             pou = self.Project.getPou(words[1])
  1331             for type, varlist in pou.getVars():
  1599             for type, varlist in pou.getVars():
  1332                 for var in varlist.getVariable():
  1600                 for var in varlist.getVariable():
  1333                     if var.getName() == varname:
  1601                     if var.getName() == varname:
  1334                         return var.getType().getValue()
  1602                         vartype_content = var.getType().getContent()
       
  1603                         if vartype_content["value"] is None:
       
  1604                             return vartype_content["name"]
       
  1605                         else:
       
  1606                             return vartype_content["value"].getName()
  1335         return None
  1607         return None
  1336     
  1608     
  1337     def SetConnectionWires(self, connection, connector):
  1609     def SetConnectionWires(self, connection, connector):
  1338         wires = connector.GetWires()
  1610         wires = connector.GetWires()
  1339         idx = 0
  1611         idx = 0
  1996 
  2268 
  1997     def OpenXMLFile(self, filepath):
  2269     def OpenXMLFile(self, filepath):
  1998         if self.VerifyXML:
  2270         if self.VerifyXML:
  1999             if sys:
  2271             if sys:
  2000                 sys.stdout = HolePseudoFile()
  2272                 sys.stdout = HolePseudoFile()
  2001             result = pyxsval.parseAndValidate(filepath, os.path.join(sys.path[0], "plcopen/TC6_XML_V10_B.xsd"))
  2273             result = pyxsval.parseAndValidate(filepath, os.path.join(ScriptDirectory, "plcopen", "TC6_XML_V10_B.xsd"))
  2002             if sys:
  2274             if sys:
  2003                 sys.stdout = sys.__stdout__
  2275                 sys.stdout = sys.__stdout__
  2004             tree = result.getTree()
  2276             tree = result.getTree()
  2005         else:
  2277         else:
  2006             xmlfile = open(filepath, 'r')
  2278             xmlfile = open(filepath, 'r')
  2014                 self.SetFilePath(filepath)
  2286                 self.SetFilePath(filepath)
  2015                 self.ProjectBuffer = UndoBuffer(self.Copy(self.Project), True)
  2287                 self.ProjectBuffer = UndoBuffer(self.Copy(self.Project), True)
  2016                 self.Buffering = False
  2288                 self.Buffering = False
  2017                 self.ElementsOpened = []
  2289                 self.ElementsOpened = []
  2018                 self.CurrentElementEditing = None
  2290                 self.CurrentElementEditing = None
       
  2291                 self.RefreshDataTypeUsingTree()
       
  2292                 self.RefreshDataTypes()
  2019                 self.RefreshPouUsingTree()
  2293                 self.RefreshPouUsingTree()
  2020                 self.RefreshBlockTypes()
  2294                 self.RefreshBlockTypes()
  2021                 return None
  2295                 return None
  2022         return "No PLC project found"
  2296         return "No PLC project found"
  2023 
  2297 
  2029             extras = {"xmlns" : "http://www.plcopen.org/xml/tc6.xsd",
  2303             extras = {"xmlns" : "http://www.plcopen.org/xml/tc6.xsd",
  2030                       "xmlns:xhtml" : "http://www.w3.org/1999/xhtml",
  2304                       "xmlns:xhtml" : "http://www.w3.org/1999/xhtml",
  2031                       "xmlns:xsi" : "http://www.w3.org/2001/XMLSchema-instance",
  2305                       "xmlns:xsi" : "http://www.w3.org/2001/XMLSchema-instance",
  2032                       "xsi:schemaLocation" : "http://www.plcopen.org/xml/tc6.xsd http://www.plcopen.org/xml/tc6.xsd"}
  2306                       "xsi:schemaLocation" : "http://www.plcopen.org/xml/tc6.xsd http://www.plcopen.org/xml/tc6.xsd"}
  2033             text += self.Project.generateXMLText("project", 0, extras)
  2307             text += self.Project.generateXMLText("project", 0, extras)
  2034 
  2308             
  2035             if self.VerifyXML:
  2309             if self.VerifyXML:
  2036                 if sys:
  2310                 if sys:
  2037                     sys.stdout = HolePseudoFile()
  2311                     sys.stdout = HolePseudoFile()
  2038                 pyxsval.parseAndValidateString(text, open(os.path.join(sys.path[0], "plcopen/TC6_XML_V10_B.xsd"),"r").read())
  2312                 pyxsval.parseAndValidateString(text, open(os.path.join(ScriptDirectory, "plcopen", "TC6_XML_V10_B.xsd"),"r").read())
  2039                 if sys:
  2313                 if sys:
  2040                     sys.stdout = sys.__stdout__
  2314                     sys.stdout = sys.__stdout__
  2041             
  2315             
  2042             if filepath:
  2316             if filepath:
  2043                 xmlfile = open(filepath,"w")
  2317                 xmlfile = open(filepath,"w")