Implemention of basic averaging telemetry filter

This commit is contained in:
Henry 2017-10-27 14:12:44 -07:00 committed by Victor Woeltjen
parent 01d93306f3
commit 0a9ea48355
5 changed files with 288 additions and 3 deletions

View File

@ -121,6 +121,9 @@ define([
};
UTCTimeFormat.prototype.parse = function (text) {
if (typeof text === 'number') {
return text;
}
return moment.utc(text, DATE_FORMATS).valueOf();
};

View File

@ -29,7 +29,8 @@ define([
'../../example/imagery/plugin',
'../../platform/import-export/bundle',
'./summaryWidget/plugin',
'./URLIndicatorPlugin/URLIndicatorPlugin'
'./URLIndicatorPlugin/URLIndicatorPlugin',
'./telemetryMean/plugin'
], function (
_,
UTCTimeSystem,
@ -39,7 +40,8 @@ define([
ExampleImagery,
ImportExport,
SummaryWidget,
URLIndicatorPlugin
URLIndicatorPlugin,
TelemetryMean
) {
var bundleMap = {
CouchDB: 'platform/persistence/couch',
@ -124,8 +126,8 @@ define([
};
plugins.ExampleImagery = ExampleImagery;
plugins.SummaryWidget = SummaryWidget;
plugins.TelemetryMean = TelemetryMean;
plugins.URLIndicatorPlugin = URLIndicatorPlugin;
return plugins;

View File

@ -0,0 +1,54 @@
define(['./src/MeanTelemetryProvider'], function (MeanTelemetryProvider) {
var DEFAULT_SAMPLES = 10;
function plugin() {
return function install(openmct) {
openmct.types.addType('telemetry-mean', {
name: 'Telemetry Mean',
description: 'Provides telemetry values that represent the mean of the last N values of a telemetry stream',
creatable: true,
cssClass: 'icon-telemetry',
initialize: function (domainObject) {
domainObject.samples = DEFAULT_SAMPLES;
domainObject.telemetry = {};
domainObject.telemetry.values =
openmct.time.getAllTimeSystems().map(function (timeSystem, index) {
return {
key: timeSystem.key,
name: timeSystem.name,
hints: {
domain: index + 1
}
}
});
domainObject.telemetry.values.push({
key: "value",
name: "Value",
hints: {
range: 1
}
});
},
form: [
{
"key": "telemetryPoint",
"name": "Telemetry Point",
"control": "textfield",
"required": true,
"cssClass": "l-input-lg"
},
{
"key": "samples",
"name": "Samples to Average",
"control": "textfield",
"required": true,
"cssClass": "l-input-sm"
}
]
});
openmct.telemetry.addProvider(new MeanTelemetryProvider(openmct));
};
}
return plugin;
});

View File

@ -0,0 +1,114 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2017, 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([
'../../../api/objects/object-utils',
'./TelemetryAverager'
], function (objectUtils, TelemetryAverager) {
function MeanTelemetryProvider(openmct) {
this.openmct = openmct;
this.telemetryAPI = openmct.telemetry;
this.timeAPI = openmct.time;
this.objectAPI = openmct.objects;
this.perObjectProviders = {};
}
MeanTelemetryProvider.prototype.canProvideTelemetry = function (domainObject) {
return domainObject.type === 'telemetry-mean';
};
MeanTelemetryProvider.prototype.supportsRequest =
MeanTelemetryProvider.prototype.supportsSubscribe =
MeanTelemetryProvider.prototype.canProvideTelemetry;
MeanTelemetryProvider.prototype.subscribe = function (domainObject, callback) {
var wrappedUnsubscribe;
var unsubscribeCalled = false;
var objectId = objectUtils.parseKeyString(domainObject.telemetryPoint);
var samples = domainObject.samples;
this.objectAPI.get(objectId).then(function (linkedDomainObject) {
if (!unsubscribeCalled) {
wrappedUnsubscribe = this.subscribeToAverage(linkedDomainObject, samples, callback);
}
}.bind(this));
return function unsubscribe(){
unsubscribeCalled = true;
if (wrappedUnsubscribe !== undefined) {
wrappedUnsubscribe();
}
}
};
MeanTelemetryProvider.prototype.subscribeToAverage = function (domainObject, samples, callback) {
var telemetryAverager = new TelemetryAverager(this.telemetryAPI, this.timeAPI, domainObject, samples);
return this.telemetryAPI.subscribe(domainObject, function (telemetryDatum) {
var avgData = telemetryAverager.createAverageDatum(telemetryDatum);
if (telemetryAverager.sampleCount() === samples){
callback(avgData);
}
}.bind(this));
}
MeanTelemetryProvider.prototype.request = function (domainObject, request) {
var objectId = objectUtils.parseKeyString(domainObject.telemetryPoint);
var samples = domainObject.samples;
return this.objectAPI.get(objectId).then(function (linkedDomainObject) {
return this.requestAverageTelemetry(linkedDomainObject, request, samples);
}.bind(this));
};
/**
* @private
*/
MeanTelemetryProvider.prototype.requestAverageTelemetry = function (domainObject, request, samples) {
var averageData = [];
var telemetryAverager = new TelemetryAverager(this.telemetryAPI, this.timeAPI, domainObject, samples);
return this.telemetryAPI.request(domainObject, request).then(function (telemetryData){
telemetryData.forEach(function (datum){
var avgData = telemetryAverager.createAverageDatum(datum);
if (telemetryAverager.sampleCount() === samples){
averageData.push(avgData);
}
}.bind(this));
return averageData;
}.bind(this));
}
/**
* @private
*/
MeanTelemetryProvider.prototype.getLinkedObject = function (domainObject) {
var objectId = objectUtils.parseKeyString(domainObject.telemetryPoint);
return this.objectAPI.get(objectId);
};
return MeanTelemetryProvider;
});

View File

@ -0,0 +1,112 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2017, 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([], function () {
function TelemetryAverager(telemetryAPI, timeAPI, domainObject, samples) {
this.telemetryAPI = telemetryAPI;
this.timeAPI = timeAPI;
this.domainObject = domainObject;
this.samples = samples;
this.averagingWindow = [];
this.rangeKey = undefined
this.rangeFormatter = undefined;
this.setRangeKeyAndFormatter();
// Defined dynamically based on current time system
this.domainKey = undefined;
this.domainFormatter = undefined;
}
TelemetryAverager.prototype.createAverageDatum = function (telemetryDatum) {
this.setDomainKeyAndFormatter();
var timeValue = this.domainFormatter.parse(telemetryDatum);
var rangeValue = this.rangeFormatter.parse(telemetryDatum);
this.averagingWindow.push(rangeValue);
if (this.averagingWindow.length > this.samples) {
this.averagingWindow.shift();
}
var averageValue = this.calculateMean();
var meanDatum = {};
meanDatum[this.domainKey] = timeValue;
meanDatum['value'] = averageValue
return meanDatum;
};
/**
* @private
*/
TelemetryAverager.prototype.calculateMean = function () {
var sum = 0;
var i = 0;
for (; i < this.averagingWindow.length; i++) {
sum += this.averagingWindow[i];
}
return sum / this.averagingWindow.length;
};
/**
* @private
*/
TelemetryAverager.prototype.setDomainKeyAndFormatter = function () {
var domainKey = this.timeAPI.timeSystem().key;
if (domainKey !== this.domainKey) {
this.domainKey = domainKey;
this.domainFormatter = this.getFormatter(domainKey);
}
};
/**
* @private
*/
TelemetryAverager.prototype.setRangeKeyAndFormatter = function () {
var metadatas = this.telemetryAPI.getMetadata(this.domainObject);
var rangeValues = metadatas.valuesForHints(['range']);
this.rangeKey = rangeValues[0].key;
this.rangeFormatter = this.getFormatter(this.rangeKey);
}
/**
* @private
*/
TelemetryAverager.prototype.getFormatter = function (key) {
var objectMetadata = this.telemetryAPI.getMetadata(this.domainObject);
var valueMetadata = objectMetadata.value(key);
return this.telemetryAPI.getValueFormatter(valueMetadata);
};
TelemetryAverager.prototype.sampleCount = function () {
return this.averagingWindow.length;
};
return TelemetryAverager;
});