update secop_psi/sea.py
fixes after serveral changes in frappy
This commit is contained in:
parent
1ded96abba
commit
f9db90d89b
@ -71,6 +71,9 @@ class GeneralConfig:
|
|||||||
if configfile is None:
|
if configfile is None:
|
||||||
configfile = environ.get('FRAPPY_CONFIG_FILE',
|
configfile = environ.get('FRAPPY_CONFIG_FILE',
|
||||||
path.join(cfg['confdir'], 'generalConfig.cfg'))
|
path.join(cfg['confdir'], 'generalConfig.cfg'))
|
||||||
|
configfile = path.expanduser(configfile)
|
||||||
|
if not path.exists(configfile):
|
||||||
|
raise FileNotFoundError(configfile)
|
||||||
if configfile and path.exists(configfile):
|
if configfile and path.exists(configfile):
|
||||||
parser = ConfigParser()
|
parser = ConfigParser()
|
||||||
parser.optionxform = str
|
parser.optionxform = str
|
||||||
|
@ -40,8 +40,9 @@ from os.path import expanduser, join, exists
|
|||||||
from secop.client import ProxyClient
|
from secop.client import ProxyClient
|
||||||
from secop.datatypes import ArrayOf, BoolType, \
|
from secop.datatypes import ArrayOf, BoolType, \
|
||||||
EnumType, FloatRange, IntRange, StringType
|
EnumType, FloatRange, IntRange, StringType
|
||||||
from secop.errors import ConfigError, HardwareError, secop_error, NoSuchModuleError
|
from secop.errors import ConfigError, HardwareError, secop_error, NoSuchModuleError, \
|
||||||
from secop.lib import getGeneralConfig, mkthread, formatExtendedStack
|
CommunicationFailedError
|
||||||
|
from secop.lib import generalConfig, mkthread, formatExtendedStack
|
||||||
from secop.lib.asynconn import AsynConn, ConnectionClosed
|
from secop.lib.asynconn import AsynConn, ConnectionClosed
|
||||||
from secop.modules import Attached, Command, Done, Drivable, \
|
from secop.modules import Attached, Command, Done, Drivable, \
|
||||||
Module, Parameter, Property, Readable, Writable
|
Module, Parameter, Property, Readable, Writable
|
||||||
@ -73,7 +74,7 @@ SERVICE_NAMES = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SEA_DIR = expanduser('~/sea')
|
SEA_DIR = expanduser('~/sea')
|
||||||
for confdir in getGeneralConfig()['confdir'].split(os.pathsep):
|
for confdir in generalConfig.confdir.split(os.pathsep):
|
||||||
seaconfdir = join(confdir, 'sea')
|
seaconfdir = join(confdir, 'sea')
|
||||||
if exists(seaconfdir):
|
if exists(seaconfdir):
|
||||||
break
|
break
|
||||||
@ -108,6 +109,7 @@ class SeaClient(ProxyClient, Module):
|
|||||||
service = Property("main/stick/addons", StringType(), default='')
|
service = Property("main/stick/addons", StringType(), default='')
|
||||||
visibility = 'expert'
|
visibility = 'expert'
|
||||||
default_json_file = {}
|
default_json_file = {}
|
||||||
|
_connect_thread = None
|
||||||
|
|
||||||
def __init__(self, name, log, opts, srv):
|
def __init__(self, name, log, opts, srv):
|
||||||
instance = srv.node_cfg['name'].rsplit('_', 1)[0]
|
instance = srv.node_cfg['name'].rsplit('_', 1)[0]
|
||||||
@ -123,8 +125,8 @@ class SeaClient(ProxyClient, Module):
|
|||||||
config = opts.get('config')
|
config = opts.get('config')
|
||||||
if config:
|
if config:
|
||||||
self.default_json_file[name] = config.split()[0] + '.json'
|
self.default_json_file[name] = config.split()[0] + '.json'
|
||||||
self.io = None
|
self.syncio = None
|
||||||
self.asyncio = None
|
self.asynio = None
|
||||||
ProxyClient.__init__(self)
|
ProxyClient.__init__(self)
|
||||||
Module.__init__(self, name, log, opts, srv)
|
Module.__init__(self, name, log, opts, srv)
|
||||||
|
|
||||||
@ -133,42 +135,58 @@ class SeaClient(ProxyClient, Module):
|
|||||||
self.path2param.update(module.path2param)
|
self.path2param.update(module.path2param)
|
||||||
self.register_callback(module.name, module.updateEvent)
|
self.register_callback(module.name, module.updateEvent)
|
||||||
|
|
||||||
def startModule(self, started_callback):
|
def startModule(self, start_events):
|
||||||
mkthread(self._connect, started_callback)
|
super().startModule(start_events)
|
||||||
|
self._connect_thread = mkthread(self._connect, start_events.get_trigger())
|
||||||
|
|
||||||
def _connect(self, started_callback):
|
def _connect(self, started_callback):
|
||||||
if '//' not in self.uri:
|
if '//' not in self.uri:
|
||||||
self.uri = 'tcp://' + self.uri
|
self.uri = 'tcp://' + self.uri
|
||||||
self.asyncio = AsynConn(self.uri)
|
self.asynio = AsynConn(self.uri)
|
||||||
assert self.asyncio.readline() == b'OK'
|
# print('CONNECT', self.uri, self.asynio)
|
||||||
self.asyncio.writeline(b'Spy 007')
|
# print(formatExtendedStack())
|
||||||
assert self.asyncio.readline() == b'Login OK'
|
reply = self.asynio.readline()
|
||||||
|
if reply != b'OK':
|
||||||
|
raise CommunicationFailedError('reply %r should be "OK"' % reply)
|
||||||
|
for _ in range(2):
|
||||||
|
self.asynio.writeline(b'Spy 007')
|
||||||
|
reply = self.asynio.readline()
|
||||||
|
if reply == b'Login OK':
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
raise CommunicationFailedError('reply %r should be "Login OK"' % reply)
|
||||||
self.request('frappy_config %s %s' % (self.service, self.config))
|
self.request('frappy_config %s %s' % (self.service, self.config))
|
||||||
|
|
||||||
# frappy_async_client switches to the json protocol (better for updates)
|
# frappy_async_client switches to the json protocol (better for updates)
|
||||||
self.asyncio.writeline(b'frappy_async_client')
|
self.asynio.writeline(b'frappy_async_client')
|
||||||
self.asyncio.writeline(('get_all_param ' + ' '.join(self.objects)).encode())
|
self.asynio.writeline(('get_all_param ' + ' '.join(self.objects)).encode())
|
||||||
|
self._connect_thread = None
|
||||||
mkthread(self._rxthread, started_callback)
|
mkthread(self._rxthread, started_callback)
|
||||||
|
|
||||||
def request(self, command):
|
def request(self, command):
|
||||||
"""send a request and wait for reply"""
|
"""send a request and wait for reply"""
|
||||||
with self._write_lock:
|
with self._write_lock:
|
||||||
if not self.io or not self.io.connection:
|
if not self.syncio or not self.syncio.connection:
|
||||||
if not self.asyncio or not self.asyncio.connection:
|
if not self.asynio or not self.asynio.connection:
|
||||||
|
try:
|
||||||
|
self._connect_thread.join()
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
self._connect(None)
|
self._connect(None)
|
||||||
self.io = AsynConn(self.uri)
|
self.syncio = AsynConn(self.uri)
|
||||||
assert self.io.readline() == b'OK'
|
# print('SYNCIO', self.uri)
|
||||||
self.io.writeline(b'seauser seaser')
|
assert self.syncio.readline() == b'OK'
|
||||||
assert self.io.readline() == b'Login OK'
|
self.syncio.writeline(b'seauser seaser')
|
||||||
|
assert self.syncio.readline() == b'Login OK'
|
||||||
print('connected to %s' % self.uri)
|
print('connected to %s' % self.uri)
|
||||||
self.io.flush_recv()
|
self.syncio.flush_recv()
|
||||||
# print('> %s' % command)
|
# print('> %s' % command)
|
||||||
self.io.writeline(('fulltransact %s' % command).encode())
|
self.syncio.writeline(('fulltransact %s' % command).encode())
|
||||||
result = None
|
result = None
|
||||||
deadline = time.time() + 10
|
deadline = time.time() + 10
|
||||||
while time.time() < deadline:
|
while time.time() < deadline:
|
||||||
try:
|
try:
|
||||||
reply = self.io.readline()
|
reply = self.syncio.readline()
|
||||||
if reply is None:
|
if reply is None:
|
||||||
continue
|
continue
|
||||||
except ConnectionClosed:
|
except ConnectionClosed:
|
||||||
@ -197,7 +215,7 @@ class SeaClient(ProxyClient, Module):
|
|||||||
def _rxthread(self, started_callback):
|
def _rxthread(self, started_callback):
|
||||||
while not self.shutdown:
|
while not self.shutdown:
|
||||||
try:
|
try:
|
||||||
reply = self.asyncio.readline()
|
reply = self.asynio.readline()
|
||||||
if reply is None:
|
if reply is None:
|
||||||
continue
|
continue
|
||||||
except ConnectionClosed:
|
except ConnectionClosed:
|
||||||
@ -252,7 +270,7 @@ class SeaClient(ProxyClient, Module):
|
|||||||
if path == '/device/changetime':
|
if path == '/device/changetime':
|
||||||
result = self.request('check_config %s %s' % (self.service, self.config))
|
result = self.request('check_config %s %s' % (self.service, self.config))
|
||||||
if result == '1':
|
if result == '1':
|
||||||
self.asyncio.writeline(('get_all_param ' + ' '.join(self.objects)).encode())
|
self.asynio.writeline(('get_all_param ' + ' '.join(self.objects)).encode())
|
||||||
else:
|
else:
|
||||||
self.DISPATCHER.shutdown()
|
self.DISPATCHER.shutdown()
|
||||||
elif path.startswith('/device/frappy_%s' % self.service) and value == '':
|
elif path.startswith('/device/frappy_%s' % self.service) and value == '':
|
||||||
@ -293,7 +311,7 @@ class SeaClient(ProxyClient, Module):
|
|||||||
class SeaConfigCreator(SeaClient):
|
class SeaConfigCreator(SeaClient):
|
||||||
def startModule(self, started_callback):
|
def startModule(self, started_callback):
|
||||||
"""save objects (and sub-objects) description and exit"""
|
"""save objects (and sub-objects) description and exit"""
|
||||||
self._connect(lambda: None)
|
self._connect(None)
|
||||||
reply = self.request('describe_all')
|
reply = self.request('describe_all')
|
||||||
reply = ''.join('' if line.startswith('WARNING') else line for line in reply.split('\n'))
|
reply = ''.join('' if line.startswith('WARNING') else line for line in reply.split('\n'))
|
||||||
description, reply = json.loads(reply)
|
description, reply = json.loads(reply)
|
||||||
@ -369,7 +387,6 @@ def get_datatype(paramdesc):
|
|||||||
class SeaModule(Module):
|
class SeaModule(Module):
|
||||||
io = Attached()
|
io = Attached()
|
||||||
|
|
||||||
# pollerClass=None
|
|
||||||
path2param = None
|
path2param = None
|
||||||
sea_object = None
|
sea_object = None
|
||||||
hdbpath = None # hdbpath for main writable
|
hdbpath = None # hdbpath for main writable
|
||||||
@ -457,6 +474,7 @@ class SeaModule(Module):
|
|||||||
if issubclass(cls, SeaWritable):
|
if issubclass(cls, SeaWritable):
|
||||||
paramdesc = params[0]
|
paramdesc = params[0]
|
||||||
assert paramdesc['key'] == 'value'
|
assert paramdesc['key'] == 'value'
|
||||||
|
params.append(paramdesc.copy()) # copy value?
|
||||||
if paramdesc.get('readonly', True):
|
if paramdesc.get('readonly', True):
|
||||||
raise ConfigError('%s/%s is not writable' % (sea_object, paramdesc['path']))
|
raise ConfigError('%s/%s is not writable' % (sea_object, paramdesc['path']))
|
||||||
paramdesc['key'] = 'target'
|
paramdesc['key'] = 'target'
|
||||||
@ -476,10 +494,12 @@ class SeaModule(Module):
|
|||||||
path = paramdesc['path']
|
path = paramdesc['path']
|
||||||
readonly = paramdesc.get('readonly', True)
|
readonly = paramdesc.get('readonly', True)
|
||||||
dt = get_datatype(paramdesc)
|
dt = get_datatype(paramdesc)
|
||||||
|
#print('----', sea_object)
|
||||||
|
#print(dt, paramdesc)
|
||||||
kwds = dict(description=paramdesc.get('description', path),
|
kwds = dict(description=paramdesc.get('description', path),
|
||||||
datatype=dt,
|
datatype=dt,
|
||||||
visibility=paramdesc.get('visibility', 1),
|
visibility=paramdesc.get('visibility', 1),
|
||||||
needscfg=False, poll=False, readonly=readonly)
|
needscfg=False, readonly=readonly)
|
||||||
if kwds['datatype'] is None:
|
if kwds['datatype'] is None:
|
||||||
kwds.update(visibility=3, default='', datatype=StringType())
|
kwds.update(visibility=3, default='', datatype=StringType())
|
||||||
pathlist = path.split('/') if path else []
|
pathlist = path.split('/') if path else []
|
||||||
@ -531,6 +551,7 @@ class SeaModule(Module):
|
|||||||
# an updateEvent will be handled before above returns
|
# an updateEvent will be handled before above returns
|
||||||
return reply
|
return reply
|
||||||
|
|
||||||
|
rfunc.poll = False
|
||||||
attributes['read_' + key] = rfunc
|
attributes['read_' + key] = rfunc
|
||||||
|
|
||||||
if not readonly:
|
if not readonly:
|
||||||
@ -555,13 +576,11 @@ class SeaModule(Module):
|
|||||||
attributes[pname] = pobj
|
attributes[pname] = pobj
|
||||||
pobj.__set_name__(cls, pname)
|
pobj.__set_name__(cls, pname)
|
||||||
elif pname not in attributes and isinstance(pobj, Parameter):
|
elif pname not in attributes and isinstance(pobj, Parameter):
|
||||||
pobj.poll = False
|
|
||||||
pobj.needscfg = False
|
pobj.needscfg = False
|
||||||
attributes[pname] = pobj
|
attributes[pname] = pobj
|
||||||
pobj.__set_name__(cls, pname)
|
pobj.__set_name__(cls, pname)
|
||||||
|
|
||||||
classname = '%s_%s' % (cls.__name__, sea_object)
|
classname = '%s_%s' % (cls.__name__, sea_object)
|
||||||
attributes['pollerClass'] = None
|
|
||||||
newcls = type(classname, (cls,), attributes)
|
newcls = type(classname, (cls,), attributes)
|
||||||
return Module.__new__(newcls)
|
return Module.__new__(newcls)
|
||||||
|
|
||||||
@ -592,6 +611,9 @@ class SeaModule(Module):
|
|||||||
self.io.register_obj(self, self.sea_object)
|
self.io.register_obj(self, self.sea_object)
|
||||||
super().initModule()
|
super().initModule()
|
||||||
|
|
||||||
|
def doPoll(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class SeaReadable(SeaModule, Readable):
|
class SeaReadable(SeaModule, Readable):
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user