diff --git a/src/plugins/condition/Condition.js b/src/plugins/condition/Condition.js index c35650bd84..6ff4a41b56 100644 --- a/src/plugins/condition/Condition.js +++ b/src/plugins/condition/Condition.js @@ -24,6 +24,7 @@ import * as EventEmitter from 'eventemitter3'; import uuid from 'uuid'; import TelemetryCriterion from "@/plugins/condition/criterion/TelemetryCriterion"; import { TRIGGER } from "@/plugins/condition/utils/constants"; +import {computeConditionForAll, computeConditionForAny} from "@/plugins/condition/utils/evaluator"; /* * conditionDefinition = { @@ -56,6 +57,7 @@ export default class ConditionClass extends EventEmitter { this.openmct = openmct; this.id = this.openmct.objects.makeKeyString(conditionDefinition.identifier); this.criteria = []; + this.criteriaResults = {}; if (conditionDefinition.definition.criteria) { this.createCriteria(conditionDefinition.definition.criteria); } @@ -71,12 +73,11 @@ export default class ConditionClass extends EventEmitter { update(newDomainObject) { this.updateTrigger(newDomainObject.definition.trigger); this.updateCriteria(newDomainObject.definition.criteria); - this.handleConditionUpdated(); } - updateTrigger(conditionDefinition) { - if (this.trigger !== conditionDefinition.trigger) { - this.trigger = conditionDefinition.trigger; + updateTrigger(trigger) { + if (this.trigger !== trigger) { + this.trigger = trigger; this.handleConditionUpdated(); } } @@ -109,6 +110,7 @@ export default class ConditionClass extends EventEmitter { let criterionDefinitionWithId = this.generateCriterion(criterionDefinition || null); let criterion = new TelemetryCriterion(criterionDefinitionWithId, this.openmct); criterion.on('criterionUpdated', (obj) => this.handleCriterionUpdated(obj)); + criterion.on('criterionResultUpdated', (obj) => this.handleCriterionResult(obj)); if (!this.criteria) { this.criteria = []; } @@ -138,12 +140,17 @@ export default class ConditionClass extends EventEmitter { if (found) { const newCriterionDefinition = this.generateCriterion(criterionDefinition); let newCriterion = new TelemetryCriterion(newCriterionDefinition, this.openmct); + newCriterion.on('criterionUpdated', (obj) => this.handleCriterionUpdated(obj)); + newCriterion.on('criterionResultUpdated', (obj) => this.handleCriterionResult(obj)); + let criterion = found.item; criterion.unsubscribe(); - criterion.off('criterionUpdated', (result) => { - this.handleCriterionUpdated(id, result); - }); + criterion.off('criterionUpdated', (obj) => this.handleCriterionUpdated(obj)); + criterion.off('criterionResultUpdated', (obj) => this.handleCriterionResult(obj)); this.criteria.splice(found.index, 1, newCriterion); + if (this.criteriaResults[criterion.id] !== undefined) { + delete this.criteriaResults[criterion.id]; + } this.handleConditionUpdated(); } } @@ -163,6 +170,9 @@ export default class ConditionClass extends EventEmitter { this.handleCriterionUpdated(id, result); }); this.criteria.splice(found.index, 1); + if (this.criteriaResults[criterion.id] !== undefined) { + delete this.criteriaResults[criterion.id]; + } return true; } return false; @@ -173,14 +183,30 @@ export default class ConditionClass extends EventEmitter { if (found) { this.criteria[found.index] = criterion.data; //Most likely don't need this. + this.subscribe(); this.emitEvent('conditionUpdated', { trigger: this.trigger, criteria: this.criteria }); } + } + + handleCriterionResult(eventData) { + let id = eventData.id; + let result = eventData.data.result; + let found = this.findCriterion(id); + if (found) { + this.criteriaResults[id] = result; + } this.handleConditionUpdated(); } + subscribe() { + this.criteria.forEach((criterion) => { + criterion.subscribe(); + }) + } + handleConditionUpdated() { // trigger an updated event so that consumers can react accordingly this.evaluate(); @@ -203,9 +229,9 @@ export default class ConditionClass extends EventEmitter { //TODO: implement as part of the evaluator class task. evaluate() { if (this.trigger === TRIGGER.ANY) { - this.result = true; + this.result = computeConditionForAny(this.criteriaResults); } else if (this.trigger === TRIGGER.ALL) { - this.result = false; + this.result = computeConditionForAll(this.criteriaResults); } } diff --git a/src/plugins/condition/ConditionSpec.js b/src/plugins/condition/ConditionSpec.js index cc32914871..2f58676cef 100644 --- a/src/plugins/condition/ConditionSpec.js +++ b/src/plugins/condition/ConditionSpec.js @@ -64,15 +64,17 @@ describe("The condition", function () { openmct.telemetry.getMetadata.and.returnValue(testTelemetryObject.telemetry.values); testConditionDefinition = { - trigger: TRIGGER.ANY, - criteria: [ - { - operation: 'equalTo', - input: false, - metaDataKey: 'value', - key: testTelemetryObject.identifier - } - ] + definition: { + trigger: TRIGGER.ANY, + criteria: [ + { + operation: 'equalTo', + input: false, + metaDataKey: 'value', + key: testTelemetryObject.identifier + } + ] + } }; conditionObj = new Condition( @@ -85,7 +87,7 @@ describe("The condition", function () { }); it("generates criteria with an id", function () { - const testCriterion = testConditionDefinition.criteria[0]; + const testCriterion = testConditionDefinition.definition.criteria[0]; let criterion = conditionObj.generateCriterion(testCriterion); expect(criterion.id).toBeDefined(); expect(criterion.operation).toEqual(testCriterion.operation); @@ -101,15 +103,15 @@ describe("The condition", function () { it("initializes with criteria from the condition definition", function () { expect(conditionObj.criteria.length).toEqual(1); let criterion = conditionObj.criteria[0]; + console.log(criterion); expect(criterion instanceof TelemetryCriterion).toBeTrue(); - expect(criterion.operator).toEqual(testConditionDefinition.operator); - expect(criterion.input).toEqual(testConditionDefinition.input); - expect(criterion.metaDataKey).toEqual(testConditionDefinition.metaDataKey); - expect(criterion.key).toEqual(testConditionDefinition.key); + expect(criterion.operator).toEqual(testConditionDefinition.definition.criteria[0].operator); + expect(criterion.input).toEqual(testConditionDefinition.definition.criteria[0].input); + expect(criterion.metaDataKey).toEqual(testConditionDefinition.definition.criteria[0].metaDataKey); }); it("initializes with the trigger from the condition definition", function () { - expect(conditionObj.trigger).toEqual(testConditionDefinition.trigger); + expect(conditionObj.trigger).toEqual(testConditionDefinition.definition.trigger); }); it("destroys all criteria for a condition", function () { diff --git a/src/plugins/condition/components/ConditionEdit.vue b/src/plugins/condition/components/ConditionEdit.vue index 9feba6455f..bb1bb63442 100644 --- a/src/plugins/condition/components/ConditionEdit.vue +++ b/src/plugins/condition/components/ConditionEdit.vue @@ -217,7 +217,6 @@ export default { this.$emit('set-move-index', Number(e.target.getAttribute('data-condition-index'))); }, handleConditionResult(args) { - // console.log('ConditionEdit::Result', args); this.$emit('condition-result-updated', { id: this.conditionIdentifier, result: args.data.result @@ -251,7 +250,6 @@ export default { this.openmct.objects.get(this.condition.definition.criteria[0].key).then((obj) => { this.telemetryObject = obj; this.telemetryMetadata = this.openmct.telemetry.getMetadata(this.telemetryObject).values(); - // this.selectedMetaDataKey = this.telemetryMetadata[0].key; this.selectedMetaDataKey = ''; this.selectedTelemetryKey = this.telemetryObject.identifier; }); diff --git a/src/plugins/condition/criterion/TelemetryCriterion.js b/src/plugins/condition/criterion/TelemetryCriterion.js index 30117c76a5..d833f25cfc 100644 --- a/src/plugins/condition/criterion/TelemetryCriterion.js +++ b/src/plugins/condition/criterion/TelemetryCriterion.js @@ -21,6 +21,7 @@ *****************************************************************************/ import * as EventEmitter from 'eventemitter3'; +import {OPERATIONS} from '../utils/operations'; export default class TelemetryCriterion extends EventEmitter { @@ -38,6 +39,9 @@ export default class TelemetryCriterion extends EventEmitter { this.objectAPI = this.openmct.objects; this.telemetryAPI = this.openmct.telemetry; this.id = telemetryDomainObjectDefinition.id; + this.operation = telemetryDomainObjectDefinition.operation; + this.input = telemetryDomainObjectDefinition.input; + this.metaDataKey = telemetryDomainObjectDefinition.metaDataKey; this.subscription = null; this.telemetryMetadata = null; this.telemetryObjectIdAsString = null; @@ -51,18 +55,35 @@ export default class TelemetryCriterion extends EventEmitter { this.emitEvent('criterionUpdated', this); } - handleSubscription(datum) { - let data = this.normalizeData(datum); + handleSubscription(data) { + let result = this.computeResult(data); this.emitEvent('criterionResultUpdated', { - result: data, + result: result, error: null }) } - normalizeData(datum) { - return { - [datum.key]: datum[datum.source] + 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 comparator = this.findOperation(this.operation); + let params = []; + let result = false; + params.push(data[this.metaDataKey]); + if (this.input instanceof Array && this.input.length) { + params.push(this.input[0]); + } + if (typeof comparator === 'function') { + result = comparator(params); + } + return result; } emitEvent(eventName, data) { @@ -76,6 +97,7 @@ export default class TelemetryCriterion extends EventEmitter { * Subscribes to the telemetry object and returns an unsubscribe function */ subscribe() { + this.unsubscribe(); this.subscription = this.telemetryAPI.subscribe(this.telemetryObject, (datum) => { this.handleSubscription(datum); }); diff --git a/src/plugins/condition/criterion/TelemetryCriterionSpec.js b/src/plugins/condition/criterion/TelemetryCriterionSpec.js index ef823ca45d..123fd600fb 100644 --- a/src/plugins/condition/criterion/TelemetryCriterionSpec.js +++ b/src/plugins/condition/criterion/TelemetryCriterionSpec.js @@ -94,17 +94,6 @@ describe("The telemetry criterion", function () { expect(telemetryCriterion.subscription).toBeDefined(); }); - it("normalizes telemetry data", function () { - let result = telemetryCriterion.normalizeData({ - key: 'some-key', - source: 'testSource', - testSource: 'Hello' - }); - expect(result).toEqual({ - 'some-key': 'Hello' - }) - }); - it("emits update event on new data from telemetry providers", function () { spyOn(telemetryCriterion, 'emitEvent').and.callThrough(); telemetryCriterion.handleSubscription({ diff --git a/src/plugins/condition/utils/evaluator.js b/src/plugins/condition/utils/evaluator.js index 51bd7173f6..f74bb1e5d4 100644 --- a/src/plugins/condition/utils/evaluator.js +++ b/src/plugins/condition/utils/evaluator.js @@ -1,7 +1,31 @@ -export const computeConditionForAny = (args) => { - return false; +/** + * Returns true only if at least one of the results is true + **/ +export const computeConditionForAny = (resultMap) => { + let result = false; + for (let key in resultMap) { + if (resultMap.hasOwnProperty(key)) { + result = resultMap[key]; + if (result) { + break; + } + } + } + return result; }; -export const computeConditionForAll = (args) => { - return false; +/** + * Returns true only if all the results are true + **/ +export const computeConditionForAll = (resultMap) => { + let result = false; + for (let key in resultMap) { + if (resultMap.hasOwnProperty(key)) { + result = resultMap[key]; + if (!result) { + break; + } + } + } + return result; };