subDesTagesMitExtraKaese 2 rokov pred
rodič
commit
de19936e7e

+ 35 - 1
box-pc/plc-connector/middlewares/common.py

@@ -1,4 +1,10 @@
+import math
+from dataclasses import fields
+
 from structures.common import BaseMeasurement
+from structures.measurement import Measurement24v, Measurement480v
+from structures.plant import S7State, CompactLogixState
+from structures.correlated import CorrelatedMeasurements
 
 class MatchSeries:
   def __init__(self, series) -> None:
@@ -11,4 +17,32 @@ class MatchSeries:
       # find the series in the data
       for key, value in measurement.__dict__.items():
         if isinstance(value, BaseMeasurement) and value.series == self._series:
-          return value
+          return value
+
+  def set_series(self, measurement: BaseMeasurement, series: BaseMeasurement):
+    if measurement.series == self._series:
+      return series
+    else:
+      # find the series in the data
+      for key, value in measurement.__dict__.items():
+        if isinstance(value, BaseMeasurement) and value.series == self._series:
+          return type(measurement)(**{**measurement.__dict__, key: series})
+
+ALLOWED_GLOBALS = {
+  'sum': sum,
+  'min': min,
+  'max': max,
+  'avg': lambda x: sum(x) / len(x),
+  'count': len,
+  'last': lambda x: x[-1],
+}
+
+ALLOWED_NAMES = \
+  [x.name for x in fields(Measurement24v)] + \
+  [x.name for x in fields(Measurement480v)] + \
+  [x.name for x in fields(CompactLogixState)] + \
+  [x.name for x in fields(S7State)] + \
+  [x.name for x in fields(CorrelatedMeasurements)] + \
+  list(ALLOWED_GLOBALS.keys())
+
+ALLOWED_NAMES = set([name for name in ALLOWED_NAMES if not name.startswith('_')])

+ 6 - 28
box-pc/plc-connector/middlewares/filters.py

@@ -1,11 +1,5 @@
 import logging
-import math
-import dataclasses
-from .common import MatchSeries
-from structures.measurement import Measurement24v, Measurement480v
-from structures.plant import S7State, CompactLogixState
-from structures.correlated import CorrelatedMeasurements
-
+from .common import MatchSeries, ALLOWED_NAMES, ALLOWED_GLOBALS
 
 logger = logging.getLogger(__name__)
 """
@@ -29,7 +23,8 @@ class MatchAny(MatchSeries):
 
       # check if any field matches
       for field, value in self._fields.items():
-        if getattr(dataset, field, None) == value:
+        v = getattr(dataset, field, None)
+        if v == value or (isinstance(v, tuple) and value in v):
           yield measurement
           break
       
@@ -50,23 +45,13 @@ class MatchAll(MatchSeries):
       # check if all fields match
       success = True
       for field, value in self._fields.items():
-        if getattr(dataset, field, None) != value:
+        v = getattr(dataset, field, None)
+        if (not isinstance(v, tuple) and v != value) or (isinstance(v, tuple) and not all(x == value for x in v)):
           success = False
           break
       if success:
         yield measurement
 
-
-ALLOWED_NAMES = \
-  [x.name for x in dataclasses.fields(Measurement24v)] + \
-  [x.name for x in dataclasses.fields(Measurement480v)] + \
-  [x.name for x in dataclasses.fields(CompactLogixState)] + \
-  [x.name for x in dataclasses.fields(S7State)] + \
-  [x.name for x in dataclasses.fields(CorrelatedMeasurements)] + \
-  ['sum', 'min', 'max', 'avg', 'count', 'last']
-
-ALLOWED_NAMES = set([name for name in ALLOWED_NAMES if not name.startswith('_')])
-
 class ComplexFilter():
   def __init__(self, parent, predicate) -> None:
     self._predicate = predicate
@@ -79,14 +64,7 @@ class ComplexFilter():
   def execute(self, values):
     for measurement in values:
       try:
-        if eval(self._compiled, {"__builtins__": {
-          'sum': sum,
-          'min': min,
-          'max': max,
-          'avg': lambda x: sum(x) / len(x),
-          'count': len,
-          'last': lambda x: x[-1],
-        }}, measurement.__dict__):
+        if eval(self._compiled, {"__builtins__": ALLOWED_GLOBALS}, measurement.__dict__):
           yield measurement
       except Exception as e:
         logger.error(f"Error while evaluating predicate '{self._predicate}': {e}")

+ 3 - 22
box-pc/plc-connector/middlewares/selectors.py

@@ -1,27 +1,15 @@
 import logging
 import re
 import dataclasses
-from .common import MatchSeries
-from structures.measurement import Measurement24v, Measurement480v
-from structures.plant import S7State, CompactLogixState
-from structures.correlated import CorrelatedMeasurements
+from .common import ALLOWED_NAMES, ALLOWED_GLOBALS
 from structures.common import BaseMeasurement
 
 logger = logging.getLogger(__name__)
 
-ALLOWED_NAMES = \
-  [x.name for x in dataclasses.fields(Measurement24v)] + \
-  [x.name for x in dataclasses.fields(Measurement480v)] + \
-  [x.name for x in dataclasses.fields(CompactLogixState)] + \
-  [x.name for x in dataclasses.fields(S7State)] + \
-  [x.name for x in dataclasses.fields(CorrelatedMeasurements)] + \
-  ['sum', 'min', 'max', 'avg', 'count', 'last']
-
-ALLOWED_NAMES = set([name for name in ALLOWED_NAMES if not name.startswith('_')])
-
 @dataclasses.dataclass(frozen=True)
 class Selection(BaseMeasurement):
   value: str
+  series: str
 
 class ComplexSelector():
   def __init__(self, parent, selector) -> None:
@@ -35,14 +23,7 @@ class ComplexSelector():
   def execute(self, values):
     for measurement in values:
       try:
-        value = eval(self._compiled, {"__builtins__": {
-          'sum': sum,
-          'min': min,
-          'max': max,
-          'avg': lambda x: sum(x) / len(x),
-          'count': len,
-          'last': lambda x: x[-1],
-        }}, measurement.__dict__)
+        value = eval(self._compiled, {"__builtins__": ALLOWED_GLOBALS}, measurement.__dict__)
         yield Selection(
           timestamp = measurement.timestamp,
           series = re.match(r"[\w_\.\-\(\)]+", self._selector).group(0),