make Graphics work again
as base for Mathis work
This commit is contained in:
@ -300,7 +300,8 @@ function successHandler(s, message) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (message.path == '_overview') {
|
} else if (message.path == '_overview') {
|
||||||
isl = insertSlide(s, message.title, "_overview", createContent(sLocal, message));
|
// remove comment of next line when you want overview _instead_ of Graphics
|
||||||
|
// isl = insertSlide(s, message.title, "_overview", createContent(sLocal, message));
|
||||||
// swiper[sLocal].slideTo(isl); /* go to found slide */
|
// swiper[sLocal].slideTo(isl); /* go to found slide */
|
||||||
} else {
|
} else {
|
||||||
// insertSlide(s, message.title, message.path, createContent(s, message));
|
// insertSlide(s, message.title, message.path, createContent(s, message));
|
||||||
|
@ -276,7 +276,7 @@ let graphs = (function (){
|
|||||||
tag_dict[block.tag] = gindex;
|
tag_dict[block.tag] = gindex;
|
||||||
let dict = {}
|
let dict = {}
|
||||||
for (let curve of block.curves) {
|
for (let curve of block.curves) {
|
||||||
if (curve.show) {
|
if (curve.show !== false) {
|
||||||
vars_array[gindex].push(curve.name);
|
vars_array[gindex].push(curve.name);
|
||||||
dict[curve.name] = curve;
|
dict[curve.name] = curve;
|
||||||
}
|
}
|
||||||
@ -752,7 +752,7 @@ let graphs = (function (){
|
|||||||
}
|
}
|
||||||
// this block is either not shown or only in a hidden graph
|
// this block is either not shown or only in a hidden graph
|
||||||
for (let curve of block.curves) {
|
for (let curve of block.curves) {
|
||||||
if (curve.show) shown = true;
|
if (curve.show !== false) shown = true;
|
||||||
}
|
}
|
||||||
if (shown) break;
|
if (shown) break;
|
||||||
}
|
}
|
||||||
@ -834,6 +834,7 @@ let graphs = (function (){
|
|||||||
panCallback: panCallback,
|
panCallback: panCallback,
|
||||||
receivedVars: receivedVars,
|
receivedVars: receivedVars,
|
||||||
createSelection: createSelection,
|
createSelection: createSelection,
|
||||||
|
createGraphs: createGraphs,
|
||||||
doUpdates: function(){return liveMode},
|
doUpdates: function(){return liveMode},
|
||||||
update: update,
|
update: update,
|
||||||
updateAuto: updateAuto,
|
updateAuto: updateAuto,
|
||||||
|
@ -41,9 +41,9 @@ function createContent(s, message) {
|
|||||||
for (var i = 0; i < message.components.length; i++) {
|
for (var i = 0; i < message.components.length; i++) {
|
||||||
var component = message.components[i];
|
var component = message.components[i];
|
||||||
if (!("title" in component))
|
if (!("title" in component))
|
||||||
component.title = name;
|
component.title = component.name;
|
||||||
if (!("command" in component))
|
if (!("command" in component))
|
||||||
component.command = name;
|
component.command = component.name;
|
||||||
createFunc = window['create_' + component.type + '_row']
|
createFunc = window['create_' + component.type + '_row']
|
||||||
if (createFunc)
|
if (createFunc)
|
||||||
content.appendChild(createFunc(s, component))
|
content.appendChild(createFunc(s, component))
|
||||||
|
@ -75,7 +75,7 @@ new Settings()
|
|||||||
.treat("showMain", "sm", to_bool, true)
|
.treat("showMain", "sm", to_bool, true)
|
||||||
.treat("showConsole", "sc", to_bool, true)
|
.treat("showConsole", "sc", to_bool, true)
|
||||||
.treat("showOverview", "so", to_bool, true)
|
.treat("showOverview", "so", to_bool, true)
|
||||||
.treat("showGraphics", "sg", to_bool, false)
|
.treat("showGraphics", "sg", to_bool, true) // false)
|
||||||
.treat("showAsync", "sa", to_bool, false)
|
.treat("showAsync", "sa", to_bool, false)
|
||||||
|
|
||||||
function loadFirstBlocks() {
|
function loadFirstBlocks() {
|
||||||
|
@ -53,6 +53,7 @@ class Scanner(object):
|
|||||||
if t > to:
|
if t > to:
|
||||||
break
|
break
|
||||||
except IOError:
|
except IOError:
|
||||||
|
# print(f'error reading {path}')
|
||||||
pass
|
pass
|
||||||
if t < start:
|
if t < start:
|
||||||
#if t == 0:
|
#if t == 0:
|
||||||
|
170
seaweb.py
170
seaweb.py
@ -37,14 +37,13 @@ def guess_mimetype(filename):
|
|||||||
mimetype = 'text/css'
|
mimetype = 'text/css'
|
||||||
elif filename.endswith('.ico'):
|
elif filename.endswith('.ico'):
|
||||||
mimetype = 'image/x-icon'
|
mimetype = 'image/x-icon'
|
||||||
print('mimetype', mimetype)
|
|
||||||
else:
|
else:
|
||||||
mimetype = 'text/html'
|
mimetype = 'text/html'
|
||||||
return mimetype
|
return mimetype
|
||||||
|
|
||||||
#class SeawebException(Exception):
|
#class SeawebException(Exception):
|
||||||
# pass
|
# pass
|
||||||
|
|
||||||
# SSE 'protocol' is described here: http://mzl.la/UPFyxY
|
# SSE 'protocol' is described here: http://mzl.la/UPFyxY
|
||||||
def to_json_sse(msg):
|
def to_json_sse(msg):
|
||||||
txt = json.dumps(msg, separators=(',',': '))
|
txt = json.dumps(msg, separators=(',',': '))
|
||||||
@ -60,12 +59,14 @@ def get_update(path=None):
|
|||||||
# Client Adress: socket.getfqdn(flask.request.remote_addr)
|
# Client Adress: socket.getfqdn(flask.request.remote_addr)
|
||||||
client = instrument.newClient()
|
client = instrument.newClient()
|
||||||
client.remote_info = circularlog.strtm() + " " + socket.getfqdn(flask.request.remote_addr.split(':')[-1])
|
client.remote_info = circularlog.strtm() + " " + socket.getfqdn(flask.request.remote_addr.split(':')[-1])
|
||||||
|
|
||||||
@flask.stream_with_context
|
@flask.stream_with_context
|
||||||
def generator():
|
def generator():
|
||||||
logging.info('UPDATE %s %s', client.id, socket.getfqdn(flask.request.remote_addr.split(':')[-1]))
|
logging.info('UPDATE %s %s', client.id, socket.getfqdn(flask.request.remote_addr.split(':')[-1]))
|
||||||
#msg = dict(type='id', id=client.id, title=instrument.title);
|
#msg = dict(type='id', id=client.id, title=instrument.title);
|
||||||
#yield to_json_sse(msg)
|
#yield to_json_sse(msg)
|
||||||
|
msg = dict(type='id', id=client.id, instrument=instrument.title, device=instrument.device);
|
||||||
|
yield to_json_sse(msg)
|
||||||
try:
|
try:
|
||||||
lastmsg = time.time()
|
lastmsg = time.time()
|
||||||
while True:
|
while True:
|
||||||
@ -113,7 +114,7 @@ def show_clients():
|
|||||||
c = instrument.clients[id]
|
c = instrument.clients[id]
|
||||||
result += c.remote_info + " " + "; ".join(c.info()) + "<br>"
|
result += c.remote_info + " " + "; ".join(c.info()) + "<br>"
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@app.route('/getblock')
|
@app.route('/getblock')
|
||||||
@app.route('/updateblock')
|
@app.route('/updateblock')
|
||||||
@app.route('/sendcommand')
|
@app.route('/sendcommand')
|
||||||
@ -220,7 +221,8 @@ def sea_request_reply(socket, command, tmo=5):
|
|||||||
socket.busy = False
|
socket.busy = False
|
||||||
return data
|
return data
|
||||||
|
|
||||||
class SeaGroup(object):
|
|
||||||
|
class SeaGroup:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.version = 0
|
self.version = 0
|
||||||
self.components = []
|
self.components = []
|
||||||
@ -228,8 +230,9 @@ class SeaGroup(object):
|
|||||||
self.lastpoll = 0
|
self.lastpoll = 0
|
||||||
self.lastreq = 0
|
self.lastreq = 0
|
||||||
self.empty_values = {}
|
self.empty_values = {}
|
||||||
|
|
||||||
class Instrument(object):
|
|
||||||
|
class Instrument:
|
||||||
def remove(self, client):
|
def remove(self, client):
|
||||||
try:
|
try:
|
||||||
del self.clients[client.id]
|
del self.clients[client.id]
|
||||||
@ -240,6 +243,7 @@ class Instrument(object):
|
|||||||
self.clients[client.id] = client
|
self.clients[client.id] = client
|
||||||
return client
|
return client
|
||||||
|
|
||||||
|
|
||||||
class SeaInstrument(Instrument):
|
class SeaInstrument(Instrument):
|
||||||
# convert SEA layout tag like "-W" to more meaningful name.
|
# convert SEA layout tag like "-W" to more meaningful name.
|
||||||
# the code: 0: modifier, 1: enum name, 2: input element
|
# the code: 0: modifier, 1: enum name, 2: input element
|
||||||
@ -265,10 +269,11 @@ class SeaInstrument(Instrument):
|
|||||||
def __init__(self, inst_name, instrument_config):
|
def __init__(self, inst_name, instrument_config):
|
||||||
self.host_port = hostport_split(instrument_config['sea'])
|
self.host_port = hostport_split(instrument_config['sea'])
|
||||||
self.inst_name = inst_name
|
self.inst_name = inst_name
|
||||||
|
self.title = inst_name
|
||||||
self.clients = {}
|
self.clients = {}
|
||||||
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
|
||||||
self.seaspy = tcp_lineserver.LineClient(self.host_port, ['Spy 007'], True, ridername='spy')
|
self.seaspy = tcp_lineserver.LineClient(self.host_port, ['Spy 007'], True, ridername='spy')
|
||||||
self.seaspy.busy = False
|
self.seaspy.busy = False
|
||||||
self.seaspy.name = "SEA seaspy"
|
self.seaspy.name = "SEA seaspy"
|
||||||
@ -277,7 +282,7 @@ class SeaInstrument(Instrument):
|
|||||||
self.history = deque(maxlen=1000)
|
self.history = deque(maxlen=1000)
|
||||||
self.init()
|
self.init()
|
||||||
gevent.Greenlet.spawn(self.checkconnections)
|
gevent.Greenlet.spawn(self.checkconnections)
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
self.values = {}
|
self.values = {}
|
||||||
self.groups = {}
|
self.groups = {}
|
||||||
@ -286,7 +291,7 @@ class SeaInstrument(Instrument):
|
|||||||
self.timeStamp = None
|
self.timeStamp = None
|
||||||
self.history.clear()
|
self.history.clear()
|
||||||
self.lastcmd = None
|
self.lastcmd = None
|
||||||
|
|
||||||
def checkconnections(self):
|
def checkconnections(self):
|
||||||
while True:
|
while True:
|
||||||
if len(self.clients) == 0 and self.seaspy.connected:
|
if len(self.clients) == 0 and self.seaspy.connected:
|
||||||
@ -302,11 +307,11 @@ class SeaInstrument(Instrument):
|
|||||||
if not self.seaspy.connected:
|
if not self.seaspy.connected:
|
||||||
self.init()
|
self.init()
|
||||||
return self.register(SeaClient())
|
return self.register(SeaClient())
|
||||||
|
|
||||||
def remove(self, client):
|
def remove(self, client):
|
||||||
Instrument.remove(self, client)
|
Instrument.remove(self, client)
|
||||||
self.last_client_remove = time.time()
|
self.last_client_remove = time.time()
|
||||||
|
|
||||||
def findgroup(self, path):
|
def findgroup(self, path):
|
||||||
'get a group from sea and store it'
|
'get a group from sea and store it'
|
||||||
if not path in self.groups:
|
if not path in self.groups:
|
||||||
@ -315,7 +320,7 @@ class SeaInstrument(Instrument):
|
|||||||
self.groups[path].lastreq = time.time()
|
self.groups[path].lastreq = time.time()
|
||||||
self.poll_groups([path])
|
self.poll_groups([path])
|
||||||
return self.groups[path]
|
return self.groups[path]
|
||||||
|
|
||||||
def poll_groups(self, paths):
|
def poll_groups(self, paths):
|
||||||
'polls values and components of requested groups'
|
'polls values and components of requested groups'
|
||||||
for path in list(paths):
|
for path in list(paths):
|
||||||
@ -404,8 +409,8 @@ class SeaInstrument(Instrument):
|
|||||||
#print 'TO ', components
|
#print 'TO ', components
|
||||||
if grouptitle != None:
|
if grouptitle != None:
|
||||||
gobj.grouptitle = grouptitle
|
gobj.grouptitle = grouptitle
|
||||||
|
|
||||||
|
|
||||||
def make_seacmd(self):
|
def make_seacmd(self):
|
||||||
global port
|
global port
|
||||||
if not self.seacmd:
|
if not self.seacmd:
|
||||||
@ -414,14 +419,14 @@ class SeaInstrument(Instrument):
|
|||||||
True, ridername='cmd')
|
True, ridername='cmd')
|
||||||
self.seacmd.name = "SEA user"
|
self.seacmd.name = "SEA user"
|
||||||
self.seacmd.connect()
|
self.seacmd.connect()
|
||||||
|
|
||||||
def console(self):
|
def console(self):
|
||||||
self.make_seacmd()
|
self.make_seacmd()
|
||||||
|
|
||||||
def addconsole(self, msg):
|
def addconsole(self, msg):
|
||||||
self.history.append(msg)
|
self.history.append(msg)
|
||||||
self.consolepos += 1
|
self.consolepos += 1
|
||||||
|
|
||||||
def pollconsole(self):
|
def pollconsole(self):
|
||||||
if not self.seacmd:
|
if not self.seacmd:
|
||||||
return
|
return
|
||||||
@ -464,22 +469,22 @@ class SeaInstrument(Instrument):
|
|||||||
idx = min(len(self.history), self.consolepos - startindex) # distance from end
|
idx = min(len(self.history), self.consolepos - startindex) # distance from end
|
||||||
messages = []
|
messages = []
|
||||||
for i in range(-idx,0):
|
for i in range(-idx,0):
|
||||||
type, line, hid = self.history[i]
|
typ, line, hid = self.history[i]
|
||||||
messages.append(dict(type=type, line=line, origin=('self' if hid==id else 'other')))
|
messages.append(dict(type=typ, line=line, origin=('self' if hid==id else 'other')))
|
||||||
return self.consolepos, messages
|
return self.consolepos, messages
|
||||||
|
|
||||||
def command(self, command, id):
|
def command(self, command, id):
|
||||||
self.make_seacmd()
|
self.make_seacmd()
|
||||||
self.seacmd.send_line('fulltransact '+command)
|
self.seacmd.send_line('fulltransact '+command)
|
||||||
self.lastid = id
|
self.lastid = id
|
||||||
self.lastcmd = command
|
self.lastcmd = command
|
||||||
|
|
||||||
|
|
||||||
class SeaGraph(object):
|
class SeaGraph:
|
||||||
HISTORICAL = 0
|
HISTORICAL = 0
|
||||||
ACTUAL = 1
|
ACTUAL = 1
|
||||||
LIVE = 2
|
LIVE = 2
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.livemode = self.HISTORICAL
|
self.livemode = self.HISTORICAL
|
||||||
self.time = [0, 0]
|
self.time = [0, 0]
|
||||||
@ -523,18 +528,18 @@ class SeaGraph(object):
|
|||||||
self.time[0] = self.time[1]
|
self.time[0] = self.time[1]
|
||||||
# reduction not yet implemented
|
# reduction not yet implemented
|
||||||
return dict(type='graph-draw', reduced=False, graph=result)
|
return dict(type='graph-draw', reduced=False, graph=result)
|
||||||
|
|
||||||
def w_gettime(self, time):
|
def w_gettime(self, time):
|
||||||
time = [float(t) for t in time.split(',')]
|
time = [float(t) for t in time.split(',')]
|
||||||
return dict(type='time', time= seagraph.get_abs_time(time))
|
return dict(type='time', time= seagraph.get_abs_time(time))
|
||||||
|
|
||||||
def w_getvars(self, time):
|
def w_getvars(self, time):
|
||||||
time = [float(t) for t in time.split(',')]
|
time = [float(t) for t in time.split(',')]
|
||||||
scanner = seagraph.VarsScanner(instrument.logger_dir, instrument.test_day)
|
scanner = seagraph.VarsScanner(instrument.logger_dir, instrument.test_day)
|
||||||
result = dict(type='var_list')
|
result = dict(type='var_list')
|
||||||
result['blocks'] = list(scanner.get_message(time[-1]).values())
|
result['blocks'] = list(scanner.get_message(time[-1]).values())
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def w_updategraph(self):
|
def w_updategraph(self):
|
||||||
logging.info("UPD GRAPH %d", self.livemode)
|
logging.info("UPD GRAPH %d", self.livemode)
|
||||||
if self.livemode == self.HISTORICAL:
|
if self.livemode == self.HISTORICAL:
|
||||||
@ -544,7 +549,7 @@ class SeaGraph(object):
|
|||||||
return dict(type='accept-graph', live=True)
|
return dict(type='accept-graph', live=True)
|
||||||
#self.livemode = self.LIVE
|
#self.livemode = self.LIVE
|
||||||
#return dict(type='accept-graph', live=True)
|
#return dict(type='accept-graph', live=True)
|
||||||
|
|
||||||
def graphpoll(self):
|
def graphpoll(self):
|
||||||
if self.livemode == self.LIVE:
|
if self.livemode == self.LIVE:
|
||||||
self.time[1], = seagraph.get_abs_time([0])
|
self.time[1], = seagraph.get_abs_time([0])
|
||||||
@ -562,9 +567,9 @@ class SeaGraph(object):
|
|||||||
if len(result) > 0:
|
if len(result) > 0:
|
||||||
return dict(type='graph-update', reduced=False, time=self.time[1], graph=result)
|
return dict(type='graph-update', reduced=False, time=self.time[1], graph=result)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
class SeaClient(SeaGraph):
|
class SeaClient(SeaGraph):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.group_version = {}
|
self.group_version = {}
|
||||||
self.group_values = {}
|
self.group_values = {}
|
||||||
@ -601,7 +606,7 @@ class SeaClient(SeaGraph):
|
|||||||
instrument.pollconsole()
|
instrument.pollconsole()
|
||||||
self.consolepos, msg = instrument.getconsole(self.consolepos, self.id)
|
self.consolepos, msg = instrument.getconsole(self.consolepos, self.id)
|
||||||
messages.extend(msg)
|
messages.extend(msg)
|
||||||
|
|
||||||
# graph messages
|
# graph messages
|
||||||
msg = self.graphpoll()
|
msg = self.graphpoll()
|
||||||
if msg:
|
if msg:
|
||||||
@ -610,7 +615,7 @@ class SeaClient(SeaGraph):
|
|||||||
|
|
||||||
def info(self):
|
def info(self):
|
||||||
return self.group_version.keys()
|
return self.group_version.keys()
|
||||||
|
|
||||||
def w_getblock(self, path):
|
def w_getblock(self, path):
|
||||||
gobj = instrument.findgroup(path.split(',')[-1])
|
gobj = instrument.findgroup(path.split(',')[-1])
|
||||||
# self.group_version[path] = gobj.version
|
# self.group_version[path] = gobj.version
|
||||||
@ -618,7 +623,7 @@ class SeaClient(SeaGraph):
|
|||||||
self.group_version = {path: gobj.version}
|
self.group_version = {path: gobj.version}
|
||||||
logging.info('getblock %s %d', path, gobj.version)
|
logging.info('getblock %s %d', path, gobj.version)
|
||||||
return dict(type='draw', title=gobj.grouptitle, path=path, components=gobj.components)
|
return dict(type='draw', title=gobj.grouptitle, path=path, components=gobj.components)
|
||||||
|
|
||||||
def w_updateblock(self, path):
|
def w_updateblock(self, path):
|
||||||
gobj = instrument.findgroup(path)
|
gobj = instrument.findgroup(path)
|
||||||
logging.info('make active %s', path)
|
logging.info('make active %s', path)
|
||||||
@ -630,15 +635,15 @@ class SeaClient(SeaGraph):
|
|||||||
self.consolepos = 0
|
self.consolepos = 0
|
||||||
instrument.console()
|
instrument.console()
|
||||||
return dict(type='accept-console')
|
return dict(type='accept-console')
|
||||||
|
|
||||||
def w_sendcommand(self, command):
|
def w_sendcommand(self, command):
|
||||||
instrument.command(command, self.id)
|
instrument.command(command, self.id)
|
||||||
return dict(type='accept-command')
|
return dict(type='accept-command')
|
||||||
|
|
||||||
|
|
||||||
class DummyClient(SeaGraph):
|
class DummyClient(SeaGraph):
|
||||||
async = set(('id','update','redraw','command','reply','graph-update','graph-redraw'))
|
asynch = set(('id','update','redraw','command','reply','graph-update','graph-redraw'))
|
||||||
|
|
||||||
def __init__(self, host_port):
|
def __init__(self, host_port):
|
||||||
self.linesocket = tcp_lineserver.LineClient(host_port)
|
self.linesocket = tcp_lineserver.LineClient(host_port)
|
||||||
self.id = uuid.uuid4().hex[0:15]
|
self.id = uuid.uuid4().hex[0:15]
|
||||||
@ -646,8 +651,8 @@ class DummyClient(SeaGraph):
|
|||||||
self.queue = []
|
self.queue = []
|
||||||
self.syncreply = []
|
self.syncreply = []
|
||||||
SeaGraph.__init__(self)
|
SeaGraph.__init__(self)
|
||||||
|
|
||||||
def cmd_reply(self, command, replytype, tmo=5):
|
def cmd_reply(self, command, replytype=None, tmo=5):
|
||||||
self.linesocket.send_line(json.dumps(command))
|
self.linesocket.send_line(json.dumps(command))
|
||||||
t = 0
|
t = 0
|
||||||
while True:
|
while True:
|
||||||
@ -657,7 +662,7 @@ class DummyClient(SeaGraph):
|
|||||||
line = self.linesocket.get_line()
|
line = self.linesocket.get_line()
|
||||||
if line != None:
|
if line != None:
|
||||||
msg = json.loads(line)
|
msg = json.loads(line)
|
||||||
if msg['type'] in self.async:
|
if msg['type'] in self.asynch:
|
||||||
t = 0
|
t = 0
|
||||||
# print 'PUSH',msg, replytype
|
# print 'PUSH',msg, replytype
|
||||||
self.queue.append(msg)
|
self.queue.append(msg)
|
||||||
@ -668,10 +673,10 @@ class DummyClient(SeaGraph):
|
|||||||
raise Exception("timeout")
|
raise Exception("timeout")
|
||||||
gevent.sleep(0.1)
|
gevent.sleep(0.1)
|
||||||
t += 0.1
|
t += 0.1
|
||||||
if msg['type'] != replytype:
|
if replytype and msg['type'] != replytype:
|
||||||
logging.error('REPLY MISMATCH %s %s <> %s' , command, replytype, msg['type'])
|
logging.error('REPLY MISMATCH %s %s <> %s' , command, replytype, msg['type'])
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
|
||||||
def w_getblock(self, path):
|
def w_getblock(self, path):
|
||||||
return self.cmd_reply(dict(type='getblock', path=path, id=self.id), 'draw')
|
return self.cmd_reply(dict(type='getblock', path=path, id=self.id), 'draw')
|
||||||
@ -694,17 +699,17 @@ class DummyClient(SeaGraph):
|
|||||||
messages = []
|
messages = []
|
||||||
if line:
|
if line:
|
||||||
msg = json.loads(line)
|
msg = json.loads(line)
|
||||||
if msg['type'] in self.async:
|
if msg['type'] in self.asynch:
|
||||||
messages.append(msg)
|
messages.append(msg)
|
||||||
else:
|
else:
|
||||||
self.syncreply.append(msg)
|
self.syncreply.append(msg)
|
||||||
|
|
||||||
# graph messages
|
# graph messages
|
||||||
msg = self.graphpoll()
|
msg = self.graphpoll()
|
||||||
if msg:
|
if msg:
|
||||||
messages.append(msg)
|
messages.append(msg)
|
||||||
return messages
|
return messages
|
||||||
|
|
||||||
def info(self):
|
def info(self):
|
||||||
return ["na"]
|
return ["na"]
|
||||||
|
|
||||||
@ -715,13 +720,14 @@ class DummyInstrument(Instrument):
|
|||||||
self.host_port = hostport_split(instrument_config['hostport'])
|
self.host_port = hostport_split(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
|
||||||
self.title = inst_name
|
self.title = inst_name
|
||||||
self.clients = {}
|
self.clients = {}
|
||||||
|
|
||||||
def newClient(self):
|
def newClient(self):
|
||||||
return self.register(DummyClient(self.host_port))
|
return self.register(DummyClient(self.host_port))
|
||||||
|
|
||||||
|
|
||||||
class SecopMsg:
|
class SecopMsg:
|
||||||
def __init__(self, line):
|
def __init__(self, line):
|
||||||
self.par = None
|
self.par = None
|
||||||
@ -736,7 +742,14 @@ class SecopMsg:
|
|||||||
self.par = sl[1]
|
self.par = sl[1]
|
||||||
if len(sl) > 2:
|
if len(sl) > 2:
|
||||||
self.value = json.loads(' '.join(sl[2:]))
|
self.value = json.loads(' '.join(sl[2:]))
|
||||||
self.async = self.type == 'event'
|
self.asynch = self.type in ('update', 'error_update')
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
value = repr(self.value)
|
||||||
|
if len(value) > 50:
|
||||||
|
value = value[:50] + '...'
|
||||||
|
return "SecopMsg('%s %s %s')" % (self.type, self.par, value)
|
||||||
|
|
||||||
|
|
||||||
def SecopEncode(cmd, par=None, value=None):
|
def SecopEncode(cmd, par=None, value=None):
|
||||||
line = cmd
|
line = cmd
|
||||||
@ -745,24 +758,34 @@ def SecopEncode(cmd, par=None, value=None):
|
|||||||
if value:
|
if value:
|
||||||
line += " " + json.dumps(value)
|
line += " " + json.dumps(value)
|
||||||
return line
|
return line
|
||||||
|
|
||||||
|
|
||||||
def convert_par(module, name, par):
|
def convert_par(module, name, par):
|
||||||
result = dict(type='input', name=module+":"+name, title=name)
|
result = dict(type='input', name=module+":"+name, title=name)
|
||||||
if par['readonly']:
|
if par.get('readonly', True):
|
||||||
result['type']='rdonly'
|
result['type'] = 'rdonly'
|
||||||
#print result
|
else:
|
||||||
|
result['command'] = 'change %s:%s' % (module, name)
|
||||||
|
if par['datainfo']['type'] == 'enum':
|
||||||
|
result['enum_names'] = [dict(title=k, value=v) for k, v in par['datainfo']['members'].items()]
|
||||||
|
result['type'] = 'enum'
|
||||||
|
elif par['datainfo']['type'] == 'bool':
|
||||||
|
result['type'] = 'checkbox'
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def convert_event(messages):
|
def convert_event(messages):
|
||||||
if isinstance(messages, SecopMsg):
|
if isinstance(messages, SecopMsg):
|
||||||
messages = [messages]
|
messages = [messages]
|
||||||
updates = []
|
updates = []
|
||||||
for msg in messages:
|
for msg in messages:
|
||||||
if msg['type'] == 'event':
|
if msg['type'] == 'update':
|
||||||
updates.append(dict(name=msg.par, value=str(msg.value[0])))
|
updates.append(dict(name=msg.par, value=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(object):
|
|
||||||
|
class SecopClient:
|
||||||
prio_par = ["value", "status", "target"]
|
prio_par = ["value", "status", "target"]
|
||||||
hide_par = ["baseclass", "class", "pollinterval"]
|
hide_par = ["baseclass", "class", "pollinterval"]
|
||||||
skip_par = ["status2"]
|
skip_par = ["status2"]
|
||||||
@ -796,7 +819,7 @@ class SecopClient(object):
|
|||||||
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
|
#print '<', msg['type'], msg.par
|
||||||
if msg.async 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:
|
||||||
@ -811,7 +834,7 @@ class SecopClient(object):
|
|||||||
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 w_getblock(self, path):
|
def w_getblock(self, path):
|
||||||
path = path.split(',')[-1]
|
path = path.split(',')[-1]
|
||||||
if path == "main":
|
if path == "main":
|
||||||
@ -866,14 +889,14 @@ class SecopClient(object):
|
|||||||
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)
|
||||||
if msg.async and self.replytype != msg['type'] + "=" + msg.par:
|
if msg.asynch and self.replytype != msg['type'] + "=" + msg.par:
|
||||||
return convert_event(SecopMsg(line))
|
return convert_event(SecopMsg(line))
|
||||||
self.syncreply.append(msg)
|
self.syncreply.append(msg)
|
||||||
return []
|
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):
|
||||||
@ -881,10 +904,10 @@ class SecopInstrument(Instrument):
|
|||||||
self.host_port = hostport_split(instrument_config['hostport'])
|
self.host_port = hostport_split(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
|
||||||
self.title = inst_name
|
self.title = inst_name
|
||||||
self.clients = {}
|
self.clients = {}
|
||||||
|
|
||||||
def newClient(self):
|
def newClient(self):
|
||||||
return self.register(SecopClient(self.host_port))
|
return self.register(SecopClient(self.host_port))
|
||||||
|
|
||||||
@ -895,21 +918,22 @@ class Logger(object):
|
|||||||
|
|
||||||
def write(self, message):
|
def write(self, message):
|
||||||
self.terminal.write(message)
|
self.terminal.write(message)
|
||||||
self.log.write(message)
|
self.log.write(message)
|
||||||
|
|
||||||
def flush(self):
|
def flush(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def handle_pdb(sig, frame):
|
def handle_pdb(sig, frame):
|
||||||
import pdb
|
import pdb
|
||||||
prin ('PDB')
|
print('PDB')
|
||||||
pdb.Pdb().set_trace(frame)
|
pdb.Pdb().set_trace(frame)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
signal.signal(signal.SIGUSR1, handle_pdb)
|
signal.signal(signal.SIGUSR1, handle_pdb)
|
||||||
print('PID', os.getpid())
|
print('PID', os.getpid())
|
||||||
|
|
||||||
if len(sys.argv) > 3:
|
if len(sys.argv) > 3:
|
||||||
instrument_config = {}
|
instrument_config = {}
|
||||||
for arg in sys.argv[1:]:
|
for arg in sys.argv[1:]:
|
||||||
@ -927,13 +951,13 @@ if __name__ == '__main__':
|
|||||||
inst_name = sys.argv[2]
|
inst_name = sys.argv[2]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
inst_name = 'seadummy'
|
inst_name = 'seadummy'
|
||||||
|
|
||||||
with open('instruments.json') as f:
|
with open('instruments.json') as f:
|
||||||
instrument_list = json.load(f)
|
instrument_list = json.load(f)
|
||||||
|
|
||||||
instrument_config = instrument_list[inst_name]
|
instrument_config = instrument_list[inst_name]
|
||||||
logging.basicConfig(filename='log/%s.log' % inst_name, filemode='w', level=logging.INFO, format='%(asctime)s %(levelname)s %(message)s')
|
logging.basicConfig(filename='log/%s.log' % inst_name, filemode='w', level=logging.INFO, format='%(asctime)s %(levelname)s %(message)s')
|
||||||
|
|
||||||
# sys.stdout = Logger(instrument_config.get('logger_dir', '.') + '/seaweb_stdout.txt')
|
# sys.stdout = Logger(instrument_config.get('logger_dir', '.') + '/seaweb_stdout.txt')
|
||||||
# print '-' * 80
|
# print '-' * 80
|
||||||
type = instrument_config.get('type', 'sea')
|
type = instrument_config.get('type', 'sea')
|
||||||
@ -945,7 +969,7 @@ if __name__ == '__main__':
|
|||||||
instrument = SecopInstrument(inst_name, instrument_config)
|
instrument = SecopInstrument(inst_name, instrument_config)
|
||||||
else:
|
else:
|
||||||
raise TypeError('bad instrument type')
|
raise TypeError('bad instrument type')
|
||||||
|
|
||||||
app.debug = True
|
app.debug = True
|
||||||
#server = gevent.wsgi.WSGIServer(('', port), app, keyfile='key.key', certfile='key.crt')
|
#server = gevent.wsgi.WSGIServer(('', port), app, keyfile='key.key', certfile='key.crt')
|
||||||
server = gevent.pywsgi.WSGIServer(('', port), app, log=logging.getLogger('server'))
|
server = gevent.pywsgi.WSGIServer(('', port), app, log=logging.getLogger('server'))
|
||||||
|
50
seweb.py
50
seweb.py
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
sys.path.append("../histreader")
|
sys.path.append("../frappyhistory")
|
||||||
# Make sure your gevent version is >= 1.0
|
# Make sure your gevent version is >= 1.0
|
||||||
import gevent
|
import gevent
|
||||||
import gevent.pywsgi
|
import gevent.pywsgi
|
||||||
@ -25,8 +25,8 @@ import circularlog
|
|||||||
import os
|
import os
|
||||||
import signal
|
import signal
|
||||||
from histgraph import get_vars, get_curves, get_abs_time
|
from histgraph import get_vars, get_curves, get_abs_time
|
||||||
from histreader.histreader import MainCache
|
from main import MainCache
|
||||||
from histreader.frappyreader import FrappyReader
|
from frappyreader import FrappyReader
|
||||||
|
|
||||||
try: import simplejson as json
|
try: import simplejson as json
|
||||||
except ImportError: import json
|
except ImportError: import json
|
||||||
@ -143,12 +143,7 @@ def reply():
|
|||||||
@app.route('/test/<file>')
|
@app.route('/test/<file>')
|
||||||
def subdir_test_file(file):
|
def subdir_test_file(file):
|
||||||
gevent.sleep(2)
|
gevent.sleep(2)
|
||||||
try:
|
resp = flask.send_file("client/test/"+file, mimetype=guess_mimetype(file))
|
||||||
with open("client/test/"+file, 'r') as content_file:
|
|
||||||
content = content_file.read()
|
|
||||||
except IOError:
|
|
||||||
flask.abort(404)
|
|
||||||
resp = flask.Response(content, mimetype=guess_mimetype(file))
|
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
@app.route('/jsFiles/<file>')
|
@app.route('/jsFiles/<file>')
|
||||||
@ -156,12 +151,7 @@ def subdir_test_file(file):
|
|||||||
@app.route('/externalFiles/<file>')
|
@app.route('/externalFiles/<file>')
|
||||||
def subdir_file(file):
|
def subdir_file(file):
|
||||||
subdir = flask.request.path.split('/')[1]
|
subdir = flask.request.path.split('/')[1]
|
||||||
try:
|
resp = flask.send_file("client/" + subdir+"/"+file, mimetype=guess_mimetype(file))
|
||||||
with open("client/" + subdir+"/"+file, 'r') as content_file:
|
|
||||||
content = content_file.read()
|
|
||||||
except IOError:
|
|
||||||
flask.abort(404)
|
|
||||||
resp = flask.Response(content, mimetype=guess_mimetype(file))
|
|
||||||
#resp.headers['Content-Security-Policy'] = "sandbox; script-src 'unsafe-inline';"
|
#resp.headers['Content-Security-Policy'] = "sandbox; script-src 'unsafe-inline';"
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
@ -176,12 +166,7 @@ def default():
|
|||||||
@app.route('/<file>')
|
@app.route('/<file>')
|
||||||
def general_file(file):
|
def general_file(file):
|
||||||
subdir = "client/"
|
subdir = "client/"
|
||||||
try:
|
resp = flask.send_file(subdir+file, mimetype=guess_mimetype(file))
|
||||||
with open(subdir+file, 'r') as content_file:
|
|
||||||
content = content_file.read()
|
|
||||||
except IOError:
|
|
||||||
flask.abort(404)
|
|
||||||
resp = flask.Response(content, mimetype=guess_mimetype(file))
|
|
||||||
#resp.headers['Content-Security-Policy'] = "sandbox; script-src 'unsafe-inline';"
|
#resp.headers['Content-Security-Policy'] = "sandbox; script-src 'unsafe-inline';"
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
@ -294,6 +279,7 @@ class SeaInstrument(Instrument):
|
|||||||
self.seacmd = None
|
self.seacmd = None
|
||||||
self.last_client_remove = time.time()
|
self.last_client_remove = time.time()
|
||||||
self.history = deque(maxlen=1000)
|
self.history = deque(maxlen=1000)
|
||||||
|
self.title = inst_name # hack?
|
||||||
self.init()
|
self.init()
|
||||||
gevent.Greenlet.spawn(self.checkconnections)
|
gevent.Greenlet.spawn(self.checkconnections)
|
||||||
|
|
||||||
@ -337,7 +323,7 @@ class SeaInstrument(Instrument):
|
|||||||
|
|
||||||
def poll_groups(self, paths):
|
def poll_groups(self, paths):
|
||||||
'polls values and components of requested groups'
|
'polls values and components of requested groups'
|
||||||
for path in paths:
|
for path in list(paths):
|
||||||
gobj = self.groups[path]
|
gobj = self.groups[path]
|
||||||
now = time.time()
|
now = time.time()
|
||||||
if now < gobj.lastpoll + 0.5:
|
if now < gobj.lastpoll + 0.5:
|
||||||
@ -483,12 +469,8 @@ class SeaInstrument(Instrument):
|
|||||||
idx = min(len(self.history), self.consolepos - startindex) # distance from end
|
idx = min(len(self.history), self.consolepos - startindex) # distance from end
|
||||||
messages = []
|
messages = []
|
||||||
for i in range(-idx,0):
|
for i in range(-idx,0):
|
||||||
type, line, origin = self.history[i]
|
typ, line, hid = self.history[i]
|
||||||
if origin == id:
|
messages.append(dict(type=typ, line=line, origin=('self' if hid==id else 'other')))
|
||||||
origin = 'self'
|
|
||||||
elif origin != 'async':
|
|
||||||
origin = 'other'
|
|
||||||
messages.append(dict(type=type, line=line, origin=origin))
|
|
||||||
return self.consolepos, messages
|
return self.consolepos, messages
|
||||||
|
|
||||||
def command(self, command, id):
|
def command(self, command, id):
|
||||||
@ -636,7 +618,9 @@ class SeaClient(SeaGraph):
|
|||||||
|
|
||||||
def w_getblock(self, path):
|
def w_getblock(self, path):
|
||||||
gobj = instrument.findgroup(path.split(',')[-1])
|
gobj = instrument.findgroup(path.split(',')[-1])
|
||||||
self.group_version[path] = gobj.version
|
# self.group_version[path] = gobj.version
|
||||||
|
# simplify: allow only one group per client
|
||||||
|
self.group_version = {path: gobj.version}
|
||||||
logging.info('getblock %s %d', path, gobj.version)
|
logging.info('getblock %s %d', path, gobj.version)
|
||||||
return dict(type='draw', title=gobj.grouptitle, path=path, components=gobj.components)
|
return dict(type='draw', title=gobj.grouptitle, path=path, components=gobj.components)
|
||||||
|
|
||||||
@ -678,7 +662,7 @@ class DummyClient(SeaGraph):
|
|||||||
line = self.linesocket.get_line()
|
line = self.linesocket.get_line()
|
||||||
if line != None:
|
if line != None:
|
||||||
msg = json.loads(line)
|
msg = json.loads(line)
|
||||||
if msg.type in self.asynch:
|
if msg['type'] in self.asynch:
|
||||||
t = 0
|
t = 0
|
||||||
# print 'PUSH',msg, replytype
|
# print 'PUSH',msg, replytype
|
||||||
self.queue.append(msg)
|
self.queue.append(msg)
|
||||||
@ -689,8 +673,8 @@ class DummyClient(SeaGraph):
|
|||||||
raise Exception("timeout")
|
raise Exception("timeout")
|
||||||
gevent.sleep(0.1)
|
gevent.sleep(0.1)
|
||||||
t += 0.1
|
t += 0.1
|
||||||
if replytype and msg.type != replytype:
|
if replytype and msg['type'] != replytype:
|
||||||
logging.error('REPLY MISMATCH %s %s <> %s', command, replytype, msg.type)
|
logging.error('REPLY MISMATCH %s %s <> %s', command, replytype, msg['type'])
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
def strip_future(self, result):
|
def strip_future(self, result):
|
||||||
@ -724,7 +708,7 @@ class DummyClient(SeaGraph):
|
|||||||
messages = []
|
messages = []
|
||||||
if line:
|
if line:
|
||||||
msg = json.loads(line)
|
msg = json.loads(line)
|
||||||
if msg.type in self.asynch:
|
if msg['type'] in self.asynch:
|
||||||
messages.append(msg)
|
messages.append(msg)
|
||||||
else:
|
else:
|
||||||
self.syncreply.append(msg)
|
self.syncreply.append(msg)
|
||||||
|
Reference in New Issue
Block a user