rework of the server side
main change: the same server may be used for several instruments - client classes are 'Interactors' dealing with the parameters etc. - methods from history are added to the clients + improvements on the js client side
This commit is contained in:
165
secop.py
165
secop.py
@ -1,9 +1,8 @@
|
||||
import logging
|
||||
import uuid
|
||||
from base import Instrument, get_abs_time
|
||||
from frappy.client import SecopClient as SecNodeClient
|
||||
from frappy.lib.enum import EnumMember
|
||||
from frappy.datatypes import get_datatype
|
||||
from base import HandlerBase
|
||||
from frappy.client import SecopClient
|
||||
# from frappy.lib.enum import EnumMember
|
||||
# from frappy.datatypes import get_datatype
|
||||
|
||||
|
||||
def convert_par(module, name, par):
|
||||
@ -20,39 +19,38 @@ def convert_par(module, name, par):
|
||||
return result
|
||||
|
||||
|
||||
class SecopClient:
|
||||
class SecopInteractor(SecopClient):
|
||||
prio_par = ["value", "status", "target"]
|
||||
hide_par = ["baseclass", "class", "pollinterval"]
|
||||
skip_par = ["status2"]
|
||||
|
||||
def __init__(self, instrument):
|
||||
self.instrument = instrument
|
||||
self.id = uuid.uuid4().hex[0:15]
|
||||
def __init__(self, uri, node_map):
|
||||
super().__init__(uri)
|
||||
self.module_updates = set()
|
||||
self.param_updates = set()
|
||||
self.updates = {}
|
||||
|
||||
def w_getblock(self, path):
|
||||
path = path.split(',')[-1] # TODO: why this?
|
||||
if path == "main":
|
||||
components = [dict(type='rdlink', name=f'{name}:value', statusname=f'{name}:status', title=name)
|
||||
for node in self.instrument.nodes for name in node.modules]
|
||||
self.param_updates = {'value', 'status'}
|
||||
return dict(type='draw', path='main', title='modules', components=components)
|
||||
def add_main_components(self, components):
|
||||
# todo: treat non Readable classes correctly
|
||||
components.extend(dict(type='rdlink', name=name + ':value', title=name)
|
||||
for name in self.modules)
|
||||
self.param_updates.add('value')
|
||||
self.param_updates.add('status')
|
||||
|
||||
def get_components(self, path):
|
||||
module = self.modules[path]
|
||||
self.module_updates.add(path) # TODO: remove others?
|
||||
node = self.instrument.node_map[path]
|
||||
module = node.modules[path]
|
||||
# logging.info('MP %r', path)
|
||||
parameters = dict(module["parameters"])
|
||||
components = []
|
||||
for name in SecopClient.skip_par:
|
||||
for name in SecopInteractor.skip_par:
|
||||
if name in parameters:
|
||||
parameters.pop(name)
|
||||
for name in SecopClient.prio_par:
|
||||
for name in SecopInteractor.prio_par:
|
||||
if name in parameters:
|
||||
components.append(convert_par(path, name, parameters.pop(name)))
|
||||
components1 = []
|
||||
for name in SecopClient.hide_par:
|
||||
for name in SecopInteractor.hide_par:
|
||||
if name in parameters:
|
||||
components1.append(convert_par(path, name, parameters.pop(name)))
|
||||
for name, p in parameters.items():
|
||||
@ -72,27 +70,22 @@ class SecopClient:
|
||||
# print(item)
|
||||
self.updates[key] = item
|
||||
|
||||
def w_updateblock(self, path):
|
||||
if path == 'main':
|
||||
path = ''
|
||||
for node in self.instrument.nodes:
|
||||
for modname in node.modules:
|
||||
key = modname, 'value'
|
||||
if key in node.cache:
|
||||
self.updateItem(*key, node.cache[key])
|
||||
else:
|
||||
node = self.instrument.node_map[path]
|
||||
for param in node.modules[path]['parameters']:
|
||||
key = path, param
|
||||
if key in node.cache:
|
||||
self.updateItem(*key, node.cache[key])
|
||||
return dict(type='accept-block')
|
||||
def update_main(self):
|
||||
cache = self.cache
|
||||
for modname in self.modules:
|
||||
key = modname, 'value'
|
||||
if key in cache:
|
||||
self.updateItem(*key, cache[key])
|
||||
|
||||
def w_console(self):
|
||||
return dict(type='accept-console')
|
||||
def update_params(self, path):
|
||||
cache = self.cache
|
||||
for param in self.modules[path]['parameters']:
|
||||
key = path, param
|
||||
if key in cache:
|
||||
self.updateItem(*key, cache[key])
|
||||
|
||||
def w_sendcommand(self, command):
|
||||
logging.info('SENDCOMMAND %r', command)
|
||||
def handle_command(self, command):
|
||||
"""handle command if we can, else return False"""
|
||||
if not command.strip():
|
||||
return dict(type='accept-command')
|
||||
if command.startswith('change '):
|
||||
@ -101,62 +94,54 @@ class SecopClient:
|
||||
module, _, parameter = modpar.partition(':')
|
||||
if not parameter:
|
||||
parameter = 'target'
|
||||
node = self.instrument.node_map[module]
|
||||
if module not in self.modules:
|
||||
return False
|
||||
logging.info('SENDCOMMAND %r', command)
|
||||
try:
|
||||
node.setParameterFromString(module, parameter, strvalue)
|
||||
self.setParameterFromString(module, parameter, strvalue)
|
||||
except Exception as e:
|
||||
print(f"{e!r} converting {strvalue} to {node.modules[module]['parameters'][parameter]['datatype']}")
|
||||
return dict(type='accept-command')
|
||||
print(f"{e!r} converting {strvalue} to {self.modules[module]['parameters'][parameter]['datatype']}")
|
||||
return True
|
||||
|
||||
def w_gettime(self, time):
|
||||
"""parse time (using server time)
|
||||
time: comma separated time range (beg,end) values < 1 year are treated as relative to the current time
|
||||
"""
|
||||
time = [float(t) for t in time.split(',')]
|
||||
return dict(type='time', time=get_abs_time(time))
|
||||
|
||||
def poll(self):
|
||||
def get_updates(self):
|
||||
updates, self.updates = self.updates, {}
|
||||
if not updates:
|
||||
return []
|
||||
messages = [dict(type='update', updates=list(updates.values()))]
|
||||
return messages
|
||||
return list(updates.values())
|
||||
|
||||
def info(self):
|
||||
return ["na"]
|
||||
|
||||
|
||||
class SecopInstrument(Instrument):
|
||||
|
||||
def __init__(self, inst_name, instrument_config):
|
||||
super().__init__()
|
||||
self.instrument_config = instrument_config
|
||||
host_ports = instrument_config['hostport']
|
||||
self.logger_dir = instrument_config.get('logger_dir', '')
|
||||
# test_day = instrument_config.get('test_day', None)
|
||||
# self.test_day = [int(x) for x in test_day.split('-')] if test_day else None
|
||||
self.title = inst_name
|
||||
self.device = ''
|
||||
self.nodes = []
|
||||
self.node_map = {}
|
||||
for host_port in host_ports.split(','):
|
||||
node = SecNodeClient(host_port)
|
||||
node.connect()
|
||||
self.nodes.append(node)
|
||||
for name, mod in node.modules.items():
|
||||
self.node_map[name] = node
|
||||
|
||||
def register(self, client):
|
||||
print('OPEN')
|
||||
for node in self.nodes:
|
||||
node.register_callback(None, client.updateItem)
|
||||
return super().register(client)
|
||||
|
||||
def remove(self, client):
|
||||
print('REMOVE')
|
||||
for node in self.nodes:
|
||||
node.unregister_callback(None, client.updateItem)
|
||||
super().remove(client)
|
||||
|
||||
def new_client(self):
|
||||
return self.register(SecopClient(self))
|
||||
# class SecopInstrument(HandlerBase):
|
||||
#
|
||||
# def __init__(self, inst_name, instrument_config):
|
||||
# super().__init__()
|
||||
# self.instrument_config = instrument_config
|
||||
# host_ports = instrument_config['hostport']
|
||||
# self.logger_dir = instrument_config.get('logger_dir', '')
|
||||
# # test_day = instrument_config.get('test_day', None)
|
||||
# # self.test_day = [int(x) for x in test_day.split('-')] if test_day else None
|
||||
# self.title = inst_name
|
||||
# self.device = ''
|
||||
# self.nodes = []
|
||||
# self.node_map = {}
|
||||
# for host_port in host_ports.split(','):
|
||||
# node = SecopClient(host_port)
|
||||
# node.connect()
|
||||
# self.nodes.append(node)
|
||||
# for name, mod in node.modules.items():
|
||||
# self.node_map[name] = node
|
||||
#
|
||||
# def register(self, client):
|
||||
# print('OPEN')
|
||||
# for node in self.nodes:
|
||||
# node.register_callback(None, client.updateItem)
|
||||
# return super().register(client)
|
||||
#
|
||||
# def remove(self, client):
|
||||
# print('REMOVE')
|
||||
# for node in self.nodes:
|
||||
# node.unregister_callback(None, client.updateItem)
|
||||
# super().remove(client)
|
||||
#
|
||||
# def new_client(self):
|
||||
# return self.register(SecopClient(self))
|
||||
|
Reference in New Issue
Block a user