master/gui: track last parameter changes

This commit is contained in:
Sebastien Bourdeauducq 2015-01-02 15:28:45 +08:00
parent 15b27a1d14
commit 3befafc4e0
5 changed files with 89 additions and 22 deletions

View File

@ -1,9 +1,10 @@
import asyncio import asyncio
from operator import itemgetter from operator import itemgetter
import time
from gi.repository import Gtk from gi.repository import Gtk
from artiq.gui.tools import Window from artiq.gui.tools import Window, ListSyncer
from artiq.management.sync_struct import Subscriber from artiq.management.sync_struct import Subscriber
@ -41,11 +42,25 @@ class _ParameterStoreSyncer:
del self.parameters_store[self._find_index(key)] del self.parameters_store[self._find_index(key)]
class _LastChangesStoreSyncer(ListSyncer):
def convert(self, x):
if len(x) == 3:
timestamp, name, value = x
else:
timestamp, name = x
value = "<deleted>"
return [time.strftime("%m/%d %H:%M:%S", time.localtime(timestamp)),
name, str(value)]
class ParametersWindow(Window): class ParametersWindow(Window):
def __init__(self): def __init__(self):
Window.__init__(self, title="Parameters") Window.__init__(self, title="Parameters")
self.set_default_size(500, 500) self.set_default_size(500, 500)
notebook = Gtk.Notebook()
self.add(notebook)
self.parameters_store = Gtk.ListStore(str, str) self.parameters_store = Gtk.ListStore(str, str)
tree = Gtk.TreeView(self.parameters_store) tree = Gtk.TreeView(self.parameters_store)
for i, title in enumerate(["Parameter", "Value"]): for i, title in enumerate(["Parameter", "Value"]):
@ -54,17 +69,38 @@ class ParametersWindow(Window):
tree.append_column(column) tree.append_column(column)
scroll = Gtk.ScrolledWindow() scroll = Gtk.ScrolledWindow()
scroll.add(tree) scroll.add(tree)
self.add(scroll) notebook.insert_page(scroll, Gtk.Label("Current values"), -1)
self.lastchanges_store = Gtk.ListStore(str, str, str)
tree = Gtk.TreeView(self.lastchanges_store)
for i, title in enumerate(["Time", "Parameter", "Value"]):
renderer = Gtk.CellRendererText()
column = Gtk.TreeViewColumn(title, renderer, text=i)
tree.append_column(column)
scroll = Gtk.ScrolledWindow()
scroll.add(tree)
notebook.insert_page(scroll, Gtk.Label("Last changes"), -1)
@asyncio.coroutine @asyncio.coroutine
def sub_connect(self, host, port): def sub_connect(self, host, port):
self.parameters_subscriber = Subscriber("parameters", self.parameters_subscriber = Subscriber("parameters",
self.init_parameters_store) self.init_parameters_store)
yield from self.parameters_subscriber.connect(host, port) yield from self.parameters_subscriber.connect(host, port)
try:
self.lastchanges_subscriber = Subscriber(
"parameters_simplehist", self.init_lastchanges_store)
yield from self.lastchanges_subscriber.connect(host, port)
except:
yield from self.parameters_subscriber.close()
raise
@asyncio.coroutine @asyncio.coroutine
def sub_close(self): def sub_close(self):
yield from self.lastchanges_subscriber.close()
yield from self.parameters_subscriber.close() yield from self.parameters_subscriber.close()
def init_parameters_store(self, init): def init_parameters_store(self, init):
return _ParameterStoreSyncer(self.parameters_store, init) return _ParameterStoreSyncer(self.parameters_store, init)
def init_lastchanges_store(self, init):
return _LastChangesStoreSyncer(self.lastchanges_store, init)

View File

@ -3,33 +3,18 @@ import asyncio
from gi.repository import Gtk from gi.repository import Gtk
from artiq.gui.tools import Window from artiq.gui.tools import Window, ListSyncer
from artiq.management.sync_struct import Subscriber from artiq.management.sync_struct import Subscriber
class _QueueStoreSyncer: class _QueueStoreSyncer(ListSyncer):
def __init__(self, queue_store, init): def convert(self, x):
self.queue_store = queue_store
self.queue_store.clear()
for x in init:
self.append(x)
def _convert(self, x):
rid, run_params, timeout = x rid, run_params, timeout = x
row = [rid, run_params["file"]] row = [rid, run_params["file"]]
for e in run_params["unit"], run_params["function"], timeout: for e in run_params["unit"], run_params["function"], timeout:
row.append("-" if e is None else str(e)) row.append("-" if e is None else str(e))
return row return row
def append(self, x):
self.queue_store.append(self._convert(x))
def insert(self, i, x):
self.queue_store.insert(i, self._convert(x))
def __delitem__(self, key):
del self.queue_store[key]
class _PeriodicStoreSyncer: class _PeriodicStoreSyncer:
def __init__(self, periodic_store, init): def __init__(self, periodic_store, init):

