Compare commits
	
		
			2 Commits
		
	
	
		
			misc-fixes
			...
			telemetry-
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | e69fb17b02 | ||
|   | 72f9a53ba3 | 
| @@ -121,6 +121,9 @@ define([ | ||||
|     }; | ||||
|  | ||||
|     UTCTimeFormat.prototype.parse = function (text) { | ||||
|         if (typeof text === 'number') { | ||||
|             return text; | ||||
|         } | ||||
|         return moment.utc(text, DATE_FORMATS).valueOf(); | ||||
|     }; | ||||
|  | ||||
|   | ||||
| @@ -27,7 +27,8 @@ define([ | ||||
|     '../../platform/features/autoflow/plugin', | ||||
|     './timeConductor/plugin', | ||||
|     '../../example/imagery/plugin', | ||||
|     '../../platform/import-export/bundle' | ||||
|     '../../platform/import-export/bundle', | ||||
|     './telemetryMean/plugin' | ||||
| ], function ( | ||||
|     _, | ||||
|     UTCTimeSystem, | ||||
| @@ -35,7 +36,8 @@ define([ | ||||
|     AutoflowPlugin, | ||||
|     TimeConductorPlugin, | ||||
|     ExampleImagery, | ||||
|     ImportExport | ||||
|     ImportExport, | ||||
|     TelemetryMean | ||||
| ) { | ||||
|     var bundleMap = { | ||||
|         CouchDB: 'platform/persistence/couch', | ||||
| @@ -120,6 +122,7 @@ define([ | ||||
|     }; | ||||
|  | ||||
|     plugins.ExampleImagery = ExampleImagery; | ||||
|     plugins.TelemetryMean = TelemetryMean; | ||||
|  | ||||
|     return plugins; | ||||
| }); | ||||
|   | ||||
							
								
								
									
										76
									
								
								src/plugins/telemetryMean/plugin.js
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										76
									
								
								src/plugins/telemetryMean/plugin.js
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,76 @@ | ||||
| /***************************************************************************** | ||||
|  * 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(['./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; | ||||
| }); | ||||
							
								
								
									
										125
									
								
								src/plugins/telemetryMean/src/MeanTelemetryProvider.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								src/plugins/telemetryMean/src/MeanTelemetryProvider.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,125 @@ | ||||
| /***************************************************************************** | ||||
|  * 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. | ||||
|  *****************************************************************************/ | ||||
| /*jshint latedef: nofunc */ | ||||
| /*global console */ | ||||
| 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)) | ||||
|             .catch(logError); | ||||
|  | ||||
|         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 avgDatum = telemetryAverager.createAverageDatum(datum); | ||||
|  | ||||
|                 if (telemetryAverager.sampleCount() === samples) { | ||||
|                     averageData.push(avgDatum); | ||||
|                 } | ||||
|             }.bind(this)); | ||||
|  | ||||
|             return averageData; | ||||
|         }.bind(this)); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * @private | ||||
|      */ | ||||
|     MeanTelemetryProvider.prototype.getLinkedObject = function (domainObject) { | ||||
|         var objectId = objectUtils.parseKeyString(domainObject.telemetryPoint); | ||||
|         return this.objectAPI.get(objectId); | ||||
|     }; | ||||
|  | ||||
|     function logError(error) { | ||||
|         if (error.stack) { | ||||
|             console.error(error.stack); | ||||
|         } else { | ||||
|             console.error(error); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return MeanTelemetryProvider; | ||||
| }); | ||||
							
								
								
									
										460
									
								
								src/plugins/telemetryMean/src/MeanTelemetryProviderSpec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										460
									
								
								src/plugins/telemetryMean/src/MeanTelemetryProviderSpec.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,460 @@ | ||||
