changeset 535:bb43ad96da8c

start homeauto_anynode for files shared between arduino and pi Ignore-this: 607e3e6e8d43f339caf6758f14619576
author drewp@bigasterisk.com
date Thu, 25 Apr 2019 17:34:53 -0700
parents db58e417b9eb
children b71ada7ab461
files lib/homeauto_anynode/MANIFEST.in lib/homeauto_anynode/setup.py lib/homeauto_anynode/static/index.html lib/homeauto_anynode/static/output-widgets.html lib/homeauto_anynode/tasks.py service/arduinoNode/static/index.html service/arduinoNode/static/output-widgets.html
diffstat 7 files changed, 421 insertions(+), 400 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/homeauto_anynode/MANIFEST.in	Thu Apr 25 17:34:53 2019 -0700
@@ -0,0 +1,1 @@
+recursive-include static *
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/homeauto_anynode/setup.py	Thu Apr 25 17:34:53 2019 -0700
@@ -0,0 +1,11 @@
+from distutils.core import setup
+ 
+setup(
+    name='homeauto_anynode',
+    version='0.0.0',
+    packages=['homeauto_anynode'],
+    package_dir={'homeauto_anynode': ''},
+    url='https://projects.bigasterisk.com/homeauto_anynode/homeauto_anynode-0.0.0.tar.gz',
+    author='Drew Perttula',
+    author_email='drewp@bigasterisk.com',
+)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/homeauto_anynode/static/index.html	Thu Apr 25 17:34:53 2019 -0700
@@ -0,0 +1,201 @@
+<!doctype html>
+<html>
+  <head>
+    <title>ha - </title>
+    <meta name=viewport content="width=device-width, initial-scale=1">
+    <meta charset="utf-8" />
+    <script src="/lib/polymer/1.0.9/webcomponentsjs/webcomponents.min.js"></script>
+    <script src="/lib/require/require-2.3.3.js"></script>
+    <script>
+     requirejs.config({
+         paths: {
+             "streamed-graph": "/rdf/streamed-graph",
+             "quadstore": "/rdf/quadstore",
+             "async-module": "/lib/async/80f1793/async",
+             "async": "/lib/async/80f1793/async",
+             "jsonld-module": "/lib/jsonld.js/0.4.11/js/jsonld",
+             "jsonld": "/lib/jsonld.js/0.4.11/js/jsonld",
+             "rdfstore": "/lib/rdf_store/0.9.7/dist/rdfstore",
+             "moment": "/lib/moment.min",
+             "underscore": "/lib/underscore-1.5.2.min",
+         }
+     });
+    </script>
+
+    <link rel="import" href="/lib/polymer/1.0.9/polymer/polymer.html">
+    <link rel="import" href="/lib/polymer/1.0.9/iron-ajax/iron-ajax.html">
+    <link rel="import" href="/lib/polymer/1.0.9/iron-flex-layout/iron-flex-layout.html">
+    <link rel="import" href="/lib/polymer/1.0.9/paper-button/paper-button.html">
+    <link rel="import" href="/rdf/rdf-oneshot.html">
+    <link rel="import" href="/rdf/rdf-uri.html">
+    <link rel="import" href="/rdf/graph-view.html">
+    <link rel="import" href="/rdf/streamed-graph.html">
+    <link rel="import" href="static/output-widgets.html">
+    <style>
+     body {
+       font-family: monospace;
+       display: flex;
+       flex-direction: column;
+       margin: 0;
+       height: 100vh;
+     }
+    </style>
+  </head>
+  <body>
+    <script>
+     window.NS = {
+       dev: 'http://projects.bigasterisk.com/device/',
+       room: 'http://projects.bigasterisk.com/room/',
+       rdfs: 'http://www.w3.org/2000/01/rdf-schema#',
+       sensor: 'http://bigasterisk.com/homeauto/sensor/',
+       b0: 'http://bigasterisk.com/homeauto/board0/',
+     };
+    </script>
+
+    <dom-module id="linked-uri">
+      <template>
+        <a href$="{{href}}">{{compactUri(href)}}</a>
+      </template>
+      <script>
+       HTMLImports.whenReady(function () {
+         Polymer({
+           is: 'linked-uri',
+           properties: { href: { notify: true } },
+           behaviors: [BigastUri]
+         });
+       });
+      </script>
+    </dom-module>
+
+    <dom-module id="watched-subgraph">
+      <style>
+       .read { font-weight: bold; }
+      </style>
+      <template>
+        <div><span>{{compactUri(subj)}}</span>, <span>{{compactUri(pred)}}</span>,
+          <span class="read">{{formatted(out)}}</span>
+        </div>
+
+      </template>
+      <script>
+       HTMLImports.whenReady(function () {
+         Polymer({
+           is: 'watched-subgraph',
+           properties: {
+             streamedGraph: { notify: true, observer: 'onGraphChange' }, // streamed-graph output
+             out: { notify: true },
+             pred: { notify: true }, // uri
+             subj: { notify: true } // uri
+           },
+           behaviors: [BigastUri],
+           onGraphChange: function(streamedGraph) {
+             if (!streamedGraph.graph) {
+               return;
+             }
+             var env = streamedGraph.graph.store.rdf;
+             streamedGraph.graph.quadStore.quads({subject: env.createNamedNode(this.subj),
+                                                  predicate: env.createNamedNode(this.pred)},
+                                                 function(quad) {
+               this.out = quad.object.valueOf();
+             }.bind(this));
+           },
+           formatted: function (obj) {
+             if (typeof(obj) == 'string') {
+               return this.compactUri(obj);
+             } else {
+               return obj;
+             }
+           }
+         });
+       });
+      </script>
+    </dom-module>
+
+    <dom-module id="arduinonode-boards">
+      <style>
+       h1 {
+         margin: 0;
+         font-size: 130%;
+       }
+       ul {
+         padding-left: 5px;
+       }
+       .board, .device {
+         border: 1px solid gray;
+         border-radius: 10px;
+         margin: 13px;
+         padding: 7px;
+         box-shadow: 2px 5px 5px rgba(0, 0, 0, 0.14);
+       }
+       .board {
+         background: rgb(244, 244, 244);
+       }
+       .device {
+         background: #fff;
+       }
+       .devs {
+         -webkit-column-width: 440px;
+       }
+       .devs .device {
+         -webkit-column-break-inside: avoid;
+       }
+      </style>
+      <template>
+        <streamed-graph url="graph/events" graph="{{graph}}"></streamed-graph>
+        <iron-ajax url="boards" auto="true" handle-as="json"
+                   last-response="{{ret}}"></iron-ajax>
+        <template is="dom-repeat" items="{{ret.boards}}" as="board">
+          <div class="board">
+            <h1>Board <linked-uri href$="{{board.uri}}"></linked-uri></h1>
+            <h2>Devices</h2>
+            <ul class="devs">
+              <template is="dom-repeat" items="{{board.devices}}" as="dev">
+                <div class="device">
+                  <h1>
+                    <span>{{dev.className}}</span>
+                    <linked-uri href$="{{dev.uri}}"></linked-uri>
+                  </h1>
+                  <template is="dom-if" if="{{dev.watchPrefixes.length}}">
+                    <div>watching:</div>
+                    <ul>
+                      <template is="dom-repeat" items="{{dev.watchPrefixes}}" as="prefix">
+                        <watched-subgraph streamed-graph="{{graph}}" subj="{{prefix.0}}" pred="{{prefix.1}}"></watched-subgraph>
+                      </template>
+                    </ul>
+                  </template>
+
+                  <template is="dom-if" if="{{dev.outputWidgets.length}}">
+                    <div>send output:</div>
+                    <ul>
+                      <template is="dom-repeat" items="{{dev.outputWidgets}}" as="out">
+                        <div>
+                          <output-widget-any streamed-graph="{{graph}}" desc="{{out}}"></output-widget-any>
+                        </div>
+                      </template>
+                    </ul>
+                  </template>
+                </div>
+              </template>
+            </ul>
+          </div>
+        </template>
+        <graph-view graph="{{graph}}"></graph-view>
+      </template>
+      <script>
+       HTMLImports.whenReady(function () {
+         Polymer({
+           is: 'arduinonode-boards',
+           properties: {
+             ret: { type: Object, notify: true, observer: 'onBoards' }
+           },
+           onBoards: function() {
+             document.title = document.title + ' ' + this.ret.host;
+           },
+           behaviors: [BigastUri]
+         });
+       });
+      </script>
+    </dom-module>
+    <arduinonode-boards></arduinonode-boards>
+  </body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/homeauto_anynode/static/output-widgets.html	Thu Apr 25 17:34:53 2019 -0700
@@ -0,0 +1,199 @@
+<link rel="import" href="/lib/polymer/1.0.9/iron-ajax/iron-ajax.html">
+<link rel="import" href="/lib/polymer/1.0.9/polymer/polymer.html">
+<link rel="import" href="/lib/polymer/1.0.9/color-picker-element/dist/color-picker.html">
+<link rel="import" href="/rdf/rdf-uri.html">
+
+<dom-module id="output-sender">
+  <template>
+    <iron-ajax id="output" url="{{output}}" method="PUT"></iron-ajax>
+    Set <a href$="{{subj}}">{{compactUri(subj)}}</a>'s
+    <span>{{compactUri(pred)}}</span> to
+  </template>
+  <script>
+   Polymer({
+     is: 'output-sender',
+     behaviors: [BigastUri],
+     properties: {
+       output: { type: String, value: "output" }, // url to PUT outputs
+       streamedGraph: { notify: true, observer: 'onGraphChange' },
+       subj: { notify: true },
+       pred: { notify: true },
+       value: { notify: true, observer: 'browserChangedValue' }
+     },
+     ready: function() {
+       this.waitOnChangeMs = 100;
+       this.smallestRequestPeriodMs = 100;
+       this.synced = false;
+       
+       this.newRequestNeedsSending = false;
+       this.lastSendMs = 0;
+       this.$.output.addEventListener('response', this.onResponse.bind(this));
+
+     },
+     onGraphChange: function(streamedGraph) {
+       if (!streamedGraph.graph) {
+         return;
+       }
+       var env = streamedGraph.graph.store.rdf;
+       streamedGraph.graph.quadStore.quads({
+         subject: env.createNamedNode(this.subj),
+         predicate: env.createNamedNode(this.pred)
+       }, function(quad) {
+         this.serverChangedValue(quad.object.valueOf());
+       }.bind(this));
+     },
+     onResponse: function() {
+       if (!this.newRequestNeedsSending) {
+         return;
+       }
+       if (this.$.output.activeRequests.length > 0) {
+         return; // 'response' event will call us back
+       }
+
+       var now = Date.now(), dt = now - this.lastSendMs;
+       if (dt < this.smallestRequestPeriodMs) {
+         setTimeout(this.onResponse.bind(this),
+                    this.smallestRequestPeriodMs - dt);
+         return;
+       } 
+       this.newRequestNeedsSending = false;
+       this.lastSendMs = now;
+       this.$.output.generateRequest();
+     },
+     browserChangedValue: function () {
+       if (!this.subj || !this.pred) {
+         return;
+       }
+       //this.$.output.headers = {'content-type': ...}
+       this.$.output.params = {s: this.subj, p: this.pred};
+       this.$.output.body = this.value;
+       this.newRequestNeedsSending = true;
+       setTimeout(this.onResponse.bind(this), this.waitOnChangeMs);
+     },
+     serverChangedValue: function(v) {
+       this.value = v;
+       this.synced = true;
+     }
+   });
+  </script>
+</dom-module>
+
+<dom-module id="output-rgb">
+  <template>
+    <div style="display: flex">
+      <div>
+        <output-sender streamed-graph="{{streamedGraph}}" subj="{{subj}}" pred="{{pred}}" value="{{value}}"></output-sender>
+        <div>color pick <span>{{value}}</span>
+        <button on-click="black">Black</button>
+        <button on-click="white">White</button>
+        </div>
+      </div>
+      <div>
+        <color-picker id="pick" width="200" height="100" color="{{value}}"></color-picker>
+      </div>
+    </div>
+  </template>
+  <script>
+   Polymer({
+     is: 'output-rgb',
+     properties: {
+       value: { notify: true },
+     },
+     ready: function () {
+       this.$.pick.addEventListener('colorselected', function (ev) {
+         this.value = ev.detail.hex;
+       }.bind(this));
+     },
+     black: function() {this.value = "#000000";},
+     white: function() {this.value = "#ffffff";}
+   });
+  </script>
+</dom-module>
+
+<dom-module id="output-slider">
+  <template>
+    <output-sender streamed-graph="{{streamedGraph}}" output="{{output}}" subj="{{subj}}" pred="{{pred}}" value="{{value}}"></output-sender>
+    <input type="range" min="{{min}}" max="{{max}}" step="{{step}}" value="{{value::input}}"> <span>{{value}}</span>
+  </template>
+  <script>
+   Polymer({
+     is: 'output-slider',
+     properties: {
+       output: { notify: true },
+       streamedGraph: { notify: true }, 
+       max: { notify: true },
+       min: { notify: true },
+       step: { notify: true }
+     },
+   });
+  </script>
+</dom-module>
+
+<!--
+    TODO(polyup): Inheriting from other custom elements is not yet supported.
+    See: https://www.polymer-project.org/1.0/docs/migration.html#inheritance
+ -->
+<dom-module id="output-fixed-text">
+  <template>
+    <output-sender streamed-graph="{{streamedGraph}}" subj="{{subj}}" pred="{{pred}}" value="{{value}}"></output-sender>
+    <textarea rows="{{rows}}" cols="{{cols}}" value="{{value::input}}"></textarea>
+  </template>
+  <script>
+    Polymer({
+      is: 'output-fixed-text',
+      properties: {
+        cols: { notify: true },
+        rows: { notify: true }
+      },
+    });
+  </script>
+</dom-module>
+
+<dom-module id="output-switch">
+  <template>
+    <output-sender streamed-graph="{{streamedGraph}}" subj="{{subj}}" pred="{{pred}}" value="{{value}}"></output-sender>
+    <input type="checkbox" checked="{{check::change}}"> <span>{{value}}</span>
+  </template>
+  <script>
+   Polymer({
+     is: 'output-switch',
+     properties: {
+       check: {
+         type: Boolean,
+         value: false,
+         observer: 'checkChanged'
+       },
+       value: { notify: true }
+     },
+     checkChanged: function () {
+       this.value = this.check ? 'high' : 'low';
+     },
+   });
+  </script>
+</dom-module>
+
+<dom-module id="output-widget-any">
+  <template></template>
+  <script>
+   Polymer({
+     is: 'output-widget-any',
+     properties: {
+       desc: { type: Object, notify: true },
+       streamedGraph: { type: Object, notify: true, observer: 'onGraph' },
+     },
+     ready: function () {
+       this.elem = document.createElement(this.desc.element);
+       this.appendChild(this.elem);
+       for (var k of Object.keys(this.desc)) {
+         this.elem.setAttribute(k, this.desc[k]);
+       }
+       this.elem.streamedGraph = this.streamedGraph;
+     },
+     onGraph: function(g) {
+       if (this.elem) {
+         this.elem.streamedGraph = g;
+       }
+     }
+   });
+  </script>
+</dom-module>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/homeauto_anynode/tasks.py	Thu Apr 25 17:34:53 2019 -0700
@@ -0,0 +1,9 @@
+from invoke import task
+
+import sys
+sys.path.append('/my/proj/release')
+from release import local_release
+
+@task
+def release(ctx):
+    local_release(ctx)
--- a/service/arduinoNode/static/index.html	Thu Apr 25 17:23:29 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,201 +0,0 @@
-<!doctype html>
-<html>
-  <head>
-    <title>ha - </title>
-    <meta name=viewport content="width=device-width, initial-scale=1">
-    <meta charset="utf-8" />
-    <script src="/lib/polymer/1.0.9/webcomponentsjs/webcomponents.min.js"></script>
-    <script src="/lib/require/require-2.3.3.js"></script>
-    <script>
-     requirejs.config({
-         paths: {
-             "streamed-graph": "/rdf/streamed-graph",
-             "quadstore": "/rdf/quadstore",
-             "async-module": "/lib/async/80f1793/async",
-             "async": "/lib/async/80f1793/async",
-             "jsonld-module": "/lib/jsonld.js/0.4.11/js/jsonld",
-             "jsonld": "/lib/jsonld.js/0.4.11/js/jsonld",
-             "rdfstore": "/lib/rdf_store/0.9.7/dist/rdfstore",
-             "moment": "/lib/moment.min",
-             "underscore": "/lib/underscore-1.5.2.min",
-         }
-     });
-    </script>
-
-    <link rel="import" href="/lib/polymer/1.0.9/polymer/polymer.html">
-    <link rel="import" href="/lib/polymer/1.0.9/iron-ajax/iron-ajax.html">
-    <link rel="import" href="/lib/polymer/1.0.9/iron-flex-layout/iron-flex-layout.html">
-    <link rel="import" href="/lib/polymer/1.0.9/paper-button/paper-button.html">
-    <link rel="import" href="/rdf/rdf-oneshot.html">
-    <link rel="import" href="/rdf/rdf-uri.html">
-    <link rel="import" href="/rdf/graph-view.html">
-    <link rel="import" href="/rdf/streamed-graph.html">
-    <link rel="import" href="static/output-widgets.html">
-    <style>
-     body {
-       font-family: monospace;
-       display: flex;
-       flex-direction: column;
-       margin: 0;
-       height: 100vh;
-     }
-    </style>
-  </head>
-  <body>
-    <script>
-     window.NS = {
-       dev: 'http://projects.bigasterisk.com/device/',
-       room: 'http://projects.bigasterisk.com/room/',
-       rdfs: 'http://www.w3.org/2000/01/rdf-schema#',
-       sensor: 'http://bigasterisk.com/homeauto/sensor/',
-       b0: 'http://bigasterisk.com/homeauto/board0/',
-     };
-    </script>
-
-    <dom-module id="linked-uri">
-      <template>
-        <a href$="{{href}}">{{compactUri(href)}}</a>
-      </template>
-      <script>
-       HTMLImports.whenReady(function () {
-         Polymer({
-           is: 'linked-uri',
-           properties: { href: { notify: true } },
-           behaviors: [BigastUri]
-         });
-       });
-      </script>
-    </dom-module>
-
-    <dom-module id="watched-subgraph">
-      <style>
-       .read { font-weight: bold; }
-      </style>
-      <template>
-        <div><span>{{compactUri(subj)}}</span>, <span>{{compactUri(pred)}}</span>,
-          <span class="read">{{formatted(out)}}</span>
-        </div>
-
-      </template>
-      <script>
-       HTMLImports.whenReady(function () {
-         Polymer({
-           is: 'watched-subgraph',
-           properties: {
-             streamedGraph: { notify: true, observer: 'onGraphChange' }, // streamed-graph output
-             out: { notify: true },
-             pred: { notify: true }, // uri
-             subj: { notify: true } // uri
-           },
-           behaviors: [BigastUri],
-           onGraphChange: function(streamedGraph) {
-             if (!streamedGraph.graph) {
-               return;
-             }
-             var env = streamedGraph.graph.store.rdf;
-             streamedGraph.graph.quadStore.quads({subject: env.createNamedNode(this.subj),
-                                                  predicate: env.createNamedNode(this.pred)},
-                                                 function(quad) {
-               this.out = quad.object.valueOf();
-             }.bind(this));
-           },
-           formatted: function (obj) {
-             if (typeof(obj) == 'string') {
-               return this.compactUri(obj);
-             } else {
-               return obj;
-             }
-           }
-         });
-       });
-      </script>
-    </dom-module>
-
-    <dom-module id="arduinonode-boards">
-      <style>
-       h1 {
-         margin: 0;
-         font-size: 130%;
-       }
-       ul {
-         padding-left: 5px;
-       }
-       .board, .device {
-         border: 1px solid gray;
-         border-radius: 10px;
-         margin: 13px;
-         padding: 7px;
-         box-shadow: 2px 5px 5px rgba(0, 0, 0, 0.14);
-       }
-       .board {
-         background: rgb(244, 244, 244);
-       }
-       .device {
-         background: #fff;
-       }
-       .devs {
-         -webkit-column-width: 440px;
-       }
-       .devs .device {
-         -webkit-column-break-inside: avoid;
-       }
-      </style>
-      <template>
-        <streamed-graph url="graph/events" graph="{{graph}}"></streamed-graph>
-        <iron-ajax url="boards" auto="true" handle-as="json"
-                   last-response="{{ret}}"></iron-ajax>
-        <template is="dom-repeat" items="{{ret.boards}}" as="board">
-          <div class="board">
-            <h1>Board <linked-uri href$="{{board.uri}}"></linked-uri></h1>
-            <h2>Devices</h2>
-            <ul class="devs">
-              <template is="dom-repeat" items="{{board.devices}}" as="dev">
-                <div class="device">
-                  <h1>
-                    <span>{{dev.className}}</span>
-                    <linked-uri href$="{{dev.uri}}"></linked-uri>
-                  </h1>
-                  <template is="dom-if" if="{{dev.watchPrefixes.length}}">
-                    <div>watching:</div>
-                    <ul>
-                      <template is="dom-repeat" items="{{dev.watchPrefixes}}" as="prefix">
-                        <watched-subgraph streamed-graph="{{graph}}" subj="{{prefix.0}}" pred="{{prefix.1}}"></watched-subgraph>
-                      </template>
-                    </ul>
-                  </template>
-
-                  <template is="dom-if" if="{{dev.outputWidgets.length}}">
-                    <div>send output:</div>
-                    <ul>
-                      <template is="dom-repeat" items="{{dev.outputWidgets}}" as="out">
-                        <div>
-                          <output-widget-any streamed-graph="{{graph}}" desc="{{out}}"></output-widget-any>
-                        </div>
-                      </template>
-                    </ul>
-                  </template>
-                </div>
-              </template>
-            </ul>
-          </div>
-        </template>
-        <graph-view graph="{{graph}}"></graph-view>
-      </template>
-      <script>
-       HTMLImports.whenReady(function () {
-         Polymer({
-           is: 'arduinonode-boards',
-           properties: {
-             ret: { type: Object, notify: true, observer: 'onBoards' }
-           },
-           onBoards: function() {
-             document.title = document.title + ' ' + this.ret.host;
-           },
-           behaviors: [BigastUri]
-         });
-       });
-      </script>
-    </dom-module>
-    <arduinonode-boards></arduinonode-boards>
-  </body>
-</html>
--- a/service/arduinoNode/static/output-widgets.html	Thu Apr 25 17:23:29 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,199 +0,0 @@
-<link rel="import" href="/lib/polymer/1.0.9/iron-ajax/iron-ajax.html">
-<link rel="import" href="/lib/polymer/1.0.9/polymer/polymer.html">
-<link rel="import" href="/lib/polymer/1.0.9/color-picker-element/dist/color-picker.html">
-<link rel="import" href="/rdf/rdf-uri.html">
-
-<dom-module id="output-sender">
-  <template>
-    <iron-ajax id="output" url="{{output}}" method="PUT"></iron-ajax>
-    Set <a href$="{{subj}}">{{compactUri(subj)}}</a>'s
-    <span>{{compactUri(pred)}}</span> to
-  </template>
-  <script>
-   Polymer({
-     is: 'output-sender',
-     behaviors: [BigastUri],
-     properties: {
-       output: { type: String, value: "output" }, // url to PUT outputs
-       streamedGraph: { notify: true, observer: 'onGraphChange' },
-       subj: { notify: true },
-       pred: { notify: true },
-       value: { notify: true, observer: 'browserChangedValue' }
-     },
-     ready: function() {
-       this.waitOnChangeMs = 100;
-       this.smallestRequestPeriodMs = 100;
-       this.synced = false;
-       
-       this.newRequestNeedsSending = false;
-       this.lastSendMs = 0;
-       this.$.output.addEventListener('response', this.onResponse.bind(this));
-
-     },
-     onGraphChange: function(streamedGraph) {
-       if (!streamedGraph.graph) {
-         return;
-       }
-       var env = streamedGraph.graph.store.rdf;
-       streamedGraph.graph.quadStore.quads({
-         subject: env.createNamedNode(this.subj),
-         predicate: env.createNamedNode(this.pred)
-       }, function(quad) {
-         this.serverChangedValue(quad.object.valueOf());
-       }.bind(this));
-     },
-     onResponse: function() {
-       if (!this.newRequestNeedsSending) {
-         return;
-       }
-       if (this.$.output.activeRequests.length > 0) {
-         return; // 'response' event will call us back
-       }
-
-       var now = Date.now(), dt = now - this.lastSendMs;
-       if (dt < this.smallestRequestPeriodMs) {
-         setTimeout(this.onResponse.bind(this),
-                    this.smallestRequestPeriodMs - dt);
-         return;
-       } 
-       this.newRequestNeedsSending = false;
-       this.lastSendMs = now;
-       this.$.output.generateRequest();
-     },
-     browserChangedValue: function () {
-       if (!this.subj || !this.pred) {
-         return;
-       }
-       //this.$.output.headers = {'content-type': ...}
-       this.$.output.params = {s: this.subj, p: this.pred};
-       this.$.output.body = this.value;
-       this.newRequestNeedsSending = true;
-       setTimeout(this.onResponse.bind(this), this.waitOnChangeMs);
-     },
-     serverChangedValue: function(v) {
-       this.value = v;
-       this.synced = true;
-     }
-   });
-  </script>
-</dom-module>
-
-<dom-module id="output-rgb">
-  <template>
-    <div style="display: flex">
-      <div>
-        <output-sender streamed-graph="{{streamedGraph}}" subj="{{subj}}" pred="{{pred}}" value="{{value}}"></output-sender>
-        <div>color pick <span>{{value}}</span>
-        <button on-click="black">Black</button>
-        <button on-click="white">White</button>
-        </div>
-      </div>
-      <div>
-        <color-picker id="pick" width="200" height="100" color="{{value}}"></color-picker>
-      </div>
-    </div>
-  </template>
-  <script>
-   Polymer({
-     is: 'output-rgb',
-     properties: {
-       value: { notify: true },
-     },
-     ready: function () {
-       this.$.pick.addEventListener('colorselected', function (ev) {
-         this.value = ev.detail.hex;
-       }.bind(this));
-     },
-     black: function() {this.value = "#000000";},
-     white: function() {this.value = "#ffffff";}
-   });
-  </script>
-</dom-module>
-
-<dom-module id="output-slider">
-  <template>
-    <output-sender streamed-graph="{{streamedGraph}}" output="{{output}}" subj="{{subj}}" pred="{{pred}}" value="{{value}}"></output-sender>
-    <input type="range" min="{{min}}" max="{{max}}" step="{{step}}" value="{{value::input}}"> <span>{{value}}</span>
-  </template>
-  <script>
-   Polymer({
-     is: 'output-slider',
-     properties: {
-       output: { notify: true },
-       streamedGraph: { notify: true }, 
-       max: { notify: true },
-       min: { notify: true },
-       step: { notify: true }
-     },
-   });
-  </script>
-</dom-module>
-
-<!--
-    TODO(polyup): Inheriting from other custom elements is not yet supported.
-    See: https://www.polymer-project.org/1.0/docs/migration.html#inheritance
- -->
-<dom-module id="output-fixed-text">
-  <template>
-    <output-sender streamed-graph="{{streamedGraph}}" subj="{{subj}}" pred="{{pred}}" value="{{value}}"></output-sender>
-    <textarea rows="{{rows}}" cols="{{cols}}" value="{{value::input}}"></textarea>
-  </template>
-  <script>
-    Polymer({
-      is: 'output-fixed-text',
-      properties: {
-        cols: { notify: true },
-        rows: { notify: true }
-      },
-    });
-  </script>
-</dom-module>
-
-<dom-module id="output-switch">
-  <template>
-    <output-sender streamed-graph="{{streamedGraph}}" subj="{{subj}}" pred="{{pred}}" value="{{value}}"></output-sender>
-    <input type="checkbox" checked="{{check::change}}"> <span>{{value}}</span>
-  </template>
-  <script>
-   Polymer({
-     is: 'output-switch',
-     properties: {
-       check: {
-         type: Boolean,
-         value: false,
-         observer: 'checkChanged'
-       },
-       value: { notify: true }
-     },
-     checkChanged: function () {
-       this.value = this.check ? 'high' : 'low';
-     },
-   });
-  </script>
-</dom-module>
-
-<dom-module id="output-widget-any">
-  <template></template>
-  <script>
-   Polymer({
-     is: 'output-widget-any',
-     properties: {
-       desc: { type: Object, notify: true },
-       streamedGraph: { type: Object, notify: true, observer: 'onGraph' },
-     },
-     ready: function () {
-       this.elem = document.createElement(this.desc.element);
-       this.appendChild(this.elem);
-       for (var k of Object.keys(this.desc)) {
-         this.elem.setAttribute(k, this.desc[k]);
-       }
-       this.elem.streamedGraph = this.streamedGraph;
-     },
-     onGraph: function(g) {
-       if (this.elem) {
-         this.elem.streamedGraph = g;
-       }
-     }
-   });
-  </script>
-</dom-module>