View File

@ -5,9 +5,27 @@ from gi.repository import Gtk
data_dir = os.path.abspath(os.path.dirname(__file__)) data_dir = os.path.abspath(os.path.dirname(__file__))
class Window(Gtk.Window): class Window(Gtk.Window):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
Gtk.Window.__init__(self, *args, **kwargs) Gtk.Window.__init__(self, *args, **kwargs)
self.set_wmclass("ARTIQ", "ARTIQ") self.set_wmclass("ARTIQ", "ARTIQ")
self.set_icon_from_file(os.path.join(data_dir, "icon.png")) self.set_icon_from_file(os.path.join(data_dir, "icon.png"))
self.set_border_width(6) self.set_border_width(6)
class ListSyncer:
def __init__(self, store, init):
self.store = store
self.store.clear()
for x in init:
self.append(x)
def append(self, x):
self.store.append(self.convert(x))
def insert(self, i, x):
self.store.insert(i, self.convert(x))
def __delitem__(self, key):
del self.store[key]

View File

@ -1,5 +1,6 @@
from collections import OrderedDict from collections import OrderedDict
import importlib import importlib
from time import time
from artiq.language.context import * from artiq.language.context import *
from artiq.management import pyon from artiq.management import pyon
@ -68,6 +69,7 @@ class DeviceParamDB:
self.pdb_file = pdb_file self.pdb_file = pdb_file
self.ddb = Notifier(pyon.load_file(self.ddb_file)) self.ddb = Notifier(pyon.load_file(self.ddb_file))
self.pdb = Notifier(pyon.load_file(self.pdb_file)) self.pdb = Notifier(pyon.load_file(self.pdb_file))
self.parameter_hooks = []
def save_ddb(self): def save_ddb(self):
pyon.store_file(self.ddb_file, self.ddb.backing_struct) pyon.store_file(self.ddb_file, self.ddb.backing_struct)
@ -92,7 +94,29 @@ class DeviceParamDB:
def set_parameter(self, name, value): def set_parameter(self, name, value):
self.pdb[name] = value self.pdb[name] = value
self.save_pdb() self.save_pdb()
timestamp = time()
for hook in self.parameter_hooks:
hook.set_parameter(timestamp, name, value)
def del_parameter(self, name): def del_parameter(self, name):
del self.pdb[name] del self.pdb[name]
self.save_pdb() self.save_pdb()
timestamp = time()
for hook in self.parameter_hooks:
hook.del_parameter(timestamp, name)
class SimpleParameterHistory:
def __init__(self, depth):
self.depth = depth
self.history = Notifier([])
def set_parameter(self, timestamp, name, value):
if len(self.history.backing_struct) >= self.depth:
del self.history[0]
self.history.append((timestamp, name, value))
def del_parameter(self, timestamp, name):
if len(self.history.backing_struct) >= self.depth:
del self.history[0]
self.history.append((timestamp, name))

View File

@ -6,7 +6,7 @@ import atexit
from artiq.management.pc_rpc import Server from artiq.management.pc_rpc import Server
from artiq.management.sync_struct import Publisher from artiq.management.sync_struct import Publisher
from artiq.management.dpdb import DeviceParamDB from artiq.management.dpdb import DeviceParamDB, SimpleParameterHistory
from artiq.management.scheduler import Scheduler from artiq.management.scheduler import Scheduler
@ -26,7 +26,10 @@ def _get_args():
def main(): def main():
args = _get_args() args = _get_args()
dpdb = DeviceParamDB("ddb.pyon", "pdb.pyon") dpdb = DeviceParamDB("ddb.pyon", "pdb.pyon")
simplephist = SimpleParameterHistory(30)
dpdb.parameter_hooks.append(simplephist)
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
atexit.register(lambda: loop.close()) atexit.register(lambda: loop.close())
@ -50,7 +53,8 @@ def main():
"queue": scheduler.queue, "queue": scheduler.queue,
"periodic": scheduler.periodic, "periodic": scheduler.periodic,
"devices": dpdb.ddb, "devices": dpdb.ddb,
"parameters": dpdb.pdb "parameters": dpdb.pdb,
"parameters_simplehist": simplephist.history
}) })
loop.run_until_complete(server_notify.start( loop.run_until_complete(server_notify.start(
args.bind, args.port_notify)) args.bind, args.port_notify))