Merge branch 'wip' of gitlab.psi.ch:samenv/frappy into wip
This commit is contained in:
commit
9e2e6074c8
@ -74,7 +74,7 @@ Mod('om',
|
|||||||
'frappy_psi.phytron.Motor',
|
'frappy_psi.phytron.Motor',
|
||||||
'stick rotation, typically used for omega',
|
'stick rotation, typically used for omega',
|
||||||
io='om_io',
|
io='om_io',
|
||||||
encoder_mode='NO',
|
encoder_mode='CHECK',
|
||||||
target_min=-180,
|
target_min=-180,
|
||||||
target_max=360,
|
target_max=360,
|
||||||
)
|
)
|
||||||
|
@ -28,8 +28,8 @@ import code
|
|||||||
import signal
|
import signal
|
||||||
import os
|
import os
|
||||||
import traceback
|
import traceback
|
||||||
|
import threading
|
||||||
from os.path import expanduser
|
from os.path import expanduser
|
||||||
from queue import Queue
|
|
||||||
from frappy.client import SecopClient
|
from frappy.client import SecopClient
|
||||||
from frappy.errors import SECoPError
|
from frappy.errors import SECoPError
|
||||||
from frappy.datatypes import get_datatype, StatusType
|
from frappy.datatypes import get_datatype, StatusType
|
||||||
@ -66,7 +66,7 @@ class Logger:
|
|||||||
|
|
||||||
def __init__(self, loglevel='info'):
|
def __init__(self, loglevel='info'):
|
||||||
func = self.noop
|
func = self.noop
|
||||||
for lev in 'debug', 'info', 'warning', 'error':
|
for lev in 'debug', 'info', 'warning', 'error', 'exception':
|
||||||
if lev == loglevel:
|
if lev == loglevel:
|
||||||
func = self.emit
|
func = self.emit
|
||||||
setattr(self, lev, func)
|
setattr(self, lev, func)
|
||||||
@ -120,7 +120,8 @@ class Module:
|
|||||||
else:
|
else:
|
||||||
self._watched_params = {'value', 'status'}
|
self._watched_params = {'value', 'status'}
|
||||||
self._log_level = 'info'
|
self._log_level = 'info'
|
||||||
self._running = None
|
self._is_driving = False
|
||||||
|
self._driving_event = threading.Event()
|
||||||
self._status = None
|
self._status = None
|
||||||
props = secnode.modules[name]['properties']
|
props = secnode.modules[name]['properties']
|
||||||
self._title = f"# {props.get('implementation', '')} ({(props.get('interface_classes') or ['Module'])[0]})"
|
self._title = f"# {props.get('implementation', '')} ({(props.get('interface_classes') or ['Module'])[0]})"
|
||||||
@ -139,13 +140,9 @@ class Module:
|
|||||||
return self.status[0] // 100 == StatusType.BUSY // 100
|
return self.status[0] // 100 == StatusType.BUSY // 100
|
||||||
|
|
||||||
def _status_value_update(self, m, p, status, t, e):
|
def _status_value_update(self, m, p, status, t, e):
|
||||||
if self._running:
|
if self._is_driving and not self._isBusy():
|
||||||
try:
|
self._is_driving = False
|
||||||
self._running.put(True)
|
self._driving_event.set()
|
||||||
if self._running and not self._isBusy():
|
|
||||||
self._running.put(False)
|
|
||||||
except TypeError: # may happen when _running is removed during above lines
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _watch_parameter(self, m, pname, *args, forced=False, mininterval=0):
|
def _watch_parameter(self, m, pname, *args, forced=False, mininterval=0):
|
||||||
"""show parameter update"""
|
"""show parameter update"""
|
||||||
@ -215,15 +212,17 @@ class Module:
|
|||||||
def __call__(self, target=None):
|
def __call__(self, target=None):
|
||||||
if target is None:
|
if target is None:
|
||||||
return self.read()
|
return self.read()
|
||||||
self.target = target # this sets self._running
|
self.target = target # this sets self._is_driving
|
||||||
type(self).value.prev = None # show at least one value
|
type(self).value.prev = None # show at least one value
|
||||||
try:
|
try:
|
||||||
while self._running.get():
|
while self._is_driving:
|
||||||
|
self._driving_event.wait()
|
||||||
self._watch_parameter(self._name, 'value', mininterval=self._secnode.mininterval)
|
self._watch_parameter(self._name, 'value', mininterval=self._secnode.mininterval)
|
||||||
self._watch_parameter(self._name, 'status')
|
self._watch_parameter(self._name, 'status')
|
||||||
|
self._driving_event.clear()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
self.stop()
|
||||||
self._secnode.log.info('-- interrupted --')
|
self._secnode.log.info('-- interrupted --')
|
||||||
self._running = None
|
|
||||||
self._watch_parameter(self._name, 'status')
|
self._watch_parameter(self._name, 'status')
|
||||||
self._secnode.readParameter(self._name, 'value')
|
self._secnode.readParameter(self._name, 'value')
|
||||||
self._watch_parameter(self._name, 'value', forced=True)
|
self._watch_parameter(self._name, 'value', forced=True)
|
||||||
@ -269,10 +268,10 @@ class Param:
|
|||||||
return self.format(value)
|
return self.format(value)
|
||||||
|
|
||||||
def __set__(self, obj, value):
|
def __set__(self, obj, value):
|
||||||
if self.name == 'target':
|
|
||||||
obj._running = Queue()
|
|
||||||
try:
|
try:
|
||||||
obj._secnode.setParameter(obj._name, self.name, value)
|
obj._secnode.setParameter(obj._name, self.name, value)
|
||||||
|
if self.name == 'target':
|
||||||
|
obj._is_driving = obj._isBusy()
|
||||||
return
|
return
|
||||||
except SECoPError as e:
|
except SECoPError as e:
|
||||||
clientenv.raise_with_short_traceback(e)
|
clientenv.raise_with_short_traceback(e)
|
||||||
|
@ -142,6 +142,8 @@ class SeaClient(ProxyClient, Module):
|
|||||||
# make sure no more connect thread is running
|
# make sure no more connect thread is running
|
||||||
if self._connect_thread and self._connect_thread.isAlive():
|
if self._connect_thread and self._connect_thread.isAlive():
|
||||||
return
|
return
|
||||||
|
if not self._last_connect:
|
||||||
|
self.log.info('reconnect to SEA %s', self.service)
|
||||||
self._connect_thread = mkthread(self._connect, None)
|
self._connect_thread = mkthread(self._connect, None)
|
||||||
|
|
||||||
def register_obj(self, module, obj):
|
def register_obj(self, module, obj):
|
||||||
@ -151,6 +153,14 @@ class SeaClient(ProxyClient, Module):
|
|||||||
self.register_callback(module.name, module.updateEvent)
|
self.register_callback(module.name, module.updateEvent)
|
||||||
|
|
||||||
def _connect(self, started_callback):
|
def _connect(self, started_callback):
|
||||||
|
self.asynio = None
|
||||||
|
if self.syncio:
|
||||||
|
# trigger syncio reconnect in self.request()
|
||||||
|
try:
|
||||||
|
self.syncio.disconnect()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
self.syncio = None
|
||||||
self._last_connect = time.time()
|
self._last_connect = time.time()
|
||||||
if self._instance:
|
if self._instance:
|
||||||
if not self._service_manager:
|
if not self._service_manager:
|
||||||
@ -192,7 +202,9 @@ class SeaClient(ProxyClient, Module):
|
|||||||
self._connect_thread.join()
|
self._connect_thread.join()
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
self._connect(None)
|
# let doPoll do the reconnect
|
||||||
|
self.pollInfo.trigger(True)
|
||||||
|
raise ConnectionClosed('disconnected - reconnect later')
|
||||||
self.syncio = AsynConn(self.uri)
|
self.syncio = AsynConn(self.uri)
|
||||||
assert self.syncio.readline() == b'OK'
|
assert self.syncio.readline() == b'OK'
|
||||||
self.syncio.writeline(b'seauser seaser')
|
self.syncio.writeline(b'seauser seaser')
|
||||||
@ -232,6 +244,7 @@ class SeaClient(ProxyClient, Module):
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
self.syncio = None
|
self.syncio = None
|
||||||
|
raise
|
||||||
raise TimeoutError('no response within 10s')
|
raise TimeoutError('no response within 10s')
|
||||||
|
|
||||||
def _rxthread(self, started_callback):
|
def _rxthread(self, started_callback):
|
||||||
@ -681,6 +694,10 @@ class SeaDrivable(SeaModule, Drivable):
|
|||||||
_sea_status = ''
|
_sea_status = ''
|
||||||
_is_running = 0
|
_is_running = 0
|
||||||
|
|
||||||
|
def earlyInit(self):
|
||||||
|
super().earlyInit()
|
||||||
|
self._run_event = threading.Event()
|
||||||
|
|
||||||
def read_status(self):
|
def read_status(self):
|
||||||
return self.status
|
return self.status
|
||||||
|
|
||||||
@ -688,8 +705,10 @@ class SeaDrivable(SeaModule, Drivable):
|
|||||||
# return self.target
|
# return self.target
|
||||||
|
|
||||||
def write_target(self, value):
|
def write_target(self, value):
|
||||||
|
self._run_event.clear()
|
||||||
self.io.query(f'run {self.sea_object} {value}')
|
self.io.query(f'run {self.sea_object} {value}')
|
||||||
# self.status = [self.Status.BUSY, 'driving']
|
if not self._run_event.wait(5):
|
||||||
|
self.log.warn('target changed but is_running stays 0')
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def update_status(self, value, timestamp, readerror):
|
def update_status(self, value, timestamp, readerror):
|
||||||
@ -701,6 +720,8 @@ class SeaDrivable(SeaModule, Drivable):
|
|||||||
if not readerror:
|
if not readerror:
|
||||||
self._is_running = value
|
self._is_running = value
|
||||||
self.updateStatus()
|
self.updateStatus()
|
||||||
|
if value:
|
||||||
|
self._run_event.set()
|
||||||
|
|
||||||
def updateStatus(self):
|
def updateStatus(self):
|
||||||
if self._sea_status:
|
if self._sea_status:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user