From ec0291c54d5441cdf2e5dec0579c7db9ff436bab Mon Sep 17 00:00:00 2001 From: Joshi Date: Thu, 26 Mar 2020 14:01:02 -0700 Subject: [PATCH 01/23] Implement any telemetry and all telemetry options --- src/plugins/condition/Condition.js | 6 +- .../criterion/AllTelemetryCriterion.js | 167 ++++++++++++++++++ 2 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 src/plugins/condition/criterion/AllTelemetryCriterion.js diff --git a/src/plugins/condition/Condition.js b/src/plugins/condition/Condition.js index 7eb4f819bb..3eaa568add 100644 --- a/src/plugins/condition/Condition.js +++ b/src/plugins/condition/Condition.js @@ -72,7 +72,11 @@ export default class ConditionClass extends EventEmitter { return; } this.criteria.forEach(criterion => { - criterion.emit(`subscription:${datum.id}`, datum); + if (criterion.telemetry && (criterion.telemetry === 'all' || criterion.telemetry === 'any')) { + criterion.handleSubscription(datum, this.conditionManager.telemetryObjects); + } else { + criterion.emit(`subscription:${datum.id}`, datum); + } }); } diff --git a/src/plugins/condition/criterion/AllTelemetryCriterion.js b/src/plugins/condition/criterion/AllTelemetryCriterion.js new file mode 100644 index 0000000000..45318f21a8 --- /dev/null +++ b/src/plugins/condition/criterion/AllTelemetryCriterion.js @@ -0,0 +1,167 @@ +/***************************************************************************** + * Open MCT, Copyright (c) 2014-2020, 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. + *****************************************************************************/ + +import EventEmitter from 'EventEmitter'; +import {OPERATIONS} from '../utils/operations'; +import {computeCondition} from "@/plugins/condition/utils/evaluator"; +import {TRIGGER} from "@/plugins/condition/utils/constants"; + +export default class TelemetryCriterion extends EventEmitter { + + /** + * Subscribes/Unsubscribes to telemetry and emits the result + * of operations performed on the telemetry data returned and a given input value. + * @constructor + * @param telemetryDomainObjectDefinition {id: uuid, operation: enum, input: Array, metadata: string, key: {domainObject.identifier} } + * @param openmct + */ + constructor(telemetryDomainObjectDefinition, openmct) { + super(); + + this.openmct = openmct; + this.objectAPI = this.openmct.objects; + this.telemetryAPI = this.openmct.telemetry; + this.timeAPI = this.openmct.time; + this.id = telemetryDomainObjectDefinition.id; + this.telemetry = telemetryDomainObjectDefinition.telemetry; + this.operation = telemetryDomainObjectDefinition.operation; + this.telemetryObjects = telemetryDomainObjectDefinition.telemetryObjects; + this.input = telemetryDomainObjectDefinition.input; + this.metadata = telemetryDomainObjectDefinition.metadata; + this.telemetryDataCache = {}; + } + + formatData(data, telemetryObjects) { + this.telemetryDataCache[data.id] = this.computeResult(data); + + telemetryObjects.forEach((telemetryObject) => { + const id = this.openmct.objects.makeKeyString(telemetryObject.identifier); + if (this.telemetryDataCache[id] === undefined) { + this.telemetryDataCache[id] = false; + } + }); + + const datum = { + result: computeCondition(this.telemetryDataCache, this.telemetry === 'all') + }; + + if (data) { + // TODO check back to see if we should format times here + this.timeAPI.getAllTimeSystems().forEach(timeSystem => { + datum[timeSystem.key] = data[timeSystem.key] + }); + } + + return datum; + } + + handleSubscription(data, telemetryObjects) { + if(this.isValid()) { + this.emitEvent('criterionResultUpdated', this.formatData(data, telemetryObjects)); + } + } + + findOperation(operation) { + for (let i=0, ii=OPERATIONS.length; i < ii; i++) { + if (operation === OPERATIONS[i].name) { + return OPERATIONS[i].operation; + } + } + return null; + } + + computeResult(data) { + let result = false; + if (data) { + let comparator = this.findOperation(this.operation); + let params = []; + params.push(data[this.metadata]); + if (this.input instanceof Array && this.input.length) { + this.input.forEach(input => params.push(input)); + } + if (typeof comparator === 'function') { + result = comparator(params); + } + } + return result; + } + + emitEvent(eventName, data) { + this.emit(eventName, { + id: this.id, + data: data + }); + } + + isValid() { + return (this.telemetry === 'any' || this.telemetry === 'all') && this.metadata && this.operation; + } + + requestLAD(options) { + options = Object.assign({}, + options, + { + strategy: 'latest', + size: 1 + } + ); + + if (!this.isValid()) { + return this.formatData({}, options.telemetryObjects); + } + + const telemetryRequests = options.telemetryObjects + .map(telemetryObject => this.telemetryAPI.request( + telemetryObject, + options + )); + + return Promise.all(telemetryRequests) + .then(telemetryRequestsResults => { + telemetryRequestsResults.forEach(results => { + const latestDatum = results.length ? results[results.length - 1] : {}; + return { + id: this.id, + data: this.formatData(latestDatum, options.telemetryObjects) + }; + }); + }); + + // return this.telemetryAPI.request( + // this.telemetryObject, + // options + // ).then(results => { + // const latestDatum = results.length ? results[results.length - 1] : {}; + // return { + // id: this.id, + // data: this.formatData(latestDatum) + // }; + // }); + } + + destroy() { + this.off(`subscription:${this.telemetryObjectIdAsString}`, this.handleSubscription); + this.emitEvent('criterionRemoved'); + delete this.telemetryObjectIdAsString; + delete this.telemetryObject; + } +} From 502d29dd250da558c4a4966a2e7fce7f1b23d3e0 Mon Sep 17 00:00:00 2001 From: Joshi Date: Thu, 26 Mar 2020 16:44:44 -0700 Subject: [PATCH 02/23] Add all and any options for telemetry --- src/plugins/condition/Condition.js | 8 +- .../condition/components/Criterion.vue | 102 +++++++++++------- .../criterion/AllTelemetryCriterion.js | 43 ++++---- 3 files changed, 95 insertions(+), 58 deletions(-) diff --git a/src/plugins/condition/Condition.js b/src/plugins/condition/Condition.js index 3eaa568add..79f8133512 100644 --- a/src/plugins/condition/Condition.js +++ b/src/plugins/condition/Condition.js @@ -25,6 +25,7 @@ import uuid from 'uuid'; import TelemetryCriterion from "./criterion/TelemetryCriterion"; import { TRIGGER } from "./utils/constants"; import {computeCondition} from "./utils/evaluator"; +import AllTelemetryCriterion from "@/plugins/condition/criterion/AllTelemetryCriterion"; /* * conditionConfiguration = { @@ -124,8 +125,13 @@ export default class ConditionClass extends EventEmitter { * adds criterion to the condition. */ addCriterion(criterionConfiguration) { + let criterion; let criterionConfigurationWithId = this.generateCriterion(criterionConfiguration || null); - let criterion = new TelemetryCriterion(criterionConfigurationWithId, this.openmct); + if (criterionConfiguration.telemetry && (criterionConfiguration.telemetry === 'any' || criterionConfiguration.telemetry === 'all')) { + criterion = new AllTelemetryCriterion(criterionConfigurationWithId, this.openmct); + } else { + criterion = new TelemetryCriterion(criterionConfigurationWithId, this.openmct); + } criterion.on('criterionUpdated', (obj) => this.handleCriterionUpdated(obj)); criterion.on('criterionResultUpdated', (obj) => this.handleCriterionResult(obj)); if (!this.criteria) { diff --git a/src/plugins/condition/components/Criterion.vue b/src/plugins/condition/components/Criterion.vue index e5fc6ab15d..dd76bc4df9 100644 --- a/src/plugins/condition/components/Criterion.vue +++ b/src/plugins/condition/components/Criterion.vue @@ -9,6 +9,8 @@ @change="updateMetadataOptions" > + +