| /***************************************************************************** | ||||
|  * 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. | ||||
|  *****************************************************************************/ | ||||
| /*jshint latedef: nofunc */ | ||||
| define([ | ||||
|     "./MeanTelemetryProvider", | ||||
|     "./MockTelemetryApi" | ||||
| ], function ( | ||||
|     MeanTelemetryProvider, | ||||
|     MockTelemetryApi | ||||
| ) { | ||||
|     var RANGE_KEY = 'value'; | ||||
|  | ||||
|     describe("The Mean Telemetry Provider", function () { | ||||
|         var mockApi; | ||||
|         var meanTelemetryProvider; | ||||
|         var outstandingPromises = 0; | ||||
|         var mockDomainObject; | ||||
|         var associatedObject; | ||||
|  | ||||
|         beforeEach(function () { | ||||
|             createMockApi(); | ||||
|             setTimeSystemTo('utc'); | ||||
|             createMockObjects(); | ||||
|             meanTelemetryProvider = new MeanTelemetryProvider(mockApi); | ||||
|         }); | ||||
|  | ||||
|         it("supports telemetry-mean objects only", function () { | ||||
|             var mockTelemetryMeanObject = mockObjectWithType('telemetry-mean'); | ||||
|             var mockOtherObject = mockObjectWithType('other'); | ||||
|  | ||||
|             expect(meanTelemetryProvider.canProvideTelemetry(mockTelemetryMeanObject)).toBe(true); | ||||
|             expect(meanTelemetryProvider.canProvideTelemetry(mockOtherObject)).toBe(false); | ||||
|         }); | ||||
|  | ||||
|         describe("the subscribe function", function () { | ||||
|             var subscriptionCallback; | ||||
|  | ||||
|             beforeEach(function () { | ||||
|                 subscriptionCallback = jasmine.createSpy('subscriptionCallback'); | ||||
|             }); | ||||
|  | ||||
|             it("subscribes to telemetry for the associated object", function () { | ||||
|                 meanTelemetryProvider.subscribe(mockDomainObject); | ||||
|  | ||||
|                 expectObjectWasSubscribedTo(associatedObject); | ||||
|             }); | ||||
|  | ||||
|             it("returns a function that unsubscribes from the associated object", function () { | ||||
|                 var unsubscribe = meanTelemetryProvider.subscribe(mockDomainObject); | ||||
|  | ||||
|                 waitsFor(allPromisesToBeResolved); | ||||
|                 runs(unsubscribe); | ||||
|  | ||||
|                 expectUnsubscribeFrom(associatedObject); | ||||
|             }); | ||||
|  | ||||
|             it("returns an average only when the sample size is reached", function () { | ||||
|                 var inputTelemetry = [ | ||||
|                     {'utc': 1, 'defaultRange': 123.1231}, | ||||
|                     {'utc': 2, 'defaultRange': 321.3223}, | ||||
|                     {'utc': 3, 'defaultRange': 111.4446}, | ||||
|                     {'utc': 4, 'defaultRange': 555.2313} | ||||
|                 ]; | ||||
|  | ||||
|                 setSampleSize(5); | ||||
|                 meanTelemetryProvider.subscribe(mockDomainObject, subscriptionCallback); | ||||
|                 feedInputTelemetry(inputTelemetry); | ||||
|  | ||||
|                 expectNoAverageForTelemetry(inputTelemetry); | ||||
|             }); | ||||
|  | ||||
|             it("correctly averages a sample of five values", function () { | ||||
|                 var inputTelemetry = [ | ||||
|                     {'utc': 1, 'defaultRange': 123.1231}, | ||||
|                     {'utc': 2, 'defaultRange': 321.3223}, | ||||
|                     {'utc': 3, 'defaultRange': 111.4446}, | ||||
|                     {'utc': 4, 'defaultRange': 555.2313}, | ||||
|                     {'utc': 5, 'defaultRange': 1.1231} | ||||
|                 ]; | ||||
|                 var expectedAverages = [{ | ||||
|                     'utc': 5, 'value': 222.44888 | ||||
|                 }]; | ||||
|  | ||||
|                 setSampleSize(5); | ||||
|                 meanTelemetryProvider.subscribe(mockDomainObject, subscriptionCallback); | ||||
|                 feedInputTelemetry(inputTelemetry); | ||||
|  | ||||
|                 expectAveragesForTelemetry(expectedAverages, inputTelemetry); | ||||
|             }); | ||||
|  | ||||
|             it("correctly averages a sample of ten values", function () { | ||||
|                 var inputTelemetry = [ | ||||
|                     {'utc': 1, 'defaultRange': 123.1231}, | ||||
|                     {'utc': 2, 'defaultRange': 321.3223}, | ||||
|                     {'utc': 3, 'defaultRange': 111.4446}, | ||||
|                     {'utc': 4, 'defaultRange': 555.2313}, | ||||
|                     {'utc': 5, 'defaultRange': 1.1231}, | ||||
|                     {'utc': 6, 'defaultRange': 2323.12}, | ||||
|                     {'utc': 7, 'defaultRange': 532.12}, | ||||
|                     {'utc': 8, 'defaultRange': 453.543}, | ||||
|                     {'utc': 9, 'defaultRange': 89.2111}, | ||||
|                     {'utc': 10, 'defaultRange': 0.543} | ||||
|                 ]; | ||||
|                 var expectedAverages = [{ | ||||
|                     'utc': 10, 'value': 451.07815 | ||||
|                 }]; | ||||
|  | ||||
|                 setSampleSize(10); | ||||
|                 meanTelemetryProvider.subscribe(mockDomainObject, subscriptionCallback); | ||||
|                 feedInputTelemetry(inputTelemetry); | ||||
|  | ||||
|                 expectAveragesForTelemetry(expectedAverages, inputTelemetry); | ||||
|             }); | ||||
|  | ||||
|             it("only averages values within its sample window", function () { | ||||
|                 var inputTelemetry = [ | ||||
|                     {'utc': 1, 'defaultRange': 123.1231}, | ||||
|                     {'utc': 2, 'defaultRange': 321.3223}, | ||||
|                     {'utc': 3, 'defaultRange': 111.4446}, | ||||
|                     {'utc': 4, 'defaultRange': 555.2313}, | ||||
|                     {'utc': 5, 'defaultRange': 1.1231}, | ||||
|                     {'utc': 6, 'defaultRange': 2323.12}, | ||||
|                     {'utc': 7, 'defaultRange': 532.12}, | ||||
|                     {'utc': 8, 'defaultRange': 453.543}, | ||||
|                     {'utc': 9, 'defaultRange': 89.2111}, | ||||
|                     {'utc': 10, 'defaultRange': 0.543} | ||||
|                 ]; | ||||
|                 var expectedAverages = [ | ||||
|                     {'utc': 5, 'value': 222.44888}, | ||||
|                     {'utc': 6, 'value': 662.4482599999999}, | ||||
|                     {'utc': 7, 'value': 704.6078}, | ||||
|                     {'utc': 8, 'value': 773.02748}, | ||||
|                     {'utc': 9, 'value': 679.8234399999999}, | ||||
|                     {'utc': 10, 'value': 679.70742} | ||||
|                 ]; | ||||
|  | ||||
|                 setSampleSize(5); | ||||
|                 meanTelemetryProvider.subscribe(mockDomainObject, subscriptionCallback); | ||||
|                 feedInputTelemetry(inputTelemetry); | ||||
|  | ||||
|                 expectAveragesForTelemetry(expectedAverages, inputTelemetry); | ||||
|             }); | ||||
|             describe("given telemetry input with range values", function () { | ||||
|                 var inputTelemetry; | ||||
|  | ||||
|                 beforeEach(function () { | ||||
|                     inputTelemetry = [{ | ||||
|                         'utc': 1, | ||||
|                         'rangeKey': 5678, | ||||
|                         'otherKey': 9999 | ||||
|                     }]; | ||||
|                     setSampleSize(1); | ||||
|                 }); | ||||
|                 it("uses the 'rangeKey' input range, when it is the default, to calculate the average", function () { | ||||
|                     var averageTelemetryForRangeKey = [{ | ||||
|                         'utc': 1, | ||||
|                         'value': 5678 | ||||
|                     }]; | ||||
|  | ||||
|                     meanTelemetryProvider.subscribe(mockDomainObject, subscriptionCallback); | ||||
|                     mockApi.telemetry.setDefaultRangeTo('rangeKey'); | ||||
|                     feedInputTelemetry(inputTelemetry); | ||||
|  | ||||
|                     expectAveragesForTelemetry(averageTelemetryForRangeKey, inputTelemetry); | ||||
|                 }); | ||||
|  | ||||
|                 it("uses the 'otherKey' input range, when it is the default, to calculate the average", function () { | ||||
|                     var averageTelemetryForOtherKey = [{ | ||||
|                         'utc': 1, | ||||
|                         'value': 9999 | ||||
|                     }]; | ||||
|  | ||||
|                     meanTelemetryProvider.subscribe(mockDomainObject, subscriptionCallback); | ||||
|                     mockApi.telemetry.setDefaultRangeTo('otherKey'); | ||||
|                     feedInputTelemetry(inputTelemetry); | ||||
|  | ||||
|                     expectAveragesForTelemetry(averageTelemetryForOtherKey, inputTelemetry); | ||||
|  | ||||
|                 }); | ||||
|             }); | ||||
|             describe("given telemetry input with range values", function () { | ||||
|                 var inputTelemetry; | ||||
|  | ||||
|                 beforeEach(function () { | ||||
|                     inputTelemetry = [{ | ||||
|                         'utc': 1, | ||||
|                         'rangeKey': 5678, | ||||
|                         'otherKey': 9999 | ||||
|                     }]; | ||||
|                     setSampleSize(1); | ||||
|                 }); | ||||
|                 it("uses the 'rangeKey' input range, when it is the default, to calculate the average", function () { | ||||
|                     var averageTelemetryForRangeKey = [{ | ||||
|                         'utc': 1, | ||||
|                         'value': 5678 | ||||
|                     }]; | ||||
|  | ||||
|                     meanTelemetryProvider.subscribe(mockDomainObject, subscriptionCallback); | ||||
|                     mockApi.telemetry.setDefaultRangeTo('rangeKey'); | ||||
|                     feedInputTelemetry(inputTelemetry); | ||||
|  | ||||
|                     expectAveragesForTelemetry(averageTelemetryForRangeKey, inputTelemetry); | ||||
|                 }); | ||||
|  | ||||
|                 it("uses the 'otherKey' input range, when it is the default, to calculate the average", function () { | ||||
|                     var averageTelemetryForOtherKey = [{ | ||||
|                         'utc': 1, | ||||
|                         'value': 9999 | ||||
|                     }]; | ||||
|  | ||||
|                     meanTelemetryProvider.subscribe(mockDomainObject, subscriptionCallback); | ||||
|                     mockApi.telemetry.setDefaultRangeTo('otherKey'); | ||||
|                     feedInputTelemetry(inputTelemetry); | ||||
|  | ||||
|                     expectAveragesForTelemetry(averageTelemetryForOtherKey, inputTelemetry); | ||||
|                 }); | ||||
|             }); | ||||
|  | ||||
|             function feedInputTelemetry(inputTelemetry) { | ||||
|                 waitsFor(allPromisesToBeResolved); | ||||
|                 runs(function () { | ||||
|                     inputTelemetry.forEach(mockApi.telemetry.mockReceiveTelemetry); | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             function expectNoAverageForTelemetry(inputTelemetry) { | ||||
|                 waitsFor(allPromisesToBeResolved); | ||||
|                 runs(function () { | ||||
|                     expect(subscriptionCallback).not.toHaveBeenCalled(); | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             function expectAveragesForTelemetry(expectedAverages) { | ||||
|                 waitsFor(allPromisesToBeResolved); | ||||
|                 runs(function () { | ||||
|                     expectedAverages.forEach(function (averageDatum) { | ||||
|                         expect(subscriptionCallback).toHaveBeenCalledWith(averageDatum); | ||||
|                     }); | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             function expectObjectWasSubscribedTo(object) { | ||||
|                 waitsFor(allPromisesToBeResolved); | ||||
|                 runs(function () { | ||||
|                     expect(mockApi.telemetry.subscribe).toHaveBeenCalledWith(object, jasmine.any(Function)); | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             function expectUnsubscribeFrom() { | ||||
|                 waitsFor(allPromisesToBeResolved); | ||||
|                 runs(function () { | ||||
|                     expect(mockApi.telemetry.unsubscribe).toHaveBeenCalled(); | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|         }); | ||||
|  | ||||
|         describe("the request function", function () { | ||||
|  | ||||
|             it("requests telemetry for the associated object", function () { | ||||
|                 meanTelemetryProvider.request(mockDomainObject); | ||||
|  | ||||
|                 expectTelemetryToBeRequestedFor(associatedObject); | ||||
|             }); | ||||
|  | ||||
|             it("returns an average only when the sample size is reached", function () { | ||||
|                 var inputTelemetry = [ | ||||
|                     {'utc': 1, 'defaultRange': 123.1231}, | ||||
|                     {'utc': 2, 'defaultRange': 321.3223}, | ||||
|                     {'utc': 3, 'defaultRange': 111.4446}, | ||||
|                     {'utc': 4, 'defaultRange': 555.2313} | ||||
|                 ]; | ||||
|                 var promiseForAverage; | ||||
|  | ||||
|                 setSampleSize(5); | ||||
|                 whenTelemetryRequestedReturn(inputTelemetry); | ||||
|                 promiseForAverage = meanTelemetryProvider.request(mockDomainObject); | ||||
|  | ||||
|                 expectEmptyResponse(promiseForAverage); | ||||
|             }); | ||||
|  | ||||
|             it("correctly averages a sample of five values", function () { | ||||
|                 var inputTelemetry = [ | ||||
|                     {'utc': 1, 'defaultRange': 123.1231}, | ||||
|                     {'utc': 2, 'defaultRange': 321.3223}, | ||||
|                     {'utc': 3, 'defaultRange': 111.4446}, | ||||
|                     {'utc': 4, 'defaultRange': 555.2313}, | ||||
|                     {'utc': 5, 'defaultRange': 1.1231} | ||||
|                 ]; | ||||
|                 var promiseForAverage; | ||||
|  | ||||
|                 setSampleSize(5); | ||||
|                 whenTelemetryRequestedReturn(inputTelemetry); | ||||
|                 promiseForAverage = meanTelemetryProvider.request(mockDomainObject); | ||||
|  | ||||
|                 expectAverageToBe(222.44888, promiseForAverage); | ||||
|             }); | ||||
|  | ||||
|             it("correctly averages a sample of ten values", function () { | ||||
|                 var inputTelemetry = [ | ||||
|                     {'utc': 1, 'defaultRange': 123.1231}, | ||||
|                     {'utc': 2, 'defaultRange': 321.3223}, | ||||
|                     {'utc': 3, 'defaultRange': 111.4446}, | ||||
|                     {'utc': 4, 'defaultRange': 555.2313}, | ||||
|                     {'utc': 5, 'defaultRange': 1.1231}, | ||||
|                     {'utc': 6, 'defaultRange': 2323.12}, | ||||
|                     {'utc': 7, 'defaultRange': 532.12}, | ||||
|                     {'utc': 8, 'defaultRange': 453.543}, | ||||
|                     {'utc': 9, 'defaultRange': 89.2111}, | ||||
|                     {'utc': 10, 'defaultRange': 0.543} | ||||
|                 ]; | ||||
|                 var promiseForAverage; | ||||
|  | ||||
|                 setSampleSize(10); | ||||
|                 whenTelemetryRequestedReturn(inputTelemetry); | ||||
|                 promiseForAverage = meanTelemetryProvider.request(mockDomainObject); | ||||
|  | ||||
|                 expectAverageToBe(451.07815, promiseForAverage); | ||||
|             }); | ||||
|  | ||||
|             it("only averages values within its sample window", function () { | ||||
|                 var inputTelemetry = [ | ||||
|                     {'utc': 1, 'defaultRange': 123.1231}, | ||||
|                     {'utc': 2, 'defaultRange': 321.3223}, | ||||
|                     {'utc': 3, 'defaultRange': 111.4446}, | ||||
|                     {'utc': 4, 'defaultRange': 555.2313}, | ||||
|                     {'utc': 5, 'defaultRange': 1.1231}, | ||||
|                     {'utc': 6, 'defaultRange': 2323.12}, | ||||
|                     {'utc': 7, 'defaultRange': 532.12}, | ||||
|                     {'utc': 8, 'defaultRange': 453.543}, | ||||
|                     {'utc': 9, 'defaultRange': 89.2111}, | ||||
|                     {'utc': 10, 'defaultRange': 0.543} | ||||
|                 ]; | ||||
|                 var promiseForAverage; | ||||
|  | ||||
|                 setSampleSize(5); | ||||
|                 whenTelemetryRequestedReturn(inputTelemetry); | ||||
|                 promiseForAverage = meanTelemetryProvider.request(mockDomainObject); | ||||
|  | ||||
|                 expectAverageToBe(679.70742, promiseForAverage); | ||||
|             }); | ||||
|  | ||||
|             function expectAverageToBe(expectedValue, promiseForAverage) { | ||||
|                 var averageData; | ||||
|  | ||||
|                 promiseForAverage.then(function (data) { | ||||
|                     averageData = data; | ||||
|                 }); | ||||
|  | ||||
|                 waitsFor(function () { | ||||
|                     return averageData !== undefined; | ||||
|                 }, 'data to return from request', 1); | ||||
|                 runs(function () { | ||||
|                     var averageDatum = averageData[averageData.length - 1]; | ||||
|                     expect(averageDatum[RANGE_KEY]).toBe(expectedValue); | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             function expectEmptyResponse(promiseForAverage) { | ||||
|                 var averageData; | ||||
|  | ||||
|                 promiseForAverage.then(function (data) { | ||||
|                     averageData = data; | ||||
|                 }); | ||||
|  | ||||
|                 waitsFor(function () { | ||||
|                     return averageData !== undefined; | ||||
|                 }, 'data to return from request', 1); | ||||
|                 runs(function () { | ||||
|                     expect(averageData.length).toBe(0); | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             function whenTelemetryRequestedReturn(telemetry) { | ||||
|                 mockApi.telemetry.request.andReturn(resolvePromiseWith(telemetry)); | ||||
|             } | ||||
|  | ||||
|             function expectTelemetryToBeRequestedFor(object) { | ||||
|                 waitsFor(allPromisesToBeResolved); | ||||
|                 runs(function () { | ||||
|                     expect(mockApi.telemetry.request).toHaveBeenCalledWith(object, undefined); | ||||
|                 }); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         function createMockObjects() { | ||||
|             mockDomainObject = { | ||||
|                 telemetryPoint: 'someTelemetryPoint' | ||||
|             }; | ||||
|             associatedObject = {}; | ||||
|             mockApi.objects.get.andReturn(resolvePromiseWith(associatedObject)); | ||||
|         } | ||||
|  | ||||
|         function setSampleSize(sampleSize) { | ||||
|             mockDomainObject.samples = sampleSize; | ||||
|         } | ||||
|  | ||||
|         function createMockApi() { | ||||
|             mockApi = { | ||||
|                 telemetry: new MockTelemetryApi(), | ||||
|                 objects: createMockObjectApi(), | ||||
|                 time: createMockTimeApi() | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         function createMockObjectApi() { | ||||
|             return jasmine.createSpyObj('ObjectAPI', [ | ||||
|                 'get' | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         function mockObjectWithType(type) { | ||||
|             return { | ||||
|                 type: type | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         function resolvePromiseWith(value) { | ||||
|             outstandingPromises++; | ||||
|             return Promise.resolve(value).then(function () { | ||||
|                 outstandingPromises--; | ||||
|                 return value; | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         function allPromisesToBeResolved() { | ||||
|             return outstandingPromises === 0; | ||||
|         } | ||||
|  | ||||
|         function createMockTimeApi() { | ||||
|             return jasmine.createSpyObj("timeApi", ['timeSystem']); | ||||
|         } | ||||
|  | ||||
|         function setTimeSystemTo(timeSystemKey) { | ||||
|             mockApi.time.timeSystem.andReturn({ | ||||
|                 key: timeSystemKey | ||||
|             }); | ||||
|         } | ||||
|     }); | ||||
|  | ||||
| }); | ||||
							
								
								
									
										106
									
								
								src/plugins/telemetryMean/src/MockTelemetryApi.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								src/plugins/telemetryMean/src/MockTelemetryApi.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,106 @@ | ||||
| /***************************************************************************** | ||||
|  * 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. | ||||
|  *****************************************************************************/ | ||||
| /*global jasmine, spyOn */ | ||||
| define([], function () { | ||||
|  | ||||
|     function MockTelemetryApi() { | ||||
|         this.createSpy('subscribe'); | ||||
|         this.createSpy('getMetadata'); | ||||
|  | ||||
|         this.metadata = this.createMockMetadata(); | ||||
|         this.setDefaultRangeTo('defaultRange'); | ||||
|         this.unsubscribe = jasmine.createSpy('unsubscribe'); | ||||
|         this.mockReceiveTelemetry = this.mockReceiveTelemetry.bind(this); | ||||
|     } | ||||
|  | ||||
|     MockTelemetryApi.prototype.subscribe = function () { | ||||
|         return this.unsubscribe; | ||||
|     }; | ||||
|  | ||||
|     MockTelemetryApi.prototype.getMetadata = function (object) { | ||||
|         return this.metadata; | ||||
|     }; | ||||
|  | ||||
|     MockTelemetryApi.prototype.request = jasmine.createSpy('request'); | ||||
|  | ||||
|     MockTelemetryApi.prototype.getValueFormatter = function (valueMetadata) { | ||||
|         var mockValueFormatter = jasmine.createSpyObj("valueFormatter", [ | ||||
|             "parse" | ||||
|         ]); | ||||
|  | ||||
|         mockValueFormatter.parse.andCallFake(function (value) { | ||||
|             return value[valueMetadata.key]; | ||||
|         }); | ||||
|  | ||||
|         return mockValueFormatter; | ||||
|     }; | ||||
|  | ||||
|     MockTelemetryApi.prototype.mockReceiveTelemetry = function (newTelemetryDatum) { | ||||
|         var subscriptionCallback = this.subscribe.mostRecentCall.args[1]; | ||||
|         subscriptionCallback(newTelemetryDatum); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * @private | ||||
|      */ | ||||
|     MockTelemetryApi.prototype.onRequestReturn = function (telemetryData) { | ||||
|         this.requestTelemetry = telemetryData; | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * @private | ||||
|      */ | ||||
|     MockTelemetryApi.prototype.setDefaultRangeTo = function (rangeKey) { | ||||
|         var mockMetadataValue = { | ||||
|             key: rangeKey | ||||
|         }; | ||||
|         this.metadata.valuesForHints.andReturn([mockMetadataValue]); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * @private | ||||
|      */ | ||||
|     MockTelemetryApi.prototype.createMockMetadata = function () { | ||||
|         var mockMetadata = jasmine.createSpyObj("metadata", [ | ||||
|             'value', | ||||
|             'valuesForHints' | ||||
|         ]); | ||||
|  | ||||
|         mockMetadata.value.andCallFake(function (key) { | ||||
|             return { | ||||
|                 key: key | ||||
|             }; | ||||
|         }); | ||||
|         return mockMetadata; | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * @private | ||||
|      */ | ||||
|     MockTelemetryApi.prototype.createSpy = function (functionName) { | ||||
|         this[functionName] = this[functionName].bind(this); | ||||
|         spyOn(this, functionName); | ||||
|         this[functionName].andCallThrough(); | ||||
|     }; | ||||
|  | ||||
|     return MockTelemetryApi; | ||||
| }); | ||||
							
								
								
									
										112
									
								
								src/plugins/telemetryMean/src/TelemetryAverager.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/plugins/telemetryMean/src/TelemetryAverager.js
									
									
									
									
									
										Normal 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; | ||||
| }); | ||||
		Reference in New Issue
	
	Block a user