omit updates of unchanged values within short time

Sometimes it happens, that the same value determined once is
assigned several times to a parameter within a very short period.
Sending multiple updates is not useful in this case.

Change-Id: Icea66934c831fd9b2eac7d0394a124d002469914
Reviewed-on: https://forge.frm2.tum.de/review/c/sine2020/secop/playground/+/27091
Tested-by: Jenkins Automated Tests <pedersen+jenkins@frm2.tum.de>
Reviewed-by: Markus Zolliker <markus.zolliker@psi.ch>
This commit is contained in:
zolliker 2021-11-10 09:27:15 +01:00
parent a64eb7f33b
commit d76d79aebb
4 changed files with 27 additions and 13 deletions

View File

@ -29,7 +29,7 @@ from collections import OrderedDict
from secop.datatypes import ArrayOf, BoolType, EnumType, FloatRange, \
IntRange, StatusType, StringType, TextType, TupleOf
from secop.errors import BadValueError, ConfigError, InternalError, \
from secop.errors import BadValueError, ConfigError, \
ProgrammingError, SECoPError, SilentError, secop_error
from secop.lib import formatException, mkthread
from secop.lib.enum import Enum
@ -243,12 +243,12 @@ class Module(HasAccessibles):
# reference to the dispatcher (used for sending async updates)
DISPATCHER = None
pollerClass = Poller #: default poller used
def __init__(self, name, logger, cfgdict, srv):
# remember the dispatcher object (for the async callbacks)
self.DISPATCHER = srv.dispatcher
self.omit_unchanged_within = getattr(self.DISPATCHER, 'omit_unchanged_within', 0.1)
self.log = logger
self.name = name
self.valueCallbacks = {}
@ -441,18 +441,21 @@ class Module(HasAccessibles):
def announceUpdate(self, pname, value=None, err=None, timestamp=None):
"""announce a changed value or readerror"""
pobj = self.parameters[pname]
if value is not None:
pobj.value = value # store the value even in case of error
if err:
if not isinstance(err, SECoPError):
err = InternalError(err)
if str(err) == str(pobj.readerror):
return # do call updates for repeated errors
else:
timestamp = timestamp or time.time()
changed = pobj.value != value
try:
# store the value even in case of error
pobj.value = pobj.datatype(value)
except Exception as e:
err = secop_error(e)
if not err: # do not overwrite given error
err = e
if err:
err = secop_error(err)
if str(err) == str(pobj.readerror):
return # do call updates for repeated errors
elif not changed and timestamp < (pobj.timestamp or 0) + self.omit_unchanged_within:
# no change within short time -> omit
return
pobj.timestamp = timestamp or time.time()
pobj.readerror = err
if pobj.export:

View File

@ -60,10 +60,11 @@ def make_update(modulename, pobj):
class Dispatcher:
def __init__(self, name, logger, options, srv):
# to avoid errors, we want to eat all options here
self.equipment_id = options.pop('id', name)
# time interval for omitting updates of unchanged values
self.omit_unchanged_within = options.pop('omit_unchanged_within', 0.1)
self.nodeprops = {}
for k in list(options):
self.nodeprops[k] = options.pop(k)

View File

@ -71,6 +71,12 @@ class Data:
class DispatcherStub:
# the first update from the poller comes a very short time after the
# initial value from the timestamp. However, in the test below
# the second update happens after the updates dict is cleared
# -> we have to inhibit the 'omit unchanged update' feature
omit_unchanged_within = 0
def __init__(self, updates):
self.updates = updates

View File

@ -34,7 +34,11 @@ from secop.poller import BasicPoller
class DispatcherStub:
OMIT_UNCHANGED_WITHIN = 0
# the first update from the poller comes a very short time after the
# initial value from the timestamp. However, in the test below
# the second update happens after the updates dict is cleared
# -> we have to inhibit the 'omit unchanged update' feature
omit_unchanged_within = 0
def __init__(self, updates):
self.updates = updates