PLCControler.py
changeset 1957 2d1cc4f5e4ef
parent 1954 b113d7de4899
child 1959 ce1bfd04b3f6
equal deleted inserted replaced
1956:2b90514edfbf 1957:2d1cc4f5e4ef
    29 from copy import deepcopy
    29 from copy import deepcopy
    30 import os
    30 import os
    31 import re
    31 import re
    32 import datetime
    32 import datetime
    33 from time import localtime
    33 from time import localtime
    34 from collections import OrderedDict, namedtuple
       
    35 
       
    36 from lxml import etree
       
    37 
    34 
    38 import util.paths as paths
    35 import util.paths as paths
    39 from plcopen import *
    36 from plcopen import *
    40 from plcopen.types_enums import *
    37 from plcopen.types_enums import *
    41 from plcopen.XSLTModelQuery import _StringValue, _BoolValue, _translate_args
    38 from plcopen.XSLTModelQuery import _StringValue, _BoolValue, _translate_args
    42 from plcopen.InstancesPathCollector import InstancesPathCollector
    39 from plcopen.InstancesPathCollector import InstancesPathCollector
    43 from plcopen.POUVariablesCollector import POUVariablesCollector
    40 from plcopen.POUVariablesCollector import POUVariablesCollector
    44 from plcopen.InstanceTagnameCollector import InstanceTagnameCollector
    41 from plcopen.InstanceTagnameCollector import InstanceTagnameCollector
       
    42 from plcopen.BlockInstanceCollector import BlockInstanceCollector
    45 from plcopen.VariableInfoCollector import VariableInfoCollector
    43 from plcopen.VariableInfoCollector import VariableInfoCollector
    46 from graphics.GraphicCommons import *
    44 from graphics.GraphicCommons import *
    47 from PLCGenerator import *
    45 from PLCGenerator import *
    48 
    46 
    49 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)?")
    47 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)?")
    50 
    48 
    51 ScriptDirectory = paths.AbsDir(__file__)
    49 ScriptDirectory = paths.AbsDir(__file__)
    52 
    50 
    53 # -------------------------------------------------------------------------------
       
    54 #           Helpers object for generating pou block instances list
       
    55 # -------------------------------------------------------------------------------
       
    56 
       
    57 
       
    58 _Point = namedtuple("Point", ["x", "y"])
       
    59 
       
    60 _BlockInstanceInfos = namedtuple(
       
    61     "BlockInstanceInfos",
       
    62     ["type", "id", "x", "y", "width", "height", "specific_values", "inputs", "outputs"])
       
    63 
       
    64 _BlockSpecificValues = (
       
    65     namedtuple("BlockSpecificValues",
       
    66                ["name", "execution_order"]),
       
    67     [_StringValue, int])
       
    68 _VariableSpecificValues = (
       
    69     namedtuple("VariableSpecificValues",
       
    70                ["name", "value_type", "execution_order"]),
       
    71     [_StringValue, _StringValue, int])
       
    72 _ConnectionSpecificValues = (
       
    73     namedtuple("ConnectionSpecificValues", ["name"]),
       
    74     [_StringValue])
       
    75 
       
    76 _PowerRailSpecificValues = (
       
    77     namedtuple("PowerRailSpecificValues", ["connectors"]),
       
    78     [int])
       
    79 
       
    80 _LDElementSpecificValues = (
       
    81     namedtuple("LDElementSpecificValues",
       
    82                ["name", "negated", "edge", "storage", "execution_order"]),
       
    83     [_StringValue, _BoolValue, _StringValue, _StringValue, int])
       
    84 
       
    85 _DivergenceSpecificValues = (
       
    86     namedtuple("DivergenceSpecificValues", ["connectors"]),
       
    87     [int])
       
    88 
       
    89 _SpecificValuesTuples = {
       
    90     "comment": (
       
    91         namedtuple("CommentSpecificValues", ["content"]),
       
    92         [_StringValue]),
       
    93     "input": _VariableSpecificValues,
       
    94     "output": _VariableSpecificValues,
       
    95     "inout": _VariableSpecificValues,
       
    96     "connector": _ConnectionSpecificValues,
       
    97     "continuation": _ConnectionSpecificValues,
       
    98     "leftPowerRail": _PowerRailSpecificValues,
       
    99     "rightPowerRail": _PowerRailSpecificValues,
       
   100     "contact": _LDElementSpecificValues,
       
   101     "coil": _LDElementSpecificValues,
       
   102     "step": (
       
   103         namedtuple("StepSpecificValues", ["name", "initial", "action"]),
       
   104         [_StringValue, _BoolValue, lambda x: x]),
       
   105     "transition": (
       
   106         namedtuple("TransitionSpecificValues",
       
   107                    ["priority", "condition_type", "condition", "connection"]),
       
   108         [int, _StringValue, _StringValue, lambda x: x]),
       
   109     "selectionDivergence": _DivergenceSpecificValues,
       
   110     "selectionConvergence": _DivergenceSpecificValues,
       
   111     "simultaneousDivergence": _DivergenceSpecificValues,
       
   112     "simultaneousConvergence": _DivergenceSpecificValues,
       
   113     "jump": (
       
   114         namedtuple("JumpSpecificValues", ["target"]),
       
   115         [_StringValue]),
       
   116     "actionBlock": (
       
   117         namedtuple("ActionBlockSpecificValues", ["actions"]),
       
   118         [lambda x: x]),
       
   119 }
       
   120 
       
   121 _InstanceConnectionInfos = namedtuple(
       
   122     "InstanceConnectionInfos",
       
   123     ["name", "negated", "edge", "position", "links"])
       
   124 
       
   125 _ConnectionLinkInfos = namedtuple(
       
   126     "ConnectionLinkInfos",
       
   127     ["refLocalId", "formalParameter", "points"])
       
   128 
       
   129 
       
   130 class _ActionInfos(object):
       
   131     __slots__ = ["qualifier", "type", "value", "duration", "indicator"]
       
   132 
       
   133     def __init__(self, *args):
       
   134         for attr, value in zip(self.__slots__, args):
       
   135             setattr(self, attr, value if value is not None else "")
       
   136 
       
   137     def copy(self):
       
   138         return _ActionInfos(*[getattr(self, attr) for attr in self.__slots__])
       
   139 
       
   140 
       
   141 class BlockInstanceFactory(object):
       
   142 
       
   143     def __init__(self, block_instances):
       
   144         self.BlockInstances = block_instances
       
   145         self.CurrentInstance = None
       
   146         self.SpecificValues = None
       
   147         self.CurrentConnection = None
       
   148         self.CurrentLink = None
       
   149 
       
   150     def SetSpecificValues(self, context, *args):
       
   151         self.SpecificValues = list(args)
       
   152         self.CurrentInstance = None
       
   153         self.CurrentConnection = None
       
   154         self.CurrentLink = None
       
   155 
       
   156     def AddBlockInstance(self, context, *args):
       
   157         specific_values_tuple, specific_values_translation = \
       
   158             _SpecificValuesTuples.get(args[0][0], _BlockSpecificValues)
       
   159 
       
   160         if args[0][0] == "step" and len(self.SpecificValues) < 3 or \
       
   161            args[0][0] == "transition" and len(self.SpecificValues) < 4:
       
   162             self.SpecificValues.append([None])
       
   163         elif args[0][0] == "actionBlock" and len(self.SpecificValues) < 1:
       
   164             self.SpecificValues.append([[]])
       
   165         specific_values = specific_values_tuple(*_translate_args(
       
   166             specific_values_translation, self.SpecificValues))
       
   167         self.SpecificValues = None
       
   168 
       
   169         self.CurrentInstance = _BlockInstanceInfos(
       
   170             *(_translate_args([_StringValue, int] + [float] * 4, args) +
       
   171               [specific_values, [], []]))
       
   172 
       
   173         self.BlockInstances[self.CurrentInstance.id] = self.CurrentInstance
       
   174 
       
   175     def AddInstanceConnection(self, context, *args):
       
   176         connection_args = _translate_args(
       
   177             [_StringValue] * 2 + [_BoolValue, _StringValue] + [float] * 2, args)
       
   178 
       
   179         self.CurrentConnection = _InstanceConnectionInfos(
       
   180             *(connection_args[1:4] + [
       
   181                 _Point(*connection_args[4:6]), []]))
       
   182 
       
   183         if self.CurrentInstance is not None:
       
   184             if connection_args[0] == "input":
       
   185                 self.CurrentInstance.inputs.append(self.CurrentConnection)
       
   186             else:
       
   187                 self.CurrentInstance.outputs.append(self.CurrentConnection)
       
   188         else:
       
   189             self.SpecificValues.append([self.CurrentConnection])
       
   190 
       
   191     def AddConnectionLink(self, context, *args):
       
   192         self.CurrentLink = _ConnectionLinkInfos(
       
   193             *(_translate_args([int, _StringValue], args) + [[]]))
       
   194         self.CurrentConnection.links.append(self.CurrentLink)
       
   195 
       
   196     def AddLinkPoint(self, context, *args):
       
   197         self.CurrentLink.points.append(_Point(
       
   198             *_translate_args([float] * 2, args)))
       
   199 
       
   200     def AddAction(self, context, *args):
       
   201         if len(self.SpecificValues) == 0:
       
   202             self.SpecificValues.append([[]])
       
   203         translated_args = _translate_args([_StringValue] * 5, args)
       
   204         self.SpecificValues[0][0].append(_ActionInfos(*translated_args))
       
   205 
       
   206 
       
   207 pou_block_instances_xslt = etree.parse(
       
   208     os.path.join(ScriptDirectory, "plcopen", "pou_block_instances.xslt"))
       
   209 
    51 
   210 
    52 
   211 # Length of the buffer
    53 # Length of the buffer
   212 UNDO_BUFFER_LENGTH = 20
    54 UNDO_BUFFER_LENGTH = 20
   213 
    55 
   306         self.LastNewIndex = 0
   148         self.LastNewIndex = 0
   307         self.Reset()
   149         self.Reset()
   308         self.InstancesPathCollector = InstancesPathCollector(self)
   150         self.InstancesPathCollector = InstancesPathCollector(self)
   309         self.POUVariablesCollector = POUVariablesCollector(self)
   151         self.POUVariablesCollector = POUVariablesCollector(self)
   310         self.InstanceTagnameCollector = InstanceTagnameCollector(self)
   152         self.InstanceTagnameCollector = InstanceTagnameCollector(self)
       
   153         self.BlockInstanceCollector = BlockInstanceCollector(self)
   311         self.VariableInfoCollector = VariableInfoCollector(self)
   154         self.VariableInfoCollector = VariableInfoCollector(self)
   312 
   155 
   313     # Reset PLCControler internal variables
   156     # Reset PLCControler internal variables
   314     def Reset(self):
   157     def Reset(self):
   315         self.Project = None
   158         self.Project = None
  2110                 instance.translate(*diff)
  1953                 instance.translate(*diff)
  2111 
  1954 
  2112             return new_id, connections
  1955             return new_id, connections
  2113 
  1956 
  2114     def GetEditedElementInstancesInfos(self, tagname, debug=False):
  1957     def GetEditedElementInstancesInfos(self, tagname, debug=False):
  2115         element_instances = OrderedDict()
       
  2116         element = self.GetEditedElement(tagname, debug)
  1958         element = self.GetEditedElement(tagname, debug)
  2117         if element is not None:
  1959         if element is not None:
  2118             factory = BlockInstanceFactory(element_instances)
  1960             return self.BlockInstanceCollector.Collect(element, debug)
  2119 
  1961         return {}
  2120             pou_block_instances_xslt_tree = etree.XSLT(
       
  2121                 pou_block_instances_xslt,
       
  2122                 extensions={
       
  2123                     ("pou_block_instances_ns", name): getattr(factory, name)
       
  2124                     for name in ["AddBlockInstance", "SetSpecificValues",
       
  2125                                  "AddInstanceConnection", "AddConnectionLink",
       
  2126                                  "AddLinkPoint", "AddAction"]})
       
  2127 
       
  2128             pou_block_instances_xslt_tree(element)
       
  2129         return element_instances
       
  2130 
  1962 
  2131     def ClearEditedElementExecutionOrder(self, tagname):
  1963     def ClearEditedElementExecutionOrder(self, tagname):
  2132         element = self.GetEditedElement(tagname)
  1964         element = self.GetEditedElement(tagname)
  2133         if element is not None:
  1965         if element is not None:
  2134             element.resetexecutionOrder()
  1966             element.resetexecutionOrder()