From 258ec60b4c3ca1d260ded229ed1171ca99cbaae5 Mon Sep 17 00:00:00 2001 From: l_samenv Date: Thu, 8 Aug 2024 16:35:28 +0200 Subject: [PATCH] frappy_psi.sea: fix issue with missing BUSY after change target The command 'maw' in NICOS sometimes does complete immediately instead of waiting for reaching the target. It seems this affects only SEA drivables. The more important fix for this has to be done in SEA. The fix here is just to improve behaviour in case SEA would not do as expected. --- frappy_psi/sea.py | 55 +++++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/frappy_psi/sea.py b/frappy_psi/sea.py index 49c81cb..e3b0a10 100644 --- a/frappy_psi/sea.py +++ b/frappy_psi/sea.py @@ -39,7 +39,7 @@ from os.path import expanduser, join, exists from frappy.client import ProxyClient from frappy.datatypes import ArrayOf, BoolType, \ EnumType, FloatRange, IntRange, StringType, StatusType -from frappy.core import IDLE, BUSY, ERROR, DISABLED +from frappy.core import IDLE, BUSY, WARN, ERROR, DISABLED from frappy.errors import ConfigError, HardwareError, ReadFailedError, CommunicationFailedError from frappy.lib import generalConfig, mkthread from frappy.lib.asynconn import AsynConn, ConnectionClosed @@ -662,9 +662,6 @@ class SeaModule(Module): self.io.register_obj(self, self.sea_object) super().initModule() - def doPoll(self): - pass - class SeaReadable(SeaModule, Readable): _readerror = None @@ -683,6 +680,7 @@ class SeaReadable(SeaModule, Readable): self.read_status() # send event for ordinary self._status def update_status(self, value, timestamp, readerror): + # value is the sea status, which is a string, not the SECoP status! if 'disable' in value.lower(): self._status = DISABLED, value elif value == '': @@ -698,6 +696,9 @@ class SeaReadable(SeaModule, Readable): return ERROR, f'{self._readerror.name} - {self._readerror}' return self._status + def doPoll(self): + self.read_status() + class SeaWritable(SeaReadable, Writable): def read_value(self): @@ -710,35 +711,53 @@ class SeaWritable(SeaReadable, Writable): class SeaDrivable(SeaReadable, Drivable): - _is_running = 0 + _is_driving = False + _is_running = 0 # SEA is_running flag + _bad_limit = 5 + _bad_start = 0 # is set to start time when is_running is not immediately true status = Parameter(datatype=StatusType(Drivable, 'DISABLED')) - def earlyInit(self): - super().earlyInit() - self._run_event = threading.Event() - def write_target(self, value): - self._run_event.clear() + self._is_driving = True + if not self._is_running: + self._is_running = None + self._bad_start = 0 self.io.query(f'run {self.sea_object} {value}') - if not self._run_event.wait(5): - self.log.warn('target changed but is_running stays 0') + if not self._is_running: + self.log.warn('is_running is not set after run') + self._bad_start = time.time() + self.status = BUSY, 'changed target' return value def update_is_running(self, value, timestamp, readerror): if not readerror: self._is_running = value self.read_status() - if value: - self._run_event.set() def read_status(self): status = super().read_status() - if self._is_running: - if status[0] >= ERROR: + if status[0] >= ERROR: + if self._is_driving: return ERROR, 'BUSY + ' + status[1] - return BUSY, 'driving' - return status + return status + if self._is_driving: + if time.time() < self._bad_start + self._bad_limit: + if self._is_running: + self.log.warn('is_running flag delayed by %.2g sec', time.time() - self._bad_start) + self._bad_start = 0 + return BUSY, 'waiting for is_running' + if self._is_running: + self._bad_start = 0 + return BUSY, 'driving' + if self._is_running is None: + self.log.warn('miss is_running update within delay') + self._is_driving = False + if self._bad_start: + self.log.warn('started, but not running') + if self._bad_start: + return IDLE, f'started, but not running' + return IDLE, '' def updateTarget(self, module, parameter, value, timestamp, readerror): if value is not None: