allow multiple SecNode connections

+ change layout when console is not to be shown
+ catch file not found error
This commit is contained in:
l_samenv
2024-09-25 16:31:58 +02:00
parent 96bcd67dc4
commit 69ea17aec6
3 changed files with 95 additions and 53 deletions

View File

@ -73,10 +73,10 @@ new Settings()
.treat("debugGraphics", "dg", to_bool, false)
.treat("hostPort", "hp", 0, location.hostname + ":" + location.port)
.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("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("showAsync", "sa", to_bool, false)

View File

@ -94,7 +94,7 @@ function adjustGrid() {
case 2:
rightWidth = Math.min(50, MINWIDTH / width * 100);
leftWidth = 100 - rightWidth;
if (nRows == 1) {
if (nRows == 1 || !window['showConsole']) {
style(0,leftWidth + "vw","100vh");
style(1,rightWidth + "vw","100vh");
style(2); // hide
@ -109,7 +109,7 @@ function adjustGrid() {
case 3:
rightWidth = MINWIDTH / width * 100;
leftWidth = 100 - rightWidth;
if (nRows == 1) {
if (nRows == 1 || !window['showConsole']) {
style(0,leftWidth + "vw","100vh");
style(1,rightWidth + "vw","100vh");
style(2); // hide
@ -124,11 +124,16 @@ function adjustGrid() {
case 4:
rightWidth = MINWIDTH / width * 100;
leftWidth = 100 - 2 * rightWidth;
if (nRows == 1) {
if (nRows == 1 || !window['showConsole']) {
style(0,leftWidth + "vw","100vh");
style(1,rightWidth + "vw","100vh");
style(2); // hide
style(3,rightWidth + "vw","100vh");
if (window['showConsole']) {
style(2); // hide
style(3,rightWidth + "vw","100vh");
} else {
style(2,rightWidth + "vw","100vh");
style(3); // hide
}
} else {
style(0,leftWidth + "vw","100vh");
style(1,rightWidth + "vw","50vh");

129
seaweb.py
View File

@ -133,13 +133,12 @@ def export():
id = kwargs.pop('id')
client = instrument.clients[id]
bytes = client.w_export(**kwargs)
return flask.send_file(
bytes,
as_attachment=True,
download_name='export.tsv',
mimetype='text/tab-separated-values'
)
)
except Exception as e:
logging.error('%s', traceback.format_exc())
@ -213,7 +212,11 @@ def default():
@app.route('/<file>')
def general_file(file):
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';"
return resp
@ -920,21 +923,18 @@ def convert_event(messages):
for msg in messages:
if msg.type == 'update':
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])))
return [dict(type='update', updates=updates)]
class SecopClient:
prio_par = ["value", "status", "target"]
hide_par = ["baseclass", "class", "pollinterval"]
skip_par = ["status2"]
class SecNodeClient:
def __init__(self, host_port):
self.linesocket = tcp_lineserver.LineClient(host_port)
self.id = uuid.uuid4().hex[0:15]
self.linesocket = tcp_lineserver.LineClient(hostport_split(host_port))
self.consolequeue = []
self.queue = []
self.syncreply = []
self.consolequeue = []
#self.out = open("debug.txt", "w")
#self.out = sys.stdout
self.out = None
@ -948,45 +948,83 @@ class SecopClient:
self.consolequeue.append(dict(type='command',line=command,origin='self'))
self.linesocket.send_line(command)
t = 0
delta = 0.001
while True:
if self.syncreply:
msg = self.syncreply.pop(0)
break
line = self.linesocket.get_line()
if line != None:
if not line.startswith('update'):
if line is not None:
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)
#print '<', msg.type, msg.par
if msg.asynch: # and replytype != msg['type'] + "=" + msg.par:
t = 0
self.queue.append(msg)
else:
break
if t >= tmo:
#print 'TIMEOUT'
raise Exception("timeout")
gevent.sleep(0.001)
t += 0.001
#print 'REPLY', msg['type'], msg.par, json.dumps(msg.value)[0:50]
gevent.sleep(delta)
t += delta
delta += 0.001
if not replytype.startswith(msg.type):
logging.error('REPLY MISMATCH %s <> %s', replytype, repr(msg))
self.replytype = ""
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):
path = path.split(',')[-1]
if path == "main":
components = []
for name, m in self.description["modules"].items():
#components.append(convert_par(name, 'value', m['parameters']['value']))
components.append(dict(type='rdlink', name=name+':value', title=name))
for node in self.nodes:
for name, m in node.description["modules"].items():
#components.append(convert_par(name, 'value', m['parameters']['value']))
components.append(dict(type='rdlink', name=name+':value', title=name))
#print components
return dict(type='draw', path='main', title='modules', components=components)
else:
module = self.description['modules'][path]
logging.info('MP %r %r', path, module)
node = self.node_map[path]
module = node.description['modules'][path]
logging.info('MP %r %r', path)
parameters = dict(module["accessibles"])
components = []
for name in SecopClient.skip_par:
@ -1007,48 +1045,40 @@ class SecopClient:
def w_updateblock(self, path):
if path == 'main':
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')
def w_console(self):
return dict(type='accept-console')
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)
if not command.strip():
return dict(type='accept-command')
# cmd = "change " + 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):
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'):
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 []
messages = []
for node in self.nodes:
messages.extend(node.poll())
return messages
def info(self):
return ["na"]
class SecopInstrument(Instrument):
def __init__(self, inst_name, 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', '')
#test_day = instrument_config.get('test_day', 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 = {}
def newClient(self):
return self.register(SecopClient(self.host_port))
return self.register(SecopClient(self.host_ports))
class SecopInfluxClient(SecopClient, InfluxGraph):
def __init__(self):
SecopClient.__init__(self, instrument.host_port)
SecopClient.__init__(self, instrument.host_ports)
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):