=0&&u.splice(r,1)}var u=[],c=A[t].converter,a=dr.succeed(null);return A[t].init=a,A[t].onEffects=e(r),{subscribe:n,unsubscribe:o}}function R(t,r){return T(t),A[t]={tag:"sub",subMap:C,converter:r,isForeign:!0},v(t)}function x(t,r){function n(t,r,e){for(var n=o(t,r,e),u=0;u<_.length;u++)a(_[u]);return _=null,h=a,d=o,n}function o(t,r,e){return l=r,v}function u(t,r,e){return d(t,r,e)}function c(t){_.push(t)}function a(t){for(var e=l;"[]"!==e.ctor;)r(e._0(t)),e=e._1}function i(r){var e=f(Zt,s,r);if("Err"===e.ctor)throw new Error("Trying to send an unexpected type of value through port `"+t+"`:\n"+e._0);h(e._0)}var _=[],l=E.Nil,s=A[t].converter,d=n,h=c,v=dr.succeed(null);return A[t].init=v,A[t].onEffects=e(u),{send:i}}var A={},S=r(function(t,r){return r}),C=r(function(t,r){return function(e){return t(r(e))}});return{sendToApp:r(s),sendToSelf:r(d),effectManagers:A,outgoingPort:N,incomingPort:R,htmlToProgram:u,program:t,programWithFlags:n,initialize:c,leaf:v,batch:p,map:r(m)}}()),dr=function(){function t(t){return{ctor:"_Task_succeed",value:t}}function e(t){return{ctor:"_Task_fail",value:t}}function n(t){return{ctor:"_Task_nativeBinding",callback:t,cancel:null}}function o(t,r){return{ctor:"_Task_andThen",callback:t,task:r}}function u(t,r){return{ctor:"_Task_onError",callback:t,task:r}}function c(t){return{ctor:"_Task_receive",callback:t}}function a(t){var r={ctor:"_Process",id:g.guid(),root:t,stack:null,mailbox:[]};return h(r),r}function i(r){return n(function(e){var n=a(r);e(t(n))})}function f(t,r){t.mailbox.push(r),h(t)}function _(r,e){return n(function(n){f(r,e),n(t(g.Tuple0))})}function l(r){return n(function(e){var n=r.root;"_Task_nativeBinding"===n.ctor&&n.cancel&&n.cancel(),r.root=null,e(t(g.Tuple0))})}function s(r){return n(function(e){var n=setTimeout(function(){e(t(g.Tuple0))},r);return function(){clearTimeout(n)}})}function d(t,r){for(;t0&&e.push(M("p-thunk",n,_)));case"tagger":for(var l=t.tagger,s=r.tagger,d=!1,h=t.node;"tagger"===h.type;)d=!0,"object"!=typeof l?l=[l,h.tagger]:l.push(h.tagger),h=h.node;for(var v=r.node;"tagger"===v.type;)d=!0,"object"!=typeof s?s=[s,v.tagger]:s.push(v.tagger),v=v.node;return d&&l.length!==s.length?void e.push(M("p-redraw",n,r)):((d?L(l,s):l===s)||e.push(M("p-tagger",n,s)),void O(h,v,e,n+1));case"text":if(t.text!==r.text)return void e.push(M("p-text",n,r.text));return;case"node":if(t.tag!==r.tag||t.namespace!==r.namespace)return void e.push(M("p-redraw",n,r));var g=P(t.facts,r.facts);return"undefined"!=typeof g&&e.push(M("p-facts",n,g)),void I(t,r,e,n);case"keyed-node":if(t.tag!==r.tag||t.namespace!==r.namespace)return void e.push(M("p-redraw",n,r));var g=P(t.facts,r.facts);return"undefined"!=typeof g&&e.push(M("p-facts",n,g)),void D(t,r,e,n);case"custom":if(t.impl!==r.impl)return void e.push(M("p-redraw",n,r));var g=P(t.facts,r.facts);"undefined"!=typeof g&&e.push(M("p-facts",n,g));var p=r.impl.diff(t,r);if(p)return void e.push(M("p-custom",n,p));return}}}function L(t,r){for(var e=0;ea?e.push(M("p-remove-last",n,c-a)):c0||c.length>0||"undefined"!=typeof S)&&e.push(M("p-reorder",n,{patches:o,inserts:c,endInserts:S}))}function J(t,r,e,n,o,u){var c=t[e];if("undefined"==typeof c)return c={tag:"insert",vnode:n,index:o,data:void 0},u.push({index:o,entry:c}),void(t[e]=c);if("remove"===c.tag){u.push({index:o,entry:c}),c.tag="move";var a=[];return O(c.vnode,n,a,c.index),c.index=o,void(c.data.data={patches:a,entry:c})}J(t,r,e+gt,n,o,u)}function j(t,r,e,n,o){var u=t[e];if("undefined"==typeof u){var c=M("p-remove",o,void 0);return r.push(c),void(t[e]={tag:"remove",vnode:n,index:o,data:c})}if("insert"===u.tag){u.tag="move";var a=[];O(n,u.vnode,a,o);var c=M("p-remove",o,{patches:a,entry:u});return void r.push(c)}j(t,r,e+gt,n,o)}function F(t,r,e,n){W(t,r,e,0,0,r.descendantsCount,n)}function W(t,r,e,n,o,u,c){for(var a=e[n],i=a.index;i===o;){var f=a.type;if("p-thunk"===f)F(t,r.node,a.data,c);else if("p-reorder"===f){a.domNode=t,a.eventNode=c;var _=a.data.patches;_.length>0&&W(t,r,_,0,o,u,c)}else if("p-remove"===f){a.domNode=t,a.eventNode=c;var l=a.data;if("undefined"!=typeof l){
+l.entry.data=t;var _=l.patches;_.length>0&&W(t,r,_,0,o,u,c)}}else a.domNode=t,a.eventNode=c;if(n++,!(a=e[n])||(i=a.index)>u)return n}switch(r.type){case"tagger":for(var s=r.node;"tagger"===s.type;)s=s.node;return W(t,s,e,n,o+1,u,t.elm_event_node_ref);case"node":for(var d=r.children,h=t.childNodes,v=0;vu))return n;o=p}return n;case"keyed-node":for(var d=r.children,h=t.childNodes,v=0;vu))return n;o=p}return n;case"text":case"thunk":throw new Error("should never traverse `text` or `thunk` nodes like this")}}function q(t,r,e,n){return 0===e.length?t:(F(t,r,e,n),U(t,e))}function U(t,r){for(var e=0;eOops! Something went wrong when starting your Elm program.
'+t+"
"),new Error(t)}function Z(t,r,e,n){r.embed=function(r,e){for(;r.lastChild;)r.removeChild(r.lastChild);return sr.initialize(n(t.init,e,r),t.update,t.subscriptions,tt(r,t.view))},r.fullscreen=function(r){return sr.initialize(n(t.init,r,document.body),t.update,t.subscriptions,tt(document.body,t.view))}}function tt(t,r){return function(e,n){var o={tagger:e,parent:void 0},u=r(n),c=N(u,o);return t.appendChild(c),rt(c,r,u,o)}}function rt(t,r,e,n){function o(){switch(c){case"NO_REQUEST":throw new Error("Unexpected draw callback.\nPlease report this to .");case"PENDING_REQUEST":bt(o),c="EXTRA_REQUEST";var e=r(u),i=C(a,e);return t=q(t,a,i,n),void(a=e);case"EXTRA_REQUEST":return void(c="NO_REQUEST")}}var u,c="NO_REQUEST",a=e;return function(t){"NO_REQUEST"===c&&bt(o),c="PENDING_REQUEST",u=t}}function et(t,r,e,n){r.fullscreen=function(r){var o={doc:void 0};return sr.initialize(n(t.init,r,document.body),t.update(nt(o)),t.subscriptions,ot(e,document.body,o,t.view,t.viewIn,t.viewOut))},r.embed=function(r,o){var u={doc:void 0};return sr.initialize(n(t.init,o,r),t.update(nt(u)),t.subscriptions,ot(e,r,u,t.view,t.viewIn,t.viewOut))}}function nt(t){return dr.nativeBinding(function(r){var e=t.doc;if(e){var n=e.getElementsByClassName("debugger-sidebar-messages")[0];n&&(n.scrollTop=n.scrollHeight)}r(dr.succeed(g.Tuple0))})}function ot(t,r,e,n,o,u){return function(c,a){var i={tagger:c,parent:void 0},f={tagger:c,parent:void 0},_=n(a),l=N(_,i);r.appendChild(l);var s=rt(l,n,_,i),d=o(a)._1,h=N(d,f);r.appendChild(h);var v=at(i,h,o),g=rt(h,v,d,f),p=ut(a,u,f,r,t,e);return function(t){s(t),g(t),p(t)}}}function ut(t,r,e,n,o,u){var c,a;return function(t){if(t.isDebuggerOpen){if(!u.doc)return c=r(t),void(a=ct(o,u,c,e));vt=u.doc;var n=r(t),i=C(c,n);a=q(a,c,i,e),c=n,vt=document}}}function ct(t,r,e,n){function o(){r.doc=void 0,f.close()}var u=900,c=360,a=screen.width-u,i=screen.height-c,f=window.open("","","width="+u+",height="+c+",left="+a+",top="+i);vt=f.document,r.doc=vt,vt.title="Debugger - "+t,vt.body.style.margin="0",vt.body.style.padding="0";var _=N(e,n);return vt.body.appendChild(_),vt.addEventListener("keydown",function(t){t.metaKey&&82===t.which&&window.location.reload(),38===t.which&&(n.tagger({ctor:"Up"}),t.preventDefault()),40===t.which&&(n.tagger({ctor:"Down"}),t.preventDefault())}),window.addEventListener("unload",o),f.addEventListener("unload",function(){r.doc=void 0,window.removeEventListener("unload",o),n.tagger({ctor:"Close"})}),vt=document,_}function at(t,r,e){var n,o=_t(r),u="Normal",c=t.tagger,a=function(){};return function(r){var i=e(r),f=i._0.ctor;return t.tagger="Normal"===f?c:a,u!==f&&(it("removeEventListener",o,u),it("addEventListener",o,f),"Normal"===u&&(n=document.body.style.overflow,document.body.style.overflow="hidden"),"Normal"===f&&(document.body.style.overflow=n),u=f),i._1}}function it(t,r,e){switch(e){case"Normal":return;case"Pause":return ft(t,r,yt);case"Message":return ft(t,r,kt)}}function ft(t,r,e){for(var n=0;n"]=r(function(t,r){return f(Er,function(t){return r},t)});var Ge=e(function(t,r,e){for(;;){var n=t;if("[]"===n.ctor)return Sr(e);var o=n._1,u=n._0._0,c=n._0._1,a=f(lt,u,r);if("Just"===a.ctor&&"Connected"===a._0.ctor)return f($e["&>"],f(De,a._0._0,c),_(Ge,o,r,e));var i=o,l=r,s=_(Ft,u,Qe(c),e);t=i,r=l,e=s}}),He=sr.leaf("WebSocket"),Ve=sr.leaf("WebSocket"),Xe=e(function(t,r,e){return{sockets:t,queues:r,subs:e}}),Ye=Sr(_(Xe,Nt,Nt,Nt)),Ze=r(function(t,r){return{ctor:"Send",_0:t,_1:r}}),tn=(r(function(t,r){return Ve(f(Ze,t,r))}),r(function(t,r){var e=r;return f(Ze,e._0,e._1)})),rn=function(t){return{ctor:"KeepAlive",_0:t}},en=r(function(t,r){return{ctor:"Listen",_0:t,_1:r}}),nn=r(function(t,r){return He(f(en,t,r))}),on=r(function(t,r){var e=r;return"Listen"===e.ctor?f(en,e._0,function(r){return t(e._1(r))}):rn(e._0)}),un=function(t){return{ctor:"Connected",_0:t}},cn=r(function(t,r){return{ctor:"Opening",_0:t,_1:r}}),an=function(t){return{ctor:"BadOpen",_0:t}},fn=r(function(t,r){return{ctor:"GoodOpen",_0:t,_1:r}}),_n=function(t){return{ctor:"Die",_0:t}},ln=r(function(t,r){return{ctor:"Receive",_0:t,_1:r}}),sn=r(function(t,e){return f(Fe,t,{onMessage:r(function(r,n){return f(br,e,f(ln,t,n))}),onClose:function(r){return f(br,e,_n(t))}})}),dn=e(function(t,r,e){var n=function(r){return f(br,t,an(e))},o=function(r){return f(br,t,f(fn,e,r))},u=f(Rr,n,f(Er,o,f(sn,e,t)));return ie(f($e["&>"],qe(r),u))}),hn=n(function(t,o,u,c){var a=f(Ke,u,Nt),i=function(o){var u=e(function(t,r,e){return f($e["&>"],We(r),e)}),i=n(function(t,r,e,n){return f(Cr,f(Wt,t,e),n)}),l=e(function(r,e,n){return f(Er,function(e){return f(Er,function(t){return Sr(_(Wt,r,f(cn,0,t),e))},_(dn,t,0,r))},n)}),s=f(qt,o,f(It,r(function(t,r){return{ctor:"[]"}}),a)),h=d(at,l,i,u,s,c.sockets,Sr(Nt));return f(Er,function(t){return Sr(_(Xe,t,o,a))},h)},l=_(Ge,o,c.sockets,c.queues);return f(Er,i,l)}),vn=e(function(t,e,n){var o=e;switch(o.ctor){case"Receive":var u=f(P,function(r){return f(yr,t,r(o._1))},f(T,{ctor:"[]"},f(lt,o._0,n.subs)));return f($e["&>"],Or(u),Sr(n));case"Die":var c=o._0,a=f(lt,c,n.sockets);return"Nothing"===a.ctor?Sr(n):f(Er,function(t){return Sr(_(ze,c,f(cn,0,t),n))},_(dn,t,0,c));case"GoodOpen":var i=o._1,l=o._0,s=f(lt,l,n.queues);return"Nothing"===s.ctor?Sr(_(ze,l,un(i),n)):_(C,r(function(t,r){return f($e["&>"],f(De,i,t),r)}),Sr(f(Ue,l,_(ze,l,un(i),n))),s._0);default:var d=o._0,h=f(lt,d,n.sockets);if("Nothing"===h.ctor)return Sr(n);if("Opening"===h._0.ctor){var v=h._0._0;return f(Er,function(t){return Sr(_(ze,d,f(cn,v+1,t),n))},_(dn,t,v+1,d))}return Sr(n)}});sr.effectManagers.WebSocket={pkg:"elm-lang/websocket",init:Ye,onEffects:hn,onSelfMsg:vn,tag:"fx",cmdMap:tn,subMap:on};var gn=r(function(t,r){var e=t;return"Nothing"===e.ctor||f(O,e._0,r)}),pn=function(t){var r=t.unit;return"Nothing"===r.ctor?f(Re,{ctor:"[]"},{ctor:"::",_0:be(t.value),_1:{ctor:"[]"}}):f(Re,{ctor:"::",_0:Se("value"),_1:{ctor:"[]"}},{ctor:"::",_0:be(f(b["++"],t.value,f(b["++"]," (",f(b["++"],r._0,")")))),_1:{ctor:"[]"}})},mn=function(t){return f(b["++"],y(oe(t)),f(b["++"],"-",f(b["++"],y(ne(t)),f(b["++"]," ",f(b["++"],y(ee(t)),f(b["++"],":",f(b["++"],y(re(t)),f(b["++"],":",y(te(t))))))))))},bn=function(t){return f(Be,{ctor:"[]"},{ctor:"::",_0:f(Re,{ctor:"[]"},{ctor:"::",_0:be(t.name),_1:{ctor:"[]"}}),_1:{ctor:"::",_0:pn(t),_1:{ctor:"::",_0:f(Re,{ctor:"[]"},{ctor:"::",_0:be(mn(ue(1e3*t.ts))),_1:{ctor:"[]"}}),_1:{ctor:"[]"}}}})},yn=function(t){return f(we,{ctor:"[]"},{ctor:"::",_0:f(Ne,{ctor:"[]"},{ctor:"::",_0:f(Be,{ctor:"[]"},{ctor:"::",_0:f(Ee,{ctor:"[]"},{ctor:"::",_0:be("Name"),_1:{ctor:"[]"}}),_1:{ctor:"::",_0:f(Ee,{ctor:"[]"},{ctor:"::",_0:be("Value"),_1:{ctor:"[]"}}),_1:{ctor:"::",_0:f(Ee,{ctor:"[]"},{ctor:"::",_0:be("Timestamp"),_1:{ctor:"[]"}}),_1:{ctor:"[]"}}}}),_1:{ctor:"[]"}}),_1:{ctor:"::",_0:f(Te,{ctor:"[]"},f(P,bn,t)),_1:{ctor:"[]"}}})},kn=function(t){var r=t.ts;return"Nothing"===r.ctor?f(ke,{ctor:"[]"},{ctor:"[]"}):f(ke,{ctor:"::",_0:Se("header"),_1:{ctor:"[]"}},{ctor:"::",_0:f(ke,{ctor:"[]"},{ctor:"::",_0:be("updated at:"),_1:{ctor:"[]"}}),_1:{ctor:"::",_0:f(ke,{ctor:"[]"},{ctor:"::",_0:be(mn(r._0)),_1:{ctor:"[]"}}),_1:{ctor:"[]"}}})},wn=r(function(t,r){return f(O,r,t.hidden)?g.update(t,{hidden:f(I,function(t){return!g.eq(t,r)},t.hidden)}):g.update(t,{hidden:{ctor:"::",_0:r,_1:t.hidden}})}),Tn=o(function(t,r,e,n,o){return{startTime:t,ts:r,status:e,hidden:n,parameters:o}}),Nn=function(t){return{ctor:"_Tuple2",_0:s(Tn,ue(t.startTime),N,"Waiting",{ctor:"[]"},N),_1:vr}},Bn=r(function(t,r){return{instrument:t,parameters:r}}),Rn=r(function(t,r){return{instrument:t,parameters:r}}),En=n(function(t,r,e,n){return{name:t,unit:r,value:e,ts:n}}),xn=_(Nr,"ts",ar(ir),_(Nr,"value",ar(lr),_(Nr,"unit",ar(lr),_(Nr,"name",lr,kr(En))))),An=_(Nr,"parameters",cr(xn),_(Nr,"instrument",ar(lr),kr(Rn))),Sn=r(function(t,r){return{ts:t,parameters:r}}),Cn=_(Nr,"parameters",cr(An),_(Nr,"ts",ir,kr(Sn))),Mn=n(function(t,r,e,n){return{name:t,unit:r,value:e,ts:n}}),On=function(t){return _(R,f(Mn,t.name,t.unit),t.value,t.ts)},Ln=function(t){return f(Bn,t.instrument,f(J,On,t.parameters))},Pn=r(function(t,r){return function(e){return s(Tn,r.startTime,B(ue(1e3*t.ts)),"Running",r.hidden,B(e))}(f(P,Ln,t.parameters))}),In=r(function(t,r){var e=t;return"Err"===e.ctor?s(Tn,ue(0),N,f(b["++"],"error:",e._0),{ctor:"[]"},N):f(Pn,e._0,r)}),Dn=r(function(t,r){var e=t;switch(e.ctor){case"NoOp":return{ctor:"_Tuple2",_0:r,_1:vr};case"WsMessage":var n=f(In,f(tr,Cn,e._0),r);return{ctor:"_Tuple2",_0:n,_1:vr};default:return{ctor:"_Tuple2",_0:f(wn,r,e._0),_1:vr}}}),Jn=function(t){return{ctor:"Hide",_0:t}},jn=function(t){var r=t;if("Nothing"===r.ctor)return{ctor:"::",_0:be(""),_1:{ctor:"[]"}};var e=r._0;return{ctor:"::",_0:f(ke,{ctor:"::",_0:Pe(Jn(e)),_1:{ctor:"[]"}},{ctor:"::",_0:be(e),_1:{ctor:"[]"}}),_1:{ctor:"[]"}}},Fn=r(function(t,r){return f(ke,{ctor:"[]"},{ctor:"::",_0:f(ke,{ctor:"::",_0:Se("instrument"),_1:{ctor:"[]"}},jn(r.instrument)),_1:{ctor:"::",_0:f(ke,{ctor:"::",_0:Se("parameters"),_1:{ctor:"::",_0:Me(f(gn,r.instrument,t)),_1:{ctor:"[]"}}},{ctor:"::",_0:yn(r.parameters),_1:{ctor:"[]"}}),_1:{ctor:"[]"}}})}),Wn=r(function(t,r){return f(ke,{ctor:"::",_0:Se("parametersContainer"),_1:{ctor:"[]"}},f(P,Fn(t),r))}),qn=function(t){var r=t.parameters;return"Nothing"===r.ctor?f(ke,{ctor:"[]"},{ctor:"::",_0:be(f(b["++"],"Status:",t.status)),_1:{ctor:"[]"}}):f(Wn,t.hidden,r._0)},Un=function(t){return f(ke,{ctor:"::",_0:Se("container"),_1:{ctor:"[]"}},{ctor:"::",_0:kn(t),_1:{ctor:"::",_0:qn(t),_1:{ctor:"[]"}}})},zn=function(t){return{ctor:"WsMessage",_0:t}},Qn=function(t){return f(nn,"ws://localhost:5678",zn)},Kn=me({view:Un,init:Nn,update:Dn,subscriptions:Qn})(f(Vt,function(t){return Yt({startTime:t})},f(or,"startTime",ir))),$n={};if($n.Main=$n.Main||{},"undefined"!=typeof Kn&&Kn($n.Main,"Main",void 0),"function"==typeof define&&define.amd)return void define([],function(){return $n});if("object"==typeof t)return void(t.exports=$n);var Gn=this.Elm;if("undefined"==typeof Gn)return void(this.Elm=$n);for(var Hn in $n){if(Hn in Gn)throw new Error("There are two Elm modules called `"+Hn+"` on this page! Rename one of them.");Gn[Hn]=$n[Hn]}}).call(this)}]);
\ No newline at end of file
diff --git a/qcodes/monitor/dist/webpack-assets.json b/qcodes/monitor/dist/webpack-assets.json
new file mode 100644
index 00000000000..397e5d7b63a
--- /dev/null
+++ b/qcodes/monitor/dist/webpack-assets.json
@@ -0,0 +1 @@
+{"main":{"js":"/js/main.b221ee88.js","css":"/css/main.0963d6b9.css"}}
\ No newline at end of file
diff --git a/qcodes/monitor/monitor.py b/qcodes/monitor/monitor.py
new file mode 100644
index 00000000000..43ed7615cff
--- /dev/null
+++ b/qcodes/monitor/monitor.py
@@ -0,0 +1,218 @@
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+# vim:fenc=utf-8
+#
+# Copyright © 2017 unga
+#
+# Distributed under terms of the MIT license.
+"""
+Monitor a set of parameter in a background thread
+stream opuput over websocket
+"""
+
+import asyncio
+import logging
+import os
+import time
+import json
+import http.server
+import socketserver
+import webbrowser
+
+from threading import Thread
+from typing import Dict
+from concurrent.futures import Future
+from concurrent.futures import CancelledError
+import functools
+
+import websockets
+
+SERVER_PORT = 3000
+
+log = logging.getLogger(__name__)
+
+
+def _get_metadata(*parameters) -> Dict[float, list]:
+ """
+ Return a dict that contains the parameter metadata grouped by the
+ instrument it belongs to.
+ """
+ ts = time.time()
+ # group meta data by instrument if any
+ metas = {}
+ for parameter in parameters:
+ _meta = getattr(parameter, "_latest", None)
+ if _meta:
+ meta = _meta()
+ else:
+ raise ValueError("Input is not a parameter; Refusing to proceed")
+ # convert to string
+ meta['value'] = str(meta['value'])
+ if meta["ts"] is not None:
+ meta["ts"] = time.mktime(meta["ts"].timetuple())
+ meta["name"] = parameter.label or parameter.name
+ meta["unit"] = parameter.unit
+ # find the base instrument in case this is a channel parameter
+ baseinst = parameter._instrument
+ while hasattr(baseinst, '_parent'):
+ baseinst = baseinst._parent
+ accumulator = metas.get(str(baseinst), [])
+ accumulator.append(meta)
+ metas[str(baseinst)] = accumulator
+ parameters = []
+ for instrument in metas:
+ temp = {"instrument": instrument, "parameters": metas[instrument]}
+ parameters.append(temp)
+ state = {"ts": ts, "parameters": parameters}
+ return state
+
+
+def _handler(parameters, interval: int):
+
+ async def serverFunc(websocket, path):
+ while True:
+ try:
+ try:
+ meta = _get_metadata(*parameters)
+ except ValueError as e:
+ log.exception(e)
+ break
+ log.debug("sending..")
+ try:
+ await websocket.send(json.dumps(meta))
+ # mute browser discconects
+ except websockets.exceptions.ConnectionClosed as e:
+ log.debug(e)
+ await asyncio.sleep(interval)
+ except CancelledError:
+ break
+ log.debug("closing sever")
+
+ return serverFunc
+
+
+class Monitor(Thread):
+ running = None
+ server = None
+
+ def __init__(self, *parameters, interval=1):
+ """
+ Monitor qcodes parameters.
+
+ Args:
+ *parameters: Parameters to monitor
+ interval: How often one wants to refresh the values
+ """
+ # let the thread start
+ time.sleep(0.01)
+ super().__init__()
+ self.loop = None
+ self._monitor(*parameters, interval=1)
+
+ def run(self):
+ """
+ Start the event loop and run forever
+ """
+ self.loop = asyncio.new_event_loop()
+ asyncio.set_event_loop(self.loop)
+ Monitor.running = self
+ self.loop.run_forever()
+
+ def stop(self):
+ """
+ Shutdown the server, close the event loop and join the thread
+ """
+ # this contains the server
+ # or any exception
+ server = self.future_restult.result()
+ # server.close()
+ self.loop.call_soon_threadsafe(server.close)
+ self.loop.call_soon_threadsafe(self.loop.stop)
+ self.join()
+ Monitor.running = None
+
+ @staticmethod
+ def show():
+ """
+ Overwrite this method to show/raise your monitor GUI
+ F.ex.
+
+ ::
+
+ import webbrowser
+ url = "localhost:3000"
+ # Open URL in new window, raising the window if possible.
+ webbrowser.open_new(url)
+
+ """
+ webbrowser.open("http://localhost:{}".format(SERVER_PORT))
+
+ def _monitor(self, *parameters, interval=1):
+ handler = _handler(parameters, interval=interval)
+ # TODO (giulioungaretti) read from config
+ server = websockets.serve(handler, '127.0.0.1', 5678)
+
+ log.debug("Start monitoring thread")
+
+ if Monitor.running:
+ # stop the old server
+ log.debug("Stoppging and restarting server")
+ Monitor.running.stop()
+
+ self.start()
+
+ # let the thread start
+ time.sleep(0.01)
+
+ log.debug("Start monitoring server")
+ self._add_task(server)
+
+ def _create_task(self, future, coro):
+ task = self.loop.create_task(coro)
+ future.set_result(task)
+
+ def _add_task(self, coro):
+ future = Future()
+ self.task = coro
+ p = functools.partial(self._create_task, future, coro)
+ self.loop.call_soon_threadsafe(p)
+ # this stores the result of the future
+ self.future_restult = future.result()
+ self.future_restult.add_done_callback(_log_result)
+
+
+def _log_result(future):
+ try:
+ future.result()
+ log.debug("Started server loop")
+ except:
+ log.exception("Could not start server loop")
+
+
+class Server():
+
+ def __init__(self, port=3000):
+ self.port = port
+ self.handler = http.server.SimpleHTTPRequestHandler
+ self.httpd = socketserver.TCPServer(("", self.port), self.handler)
+ self.static_dir = os.path.join(os.path.dirname(__file__), 'dist')
+
+ def run(self):
+ os.chdir(self.static_dir)
+ log.debug("serving directory %s", self.static_dir)
+ log.info("Open broswer at http://localhost::{}".format(self.port))
+ self.httpd.serve_forever()
+
+ def stop(self):
+ self.httpd.shutdown()
+ self.join()
+
+
+if __name__ == "__main__":
+ server = Server(SERVER_PORT)
+ print("Open broswer at http://localhost:{}".format(server.port))
+ try:
+ webbrowser.open("http://localhost:{}".format(server.port))
+ server.run()
+ except KeyboardInterrupt:
+ exit()
diff --git a/qcodes/monitor/readme.md b/qcodes/monitor/readme.md
new file mode 100644
index 00000000000..6226565cb19
--- /dev/null
+++ b/qcodes/monitor/readme.md
@@ -0,0 +1,9 @@
+This is a WebBased Monitor for displaying QCoDeS
+parameters written in ELM.
+
+To launch do `python monitor.py`
+and from your QCoDeS shell launch as
+`qcodes.Monitor(*listofparamterstomonitor)`
+
+The ELM source code is available at
+https://github.com/QCoDeS/GUI
diff --git a/setup.py b/setup.py
index 2aafa475040..d8ca9bf8632 100644
--- a/setup.py
+++ b/setup.py
@@ -55,11 +55,13 @@ def readme():
# if we want to install without tests:
# packages=find_packages(exclude=["*.tests", "tests"]),
packages=find_packages(),
- package_data={'qcodes': ['widgets/*.js', 'widgets/*.css', 'config/*.json']},
- install_requires= [
+ package_data={'qcodes': ['monitor/dist/*', 'monitor/dist/js/*',
+ 'monitor/dist/css/*', 'config/*.json']},
+ install_requires=[
'numpy>=1.10',
'pyvisa>=1.8',
- 'h5py>=2.6'
+ 'h5py>=2.6',
+ 'websockets>=3.2,<3.4'
],
test_suite='qcodes.tests',