PLCGenerator.py
changeset 248 f7df265edd54
parent 244 05f6e0d7710c
child 257 d0a0ffbbd61c
equal deleted inserted replaced
247:4a47ccafbef7 248:f7df265edd54
   670         body_content = body.getcontent()
   670         body_content = body.getcontent()
   671         body_type = body_content["name"]
   671         body_type = body_content["name"]
   672         if body_type in ["IL","ST"]:
   672         if body_type in ["IL","ST"]:
   673             self.Program = [(ReIndentText(body_content["value"].gettext(), len(self.CurrentIndent)), 
   673             self.Program = [(ReIndentText(body_content["value"].gettext(), len(self.CurrentIndent)), 
   674                             (self.TagName, "body", len(self.CurrentIndent)))]
   674                             (self.TagName, "body", len(self.CurrentIndent)))]
   675         elif body_type == "FBD":
       
   676             orderedInstances = []
       
   677             otherInstances = {"outVariables" : [], "block" : [], "connector" : []}
       
   678             for instance in body.getcontentInstances():
       
   679                 if isinstance(instance, (plcopen.fbdObjects_outVariable, plcopen.fbdObjects_inOutVariable, plcopen.fbdObjects_block)):
       
   680                     executionOrderId = instance.getexecutionOrderId()
       
   681                     if executionOrderId > 0:
       
   682                         orderedInstances.append((executionOrderId, instance))
       
   683                     elif isinstance(instance, (plcopen.fbdObjects_outVariable, plcopen.fbdObjects_inOutVariable)):
       
   684                         otherInstances["outVariables"].append(instance)
       
   685                     elif isinstance(instance, plcopen.fbdObjects_block):
       
   686                         otherInstances["block"].append(instance)
       
   687                 elif isinstance(instance, plcopen.commonObjects_connector):
       
   688                     otherInstances["connector"].append(instance)
       
   689             orderedInstances.sort()
       
   690             instances = [instance for (executionOrderId, instance) in orderedInstances]
       
   691             instances.extend(otherInstances["connector"] + otherInstances["outVariables"] + otherInstances["block"])
       
   692             for instance in instances:
       
   693                 if isinstance(instance, (plcopen.fbdObjects_outVariable, plcopen.fbdObjects_inOutVariable)):
       
   694                     connections = instance.connectionPointIn.getconnections()
       
   695                     if connections and len(connections) == 1:
       
   696                         expression = self.ComputeFBDExpression(body, connections[0])
       
   697                         self.Program += [(self.CurrentIndent, ()),
       
   698                                          (instance.getexpression(), (self.TagName, "io_variable", instance.getlocalId(), "expression")),
       
   699                                          (" := ", ())]
       
   700                         self.Program += expression
       
   701                         self.Program += [(";\n", ())]
       
   702                 elif isinstance(instance, plcopen.fbdObjects_block):
       
   703                     block_type = instance.gettypeName()
       
   704                     self.ParentGenerator.GeneratePouProgram(block_type)
       
   705                     block_infos = self.GetBlockType(block_type)
       
   706                     block_infos["generate"](self, instance, body, None)
       
   707                 elif isinstance(instance, plcopen.commonObjects_connector):
       
   708                     connector = instance.getname()
       
   709                     if self.ComputedConnectors.get(connector, None):
       
   710                         continue 
       
   711                     connections = instance.connectionPointIn.getconnections()
       
   712                     if connections and len(connections) == 1:
       
   713                         self.ComputedConnectors[connector] = self.ComputeFBDExpression(body, connections[0])
       
   714         elif body_type == "LD":
       
   715             for instance in body.getcontentInstances():
       
   716                 if isinstance(instance, plcopen.ldObjects_coil):
       
   717                     expression = self.ComputeLDExpression(body, instance.connectionPointIn.getconnections())
       
   718                     coil_info = (self.TagName, "coil", instance.getlocalId())
       
   719                     variable = self.ExtractModifier(instance, [(instance.getvariable(), coil_info + ("reference",))], coil_info)
       
   720                     self.Program += [(self.CurrentIndent, ())] + variable
       
   721                     self.Program += [(" := ", ())] + expression + [(";\n", ())]
       
   722         elif body_type == "SFC":
   675         elif body_type == "SFC":
   723             self.IndentRight()
   676             self.IndentRight()
   724             for instance in body.getcontentInstances():
   677             for instance in body.getcontentInstances():
   725                 if isinstance(instance, plcopen.sfcObjects_step):
   678                 if isinstance(instance, plcopen.sfcObjects_step):
   726                     self.GenerateSFCStep(instance, pou)
   679                     self.GenerateSFCStep(instance, pou)
   737                 self.SFCNetworks["Actions"][action_name] = (self.SFCComputedBlocks, ())
   690                 self.SFCNetworks["Actions"][action_name] = (self.SFCComputedBlocks, ())
   738                 self.Program = []
   691                 self.Program = []
   739             self.IndentLeft()
   692             self.IndentLeft()
   740             for initialstep in self.InitialSteps:
   693             for initialstep in self.InitialSteps:
   741                 self.ComputeSFCStep(initialstep)
   694                 self.ComputeSFCStep(initialstep)
       
   695         else:
       
   696             orderedInstances = []
       
   697             otherInstances = {"outVariables" : [], "block" : [], "connector" : [], "coil" : []}
       
   698             for instance in body.getcontentInstances():
       
   699                 if isinstance(instance, (plcopen.fbdObjects_outVariable, plcopen.fbdObjects_inOutVariable, plcopen.fbdObjects_block)):
       
   700                     executionOrderId = instance.getexecutionOrderId()
       
   701                     if executionOrderId > 0:
       
   702                         orderedInstances.append((executionOrderId, instance))
       
   703                     elif isinstance(instance, (plcopen.fbdObjects_outVariable, plcopen.fbdObjects_inOutVariable)):
       
   704                         otherInstances["outVariables"].append(instance)
       
   705                     elif isinstance(instance, plcopen.fbdObjects_block):
       
   706                         otherInstances["block"].append(instance)
       
   707                 elif isinstance(instance, plcopen.commonObjects_connector):
       
   708                     otherInstances["connector"].append(instance)
       
   709                 elif isinstance(instance, plcopen.ldObjects_coil):
       
   710                     otherInstances["coil"].append(instance)
       
   711             orderedInstances.sort()
       
   712             instances = [instance for (executionOrderId, instance) in orderedInstances]
       
   713             instances.extend(otherInstances["connector"] + otherInstances["outVariables"] + otherInstances["coil"] + otherInstances["block"])
       
   714             for instance in instances:
       
   715                 if isinstance(instance, (plcopen.fbdObjects_outVariable, plcopen.fbdObjects_inOutVariable)):
       
   716                     connections = instance.connectionPointIn.getconnections()
       
   717                     if connections is not None:
       
   718                         expression = self.ComputeExpression(body, connections)
       
   719                         self.Program += [(self.CurrentIndent, ()),
       
   720                                          (instance.getexpression(), (self.TagName, "io_variable", instance.getlocalId(), "expression")),
       
   721                                          (" := ", ())]
       
   722                         self.Program += expression
       
   723                         self.Program += [(";\n", ())]
       
   724                 elif isinstance(instance, plcopen.fbdObjects_block):
       
   725                     block_type = instance.gettypeName()
       
   726                     self.ParentGenerator.GeneratePouProgram(block_type)
       
   727                     block_infos = self.GetBlockType(block_type)
       
   728                     block_infos["generate"](self, instance, body, None)
       
   729                 elif isinstance(instance, plcopen.commonObjects_connector):
       
   730                     connector = instance.getname()
       
   731                     if self.ComputedConnectors.get(connector, None):
       
   732                         continue 
       
   733                     self.ComputedConnectors[connector] = self.ComputeExpression(body, instance.connectionPointIn.getconnections())
       
   734                 elif isinstance(instance, plcopen.ldObjects_coil):
       
   735                     connections = instance.connectionPointIn.getconnections()
       
   736                     if connections is not None:
       
   737                         expression = self.ComputeExpression(body, connections)
       
   738                         coil_info = (self.TagName, "coil", instance.getlocalId())
       
   739                         variable = self.ExtractModifier(instance, [(instance.getvariable(), coil_info + ("reference",))], coil_info)
       
   740                         self.Program += [(self.CurrentIndent, ())] + variable
       
   741                         self.Program += [(" := ", ())] + expression + [(";\n", ())]
   742             
   742             
   743     def ComputeFBDExpression(self, body, link, order = False):
   743     def FactorizePaths(self, paths):
   744         localid = link.getrefLocalId()
       
   745         instance = body.getcontentInstance(localid)
       
   746         if isinstance(instance, (plcopen.fbdObjects_inVariable, plcopen.fbdObjects_inOutVariable)):
       
   747             return [(instance.getexpression(), (self.TagName, "io_variable", localid, "expression"))]
       
   748         elif isinstance(instance, plcopen.fbdObjects_block):
       
   749             block_type = instance.gettypeName()
       
   750             self.ParentGenerator.GeneratePouProgram(block_type)
       
   751             block_infos = self.GetBlockType(block_type)
       
   752             return block_infos["generate"](self, instance, body, link, order)
       
   753         elif isinstance(instance, plcopen.commonObjects_continuation):
       
   754             name = instance.getname()
       
   755             computed_value = self.ComputedConnectors.get(name, None)
       
   756             if computed_value != None:
       
   757                 return computed_value
       
   758             for tmp_instance in body.getcontentInstances():
       
   759                 if isinstance(tmp_instance, plcopen.commonObjects_connector):
       
   760                     if tmp_instance.getname() == name:
       
   761                         connections = tmp_instance.connectionPointIn.getconnections()
       
   762                         if connections and len(connections) == 1:
       
   763                             expression = self.ComputeFBDExpression(body, connections[0], order)
       
   764                             self.ComputedConnectors[name] = expression
       
   765                             return expression
       
   766             raise PLCGenException, "No connector found corresponding to \"%s\" continuation in \"%s\" POU"%(name, self.Name)
       
   767 
       
   768     def FactorizeLDPaths(self, paths):
       
   769         same_paths = {}
   744         same_paths = {}
   770         uncomputed_index = range(len(paths))
   745         uncomputed_index = range(len(paths))
   771         factorized_paths = []
   746         factorized_paths = []
   772         for num, path in enumerate(paths):
   747         for num, path in enumerate(paths):
   773             if type(path) == ListType:
   748             if type(path) == ListType:
   786         for num in uncomputed_index:
   761         for num in uncomputed_index:
   787             factorized_paths.append(paths[num])
   762             factorized_paths.append(paths[num])
   788         factorized_paths.sort()
   763         factorized_paths.sort()
   789         return factorized_paths
   764         return factorized_paths
   790 
   765 
   791     def GenerateLDPaths(self, connections, body):
   766     def GeneratePaths(self, connections, body, order = False):
   792         paths = []
   767         paths = []
   793         for connection in connections:
   768         for connection in connections:
   794             localId = connection.getrefLocalId()
   769             localId = connection.getrefLocalId()
   795             next = body.getcontentInstance(localId)
   770             next = body.getcontentInstance(localId)
   796             if isinstance(next, plcopen.ldObjects_leftPowerRail):
   771             if isinstance(next, plcopen.ldObjects_leftPowerRail):
   797                 paths.append(None)
   772                 paths.append(None)
       
   773             elif isinstance(next, (plcopen.fbdObjects_inVariable, plcopen.fbdObjects_inOutVariable)):
       
   774                 paths.append(str([(next.getexpression(), (self.TagName, "io_variable", localId, "expression"))]))
   798             elif isinstance(next, plcopen.fbdObjects_block):
   775             elif isinstance(next, plcopen.fbdObjects_block):
   799                 block_type = next.gettypeName()
   776                 block_type = next.gettypeName()
   800                 self.ParentGenerator.GeneratePouProgram(block_type)
   777                 self.ParentGenerator.GeneratePouProgram(block_type)
   801                 block_infos = self.GetBlockType(block_type)
   778                 block_infos = self.GetBlockType(block_type)
   802                 paths.append(str(block_infos["generate"](self, next, body, connection)))
   779                 paths.append(str(block_infos["generate"](self, next, body, connection, order)))
       
   780             elif isinstance(next, plcopen.commonObjects_continuation):
       
   781                 name = next.getname()
       
   782                 computed_value = self.ComputedConnectors.get(name, None)
       
   783                 if computed_value != None:
       
   784                     paths.append(computed_value)
       
   785                 for tmp_instance in body.getcontentInstances():
       
   786                     if isinstance(tmp_instance, plcopen.commonObjects_connector):
       
   787                         if tmp_instance.getname() == name:
       
   788                             connections = tmp_instance.connectionPointIn.getconnections()
       
   789                             if connections is not None:
       
   790                                 expression = str(self.ComputeExpression(body, connections, order))
       
   791                                 self.ComputedConnectors[name] = expression
       
   792                                 paths.append(expression)
       
   793                 raise PLCGenException, "No connector found corresponding to \"%s\" continuation in \"%s\" POU"%(name, self.Name)
   803             else:
   794             else:
   804                 contact_info = (self.TagName, "contact", next.getlocalId())
   795                 contact_info = (self.TagName, "contact", next.getlocalId())
   805                 variable = str(self.ExtractModifier(next, [(next.getvariable(), contact_info + ("reference",))], contact_info))
   796                 variable = str(self.ExtractModifier(next, [(next.getvariable(), contact_info + ("reference",))], contact_info))
   806                 result = self.GenerateLDPaths(next.connectionPointIn.getconnections(), body)
   797                 result = self.GeneratePaths(next.connectionPointIn.getconnections(), body, order)
   807                 if len(result) > 1:
   798                 if len(result) > 1:
   808                     factorized_paths = self.FactorizeLDPaths(result)
   799                     factorized_paths = self.FactorizePaths(result)
   809                     if len(factorized_paths) > 1:
   800                     if len(factorized_paths) > 1:
   810                         paths.append([variable, tuple(factorized_paths)])
   801                         paths.append([variable, tuple(factorized_paths)])
   811                     else:
   802                     else:
   812                         paths.append([variable] + factorized_paths)
   803                         paths.append([variable] + factorized_paths)
   813                 elif type(result[0]) == ListType:
   804                 elif type(result[0]) == ListType:
   816                     paths.append([variable, result[0]])
   807                     paths.append([variable, result[0]])
   817                 else:
   808                 else:
   818                     paths.append(variable)
   809                     paths.append(variable)
   819         return paths
   810         return paths
   820 
   811 
   821     def ComputeLDPaths(self, paths, first = False):
   812     def ComputePaths(self, paths, first = False):
   822         if type(paths) == TupleType:
   813         if type(paths) == TupleType:
   823             if None in paths:
   814             if None in paths:
   824                 return [("TRUE", ())]
   815                 return [("TRUE", ())]
   825             else:
   816             else:
   826                 vars = [self.ComputeLDPaths(path) for path in paths]
   817                 vars = [self.ComputePaths(path) for path in paths]
   827                 if first:
   818                 if first:
   828                     return JoinList([(" OR ", ())], vars)
   819                     return JoinList([(" OR ", ())], vars)
   829                 else:
   820                 else:
   830                     return [("(", ())] + JoinList([(" OR ", ())], vars) + [(")", ())]
   821                     return [("(", ())] + JoinList([(" OR ", ())], vars) + [(")", ())]
   831         elif type(paths) == ListType:
   822         elif type(paths) == ListType:
   832             vars = [self.ComputeLDPaths(path) for path in paths]
   823             vars = [self.ComputePaths(path) for path in paths]
   833             return JoinList([(" AND ", ())], vars)
   824             return JoinList([(" AND ", ())], vars)
   834         else:
   825         else:
   835             return eval(paths)
   826             return eval(paths)
   836 
   827 
   837     def ComputeLDExpression(self, body, connections):
   828     def ComputeExpression(self, body, connections, order = False):
   838         paths = self.GenerateLDPaths(connections, body)
   829         paths = self.GeneratePaths(connections, body, order)
   839         if len(paths) > 1:
   830         if len(paths) > 1:
   840             factorized_paths = self.FactorizeLDPaths(paths)
   831             factorized_paths = self.FactorizePaths(paths)
   841             if len(factorized_paths) > 1:
   832             if len(factorized_paths) > 1:
   842                 paths = tuple(factorized_paths)
   833                 paths = tuple(factorized_paths)
   843             else:
   834             else:
   844                 paths = factorized_paths[0]
   835                 paths = factorized_paths[0]
   845         else:
   836         else:
   846             paths = paths[0]
   837             paths = paths[0]
   847         return self.ComputeLDPaths(paths, True)
   838         return self.ComputePaths(paths, True)
   848 
   839 
   849     def ExtractModifier(self, variable, expression, var_info):
   840     def ExtractModifier(self, variable, expression, var_info):
   850         if variable.getnegated():
   841         if variable.getnegated():
   851             return [("NOT(", var_info + ("negated",))] + expression + [(")", ())]
   842             return [("NOT(", var_info + ("negated",))] + expression + [(")", ())]
   852         else:
   843         else:
  1023                     transition_infos["content"] = [(":\n", ()),
  1014                     transition_infos["content"] = [(":\n", ()),
  1024                                                    (ReIndentText(transitionBody.gettext(), len(self.CurrentIndent)), (self.TagName, "body", len(self.CurrentIndent)))]
  1015                                                    (ReIndentText(transitionBody.gettext(), len(self.CurrentIndent)), (self.TagName, "body", len(self.CurrentIndent)))]
  1025                 elif transitionType == "ST":
  1016                 elif transitionType == "ST":
  1026                     transition_infos["content"] = [("\n", ()),
  1017                     transition_infos["content"] = [("\n", ()),
  1027                                                    (ReIndentText(transitionBody.gettext(), len(self.CurrentIndent)), (self.TagName, "body", len(self.CurrentIndent)))]
  1018                                                    (ReIndentText(transitionBody.gettext(), len(self.CurrentIndent)), (self.TagName, "body", len(self.CurrentIndent)))]
  1028                 elif transitionType == "FBD":
  1019                 else:
  1029                     for instance in transitionBody.getcontentInstances():
  1020                     for instance in transitionBody.getcontentInstances():
  1030                         if isinstance(instance, plcopen.fbdObjects_outVariable):
  1021                         if isinstance(instance, plcopen.fbdObjects_outVariable) and instance.getexpression() == transitionValues["value"]\
       
  1022                             or isinstance(instance, plcopen.ldObjects_coil) and instance.getvariable() == transitionValues["value"]:
  1031                             connections = instance.connectionPointIn.getconnections()
  1023                             connections = instance.connectionPointIn.getconnections()
  1032                             if connections and len(connections) == 1:
  1024                             if connections is not None:
  1033                                 expression = self.ComputeFBDExpression(transitionBody, connections[0])
  1025                                 expression = self.ComputeExpression(transitionBody, connections)
  1034                                 transition_infos["content"] = [("\n%s:= "%self.CurrentIndent, ())] + expression + [(";\n", ())]
  1026                                 transition_infos["content"] = [("\n%s:= "%self.CurrentIndent, ())] + expression + [(";\n", ())]
  1035                                 self.SFCComputedBlocks += self.Program
  1027                                 self.SFCComputedBlocks += self.Program
  1036                                 self.Program = []
  1028                                 self.Program = []
  1037                 elif transitionType == "LD":
       
  1038                     for instance in transitionBody.getcontentInstances():
       
  1039                         if isinstance(instance, plcopen.ldObjects_coil):
       
  1040                             expression = self.ComputeLDExpression(transitionBody, instance.connectionPointIn.getconnections())
       
  1041                             transition_infos["content"] = [("\n%s:= "%self.CurrentIndent, ())] + expression + [(";\n", ())]
       
  1042                             self.SFCComputedBlocks += self.Program
       
  1043                             self.Program = []
       
  1044                 self.TagName = previous_tagname
  1029                 self.TagName = previous_tagname
  1045             elif transitionValues["type"] == "connection":
  1030             elif transitionValues["type"] == "connection":
  1046                 body = pou.getbody()
  1031                 body = pou.getbody()
  1047                 connections = transition.getconnections()
  1032                 connections = transition.getconnections()
  1048                 network_type = self.GetNetworkType(connections, body)
  1033                 if connections is not None:
  1049                 if network_type == None:
  1034                     expression = self.ComputeExpression(body, connections)
  1050                     raise PLCGenException, "Type of network connected to transition impossible to define in \"%s\" POU"%self.Name
  1035                     transition_infos["content"] = [("\n%s:= "%self.CurrentIndent, ())] + expression + [(";\n", ())]
  1051                 if len(connections) > 1 or network_type == "LD":
  1036                     self.SFCComputedBlocks += self.Program
  1052                     expression = self.ComputeLDExpression(body, connections)
  1037                     self.Program = []
  1053                 else:
       
  1054                     expression = self.ComputeFBDExpression(body, connections[0])
       
  1055                 transition_infos["content"] = [("\n%s:= "%self.CurrentIndent, ())] + expression + [(";\n", ())]
       
  1056                 self.SFCComputedBlocks += self.Program
       
  1057                 self.Program = []
       
  1058             for step in steps:
  1038             for step in steps:
  1059                 self.GenerateSFCStep(step, pou)
  1039                 self.GenerateSFCStep(step, pou)
  1060                 step_name = step.getname()
  1040                 step_name = step.getname()
  1061                 if step_name in self.SFCNetworks["Steps"].keys():
  1041                 if step_name in self.SFCNetworks["Steps"].keys():
  1062                     transition_infos["from"].append([(step_name, (self.TagName, "transition", transition.getlocalId(), "from", step.getlocalId()))])
  1042                     transition_infos["from"].append([(step_name, (self.TagName, "transition", transition.getlocalId(), "from", step.getlocalId()))])