rework polling
Readable/Moveable can't be busy.... Change-Id: Icfe250e16dd30646cf3081f4850a8bacaa77a935 Reviewed-on: https://forge.frm2.tum.de/review/17859 Tested-by: JenkinsCodeReview <bjoern_pedersen@frm2.tum.de> Reviewed-by: Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
This commit is contained in:
@ -21,6 +21,8 @@
|
|||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
"""Define Baseclasses for real Modules implemented in the server"""
|
"""Define Baseclasses for real Modules implemented in the server"""
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
# XXX: connect with 'protocol'-Modules.
|
# XXX: connect with 'protocol'-Modules.
|
||||||
# Idea: every Module defined herein is also a 'protocol'-Module,
|
# Idea: every Module defined herein is also a 'protocol'-Module,
|
||||||
# all others MUST derive from those, the 'interface'-class is still derived
|
# all others MUST derive from those, the 'interface'-class is still derived
|
||||||
@ -59,15 +61,23 @@ from secop.datatypes import DataType, EnumType, TupleOf, StringType, FloatRange,
|
|||||||
|
|
||||||
EVENT_ONLY_ON_CHANGED_VALUES = False
|
EVENT_ONLY_ON_CHANGED_VALUES = False
|
||||||
|
|
||||||
# storage for Parameter settings:
|
|
||||||
# if readonly is False, the value can be changed (by code, or remote)
|
|
||||||
# if no default is given, the parameter MUST be specified in the configfile
|
|
||||||
# during startup, value is initialized with the default value or
|
|
||||||
# from the config file if specified there
|
|
||||||
|
|
||||||
|
|
||||||
class Param(object):
|
class Param(object):
|
||||||
|
"""storage for Parameter settings + value + qualifiers
|
||||||
|
|
||||||
|
if readonly is False, the value can be changed (by code, or remote)
|
||||||
|
if no default is given, the parameter MUST be specified in the configfile
|
||||||
|
during startup, value is initialized with the default value or
|
||||||
|
from the config file if specified there
|
||||||
|
|
||||||
|
poll can be:
|
||||||
|
- False (never poll this parameter)
|
||||||
|
- True (poll this ever pollinterval)
|
||||||
|
- positive int (poll every N(th) pollinterval)
|
||||||
|
- negative int (normally poll every N(th) pollinterval, if module is busy, poll every pollinterval)
|
||||||
|
|
||||||
|
note: Drivable (and derived classes) poll with 10 fold frequency if module is busy....
|
||||||
|
"""
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
description,
|
description,
|
||||||
datatype=None,
|
datatype=None,
|
||||||
@ -432,6 +442,7 @@ class Module(object):
|
|||||||
mkthread(self.late_init)
|
mkthread(self.late_init)
|
||||||
|
|
||||||
def late_init(self):
|
def late_init(self):
|
||||||
|
# this runs async somewhen after init
|
||||||
self.log.debug('late init()')
|
self.log.debug('late init()')
|
||||||
|
|
||||||
|
|
||||||
@ -463,45 +474,37 @@ class Readable(Module):
|
|||||||
self._pollthread = mkthread(self.__pollThread)
|
self._pollthread = mkthread(self.__pollThread)
|
||||||
|
|
||||||
def __pollThread(self):
|
def __pollThread(self):
|
||||||
|
try:
|
||||||
|
self.__pollThread_inner()
|
||||||
|
except Exception as e:
|
||||||
|
self.log.exception(e)
|
||||||
|
print(formatExtendedStack())
|
||||||
|
|
||||||
|
def __pollThread_inner(self):
|
||||||
"""super simple and super stupid per-module polling thread"""
|
"""super simple and super stupid per-module polling thread"""
|
||||||
i = 0
|
i = 0
|
||||||
fastpoll = True # first update should be quick
|
|
||||||
while True:
|
while True:
|
||||||
i = 1
|
fastpoll = self.poll(i)
|
||||||
|
i += 1
|
||||||
try:
|
try:
|
||||||
time.sleep(self.pollinterval * (0.1 if fastpoll else 1))
|
time.sleep(self.pollinterval * (0.1 if fastpoll else 1))
|
||||||
except TypeError:
|
except TypeError:
|
||||||
time.sleep(min(self.pollinterval)
|
time.sleep(min(self.pollinterval)
|
||||||
if fastpoll else max(self.pollinterval))
|
if fastpoll else max(self.pollinterval))
|
||||||
fastpoll = self.poll(i)
|
|
||||||
|
|
||||||
def poll(self, nr):
|
def poll(self, nr=0):
|
||||||
# poll status first
|
# Just poll all parameters regularly where polling is enabled
|
||||||
fastpoll = False
|
|
||||||
if 'status' in self.parameters:
|
|
||||||
stat = self.read_status(0)
|
|
||||||
# self.log.info('polling read_status -> %r' % (stat,))
|
|
||||||
fastpoll = stat[0] == status.BUSY
|
|
||||||
# if fastpoll:
|
|
||||||
# self.log.info('fastpoll!')
|
|
||||||
for pname, pobj in self.parameters.items():
|
for pname, pobj in self.parameters.items():
|
||||||
if not pobj.poll:
|
if not pobj.poll:
|
||||||
continue
|
continue
|
||||||
if pname == 'status':
|
if nr % abs(int(pobj.poll)) == 0:
|
||||||
# status was already polled above
|
# poll every 'pobj.poll' iteration
|
||||||
continue
|
|
||||||
if ((int(pobj.poll) < 0) and fastpoll) or (
|
|
||||||
nr % abs(int(pobj.poll))) == 0:
|
|
||||||
# poll always if pobj.poll is negative and fastpoll (i.e. Module is busy)
|
|
||||||
# otherwise poll every 'pobj.poll' iteration
|
|
||||||
rfunc = getattr(self, 'read_' + pname, None)
|
rfunc = getattr(self, 'read_' + pname, None)
|
||||||
if rfunc:
|
if rfunc:
|
||||||
try:
|
try:
|
||||||
# self.log.info('polling read_%s -> %r' % (pname, rfunc()))
|
|
||||||
rfunc()
|
rfunc()
|
||||||
except Exception: # really all!
|
except Exception: # really all!
|
||||||
pass
|
pass
|
||||||
return fastpoll
|
|
||||||
|
|
||||||
|
|
||||||
class Writable(Readable):
|
class Writable(Readable):
|
||||||
@ -527,6 +530,29 @@ class Drivable(Writable):
|
|||||||
Also status gets extended with a BUSY state indicating a running action.
|
Also status gets extended with a BUSY state indicating a running action.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# improved polling: may poll faster if module is BUSY
|
||||||
|
def poll(self, nr=0):
|
||||||
|
# poll status first
|
||||||
|
stat = self.read_status(0)
|
||||||
|
fastpoll = stat[0] == status.BUSY
|
||||||
|
for pname, pobj in self.parameters.items():
|
||||||
|
if not pobj.poll:
|
||||||
|
continue
|
||||||
|
if pname == 'status':
|
||||||
|
# status was already polled above
|
||||||
|
continue
|
||||||
|
if ((int(pobj.poll) < 0) and fastpoll) or (
|
||||||
|
nr % abs(int(pobj.poll))) == 0:
|
||||||
|
# poll always if pobj.poll is negative and fastpoll (i.e. Module is busy)
|
||||||
|
# otherwise poll every 'pobj.poll' iteration
|
||||||
|
rfunc = getattr(self, 'read_' + pname, None)
|
||||||
|
if rfunc:
|
||||||
|
try:
|
||||||
|
rfunc()
|
||||||
|
except Exception: # really all!
|
||||||
|
pass
|
||||||
|
return fastpoll
|
||||||
|
|
||||||
def do_stop(self):
|
def do_stop(self):
|
||||||
"""default implementation of the stop command
|
"""default implementation of the stop command
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user