[Tables] Support for subscriptions from new Telemetry API

Historical and real-time data flowing

Added formatting, and limits. Support telemetry objects themselves and not just composition of telemetry objects

Apply default time range if none supplied (15 minutes)
This commit is contained in:
Henry 2016-12-06 18:04:47 -08:00
parent 6d5530ba9c
commit 976333d7f7
12 changed files with 159 additions and 592 deletions

View File

@ -75,8 +75,7 @@ define([
}, },
{ {
"key": "delta", "key": "delta",
"name": "Delta", "name": "Delta"
"format": "example.delta"
} }
], ],
"priority": -1 "priority": -1
@ -103,11 +102,13 @@ define([
"domains": [ "domains": [
{ {
"key": "utc", "key": "utc",
"name": "Time" "name": "Time",
"format": "utc"
}, },
{ {
"key": "yesterday", "key": "yesterday",
"name": "Yesterday" "name": "Yesterday",
"format": "utc"
}, },
{ {
"key": "delta", "key": "delta",

View File

@ -24,6 +24,7 @@
(function () { (function () {
var FIFTEEN_MINUTES = 15 * 60 * 1000;
var handlers = { var handlers = {
subscribe: onSubscribe, subscribe: onSubscribe,
@ -82,8 +83,11 @@
function onRequest(message) { function onRequest(message) {
var data = message.data; var data = message.data;
if (!data.start || !data.end) { if (data.end == undefined) {
throw new Error('missing start and end!'); data.end = Date.now();
}
if (data.start == undefined){
data.start = data.end - FIFTEEN_MINUTES;
} }
var now = Date.now(); var now = Date.now();

View File

@ -22,25 +22,21 @@
define([ define([
"./src/directives/MCTTable", "./src/directives/MCTTable",
"./src/controllers/RealtimeTableController", "./src/controllers/TelemetryTableController",
"./src/controllers/HistoricalTableController",
"./src/controllers/TableOptionsController", "./src/controllers/TableOptionsController",
'../../commonUI/regions/src/Region', '../../commonUI/regions/src/Region',
'../../commonUI/browse/src/InspectorRegion', '../../commonUI/browse/src/InspectorRegion',
"text!./res/templates/table-options-edit.html", "text!./res/templates/table-options-edit.html",
"text!./res/templates/rt-table.html", "text!./res/templates/telemetry-table.html",
"text!./res/templates/historical-table.html",
"legacyRegistry" "legacyRegistry"
], function ( ], function (
MCTTable, MCTTable,
RealtimeTableController, TelemetryTableController,
HistoricalTableController,
TableOptionsController, TableOptionsController,
Region, Region,
InspectorRegion, InspectorRegion,
tableOptionsEditTemplate, tableOptionsEditTemplate,
rtTableTemplate, telemetryTableTemplate,
historicalTableTemplate,
legacyRegistry legacyRegistry
) { ) {
/** /**
@ -65,9 +61,9 @@ define([
"types": [ "types": [
{ {
"key": "table", "key": "table",
"name": "Historical Telemetry Table", "name": "Telemetry Table",
"cssclass": "icon-tabular", "cssclass": "icon-tabular-realtime",
"description": "A static table of all values over time for all included telemetry elements. Rows are timestamped data values for each telemetry element; columns are data fields. The number of rows is based on the range of your query. New incoming data must be manually re-queried for.", "description": "A table of values over a given time period. The table will be automatically updated with new values as they become available",
"priority": 861, "priority": 861,
"features": "creation", "features": "creation",
"delegates": [ "delegates": [
@ -85,42 +81,13 @@ define([
"views": [ "views": [
"table" "table"
] ]
},
{
"key": "rttable",
"name": "Real-time Telemetry Table",
"cssclass": "icon-tabular-realtime",
"description": "A scrolling table of latest values for all included telemetry elements. Rows are timestamped data values for each telemetry element; columns are data fields. New incoming data is automatically added to the view.",
"priority": 860,
"features": "creation",
"delegates": [
"telemetry"
],
"inspector": tableInspector,
"contains": [
{
"has": "telemetry"
}
],
"model": {
"composition": []
},
"views": [
"rt-table",
"scrolling-table"
]
} }
], ],
"controllers": [ "controllers": [
{ {
"key": "HistoricalTableController", "key": "TelemetryTableController",
"implementation": HistoricalTableController, "implementation": TelemetryTableController,
"depends": ["$scope", "telemetryHandler", "telemetryFormatter", "$timeout", "openmct"] "depends": ["$scope", "openmct"]
},
{
"key": "RealtimeTableController",
"implementation": RealtimeTableController,
"depends": ["$scope", "telemetryHandler", "telemetryFormatter", "openmct"]
}, },
{ {
"key": "TableOptionsController", "key": "TableOptionsController",
@ -131,21 +98,10 @@ define([
], ],
"views": [ "views": [
{ {
"name": "Historical Table", "name": "Telemetry Table",
"key": "table", "key": "table",
"template": historicalTableTemplate,
"cssclass": "icon-tabular",
"needs": [
"telemetry"
],
"delegation": true,
"editable": false
},
{
"name": "Real-time Table",
"key": "rt-table",
"cssclass": "icon-tabular-realtime", "cssclass": "icon-tabular-realtime",
"template": rtTableTemplate, "template": telemetryTableTemplate,
"needs": [ "needs": [
"telemetry" "telemetry"
], ],

View File

@ -1,12 +0,0 @@
<div ng-controller="RealtimeTableController as tableController">
<mct-table
headers="headers"
rows="rows"
time-columns="tableController.timeColumns"
enableFilter="true"
enableSort="true"
class="tabular-holder has-control-bar"
sort-column="defaultSort"
auto-scroll="true">
</mct-table>
</div>

View File

@ -1,4 +1,4 @@
<div ng-controller="HistoricalTableController as tableController" <div ng-controller="TelemetryTableController as tableController"
ng-class="{'loading': loading}"> ng-class="{'loading': loading}">
<mct-table <mct-table
headers="headers" headers="headers"

View File

@ -1,62 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT 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 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.
*****************************************************************************/
/**
* Module defining DomainColumn.
*/
define(
[],
function () {
/**
* A column which will report telemetry domain values
* (typically, timestamps.) Used by the ScrollingListController.
*
* @memberof platform/features/table
* @constructor
* @param domainMetadata an object with the machine- and human-
* readable names for this domain (in `key` and `name`
* fields, respectively.)
* @param {TelemetryFormatter} telemetryFormatter the telemetry
* formatting service, for making values human-readable.
*/
function DomainColumn(domainMetadata, telemetryFormatter) {
this.domainMetadata = domainMetadata;
this.telemetryFormatter = telemetryFormatter;
}
DomainColumn.prototype.getTitle = function () {
return this.domainMetadata.name;
};
DomainColumn.prototype.getValue = function (domainObject, datum) {
return {
text: this.telemetryFormatter.formatDomainValue(
datum[this.domainMetadata.key],
this.domainMetadata.format
)
};
};
return DomainColumn;
}
);

View File

@ -1,52 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT 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 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.
*****************************************************************************/
/**
* Module defining NameColumn. Created by vwoeltje on 11/18/14.
*/
define(
[],
function () {
/**
* A column which will report the name of the domain object
* which exposed specific telemetry values.
*
* @memberof platform/features/table
* @constructor
*/
function NameColumn() {
}
NameColumn.prototype.getTitle = function () {
return "Name";
};
NameColumn.prototype.getValue = function (domainObject) {
return {
text: domainObject.getModel().name
};
};
return NameColumn;
}
);

View File

@ -1,65 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT 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 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.
*****************************************************************************/
/**
* Module defining DomainColumn. Created by vwoeltje on 11/18/14.
*/
define(
[],
function () {
/**
* A column which will report telemetry range values
* (typically, measurements.) Used by the ScrollingListController.
*
* @memberof platform/features/table
* @constructor
* @param rangeMetadata an object with the machine- and human-
* readable names for this range (in `key` and `name`
* fields, respectively.)
* @param {TelemetryFormatter} telemetryFormatter the telemetry
* formatting service, for making values human-readable.
*/
function RangeColumn(rangeMetadata, telemetryFormatter) {
this.rangeMetadata = rangeMetadata;
this.telemetryFormatter = telemetryFormatter;
}
RangeColumn.prototype.getTitle = function () {
return this.rangeMetadata.name;
};
RangeColumn.prototype.getValue = function (domainObject, datum) {
var range = this.rangeMetadata.key,
limit = domainObject.getCapability('limit'),
value = isNaN(datum[range]) ? datum[range] : parseFloat(datum[range]),
alarm = limit && limit.evaluate(datum, range);
return {
cssClass: alarm && alarm.cssClass,
text: typeof (value) === 'undefined' ? undefined : this.telemetryFormatter.formatRangeValue(value)
};
};
return RangeColumn;
}
);

View File

@ -21,12 +21,8 @@
*****************************************************************************/ *****************************************************************************/
define( define(
[ [],
'./DomainColumn', function () {
'./RangeColumn',
'./NameColumn'
],
function (DomainColumn, RangeColumn, NameColumn) {
/** /**
* Class that manages table metadata, state, and contents. * Class that manages table metadata, state, and contents.
@ -34,10 +30,10 @@ define(
* @param domainObject * @param domainObject
* @constructor * @constructor
*/ */
function TableConfiguration(domainObject, telemetryFormatter) { function TableConfiguration(domainObject, openmct) {
this.domainObject = domainObject; this.domainObject = domainObject;
this.columns = []; this.columns = [];
this.telemetryFormatter = telemetryFormatter; this.openmct = openmct;
} }
/** /**
@ -47,27 +43,34 @@ define(
*/ */
TableConfiguration.prototype.populateColumns = function (metadata) { TableConfiguration.prototype.populateColumns = function (metadata) {
var self = this; var self = this;
var telemetryApi = this.openmct.telemetry;
this.columns = []; this.columns = [];
if (metadata) { if (metadata) {
metadata.forEach(function (metadatum) { metadata.forEach(function (metadatum) {
//Push domains first var formatter = telemetryApi.getValueFormatter(metadatum);
(metadatum.domains || []).forEach(function (domainMetadata) {
self.addColumn(new DomainColumn(domainMetadata,
self.telemetryFormatter));
});
(metadatum.ranges || []).forEach(function (rangeMetadata) {
self.addColumn(new RangeColumn(rangeMetadata,
self.telemetryFormatter));
});
});
if (this.columns.length > 0) { self.addColumn({
self.addColumn(new NameColumn(), 0); getTitle: function () {
return metadatum.name;
},
getValue: function(telemetryDatum, limitEvaluator) {
var isValueColumn = !!(metadatum.hints.y || metadatum.hints.range);
var alarm = isValueColumn &&
limitEvaluator &&
limitEvaluator.evaluate(telemetryDatum, metadatum);
return {
cssClass: alarm && alarm.cssClass,
text: formatter ? formatter.format(telemetryDatum[metadatum.key])
: telemetryDatum[metadatum.key]
} }
} }
});
});
}
return this; return this;
}; };
@ -99,9 +102,8 @@ define(
* @returns {Array} The titles of the columns * @returns {Array} The titles of the columns
*/ */
TableConfiguration.prototype.getHeaders = function () { TableConfiguration.prototype.getHeaders = function () {
var self = this;
return this.columns.map(function (column, i) { return this.columns.map(function (column, i) {
return self.getColumnTitle(column) || 'Column ' + (i + 1); return column.getTitle()|| 'Column ' + (i + 1);
}); });
}; };
@ -113,11 +115,11 @@ define(
* @returns {Object} Key value pairs where the key is the column * @returns {Object} Key value pairs where the key is the column
* title, and the value is the formatted value from the provided datum. * title, and the value is the formatted value from the provided datum.
*/ */
TableConfiguration.prototype.getRowValues = function (telemetryObject, datum) { TableConfiguration.prototype.getRowValues = function (limitEvaluator, datum) {
var self = this; var self = this;
return this.columns.reduce(function (rowObject, column, i) { return this.columns.reduce(function (rowObject, column, i) {
var columnTitle = self.getColumnTitle(column) || 'Column ' + (i + 1), var columnTitle = self.getColumnTitle(column) || 'Column ' + (i + 1),
columnValue = column.getValue(telemetryObject, datum); columnValue = column.getValue(datum, limitEvaluator);
if (columnValue !== undefined && columnValue.text === undefined) { if (columnValue !== undefined && columnValue.text === undefined) {
columnValue.text = ''; columnValue.text = '';

View File

@ -1,141 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT 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 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.
*****************************************************************************/
define(
[
'./TelemetryTableController'
],
function (TableController) {
var BATCH_SIZE = 1000;
/**
* Extends TelemetryTableController and adds real-time streaming
* support.
* @memberof platform/features/table
* @param $scope
* @param telemetryHandler
* @param telemetryFormatter
* @constructor
*/
function HistoricalTableController($scope, telemetryHandler, telemetryFormatter, $timeout, openmct) {
var self = this;
this.$timeout = $timeout;
this.timeoutHandle = undefined;
this.batchSize = BATCH_SIZE;
$scope.$on("$destroy", function () {
if (self.timeoutHandle) {
self.$timeout.cancel(self.timeoutHandle);
}
});
TableController.call(this, $scope, telemetryHandler, telemetryFormatter, openmct);
}
HistoricalTableController.prototype = Object.create(TableController.prototype);
/**
* Set provided row data on scope, and cancel loading spinner
* @private
*/
HistoricalTableController.prototype.doneProcessing = function (rowData) {
this.$scope.rows = rowData;
this.$scope.loading = false;
};
/**
* @private
*/
HistoricalTableController.prototype.registerChangeListeners = function () {
TableController.prototype.registerChangeListeners.call(this);
//Change of bounds in time conductor
this.changeListeners.push(this.$scope.$on('telemetry:display:bounds',
this.boundsChange.bind(this))
);
};
/**
* @private
*/
HistoricalTableController.prototype.boundsChange = function (event, bounds, follow) {
// If in follow mode, don't bother re-subscribing, data will be
// received from existing subscription.
if (follow !== true) {
this.subscribe();
}
};
/**
* Processes an array of objects, formatting the telemetry available
* for them and setting it on scope when done
* @private
*/
HistoricalTableController.prototype.processTelemetryObjects = function (objects, offset, start, rowData) {
var telemetryObject = objects[offset],
series,
i = start,
pointCount,
end;
//No more objects to process
if (!telemetryObject) {
return this.doneProcessing(rowData);
}
series = this.handle.getSeries(telemetryObject);
pointCount = series.getPointCount();
end = Math.min(start + this.batchSize, pointCount);
//Process rows in a batch with size not exceeding a maximum length
for (; i < end; i++) {
rowData.push(this.table.getRowValues(telemetryObject,
this.handle.makeDatum(telemetryObject, series, i)));
}
//Done processing all rows for this object.
if (end >= pointCount) {
offset++;
end = 0;
}
// Done processing either a batch or an object, yield process
// before continuing processing
this.timeoutHandle = this.$timeout(this.processTelemetryObjects.bind(this, objects, offset, end, rowData));
};
/**
* Populates historical data on scope when it becomes available from
* the telemetry API
*/
HistoricalTableController.prototype.addHistoricalData = function () {
if (this.timeoutHandle) {
this.$timeout.cancel(this.timeoutHandle);
}
this.timeoutHandle = this.$timeout(this.processTelemetryObjects.bind(this, this.handle.getTelemetryObjects(), 0, 0, []));
};
return HistoricalTableController;
}
);

View File

@ -1,76 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT 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 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.
*****************************************************************************/
define(
[
'./TelemetryTableController'
],
function (TableController) {
/**
* Extends TelemetryTableController and adds real-time streaming
* support.
* @memberof platform/features/table
* @param $scope
* @param telemetryHandler
* @param telemetryFormatter
* @constructor
*/
function RealtimeTableController($scope, telemetryHandler, telemetryFormatter, openmct) {
TableController.call(this, $scope, telemetryHandler, telemetryFormatter, openmct);
this.maxRows = 100000;
}
RealtimeTableController.prototype = Object.create(TableController.prototype);
/**
* Overrides method on TelemetryTableController providing handling
* for realtime data.
*/
RealtimeTableController.prototype.addRealtimeData = function () {
var self = this,
datum,
row;
this.handle.getTelemetryObjects().forEach(function (telemetryObject) {
datum = self.handle.getDatum(telemetryObject);
if (datum) {
//Populate row values from telemetry datum
row = self.table.getRowValues(telemetryObject, datum);
self.$scope.rows.push(row);
//Inform table that a new row has been added
if (self.$scope.rows.length > self.maxRows) {
self.$scope.$broadcast('remove:row', 0);
self.$scope.rows.shift();
}
self.$scope.$broadcast('add:row',
self.$scope.rows.length - 1);
}
});
this.$scope.loading = false;
};
return RealtimeTableController;
}
);

View File

@ -38,14 +38,10 @@ define(
* configuration, and telemetry subscriptions. * configuration, and telemetry subscriptions.
* @memberof platform/features/table * @memberof platform/features/table
* @param $scope * @param $scope
* @param telemetryHandler
* @param telemetryFormatter
* @constructor * @constructor
*/ */
function TelemetryTableController( function TelemetryTableController(
$scope, $scope,
telemetryHandler,
telemetryFormatter,
openmct openmct
) { ) {
var self = this; var self = this;
@ -53,9 +49,8 @@ define(
this.$scope = $scope; this.$scope = $scope;
this.columns = {}; //Range and Domain columns this.columns = {}; //Range and Domain columns
this.handle = undefined; this.handle = undefined;
this.telemetryHandler = telemetryHandler;
this.table = new TableConfiguration($scope.domainObject, this.table = new TableConfiguration($scope.domainObject,
telemetryFormatter); openmct);
this.changeListeners = []; this.changeListeners = [];
this.conductor = openmct.conductor; this.conductor = openmct.conductor;
this.openmct = openmct; this.openmct = openmct;
@ -68,6 +63,9 @@ define(
self.subscribe(); self.subscribe();
self.registerChangeListeners(); self.registerChangeListeners();
}); });
this.mutationListener = openmct.objects.observe(this.newObject, "*", function (domainObject){
self.newObject = domainObject;
});
this.destroy = this.destroy.bind(this); this.destroy = this.destroy.bind(this);
@ -79,6 +77,8 @@ define(
this.sortByTimeSystem = this.sortByTimeSystem.bind(this); this.sortByTimeSystem = this.sortByTimeSystem.bind(this);
this.conductor.on('timeSystem', this.sortByTimeSystem); this.conductor.on('timeSystem', this.sortByTimeSystem);
this.conductor.off('timeSystem', this.sortByTimeSystem); this.conductor.off('timeSystem', this.sortByTimeSystem);
this.subscriptions = [];
} }
/** /**
@ -130,29 +130,12 @@ define(
* Release the current subscription (called when scope is destroyed) * Release the current subscription (called when scope is destroyed)
*/ */
TelemetryTableController.prototype.destroy = function () { TelemetryTableController.prototype.destroy = function () {
if (this.handle) { this.subscriptions.forEach(function (subscription) {
this.handle.unsubscribe(); subscription()
this.handle = undefined; });
} this.mutationListener();
}; };
/**
* Function for handling realtime data when it is available. This
* will be called by the telemetry framework when new data is
* available.
*
* Method should be overridden by specializing class.
*/
TelemetryTableController.prototype.addRealtimeData = function () {
};
/**
* Function for handling historical data. Will be called by
* telemetry framework when requested historical data is available.
* Should be overridden by specializing class.
*/
TelemetryTableController.prototype.addHistoricalData = function () {
};
/** /**
Create a new subscription. This can be overridden by children to Create a new subscription. This can be overridden by children to
@ -160,94 +143,123 @@ define(
only). only).
*/ */
TelemetryTableController.prototype.subscribe = function () { TelemetryTableController.prototype.subscribe = function () {
var self = this;
var telemetryApi = this.openmct.telemetry; var telemetryApi = this.openmct.telemetry;
var compositionApi = this.openmct.composition;
var subscriptions = this.subscriptions;
var tableConfiguration = this.table;
var scope = this.$scope;
var maxRows = 100000;
var conductor = this.conductor;
var newObject = this.newObject;
if (this.handle) {
this.handle.unsubscribe();
}
this.$scope.loading = true; this.$scope.loading = true;
function map(func){ function makeTableRows(object, historicalData){
return function (objects) { var limitEvaluator = telemetryApi.limitEvaluator(object);
return Promise.all(objects.map(func)); return historicalData.map(tableConfiguration.getRowValues.bind(tableConfiguration, limitEvaluator));
}
} }
function add(object){ function requestData(objects) {
return function (objects) { var bounds = conductor.bounds();
objects.unshift(object);
return Promise.all(
objects.map(function (object) {
return telemetryApi.request(object, {
start: bounds.start,
end: bounds.end
}).then(
makeTableRows.bind(this, object)
);
})
);
}
function addHistoricalData(historicalData){
scope.rows = Array.prototype.concat.apply([], historicalData);
scope.loading = false;
}
function newData(domainObject, datum) {
scope.rows.push(tableConfiguration.getRowValues(datum, telemetryApi.limitEvaluator(domainObject)));
//Inform table that a new row has been added
if (scope.rows.length > maxRows) {
scope.$broadcast('remove:row', 0);
scope.rows.shift();
}
scope.$broadcast('add:row',
scope.rows.length - 1);
}
function subscribe(objects) {
objects.forEach(function (object){
subscriptions.push(telemetryApi.subscribe(object, newData.bind(this, object), {}));
});
return objects; return objects;
} }
function error(e) {
throw e;
} }
function subscribeTo(object) { function loadColumns(objects) {
return telemetryApi.request(object, {}); var metadatas = objects.map(telemetryApi.getMetadata.bind(telemetryApi));
} var allColumns = telemetryApi.commonValuesForHints(metadatas, []);
function error() { tableConfiguration.populateColumns(allColumns);
console.log("Unable to subscribe");
}
this.openmct.composition.get(this.newObject) this.timeColumns = telemetryApi.commonValuesForHints(metadatas, ['x']).map(function (metadatum){
.load() return metadatum.name;
.then(add(this.newObject)) });
.then(map(subscribeTo))
.then(function (telemetry) {
console.log(telemetry.length);
}).catch(error);
this.handle = this.$scope.domainObject && this.telemetryHandler.handle(
this.$scope.domainObject,
this.addRealtimeData.bind(this),
true // Lossless
);
this.handle.request({}).then(this.addHistoricalData.bind(this));
this.setup();
};
TelemetryTableController.prototype.populateColumns = function (telemetryMetadata) {
this.table.populateColumns(telemetryMetadata);
//Identify time columns
telemetryMetadata.forEach(function (metadatum) {
//Push domains first
(metadatum.domains || []).forEach(function (domainMetadata) {
this.timeColumns.push(domainMetadata.name);
}.bind(this));
}.bind(this));
var timeSystem = this.conductor.timeSystem();
if (timeSystem) {
this.sortByTimeSystem(timeSystem);
}
};
/**
* Setup table columns based on domain object metadata
*/
TelemetryTableController.prototype.setup = function () {
var handle = this.handle,
self = this;
if (handle) {
this.timeColumns = [];
handle.promiseTelemetryObjects().then(function () {
self.$scope.headers = [];
self.$scope.rows = [];
self.populateColumns(handle.getMetadata());
self.filterColumns(); self.filterColumns();
// When table column configuration changes, (due to being return Promise.resolve(objects);
// selected or deselected), filter columns appropriately. }
self.changeListeners.push(self.$scope.$watchCollection(
'domainObject.getModel().configuration.table.columns', function filterForTelemetry(objects){
self.filterColumns.bind(self) return objects.filter(telemetryApi.canProvideTelemetry.bind(telemetryApi));
)); }
function getDomainObjects() {
return new Promise(function (resolve, reject){
var objects = [newObject];
var composition = compositionApi.get(newObject);
if (composition) {
composition
.load()
.then(function (children) {
return objects.concat(children);
})
.then(resolve)
.catch(reject);
} else {
return resolve(objects);
}
}); });
} }
scope.headers = [];
scope.rows = [];
getDomainObjects()
.then(filterForTelemetry)
.catch(error)
.then(function (objects){
if (objects.length > 0){
return loadColumns(objects)
.then(subscribe)
.then(requestData)
.then(addHistoricalData)
.catch(error);
} else {
scope.loading = false;
}
})
}; };
/** /**