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: