allow multiple SecNode connections
+ change layout when console is not to be shown + catch file not found error
This commit is contained in:
@ -73,10 +73,10 @@ new Settings()
|
|||||||
.treat("debugGraphics", "dg", to_bool, false)
|
.treat("debugGraphics", "dg", to_bool, false)
|
||||||
.treat("hostPort", "hp", 0, location.hostname + ":" + location.port)
|
.treat("hostPort", "hp", 0, location.hostname + ":" + location.port)
|
||||||
.treat("showMain", "sm", to_bool, true)
|
.treat("showMain", "sm", to_bool, true)
|
||||||
.treat("showConsole", "sc", to_bool, true)
|
.treat("showConsole", "sc", to_bool, false)
|
||||||
.treat("showOverview", "so", to_bool, false)
|
.treat("showOverview", "so", to_bool, false)
|
||||||
.treat("showGraphics", "sg", to_bool, true) // false)
|
.treat("showGraphics", "sg", to_bool, true) // false)
|
||||||
.treat("hideRightPart", "hr", to_bool, true) //used to completely disable the right part
|
.treat("hideRightPart", "hr", to_bool, false) //used to completely disable the right part
|
||||||
.treat("wideGraphs", "wg", to_bool, false) //used to toggle the size of the graphs part
|
.treat("wideGraphs", "wg", to_bool, false) //used to toggle the size of the graphs part
|
||||||
.treat("showAsync", "sa", to_bool, false)
|
.treat("showAsync", "sa", to_bool, false)
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ function adjustGrid() {
|
|||||||
case 2:
|
case 2:
|
||||||
rightWidth = Math.min(50, MINWIDTH / width * 100);
|
rightWidth = Math.min(50, MINWIDTH / width * 100);
|
||||||
leftWidth = 100 - rightWidth;
|
leftWidth = 100 - rightWidth;
|
||||||
if (nRows == 1) {
|
if (nRows == 1 || !window['showConsole']) {
|
||||||
style(0,leftWidth + "vw","100vh");
|
style(0,leftWidth + "vw","100vh");
|
||||||
style(1,rightWidth + "vw","100vh");
|
style(1,rightWidth + "vw","100vh");
|
||||||
style(2); // hide
|
style(2); // hide
|
||||||
@ -109,7 +109,7 @@ function adjustGrid() {
|
|||||||
case 3:
|
case 3:
|
||||||
rightWidth = MINWIDTH / width * 100;
|
rightWidth = MINWIDTH / width * 100;
|
||||||
leftWidth = 100 - rightWidth;
|
leftWidth = 100 - rightWidth;
|
||||||
if (nRows == 1) {
|
if (nRows == 1 || !window['showConsole']) {
|
||||||
style(0,leftWidth + "vw","100vh");
|
style(0,leftWidth + "vw","100vh");
|
||||||
style(1,rightWidth + "vw","100vh");
|
style(1,rightWidth + "vw","100vh");
|
||||||
style(2); // hide
|
style(2); // hide
|
||||||
@ -124,11 +124,16 @@ function adjustGrid() {
|
|||||||
case 4:
|
case 4:
|
||||||
rightWidth = MINWIDTH / width * 100;
|
rightWidth = MINWIDTH / width * 100;
|
||||||
leftWidth = 100 - 2 * rightWidth;
|
leftWidth = 100 - 2 * rightWidth;
|
||||||
if (nRows == 1) {
|
if (nRows == 1 || !window['showConsole']) {
|
||||||
style(0,leftWidth + "vw","100vh");
|
style(0,leftWidth + "vw","100vh");
|
||||||
style(1,rightWidth + "vw","100vh");
|
style(1,rightWidth + "vw","100vh");
|
||||||
style(2); // hide
|
if (window['showConsole']) {
|
||||||
style(3,rightWidth + "vw","100vh");
|
style(2); // hide
|
||||||
|
style(3,rightWidth + "vw","100vh");
|
||||||
|
} else {
|
||||||
|
style(2,rightWidth + "vw","100vh");
|
||||||
|
style(3); // hide
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
style(0,leftWidth + "vw","100vh");
|
style(0,leftWidth + "vw","100vh");
|
||||||
style(1,rightWidth + "vw","50vh");
|
style(1,rightWidth + "vw","50vh");
|
||||||
|
129
seaweb.py
129
seaweb.py
@ -133,13 +133,12 @@ def export():
|
|||||||
id = kwargs.pop('id')
|
id = kwargs.pop('id')
|
||||||
client = instrument.clients[id]
|
client = instrument.clients[id]
|
||||||
bytes = client.w_export(**kwargs)
|
bytes = client.w_export(**kwargs)
|
||||||
|
|
||||||
return flask.send_file(
|
return flask.send_file(
|
||||||
bytes,
|
bytes,
|
||||||
as_attachment=True,
|
as_attachment=True,
|
||||||
download_name='export.tsv',
|
download_name='export.tsv',
|
||||||
mimetype='text/tab-separated-values'
|
mimetype='text/tab-separated-values'
|
||||||
)
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error('%s', traceback.format_exc())
|
logging.error('%s', traceback.format_exc())
|
||||||
@ -213,7 +212,11 @@ def default():
|
|||||||
@app.route('/<file>')
|
@app.route('/<file>')
|
||||||
def general_file(file):
|
def general_file(file):
|
||||||
subdir = "client/"
|
subdir = "client/"
|
||||||
resp = flask.send_file(subdir+file, mimetype=guess_mimetype(file))
|
try:
|
||||||
|
resp = flask.send_file(subdir+file, mimetype=guess_mimetype(file))
|
||||||
|
except FileNotFoundError:
|
||||||
|
logging.warning('file %s not found', file)
|
||||||
|
return 'file not found'
|
||||||
#resp.headers['Content-Security-Policy'] = "sandbox; script-src 'unsafe-inline';"
|
#resp.headers['Content-Security-Policy'] = "sandbox; script-src 'unsafe-inline';"
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
@ -920,21 +923,18 @@ def convert_event(messages):
|
|||||||
for msg in messages:
|
for msg in messages:
|
||||||
if msg.type == 'update':
|
if msg.type == 'update':
|
||||||
updates.append(dict(name=msg.par, value=msg.value[0]))
|
updates.append(dict(name=msg.par, value=msg.value[0]))
|
||||||
|
elif msg.type == 'error_update':
|
||||||
|
updates.append(dict(name=msg.par, value=f'{msg.value[0]} - {msg.value[1]}'))
|
||||||
# updates.append(dict(name=msg.par, value=str(msg.value[0])))
|
# updates.append(dict(name=msg.par, value=str(msg.value[0])))
|
||||||
return [dict(type='update', updates=updates)]
|
return [dict(type='update', updates=updates)]
|
||||||
|
|
||||||
|
|
||||||
class SecopClient:
|
class SecNodeClient:
|
||||||
prio_par = ["value", "status", "target"]
|
|
||||||
hide_par = ["baseclass", "class", "pollinterval"]
|
|
||||||
skip_par = ["status2"]
|
|
||||||
|
|
||||||
def __init__(self, host_port):
|
def __init__(self, host_port):
|
||||||
self.linesocket = tcp_lineserver.LineClient(host_port)
|
self.linesocket = tcp_lineserver.LineClient(hostport_split(host_port))
|
||||||
self.id = uuid.uuid4().hex[0:15]
|
self.consolequeue = []
|
||||||
self.queue = []
|
self.queue = []
|
||||||
self.syncreply = []
|
self.syncreply = []
|
||||||
self.consolequeue = []
|
|
||||||
#self.out = open("debug.txt", "w")
|
#self.out = open("debug.txt", "w")
|
||||||
#self.out = sys.stdout
|
#self.out = sys.stdout
|
||||||
self.out = None
|
self.out = None
|
||||||
@ -948,45 +948,83 @@ class SecopClient:
|
|||||||
self.consolequeue.append(dict(type='command',line=command,origin='self'))
|
self.consolequeue.append(dict(type='command',line=command,origin='self'))
|
||||||
self.linesocket.send_line(command)
|
self.linesocket.send_line(command)
|
||||||
t = 0
|
t = 0
|
||||||
|
delta = 0.001
|
||||||
while True:
|
while True:
|
||||||
if self.syncreply:
|
if self.syncreply:
|
||||||
msg = self.syncreply.pop(0)
|
msg = self.syncreply.pop(0)
|
||||||
break
|
break
|
||||||
line = self.linesocket.get_line()
|
line = self.linesocket.get_line()
|
||||||
if line != None:
|
if line is not None:
|
||||||
if not line.startswith('update'):
|
if not line.startswith(('update', 'error_update')):
|
||||||
self.consolequeue.append(dict(type='reply',line=line,origin='other'))
|
self.consolequeue.append(dict(type='reply',line=line,origin='other'))
|
||||||
if self.out: self.out.write("<"+line+"\n")
|
if self.out: self.out.write("<"+line+"\n")
|
||||||
msg = SecopMsg(line)
|
msg = SecopMsg(line)
|
||||||
#print '<', msg.type, msg.par
|
|
||||||
if msg.asynch: # and replytype != msg['type'] + "=" + msg.par:
|
if msg.asynch: # and replytype != msg['type'] + "=" + msg.par:
|
||||||
t = 0
|
t = 0
|
||||||
self.queue.append(msg)
|
self.queue.append(msg)
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
if t >= tmo:
|
if t >= tmo:
|
||||||
#print 'TIMEOUT'
|
|
||||||
raise Exception("timeout")
|
raise Exception("timeout")
|
||||||
gevent.sleep(0.001)
|
gevent.sleep(delta)
|
||||||
t += 0.001
|
t += delta
|
||||||
#print 'REPLY', msg['type'], msg.par, json.dumps(msg.value)[0:50]
|
delta += 0.001
|
||||||
if not replytype.startswith(msg.type):
|
if not replytype.startswith(msg.type):
|
||||||
logging.error('REPLY MISMATCH %s <> %s', replytype, repr(msg))
|
logging.error('REPLY MISMATCH %s <> %s', replytype, repr(msg))
|
||||||
self.replytype = ""
|
self.replytype = ""
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
def poll(self):
|
||||||
|
if self.consolequeue:
|
||||||
|
messages = self.consolequeue
|
||||||
|
self.consolequeue = []
|
||||||
|
return messages
|
||||||
|
if self.queue:
|
||||||
|
messages = convert_event(self.queue)
|
||||||
|
self.queue = []
|
||||||
|
return messages
|
||||||
|
line = self.linesocket.get_line()
|
||||||
|
if line:
|
||||||
|
if not line.startswith(('update', 'error_update')):
|
||||||
|
self.consolequeue.append(dict(type='reply',line=line,origin='other'))
|
||||||
|
if self.out: self.out.write("<"+line+"\n")
|
||||||
|
msg = SecopMsg(line)
|
||||||
|
if msg.asynch: # and self.replytype != msg['type'] + "=" + msg.par:
|
||||||
|
return convert_event(SecopMsg(line))
|
||||||
|
self.syncreply.append(msg)
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class SecopClient:
|
||||||
|
prio_par = ["value", "status", "target"]
|
||||||
|
hide_par = ["baseclass", "class", "pollinterval"]
|
||||||
|
skip_par = ["status2"]
|
||||||
|
|
||||||
|
def __init__(self, host_ports):
|
||||||
|
self.nodes = []
|
||||||
|
self.node_map = {}
|
||||||
|
for host_port in host_ports.split(','):
|
||||||
|
node = SecNodeClient(host_port)
|
||||||
|
self.nodes.append(node)
|
||||||
|
for name, mod in node.description["modules"].items():
|
||||||
|
self.node_map[name] = node
|
||||||
|
self.id = uuid.uuid4().hex[0:15]
|
||||||
|
|
||||||
def w_getblock(self, path):
|
def w_getblock(self, path):
|
||||||
path = path.split(',')[-1]
|
path = path.split(',')[-1]
|
||||||
if path == "main":
|
if path == "main":
|
||||||
components = []
|
components = []
|
||||||
for name, m in self.description["modules"].items():
|
for node in self.nodes:
|
||||||
#components.append(convert_par(name, 'value', m['parameters']['value']))
|
for name, m in node.description["modules"].items():
|
||||||
components.append(dict(type='rdlink', name=name+':value', title=name))
|
#components.append(convert_par(name, 'value', m['parameters']['value']))
|
||||||
|
components.append(dict(type='rdlink', name=name+':value', title=name))
|
||||||
#print components
|
#print components
|
||||||
return dict(type='draw', path='main', title='modules', components=components)
|
return dict(type='draw', path='main', title='modules', components=components)
|
||||||
else:
|
else:
|
||||||
module = self.description['modules'][path]
|
node = self.node_map[path]
|
||||||
logging.info('MP %r %r', path, module)
|
module = node.description['modules'][path]
|
||||||
|
logging.info('MP %r %r', path)
|
||||||
parameters = dict(module["accessibles"])
|
parameters = dict(module["accessibles"])
|
||||||
components = []
|
components = []
|
||||||
for name in SecopClient.skip_par:
|
for name in SecopClient.skip_par:
|
||||||
@ -1007,48 +1045,40 @@ class SecopClient:
|
|||||||
def w_updateblock(self, path):
|
def w_updateblock(self, path):
|
||||||
if path == 'main':
|
if path == 'main':
|
||||||
path = ''
|
path = ''
|
||||||
self.cmd_reply(f"activate {path}", "active")
|
for node in self.nodes:
|
||||||
|
node.cmd_reply(f"activate", "active")
|
||||||
|
else:
|
||||||
|
node = self.node_map[path]
|
||||||
|
node.cmd_reply(f"activate {path}", "active")
|
||||||
return dict(type='accept-block')
|
return dict(type='accept-block')
|
||||||
|
|
||||||
def w_console(self):
|
def w_console(self):
|
||||||
return dict(type='accept-console')
|
return dict(type='accept-console')
|
||||||
|
|
||||||
def w_sendcommand(self, command):
|
def w_sendcommand(self, command):
|
||||||
|
# TODO: if not obsolete: add node to command. now its always sending to the first node
|
||||||
logging.info('SENDCOMMAND %r', command)
|
logging.info('SENDCOMMAND %r', command)
|
||||||
if not command.strip():
|
if not command.strip():
|
||||||
return dict(type='accept-command')
|
return dict(type='accept-command')
|
||||||
# cmd = "change " + command
|
# cmd = "change " + command
|
||||||
cmd = command
|
cmd = command
|
||||||
return self.cmd_reply(cmd, 'event ' + command.split(' ')[0])
|
return self.nodes[0].cmd_reply(cmd, 'event ' + command.split(' ')[0])
|
||||||
|
|
||||||
def poll(self):
|
def poll(self):
|
||||||
if self.consolequeue:
|
messages = []
|
||||||
messages = self.consolequeue
|
for node in self.nodes:
|
||||||
self.consolequeue = []
|
messages.extend(node.poll())
|
||||||
return messages
|
return messages
|
||||||
if self.queue:
|
|
||||||
messages = convert_event(self.queue)
|
|
||||||
self.queue = []
|
|
||||||
return messages
|
|
||||||
line = self.linesocket.get_line()
|
|
||||||
if line:
|
|
||||||
if not line.startswith('update'):
|
|
||||||
self.consolequeue.append(dict(type='reply',line=line,origin='other'))
|
|
||||||
if self.out: self.out.write("<"+line+"\n")
|
|
||||||
msg = SecopMsg(line)
|
|
||||||
if msg.asynch: # and self.replytype != msg['type'] + "=" + msg.par:
|
|
||||||
return convert_event(SecopMsg(line))
|
|
||||||
self.syncreply.append(msg)
|
|
||||||
return []
|
|
||||||
|
|
||||||
def info(self):
|
def info(self):
|
||||||
return ["na"]
|
return ["na"]
|
||||||
|
|
||||||
|
|
||||||
class SecopInstrument(Instrument):
|
class SecopInstrument(Instrument):
|
||||||
|
|
||||||
def __init__(self, inst_name, instrument_config):
|
def __init__(self, inst_name, instrument_config):
|
||||||
self.instrument_config = instrument_config
|
self.instrument_config = instrument_config
|
||||||
self.host_port = hostport_split(instrument_config['hostport'])
|
self.host_ports = instrument_config['hostport']
|
||||||
self.logger_dir = instrument_config.get('logger_dir', '')
|
self.logger_dir = instrument_config.get('logger_dir', '')
|
||||||
#test_day = instrument_config.get('test_day', None)
|
#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.test_day = [int(x) for x in test_day.split('-')] if test_day else None
|
||||||
@ -1056,14 +1086,21 @@ class SecopInstrument(Instrument):
|
|||||||
self.clients = {}
|
self.clients = {}
|
||||||
|
|
||||||
def newClient(self):
|
def newClient(self):
|
||||||
return self.register(SecopClient(self.host_port))
|
return self.register(SecopClient(self.host_ports))
|
||||||
|
|
||||||
|
|
||||||
class SecopInfluxClient(SecopClient, InfluxGraph):
|
class SecopInfluxClient(SecopClient, InfluxGraph):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
SecopClient.__init__(self, instrument.host_port)
|
SecopClient.__init__(self, instrument.host_ports)
|
||||||
InfluxGraph.__init__(self, instrument.influx_data_getter, instrument.title)
|
InfluxGraph.__init__(self, instrument.influx_data_getter, instrument.title)
|
||||||
|
|
||||||
|
def poll(self):
|
||||||
|
messages = super().poll()
|
||||||
|
msg = self.graphpoll()
|
||||||
|
if msg:
|
||||||
|
messages.append(msg)
|
||||||
|
return messages
|
||||||
|
|
||||||
|
|
||||||
class SecopInfluxInstrument(SecopInstrument):
|
class SecopInfluxInstrument(SecopInstrument):
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user