From 37c5a11ece1f4e13d92e029a98ade27fecd95eb0 Mon Sep 17 00:00:00 2001 From: Henry Date: Tue, 26 Apr 2016 14:47:03 -0700 Subject: [PATCH] [Demo] Updated demo telemetry source --- demo/bundle.js | 16 +- demo/src/DemoInitializer.js | 17 -- demo/src/telemetry/DemoTelemetryProvider.js | 162 +++++++++++++----- .../DemoTelemetryProviderDecorator.js | 88 ++++++++++ demo/src/telemetry/DemoTelemetrySeries.js | 83 +++++++++ 5 files changed, 298 insertions(+), 68 deletions(-) create mode 100644 demo/src/telemetry/DemoTelemetryProviderDecorator.js create mode 100644 demo/src/telemetry/DemoTelemetrySeries.js diff --git a/demo/bundle.js b/demo/bundle.js index f96df69e1e..98aed6de2c 100644 --- a/demo/bundle.js +++ b/demo/bundle.js @@ -56,12 +56,6 @@ define([ "provides": "conductorService", "type": "decorator" }, - { - "implementation": DemoTelemetryDecorator, - "provides": "telemetryService", - "type": "decorator", - "priority": "mandatory" - }, { "implementation": DemoTelemetryProvider, "type": "provider", @@ -147,7 +141,15 @@ define([ { "stylesheetUrl": "css/tour.css" } - ] + ], + "constants": [ + { + "key": "PLOT_FIXED_DURATION", + "value": 60000, + "comment": "1 minute." + } + ], + } }); }); diff --git a/demo/src/DemoInitializer.js b/demo/src/DemoInitializer.js index 994086efae..95574a8c9e 100644 --- a/demo/src/DemoInitializer.js +++ b/demo/src/DemoInitializer.js @@ -97,26 +97,9 @@ define( target: document.querySelector(".create-btn"), placement: "bottom" }, - /* - { - title: "Composing objects", - content: "Objects can be composed by dragging" + - " them from the tree...", - target: document.querySelector("mct-tree" + - " ul.tree"), - placement: "right" - }, - { - title: "Composing objects (cont.)", - content: "...into the current view", - target: document.querySelector(".object-holder-main"), - placement: "top", - yOffset: "100px;" - }*/ ] }; hopscotch.endTour(true); - // Start the tour! hopscotch.startTour(tour); }, 3000); diff --git a/demo/src/telemetry/DemoTelemetryProvider.js b/demo/src/telemetry/DemoTelemetryProvider.js index c69864ab59..e3518ed7dd 100644 --- a/demo/src/telemetry/DemoTelemetryProvider.js +++ b/demo/src/telemetry/DemoTelemetryProvider.js @@ -21,68 +21,142 @@ *****************************************************************************/ /*global define,Promise*/ +/** + * Module defining SinewaveTelemetryProvider. + * Created by vwoeltje on 11/12/14. + * + * @memberof example/generator + */ define( - ["../../../example/generator/src/SinewaveTelemetryProvider"], - function (SinewaveTelemetryProvider) { + ["./DemoTelemetrySeries"], + function (DemoTelemetrySeries) { "use strict"; - var SOURCE = 'demo-telemetry'; + var SOURCE = 'demo-telemetry', + series = {}; + /** + * A telemetry provider that generates sine wave data for testing + * and telemetry purposes. + * @constructor + */ function DemoTelemetryProvider($q, $timeout) { - SinewaveTelemetryProvider.call(this, $q, $timeout); - } - - DemoTelemetryProvider.prototype = Object.create(SinewaveTelemetryProvider.prototype); - - DemoTelemetryProvider.prototype.doPackage = function (results) { - var packaged = {}; - results.forEach(function (result) { - packaged[result.key] = result.telemetry; - }); - // Format as expected (sources -> keys -> telemetry) - return { "demo-telemetry": packaged }; + this.$q = $q; + this.$timeout = $timeout; + this.subscriptions = []; + this.generating = false; } DemoTelemetryProvider.prototype.matchesSource = function (request) { return request.source === SOURCE; + }; + + DemoTelemetryProvider.prototype.doPackage = function (results) { + var packaged = {}, + result = {}; + results.forEach(function (result) { + packaged[result.key] = result.telemetry; + }); + result[SOURCE] = packaged; + // Format as expected (sources -> keys -> telemetry) + return result; } - DemoTelemetryProvider.prototype.subscribe = function (callback, requests) { - var offsets = {}; + /** + * Produce some data to be passed to registered subscription callbacks + * @param request + * @returns {{key: string, telemetry: DemoTelemetrySeries}} + */ + DemoTelemetryProvider.prototype.generateData = function (request) { + if (!series[request.id]){ + series[request.id] = { + phaseShift: Math.random() * 2 * Math.PI, + rangeOffset: 1 + Math.random() + }; + } + return { + key: request.key, + telemetry: new DemoTelemetrySeries(request, series[request.id]) + }; + }; - function wrapSeries(telemetrySeries, offset) { - return { - getDomainValue: function (index, domain) { - return telemetrySeries.getDomainValue(index, domain); - }, - getRangeValue: function (index, range) { - // Sine wave 'carrier' signal, with random phase shift - return telemetrySeries.getRangeValue(index, range) - // Introduce some random variability so that line is - // not straight or perfectly curved - + Math.random(1)/50 - //Add a random range offset so that lines - // are not all bunched together - + offset; - }, - getPointCount: function () { - return telemetrySeries.getPointCount(); - } + /** + * Invoke callbacks on all registered subscriptions when data is + * available. + */ + DemoTelemetryProvider.prototype.handleSubscriptions = function () { + var self = this; + self.subscriptions.forEach(function (subscription) { + var requests = subscription.requests; + subscription.callback(self.doPackage( + requests.filter(self.matchesSource).map(self.generateData) + )); + }); + }; + + /** + * Will start producing telemetry @ 1hz + */ + DemoTelemetryProvider.prototype.startGenerating = function () { + var self = this; + self.generating = true; + self.$timeout(function () { + self.handleSubscriptions(); + if (self.generating && self.subscriptions.length > 0) { + self.startGenerating(); + } else { + self.generating = false; } - } + }, 1000); + }; - function randomize(telemetry){ - Object.keys(telemetry[SOURCE]).forEach(function(key) { - if (!offsets[key]) - offsets[key] = 1 + Math.random(10); - telemetry[SOURCE][key] = wrapSeries(telemetry[SOURCE][key], offsets[key]); + /** + * Request historical telemetry from this source. + * @param requests + * @returns {object} an object with the request key as the key, and + * a SinewaveTelemetrySeries as its value + */ + DemoTelemetryProvider.prototype.requestTelemetry = function (requests) { + var self = this; + return this.$timeout(function () { + return self.doPackage(requests.filter(self.matchesSource).map(self.generateData)); + }, 0); + }; + + /** + * Subscribe to realtime telemetry + * @param callback a function to call when data is available + * @param requests all current telemetry requests (will be tested to + * see if they match this source) + * @returns {function} a function to call to unsubscribe from this + * telemetry source + */ + DemoTelemetryProvider.prototype.subscribe = function (callback, requests) { + var self = this, + subscription = { + callback: callback, + requests: requests + }; + + function unsubscribe() { + self.subscriptions = self.subscriptions.filter(function (s) { + return s !== subscription; + }); + //Also delete series object + subscription.requests.forEach(function (request) { + delete series[request.id]; }); - callback(telemetry); } - return SinewaveTelemetryProvider.prototype.subscribe.call(this, randomize, requests); + self.subscriptions.push(subscription); + + if (!this.generating) { + this.startGenerating(); + } + + return unsubscribe; }; return DemoTelemetryProvider; } -); \ No newline at end of file +); diff --git a/demo/src/telemetry/DemoTelemetryProviderDecorator.js b/demo/src/telemetry/DemoTelemetryProviderDecorator.js new file mode 100644 index 0000000000..32de42b125 --- /dev/null +++ b/demo/src/telemetry/DemoTelemetryProviderDecorator.js @@ -0,0 +1,88 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,Promise*/ + +define( + ["../../../example/generator/src/SinewaveTelemetryProvider"], + function (SinewaveTelemetryProvider) { + "use strict"; + + var SOURCE = 'demo-telemetry'; + + function DemoTelemetryProvider($q, $timeout) { + SinewaveTelemetryProvider.call(this, $q, $timeout); + } + + DemoTelemetryProvider.prototype = Object.create(SinewaveTelemetryProvider.prototype); + + DemoTelemetryProvider.prototype.doPackage = function (results) { + var packaged = {}; + results.forEach(function (result) { + packaged[result.key] = result.telemetry; + }); + // Format as expected (sources -> keys -> telemetry) + return { "demo-telemetry": packaged }; + } + + DemoTelemetryProvider.prototype.matchesSource = function (request) { + return request.source === SOURCE; + } + + DemoTelemetryProvider.prototype.subscribe = function (callback, requests) { + var offsets = {}; + + function wrapSeries(telemetrySeries, offset) { + return { + getDomainValue: function (index, domain) { + return telemetrySeries.getDomainValue(index, domain); + }, + getRangeValue: function (index, range) { + // Sine wave 'carrier' signal, with random phase shift + return telemetrySeries.getRangeValue(index, range) + // Introduce some random variability so that line is + // not straight or perfectly curved + + Math.random(1)/50 + //Add a random range offset so that lines + // are not all bunched together + + offset; + }, + getPointCount: function () { + return telemetrySeries.getPointCount(); + } + } + } + + function randomize(telemetry){ + Object.keys(telemetry[SOURCE]).forEach(function(key) { + if (!offsets[key]) + offsets[key] = 1 + Math.random(); + telemetry[SOURCE][key] = wrapSeries(telemetry[SOURCE][key], offsets[key]); + }); + callback(telemetry); + } + + return SinewaveTelemetryProvider.prototype.subscribe.call(this, randomize, requests); + }; + + return DemoTelemetryProvider; + } +); \ No newline at end of file diff --git a/demo/src/telemetry/DemoTelemetrySeries.js b/demo/src/telemetry/DemoTelemetrySeries.js new file mode 100644 index 0000000000..0ce89035a1 --- /dev/null +++ b/demo/src/telemetry/DemoTelemetrySeries.js @@ -0,0 +1,83 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,Promise*/ + +/** + * Module defining SinewaveTelemetry. Created by vwoeltje on 11/12/14. + */ +define( + [], + function () { + "use strict"; + + var ONE_DAY = 60 * 60 * 24, + START_TIME = Date.now() - 24 * 60 * 60 * 1000, // Now minus a day. + firstObservedTime = Math.floor(START_TIME / 1000); + + /** + * + * @constructor + */ + function DemoTelemetrySeries(request, options) { + var timeOffset = (request.domain === 'yesterday') ? ONE_DAY : 0, + latestTime = Math.floor(Date.now() / 1000) - timeOffset, + firstTime = firstObservedTime - timeOffset, + endTime = (request.end !== undefined) ? + Math.floor(request.end / 1000) : latestTime, + count = Math.min(endTime, latestTime) - firstTime, + period = +request.period || 30, + generatorData = {}, + requestStart = (request.start === undefined) ? firstTime : + Math.max(Math.floor(request.start / 1000), firstTime), + offset = requestStart - firstTime; + + if (request.size !== undefined) { + offset = Math.max(offset, count - request.size); + } + + generatorData.getPointCount = function () { + return count - offset; + }; + + generatorData.getDomainValue = function (i, domain) { + // delta uses the same numeric values as the default domain, + // so it's not checked for here, just formatted for display + // differently. + return (i + offset) * 1000 + firstTime * 1000 - + (domain === 'yesterday' ? (ONE_DAY * 1000) : 0); + }; + + generatorData.getRangeValue = function (i, range) { + var rangeValue = Math[range || "sin"]((i + offset) * options.phaseShift / period), + damper = 0.05, + noise = Math.random() * damper; + rangeValue += options.rangeOffset; + rangeValue += noise; + return rangeValue; + }; + + return generatorData; + } + + return DemoTelemetrySeries; + } +);