From 3e6509ce6f406395f2322ebd5d59157b6fcfe137 Mon Sep 17 00:00:00 2001 From: David Tsay Date: Thu, 5 Mar 2020 12:14:27 -0800 Subject: [PATCH 01/32] WIP add support for LAD request --- src/plugins/condition/Condition.js | 11 ++++++ src/plugins/condition/ConditionManager.js | 4 ++ .../ConditionSetTelemetryProvider.js | 13 ++++++- .../condition/components/ConditionSet.vue | 5 +++ .../condition/criterion/TelemetryCriterion.js | 38 +++++++++++++++++-- 5 files changed, 66 insertions(+), 5 deletions(-) diff --git a/src/plugins/condition/Condition.js b/src/plugins/condition/Condition.js index 556feb766b..6f7a4d7b9d 100644 --- a/src/plugins/condition/Condition.js +++ b/src/plugins/condition/Condition.js @@ -189,6 +189,10 @@ export default class ConditionClass extends EventEmitter { } } + handleLADCriterionResult(eventData) { + + } + handleCriterionResult(eventData) { const id = eventData.id; @@ -199,6 +203,13 @@ export default class ConditionClass extends EventEmitter { this.handleConditionUpdated(eventData.data); } + requestLatest() { + const promises = + + Promise.all(promises) + .then() + } + subscribe() { // TODO it looks like on any single criterion update subscriptions fire for all criteria this.criteria.forEach((criterion) => { diff --git a/src/plugins/condition/ConditionManager.js b/src/plugins/condition/ConditionManager.js index 25a3512155..c7706db789 100644 --- a/src/plugins/condition/ConditionManager.js +++ b/src/plugins/condition/ConditionManager.js @@ -251,6 +251,10 @@ export default class ConditionManager extends EventEmitter { }); } + requestLatest() { + + } + persist() { this.openmct.objects.mutate(this.domainObject, 'configuration.conditionCollection', this.domainObject.configuration.conditionCollection); } diff --git a/src/plugins/condition/ConditionSetTelemetryProvider.js b/src/plugins/condition/ConditionSetTelemetryProvider.js index cf721654ce..6809099403 100644 --- a/src/plugins/condition/ConditionSetTelemetryProvider.js +++ b/src/plugins/condition/ConditionSetTelemetryProvider.js @@ -9,14 +9,23 @@ export default class ConditionSetTelemetryProvider { return domainObject.type === 'conditionSet'; } - supportsRequest(domainObject, options) { - return false; + supportsRequest(domainObject) { + return domainObject.type === 'conditionSet'; } supportsSubscribe(domainObject) { return domainObject.type === 'conditionSet'; } + request(domainObject, options) { + let conditionManager = new ConditionManager(domainObject, this.openmct); + return conditionManager.requestLatest() + .then(latestDatum => { + return latestDatum ? [latestDatum] : []; + }); + // return Promise.resolve([]); + } + subscribe(domainObject, callback) { let conditionManager = new ConditionManager(domainObject, this.openmct); conditionManager.on('conditionSetResultUpdated', callback); diff --git a/src/plugins/condition/components/ConditionSet.vue b/src/plugins/condition/components/ConditionSet.vue index b81fb29745..50e1a5bb5e 100644 --- a/src/plugins/condition/components/ConditionSet.vue +++ b/src/plugins/condition/components/ConditionSet.vue @@ -74,6 +74,11 @@ export default { this.currentConditionOutput = currentConditionResult.output; }, provideTelemetry() { + this.openmct.telemetry + .request(this.domainObject) + .then(output => { + this.updateCurrentOutput(output); + }); this.stopProvidingTelemetry = this.openmct.telemetry .subscribe(this.domainObject, output => { this.updateCurrentOutput(output); }); } diff --git a/src/plugins/condition/criterion/TelemetryCriterion.js b/src/plugins/condition/criterion/TelemetryCriterion.js index c9b9498b21..b57a56f822 100644 --- a/src/plugins/condition/criterion/TelemetryCriterion.js +++ b/src/plugins/condition/criterion/TelemetryCriterion.js @@ -55,10 +55,11 @@ export default class TelemetryCriterion extends EventEmitter { this.emitEvent('criterionUpdated', this); } - handleSubscription(data) { + formatData(data) { const datum = { result: this.computeResult(data) - }; + } + if (data) { // TODO check back to see if we should format times here this.timeAPI.getAllTimeSystems().forEach(timeSystem => { @@ -66,7 +67,15 @@ export default class TelemetryCriterion extends EventEmitter { }); } - this.emitEvent('criterionResultUpdated', datum); + return datum; + } + + handleRequest(data) { + this.emitEvent('criterionLADResultUpdated', this.formatData(data)); + } + + handleSubscription(data) { + this.emitEvent('criterionResultUpdated', this.formatData(data)); } findOperation(operation) { @@ -105,6 +114,29 @@ export default class TelemetryCriterion extends EventEmitter { return this.telemetryObject && this.metadata && this.operation; } + requestLatest(options) { + if (this.isValid()) { + options = Object.assign({}, + options, + { + strategy: 'latest', + size: 1 + } + ); + + this.telemetryAPI.request( + this.telemetryObject, + options + ).then(results => { + if(results && results.length) { + results[results.length - 1] + } + }) + } else { + // default + } + } + /** * Subscribes to the telemetry object and returns an unsubscribe function * If the telemetry is not valid, returns nothing From 897d05276abf61ee9520d19da835f66d9d895d0a Mon Sep 17 00:00:00 2001 From: David Tsay Date: Thu, 5 Mar 2020 16:42:31 -0800 Subject: [PATCH 02/32] WIP continue to add support for LAD request TODO conditionCollection needs to load before condition requests can be made --- src/plugins/condition/Condition.js | 29 +++++-- src/plugins/condition/ConditionManager.js | 85 ++++++++++++++++--- .../ConditionSetTelemetryProvider.js | 12 ++- .../condition/criterion/TelemetryCriterion.js | 43 +++++----- 4 files changed, 116 insertions(+), 53 deletions(-) diff --git a/src/plugins/condition/Condition.js b/src/plugins/condition/Condition.js index 6f7a4d7b9d..14df0e2555 100644 --- a/src/plugins/condition/Condition.js +++ b/src/plugins/condition/Condition.js @@ -189,25 +189,36 @@ export default class ConditionClass extends EventEmitter { } } - handleLADCriterionResult(eventData) { - - } - - handleCriterionResult(eventData) { + updateCriteriaResults(eventData) { const id = eventData.id; if (this.findCriterion(id)) { this.criteriaResults[id] = eventData.data.result; } + } + handleCriterionResult(eventData) { + this.updateCriteriaResults(eventData); this.handleConditionUpdated(eventData.data); } - requestLatest() { - const promises = + requestLADConditionResult() { + const criteriaResults = []; - Promise.all(promises) - .then() + this.criteria.forEach(criterion => { + criteriaResults.push( + criterion.requestLAD() + ); + }); + + Promise.all(criteriaResults) + .then(results => { + results.forEach(result => { + this.updateCriteriaResults(result); + }); + + return Object.assign({}, /*datum,*/ { result: this.result }); + }); } subscribe() { diff --git a/src/plugins/condition/ConditionManager.js b/src/plugins/condition/ConditionManager.js index c7706db789..e54d0aa19c 100644 --- a/src/plugins/condition/ConditionManager.js +++ b/src/plugins/condition/ConditionManager.js @@ -32,24 +32,35 @@ export default class ConditionManager extends EventEmitter { this.timeAPI = this.openmct.time; this.latestTimestamp = {}; this.instantiate = this.openmct.$injector.get('instantiate'); + this.loaded = undefined; this.initialize(); } + load() { + return this.loaded; + } + initialize() { this.conditionResults = {}; + let loading = []; + this.openmct.objects.get(this.domainObject.identifier).then((obj) => { this.observeForChanges(obj); this.conditionCollection = []; if (this.domainObject.configuration.conditionCollection.length) { this.domainObject.configuration.conditionCollection.forEach((conditionConfigurationId, index) => { this.openmct.objects.get(conditionConfigurationId).then((conditionConfiguration) => { - this.initCondition(conditionConfiguration, index) + loading.push( + this.initCondition(conditionConfiguration, index) + ); }); }); } else { this.addCondition(true); } }); + this.loaded = Promise.all(loading) + .then(() => { return true; }); } observeForChanges(domainObject) { @@ -98,6 +109,8 @@ export default class ConditionManager extends EventEmitter { if (conditionConfiguration.isDefault) { this.handleConditionResult(); } + + return Promise.resolve(true); } createConditionDomainObject(isDefault, conditionConfiguration) { @@ -206,20 +219,12 @@ export default class ConditionManager extends EventEmitter { this.persist(); } - handleConditionResult(resultObj) { - let conditionCollection = this.domainObject.configuration.conditionCollection; + getCurrentConditionId() { + const conditionCollection = this.domainObject.configuration.conditionCollection; let currentConditionIdentifier = conditionCollection[conditionCollection.length-1]; - if (resultObj) { - let idAsString = this.openmct.objects.makeKeyString(resultObj.id); - if (this.findConditionById(idAsString)) { - this.conditionResults[idAsString] = resultObj.data.result; - } - this.updateTimestamp(resultObj.data); - } - for (let i = 0; i < conditionCollection.length - 1; i++) { - let conditionIdAsString = this.openmct.objects.makeKeyString(conditionCollection[i]); + const conditionIdAsString = this.openmct.objects.makeKeyString(conditionCollection[i]); if (this.conditionResults[conditionIdAsString]) { //first condition to be true wins currentConditionIdentifier = conditionCollection[i]; @@ -227,6 +232,30 @@ export default class ConditionManager extends EventEmitter { } } + return currentConditionIdentifier; + } + + updateConditionResults(resultObj) { + console.log(this.conditionCollection); + + if (!resultObj) { + return; + } + + let idAsString = this.openmct.objects.makeKeyString(resultObj.id); + + if (this.findConditionById(idAsString)) { + this.conditionResults[idAsString] = resultObj.data.result; + } + + this.updateTimestamp(resultObj.data); + } + + handleConditionResult(resultObj) { + this.updateConditionResults(resultObj); + + const currentConditionIdentifier = this.getCurrentConditionId(); + this.openmct.objects.get(currentConditionIdentifier).then((obj) => { this.emit('conditionSetResultUpdated', Object.assign( @@ -251,8 +280,38 @@ export default class ConditionManager extends EventEmitter { }); } - requestLatest() { + requestLADConditionSetOutput() { + const conditionResults = []; + this.load() + .then(() => { + this.conditionCollection.forEach(conditionId => { + this.openmct.objects.get(conditionId) + .then(condition => { + conditionResults.push( + condition.requestLADConditionResult() + ); + }); + }); + + Promise.all(conditionResults) + .then((results) => { + results.forEach(resultObj => { this.updateConditionResults(resultObj); }); + const currentConditionIdentifier = this.getCurrentConditionId(); + + this.openmct.objects.get(currentConditionIdentifier).then((obj) => { + return Object.assign( + { + output: obj.configuration.output, + id: this.domainObject.identifier, + conditionId: currentConditionIdentifier + }, + this.latestTimestamp + ); + }); + }); + + }); } persist() { diff --git a/src/plugins/condition/ConditionSetTelemetryProvider.js b/src/plugins/condition/ConditionSetTelemetryProvider.js index 6809099403..a3ec173ae1 100644 --- a/src/plugins/condition/ConditionSetTelemetryProvider.js +++ b/src/plugins/condition/ConditionSetTelemetryProvider.js @@ -18,16 +18,14 @@ export default class ConditionSetTelemetryProvider { } request(domainObject, options) { - let conditionManager = new ConditionManager(domainObject, this.openmct); - return conditionManager.requestLatest() - .then(latestDatum => { - return latestDatum ? [latestDatum] : []; - }); - // return Promise.resolve([]); + const conditionManager = new ConditionManager(domainObject, this.openmct); + const output = conditionManager.requestLADConditionSetOutput(); + + return output; } subscribe(domainObject, callback) { - let conditionManager = new ConditionManager(domainObject, this.openmct); + const conditionManager = new ConditionManager(domainObject, this.openmct); conditionManager.on('conditionSetResultUpdated', callback); return function unsubscribe() { diff --git a/src/plugins/condition/criterion/TelemetryCriterion.js b/src/plugins/condition/criterion/TelemetryCriterion.js index b57a56f822..38482bb82a 100644 --- a/src/plugins/condition/criterion/TelemetryCriterion.js +++ b/src/plugins/condition/criterion/TelemetryCriterion.js @@ -70,10 +70,6 @@ export default class TelemetryCriterion extends EventEmitter { return datum; } - handleRequest(data) { - this.emitEvent('criterionLADResultUpdated', this.formatData(data)); - } - handleSubscription(data) { this.emitEvent('criterionResultUpdated', this.formatData(data)); } @@ -114,27 +110,26 @@ export default class TelemetryCriterion extends EventEmitter { return this.telemetryObject && this.metadata && this.operation; } - requestLatest(options) { - if (this.isValid()) { - options = Object.assign({}, - options, - { - strategy: 'latest', - size: 1 - } - ); - - this.telemetryAPI.request( - this.telemetryObject, - options - ).then(results => { - if(results && results.length) { - results[results.length - 1] - } - }) - } else { - // default + requestLAD(options) { + if (!this.isValid()) { + return this.formatData({}); } + + options = Object.assign({}, + options, + { + strategy: 'latest', + size: 1 + } + ); + + this.telemetryAPI.request( + this.telemetryObject, + options + ).then(results => { + const datum = results.length ? results[results.length - 1] : {}; + return this.formatData(datum); + }); } /** From 7f32d196e441739a31ccb73d43066889633efc6d Mon Sep 17 00:00:00 2001 From: David Tsay Date: Thu, 5 Mar 2020 23:11:20 -0800 Subject: [PATCH 03/32] WIP request gets to telemetry criterion before erroring --- src/plugins/condition/Condition.js | 2 +- src/plugins/condition/ConditionManager.js | 92 +++++++++---------- .../ConditionSetTelemetryProvider.js | 15 ++- .../condition/criterion/TelemetryCriterion.js | 26 +++--- 4 files changed, 68 insertions(+), 67 deletions(-) diff --git a/src/plugins/condition/Condition.js b/src/plugins/condition/Condition.js index 14df0e2555..af6cdc79ec 100644 --- a/src/plugins/condition/Condition.js +++ b/src/plugins/condition/Condition.js @@ -211,7 +211,7 @@ export default class ConditionClass extends EventEmitter { ); }); - Promise.all(criteriaResults) + return Promise.all(criteriaResults) .then(results => { results.forEach(result => { this.updateCriteriaResults(result); diff --git a/src/plugins/condition/ConditionManager.js b/src/plugins/condition/ConditionManager.js index e54d0aa19c..7e2dff198c 100644 --- a/src/plugins/condition/ConditionManager.js +++ b/src/plugins/condition/ConditionManager.js @@ -33,6 +33,7 @@ export default class ConditionManager extends EventEmitter { this.latestTimestamp = {}; this.instantiate = this.openmct.$injector.get('instantiate'); this.loaded = undefined; + this.conditionCollection = []; this.initialize(); } @@ -42,25 +43,20 @@ export default class ConditionManager extends EventEmitter { initialize() { this.conditionResults = {}; - let loading = []; - this.openmct.objects.get(this.domainObject.identifier).then((obj) => { - this.observeForChanges(obj); - this.conditionCollection = []; - if (this.domainObject.configuration.conditionCollection.length) { - this.domainObject.configuration.conditionCollection.forEach((conditionConfigurationId, index) => { - this.openmct.objects.get(conditionConfigurationId).then((conditionConfiguration) => { - loading.push( - this.initCondition(conditionConfiguration, index) - ); + this.openmct.objects.get(this.domainObject.identifier) + .then((obj) => { + this.observeForChanges(obj); + if (this.domainObject.configuration.conditionCollection.length) { + this.domainObject.configuration.conditionCollection.forEach((conditionConfigurationId, index) => { + this.openmct.objects.get(conditionConfigurationId).then((conditionConfiguration) => { + this.initCondition(conditionConfiguration, index); + }); }); - }); - } else { - this.addCondition(true); - } - }); - this.loaded = Promise.all(loading) - .then(() => { return true; }); + } else { + this.addCondition(true); + } + }); } observeForChanges(domainObject) { @@ -109,8 +105,6 @@ export default class ConditionManager extends EventEmitter { if (conditionConfiguration.isDefault) { this.handleConditionResult(); } - - return Promise.resolve(true); } createConditionDomainObject(isDefault, conditionConfiguration) { @@ -236,8 +230,6 @@ export default class ConditionManager extends EventEmitter { } updateConditionResults(resultObj) { - console.log(this.conditionCollection); - if (!resultObj) { return; } @@ -281,37 +273,45 @@ export default class ConditionManager extends EventEmitter { } requestLADConditionSetOutput() { + if (!this.domainObject.configuration.conditionCollection.length) { + return Promise.resolve([]); + } + const conditionResults = []; - this.load() - .then(() => { - this.conditionCollection.forEach(conditionId => { - this.openmct.objects.get(conditionId) - .then(condition => { - conditionResults.push( - condition.requestLADConditionResult() - ); - }); + this.domainObject.configuration.conditionCollection.forEach((conditionId, index) => { + this.openmct.objects.get(conditionId) + .then(conditionConfiguration => { + let condition = new Condition(conditionConfiguration, this.openmct); + if (index !== undefined) { + this.conditionCollection.splice(index + 1, 0, condition); + } else { + this.conditionCollection.unshift(condition); + } + + conditionResults.push( + condition.requestLADConditionResult() + ); }); + }); - Promise.all(conditionResults) - .then((results) => { - results.forEach(resultObj => { this.updateConditionResults(resultObj); }); - const currentConditionIdentifier = this.getCurrentConditionId(); - - this.openmct.objects.get(currentConditionIdentifier).then((obj) => { - return Object.assign( - { - output: obj.configuration.output, - id: this.domainObject.identifier, - conditionId: currentConditionIdentifier - }, - this.latestTimestamp - ); - }); - }); + return Promise.all(conditionResults) + .then((results) => { + results.forEach(resultObj => { this.updateConditionResults(resultObj); }); + const currentConditionIdentifier = this.getCurrentConditionId(); + this.openmct.objects.get(currentConditionIdentifier).then((obj) => { + return Object.assign( + { + output: obj.configuration.output, + id: this.domainObject.identifier, + conditionId: currentConditionIdentifier + }, + this.latestTimestamp + ); + }); }); + } persist() { diff --git a/src/plugins/condition/ConditionSetTelemetryProvider.js b/src/plugins/condition/ConditionSetTelemetryProvider.js index a3ec173ae1..2075660440 100644 --- a/src/plugins/condition/ConditionSetTelemetryProvider.js +++ b/src/plugins/condition/ConditionSetTelemetryProvider.js @@ -19,18 +19,17 @@ export default class ConditionSetTelemetryProvider { request(domainObject, options) { const conditionManager = new ConditionManager(domainObject, this.openmct); - const output = conditionManager.requestLADConditionSetOutput(); - return output; + return conditionManager.requestLADConditionSetOutput(); } subscribe(domainObject, callback) { - const conditionManager = new ConditionManager(domainObject, this.openmct); - conditionManager.on('conditionSetResultUpdated', callback); + // const conditionManager = new ConditionManager(domainObject, this.openmct); + // conditionManager.on('conditionSetResultUpdated', callback); - return function unsubscribe() { - conditionManager.off('conditionSetResultUpdated'); - conditionManager.destroy(); - } + // return function unsubscribe() { + // conditionManager.off('conditionSetResultUpdated'); + // conditionManager.destroy(); + // } } } diff --git a/src/plugins/condition/criterion/TelemetryCriterion.js b/src/plugins/condition/criterion/TelemetryCriterion.js index 38482bb82a..f3bb0f5603 100644 --- a/src/plugins/condition/criterion/TelemetryCriterion.js +++ b/src/plugins/condition/criterion/TelemetryCriterion.js @@ -111,10 +111,6 @@ export default class TelemetryCriterion extends EventEmitter { } requestLAD(options) { - if (!this.isValid()) { - return this.formatData({}); - } - options = Object.assign({}, options, { @@ -122,14 +118,20 @@ export default class TelemetryCriterion extends EventEmitter { size: 1 } ); - - this.telemetryAPI.request( - this.telemetryObject, - options - ).then(results => { - const datum = results.length ? results[results.length - 1] : {}; - return this.formatData(datum); - }); + + return this.objectAPI.get(this.objectAPI.makeKeyString(this.telemetry)) + .then((obj) => { + if (!obj || !this.metadata || !this.operation) { + return this.formatData({}); + } + return this.telemetryAPI.request( + obj, + options + ).then(results => { + const datum = results.length ? results[results.length - 1] : {}; + return this.formatData(datum); + }); + }); } /** From cf9336dae9da94f0aea354caee4144d9aedef641 Mon Sep 17 00:00:00 2001 From: David Tsay Date: Fri, 6 Mar 2020 11:01:15 -0800 Subject: [PATCH 04/32] WIP receive criterion results and compute condition results --- src/plugins/condition/Condition.js | 30 +++++++++++++------ .../condition/criterion/TelemetryCriterion.js | 6 ++-- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/plugins/condition/Condition.js b/src/plugins/condition/Condition.js index af6cdc79ec..7aca82bc16 100644 --- a/src/plugins/condition/Condition.js +++ b/src/plugins/condition/Condition.js @@ -59,6 +59,7 @@ export default class ConditionClass extends EventEmitter { this.criteria = []; this.criteriaResults = {}; this.result = undefined; + this.latestTimestamp = {}; if (conditionConfiguration.configuration.criteria) { this.createCriteria(conditionConfiguration.configuration.criteria); } @@ -203,21 +204,18 @@ export default class ConditionClass extends EventEmitter { } requestLADConditionResult() { - const criteriaResults = []; - - this.criteria.forEach(criterion => { - criteriaResults.push( - criterion.requestLAD() - ); - }); + const criteriaResults = this.criteria.map(criterion => + criterion.requestLAD() + ); return Promise.all(criteriaResults) .then(results => { results.forEach(result => { this.updateCriteriaResults(result); + this.latestTimestamp = this.getLatestTimestamp(this.latestTimestamp, result) }); - - return Object.assign({}, /*datum,*/ { result: this.result }); +console.log(Object.assign({}, this.latestTimestamp, { result: this.result })); + return Object.assign({}, this.latestTimestamp, { result: this.result }); }); } @@ -253,6 +251,20 @@ export default class ConditionClass extends EventEmitter { this.result = computeCondition(this.criteriaResults, this.trigger === TRIGGER.ALL); } + getLatestTimestamp(current, compare) { + const timestamp = Object.assign({}, current); + + this.openmct.time.getAllTimeSystems().forEach(timeSystem => { + if (!timestamp[timeSystem.key] + || compare[timeSystem.key] > timestamp[timeSystem.key] + ) { + timestamp[timeSystem.key] = compare[timeSystem.key]; + } + }); + + return timestamp; + } + emitEvent(eventName, data) { this.emit(eventName, { id: this.id, diff --git a/src/plugins/condition/criterion/TelemetryCriterion.js b/src/plugins/condition/criterion/TelemetryCriterion.js index f3bb0f5603..567d7fcbeb 100644 --- a/src/plugins/condition/criterion/TelemetryCriterion.js +++ b/src/plugins/condition/criterion/TelemetryCriterion.js @@ -118,7 +118,7 @@ export default class TelemetryCriterion extends EventEmitter { size: 1 } ); - + return this.objectAPI.get(this.objectAPI.makeKeyString(this.telemetry)) .then((obj) => { if (!obj || !this.metadata || !this.operation) { @@ -128,8 +128,8 @@ export default class TelemetryCriterion extends EventEmitter { obj, options ).then(results => { - const datum = results.length ? results[results.length - 1] : {}; - return this.formatData(datum); + const latestDatum = results.length ? results[results.length - 1] : {}; + return this.formatData(latestDatum); }); }); } From 4a5e1067094ef19b8988a31ea199fddd5f7dde94 Mon Sep 17 00:00:00 2001 From: David Tsay Date: Fri, 6 Mar 2020 17:33:21 -0800 Subject: [PATCH 05/32] request LAD for conditions provides telemetry --- src/plugins/condition/Condition.js | 13 ++-- src/plugins/condition/ConditionManager.js | 64 +++++++++---------- .../ConditionSetTelemetryProvider.js | 15 +++-- .../condition/components/ConditionSet.vue | 2 +- .../condition/criterion/TelemetryCriterion.js | 6 +- 5 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/plugins/condition/Condition.js b/src/plugins/condition/Condition.js index 7aca82bc16..a8d1282577 100644 --- a/src/plugins/condition/Condition.js +++ b/src/plugins/condition/Condition.js @@ -204,9 +204,8 @@ export default class ConditionClass extends EventEmitter { } requestLADConditionResult() { - const criteriaResults = this.criteria.map(criterion => - criterion.requestLAD() - ); + const criteriaResults = this.criteria + .map(criterion => criterion.requestLAD()); return Promise.all(criteriaResults) .then(results => { @@ -214,8 +213,12 @@ export default class ConditionClass extends EventEmitter { this.updateCriteriaResults(result); this.latestTimestamp = this.getLatestTimestamp(this.latestTimestamp, result) }); -console.log(Object.assign({}, this.latestTimestamp, { result: this.result })); - return Object.assign({}, this.latestTimestamp, { result: this.result }); + this.evaluate(); + + return { + id: this.id, + data: Object.assign({}, this.latestTimestamp, { result: this.result }) + } }); } diff --git a/src/plugins/condition/ConditionManager.js b/src/plugins/condition/ConditionManager.js index 7e2dff198c..127074afae 100644 --- a/src/plugins/condition/ConditionManager.js +++ b/src/plugins/condition/ConditionManager.js @@ -32,8 +32,9 @@ export default class ConditionManager extends EventEmitter { this.timeAPI = this.openmct.time; this.latestTimestamp = {}; this.instantiate = this.openmct.$injector.get('instantiate'); - this.loaded = undefined; this.conditionCollection = []; + this.composition = this.openmct.composition.get(domainObject); + this.loaded = this.composition.load(); this.initialize(); } @@ -45,7 +46,7 @@ export default class ConditionManager extends EventEmitter { this.conditionResults = {}; this.openmct.objects.get(this.domainObject.identifier) - .then((obj) => { + .then((obj) => { this.observeForChanges(obj); if (this.domainObject.configuration.conditionCollection.length) { this.domainObject.configuration.conditionCollection.forEach((conditionConfigurationId, index) => { @@ -225,7 +226,6 @@ export default class ConditionManager extends EventEmitter { break; } } - return currentConditionIdentifier; } @@ -247,7 +247,6 @@ export default class ConditionManager extends EventEmitter { this.updateConditionResults(resultObj); const currentConditionIdentifier = this.getCurrentConditionId(); - this.openmct.objects.get(currentConditionIdentifier).then((obj) => { this.emit('conditionSetResultUpdated', Object.assign( @@ -277,41 +276,36 @@ export default class ConditionManager extends EventEmitter { return Promise.resolve([]); } - const conditionResults = []; + return this.load().then(() => { + if (this.conditionCollection && this.conditionCollection.length === 1) { + return Promise([]); + } - this.domainObject.configuration.conditionCollection.forEach((conditionId, index) => { - this.openmct.objects.get(conditionId) - .then(conditionConfiguration => { - let condition = new Condition(conditionConfiguration, this.openmct); - if (index !== undefined) { - this.conditionCollection.splice(index + 1, 0, condition); - } else { - this.conditionCollection.unshift(condition); - } + let ladConditionResults = []; - conditionResults.push( - condition.requestLADConditionResult() - ); + // do not request LAD for default collection, which is always last + for (let i = 0; i < this.conditionCollection.length - 1; i++) { + ladConditionResults.push(this.conditionCollection[i].requestLADConditionResult()); + } + return Promise.all(ladConditionResults) + .then((results) => { + results.forEach(resultObj => { this.updateConditionResults(resultObj); }); + const currentConditionIdentifier = this.getCurrentConditionId(); + return this.openmct.objects.get(currentConditionIdentifier) + .then(obj => { + // uncomment to see output of lad request (before subscriptions kick in) + // console.log(obj.configuration.output); + return Object.assign( + { + output: obj.configuration.output, + id: this.domainObject.identifier, + conditionId: currentConditionIdentifier + }, + this.latestTimestamp + ); + }); }); }); - - return Promise.all(conditionResults) - .then((results) => { - results.forEach(resultObj => { this.updateConditionResults(resultObj); }); - const currentConditionIdentifier = this.getCurrentConditionId(); - - this.openmct.objects.get(currentConditionIdentifier).then((obj) => { - return Object.assign( - { - output: obj.configuration.output, - id: this.domainObject.identifier, - conditionId: currentConditionIdentifier - }, - this.latestTimestamp - ); - }); - }); - } persist() { diff --git a/src/plugins/condition/ConditionSetTelemetryProvider.js b/src/plugins/condition/ConditionSetTelemetryProvider.js index 2075660440..3dfdce77a1 100644 --- a/src/plugins/condition/ConditionSetTelemetryProvider.js +++ b/src/plugins/condition/ConditionSetTelemetryProvider.js @@ -20,16 +20,17 @@ export default class ConditionSetTelemetryProvider { request(domainObject, options) { const conditionManager = new ConditionManager(domainObject, this.openmct); - return conditionManager.requestLADConditionSetOutput(); + return conditionManager.requestLADConditionSetOutput() + .then(latestOutput => { return latestOutput ? [latestOutput] : []; }); } subscribe(domainObject, callback) { - // const conditionManager = new ConditionManager(domainObject, this.openmct); - // conditionManager.on('conditionSetResultUpdated', callback); + const conditionManager = new ConditionManager(domainObject, this.openmct); + conditionManager.on('conditionSetResultUpdated', callback); - // return function unsubscribe() { - // conditionManager.off('conditionSetResultUpdated'); - // conditionManager.destroy(); - // } + return function unsubscribe() { + conditionManager.off('conditionSetResultUpdated'); + conditionManager.destroy(); + } } } diff --git a/src/plugins/condition/components/ConditionSet.vue b/src/plugins/condition/components/ConditionSet.vue index 50e1a5bb5e..8c573c0eb7 100644 --- a/src/plugins/condition/components/ConditionSet.vue +++ b/src/plugins/condition/components/ConditionSet.vue @@ -77,7 +77,7 @@ export default { this.openmct.telemetry .request(this.domainObject) .then(output => { - this.updateCurrentOutput(output); + this.updateCurrentOutput(output[0]); }); this.stopProvidingTelemetry = this.openmct.telemetry .subscribe(this.domainObject, output => { this.updateCurrentOutput(output); }); diff --git a/src/plugins/condition/criterion/TelemetryCriterion.js b/src/plugins/condition/criterion/TelemetryCriterion.js index 567d7fcbeb..1b026fa307 100644 --- a/src/plugins/condition/criterion/TelemetryCriterion.js +++ b/src/plugins/condition/criterion/TelemetryCriterion.js @@ -66,7 +66,6 @@ export default class TelemetryCriterion extends EventEmitter { datum[timeSystem.key] = data[timeSystem.key] }); } - return datum; } @@ -129,7 +128,10 @@ export default class TelemetryCriterion extends EventEmitter { options ).then(results => { const latestDatum = results.length ? results[results.length - 1] : {}; - return this.formatData(latestDatum); + return { + id: this.id, + data: this.formatData(latestDatum) + }; }); }); } From 24bade2284df81fef15d3d3ad6a74752e27e6324 Mon Sep 17 00:00:00 2001 From: David Tsay Date: Mon, 9 Mar 2020 10:59:05 -0700 Subject: [PATCH 06/32] provide correct data to getLatestTimestamp call --- src/plugins/condition/Condition.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/plugins/condition/Condition.js b/src/plugins/condition/Condition.js index a8d1282577..d00303e4cf 100644 --- a/src/plugins/condition/Condition.js +++ b/src/plugins/condition/Condition.js @@ -211,7 +211,7 @@ export default class ConditionClass extends EventEmitter { .then(results => { results.forEach(result => { this.updateCriteriaResults(result); - this.latestTimestamp = this.getLatestTimestamp(this.latestTimestamp, result) + this.latestTimestamp = this.getLatestTimestamp(this.latestTimestamp, result.data) }); this.evaluate(); @@ -264,7 +264,6 @@ export default class ConditionClass extends EventEmitter { timestamp[timeSystem.key] = compare[timeSystem.key]; } }); - return timestamp; } From 7a4b967a0133148d60108974ab7bf591d6449033 Mon Sep 17 00:00:00 2001 From: David Tsay Date: Mon, 9 Mar 2020 13:28:37 -0700 Subject: [PATCH 07/32] condition sets with no telemetry points should not provide telemetry --- src/plugins/condition/ConditionManager.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/plugins/condition/ConditionManager.js b/src/plugins/condition/ConditionManager.js index 127074afae..e59d538b8b 100644 --- a/src/plugins/condition/ConditionManager.js +++ b/src/plugins/condition/ConditionManager.js @@ -101,11 +101,6 @@ export default class ConditionManager extends EventEmitter { } else { this.conditionCollection.unshift(condition); } - //There are no criteria for a default condition and hence no subscriptions. - //Hence the conditionResult must be manually triggered for it. - if (conditionConfiguration.isDefault) { - this.handleConditionResult(); - } } createConditionDomainObject(isDefault, conditionConfiguration) { From 49ff0c79dbcdd0722f9ff0bad3c76a15c34bd8d8 Mon Sep 17 00:00:00 2001 From: David Tsay Date: Mon, 9 Mar 2020 16:15:53 -0700 Subject: [PATCH 08/32] tidy up condition manager use in telemetry provider --- .../condition/ConditionSetTelemetryProvider.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/plugins/condition/ConditionSetTelemetryProvider.js b/src/plugins/condition/ConditionSetTelemetryProvider.js index 3dfdce77a1..3358b1cc48 100644 --- a/src/plugins/condition/ConditionSetTelemetryProvider.js +++ b/src/plugins/condition/ConditionSetTelemetryProvider.js @@ -18,19 +18,24 @@ export default class ConditionSetTelemetryProvider { } request(domainObject, options) { - const conditionManager = new ConditionManager(domainObject, this.openmct); + let conditionManager = new ConditionManager(domainObject, this.openmct); return conditionManager.requestLADConditionSetOutput() - .then(latestOutput => { return latestOutput ? [latestOutput] : []; }); + .then(latestOutput => { + conditionManager.destroy(); + conditionManager = undefined; + return latestOutput ? [latestOutput] : []; + }); } subscribe(domainObject, callback) { - const conditionManager = new ConditionManager(domainObject, this.openmct); + let conditionManager = new ConditionManager(domainObject, this.openmct); conditionManager.on('conditionSetResultUpdated', callback); - return function unsubscribe() { + return () => { // unsubscribe function conditionManager.off('conditionSetResultUpdated'); conditionManager.destroy(); - } + conditionManager = undefined; + }; } } From 0da80c2a6703427b34d192133428d12fe0942103 Mon Sep 17 00:00:00 2001 From: David Tsay Date: Tue, 10 Mar 2020 09:58:57 -0700 Subject: [PATCH 09/32] move var declaration around for clarity --- src/plugins/condition/ConditionManager.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/plugins/condition/ConditionManager.js b/src/plugins/condition/ConditionManager.js index f5ee84f626..d5a18dbd12 100644 --- a/src/plugins/condition/ConditionManager.js +++ b/src/plugins/condition/ConditionManager.js @@ -31,10 +31,13 @@ export default class ConditionManager extends EventEmitter { this.domainObject = domainObject; this.timeAPI = this.openmct.time; this.latestTimestamp = {}; - this.instantiate = this.openmct.$injector.get('instantiate'); + this.conditionResults = {}; this.conditionCollection = []; + this.instantiate = this.openmct.$injector.get('instantiate'); this.composition = this.openmct.composition.get(domainObject); + console.log(this.composition); this.loaded = this.composition.load(); + console.log(this.loaded); this.initialize(); } @@ -43,8 +46,6 @@ export default class ConditionManager extends EventEmitter { } initialize() { - this.conditionResults = {}; - this.openmct.objects.get(this.domainObject.identifier) .then((obj) => { this.observeForChanges(obj); From dba55867f4427b70685f340626ab6cf15bf20cc0 Mon Sep 17 00:00:00 2001 From: David Tsay Date: Tue, 10 Mar 2020 09:59:12 -0700 Subject: [PATCH 10/32] fix broken unit tests --- src/plugins/condition/ConditionManagerSpec.js | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/src/plugins/condition/ConditionManagerSpec.js b/src/plugins/condition/ConditionManagerSpec.js index c5e50e9694..7dfc7a08e4 100644 --- a/src/plugins/condition/ConditionManagerSpec.js +++ b/src/plugins/condition/ConditionManagerSpec.js @@ -46,6 +46,8 @@ describe('ConditionManager', () => { key: '1234-5678' } }; + let mockComposition; + let loader; function mockAngularComponents() { let mockInjector = jasmine.createSpyObj('$injector', ['get']); @@ -70,10 +72,30 @@ describe('ConditionManager', () => { openmct.$injector = mockInjector; } - beforeAll(function () { + beforeEach(function () { mockAngularComponents(); + loader = {}; + loader.promise = new Promise(function (resolve, reject) { + loader.resolve = resolve; + loader.reject = reject; + }); + + mockComposition = jasmine.createSpyObj('compositionCollection', [ + 'load' + ]); + mockComposition.load.and.callFake(() => { + setTimeout(() => { + loader.resolve(); + }); + return loader.promise; + }); + openmct.composition = jasmine.createSpyObj('compositionAPI', [ + 'get' + ]); + openmct.composition.get.and.returnValue(mockComposition); + openmct.objects = jasmine.createSpyObj('objects', ['get', 'makeKeyString', 'observe', 'mutate']); openmct.objects.get.and.returnValues(new Promise(function (resolve, reject) { resolve(conditionSetDomainObject); @@ -83,6 +105,7 @@ describe('ConditionManager', () => { openmct.objects.makeKeyString.and.returnValue(conditionSetDomainObject.identifier.key); openmct.objects.observe.and.returnValue(function () {}); openmct.objects.mutate.and.returnValue(function () {}); + conditionMgr = new ConditionManager(conditionSetDomainObject, openmct); mockListener = jasmine.createSpy('mockListener'); @@ -90,9 +113,15 @@ describe('ConditionManager', () => { }); it('creates a conditionCollection with a default condition', function () { - expect(conditionMgr.domainObject.configuration.conditionCollection.length).toEqual(1); - let defaultConditionIdentifier = conditionMgr.domainObject.configuration.conditionCollection[0]; - expect(defaultConditionIdentifier).toEqual(mockConditionDomainObject.identifier); + return loader.promise.then(function () { + return new Promise(function (resolve) { + setTimeout(resolve); + }); + }).then(function () { + expect(conditionMgr.domainObject.configuration.conditionCollection.length).toEqual(1); + let defaultConditionIdentifier = conditionMgr.domainObject.configuration.conditionCollection[0]; + expect(defaultConditionIdentifier).toEqual(mockConditionDomainObject.identifier); + }); }); }); From 6095872682aa10e3e80d14cba29d6f235aed9eb6 Mon Sep 17 00:00:00 2001 From: David Tsay Date: Tue, 10 Mar 2020 10:08:53 -0700 Subject: [PATCH 11/32] remove logging --- src/plugins/condition/ConditionManager.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/plugins/condition/ConditionManager.js b/src/plugins/condition/ConditionManager.js index d5a18dbd12..67c110f082 100644 --- a/src/plugins/condition/ConditionManager.js +++ b/src/plugins/condition/ConditionManager.js @@ -35,9 +35,7 @@ export default class ConditionManager extends EventEmitter { this.conditionCollection = []; this.instantiate = this.openmct.$injector.get('instantiate'); this.composition = this.openmct.composition.get(domainObject); - console.log(this.composition); this.loaded = this.composition.load(); - console.log(this.loaded); this.initialize(); } From 1dc974348463b1fb40c9efcc35738b3a941aabd2 Mon Sep 17 00:00:00 2001 From: David Tsay Date: Fri, 13 Mar 2020 09:26:46 -0700 Subject: [PATCH 12/32] remove unecessary get call --- src/plugins/condition/ConditionManager.js | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/plugins/condition/ConditionManager.js b/src/plugins/condition/ConditionManager.js index 67c110f082..8fa105334e 100644 --- a/src/plugins/condition/ConditionManager.js +++ b/src/plugins/condition/ConditionManager.js @@ -44,19 +44,16 @@ export default class ConditionManager extends EventEmitter { } initialize() { - this.openmct.objects.get(this.domainObject.identifier) - .then((obj) => { - this.observeForChanges(obj); - if (this.domainObject.configuration.conditionCollection.length) { - this.domainObject.configuration.conditionCollection.forEach((conditionConfigurationId, index) => { - this.openmct.objects.get(conditionConfigurationId).then((conditionConfiguration) => { - this.initCondition(conditionConfiguration, index); - }); - }); - } else { - this.addCondition(true); - } + this.observeForChanges(this.domainObject); + if (this.domainObject.configuration.conditionCollection.length) { + this.domainObject.configuration.conditionCollection.forEach((conditionConfigurationId, index) => { + this.openmct.objects.get(conditionConfigurationId).then((conditionConfiguration) => { + this.initCondition(conditionConfiguration, index); + }); }); + } else { + this.addCondition(true); + } } observeForChanges(domainObject) { From 15a7d03e7454e8c39931704fde6454f31e83c22d Mon Sep 17 00:00:00 2001 From: David Tsay Date: Fri, 13 Mar 2020 09:36:17 -0700 Subject: [PATCH 13/32] rename function for clarity --- src/plugins/condition/ConditionSetTelemetryProvider.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/condition/ConditionSetTelemetryProvider.js b/src/plugins/condition/ConditionSetTelemetryProvider.js index 3358b1cc48..5728282664 100644 --- a/src/plugins/condition/ConditionSetTelemetryProvider.js +++ b/src/plugins/condition/ConditionSetTelemetryProvider.js @@ -32,7 +32,7 @@ export default class ConditionSetTelemetryProvider { let conditionManager = new ConditionManager(domainObject, this.openmct); conditionManager.on('conditionSetResultUpdated', callback); - return () => { // unsubscribe function + return function unsubscribe() { conditionManager.off('conditionSetResultUpdated'); conditionManager.destroy(); conditionManager = undefined; From 090e89d524d104f0504dc7caf52210d751b888f6 Mon Sep 17 00:00:00 2001 From: David Tsay Date: Mon, 16 Mar 2020 15:34:12 -0700 Subject: [PATCH 14/32] remove testing aid --- src/plugins/condition/components/TestData.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/condition/components/TestData.vue b/src/plugins/condition/components/TestData.vue index f659ae2166..daedc68ff8 100644 --- a/src/plugins/condition/components/TestData.vue +++ b/src/plugins/condition/components/TestData.vue @@ -79,7 +79,7 @@ export default { }, data() { return { - expanded: false, + expanded: true, isApplied: true }; }, From 84f0d49d6f0287293330a1cdf820e2acbfa25b65 Mon Sep 17 00:00:00 2001 From: David Tsay Date: Mon, 16 Mar 2020 15:35:13 -0700 Subject: [PATCH 15/32] code is documentation --- src/plugins/condition/ConditionManager.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/plugins/condition/ConditionManager.js b/src/plugins/condition/ConditionManager.js index 1ae950c226..c7906806af 100644 --- a/src/plugins/condition/ConditionManager.js +++ b/src/plugins/condition/ConditionManager.js @@ -235,10 +235,6 @@ export default class ConditionManager extends EventEmitter { const ladConditionResults = this.conditionClassCollection .filter(condition => !condition.isDefault) .map(condition => condition.requestLADConditionResult()); - // // do not request LAD for default collection, which is always last - // for (let i = 0; i < this.conditionClassCollection.length - 1; i++) { - // ladConditionResults.push(this.conditionClassCollection[i].requestLADConditionResult()); - // } return Promise.all(ladConditionResults) .then((results) => { From b7fffeab1cb9d3c5d5d405e6401d6f6c44c2d20d Mon Sep 17 00:00:00 2001 From: David Tsay Date: Mon, 16 Mar 2020 21:57:42 -0700 Subject: [PATCH 16/32] conditionManager controls subscriptions --- src/plugins/condition/Condition.js | 22 ++++++-- src/plugins/condition/ConditionManager.js | 24 +++++++++ .../condition/criterion/TelemetryCriterion.js | 54 ++++++------------- 3 files changed, 56 insertions(+), 44 deletions(-) diff --git a/src/plugins/condition/Condition.js b/src/plugins/condition/Condition.js index b42c4fc4ac..6c5ebfa92e 100644 --- a/src/plugins/condition/Condition.js +++ b/src/plugins/condition/Condition.js @@ -61,6 +61,21 @@ export default class ConditionClass extends EventEmitter { this.createCriteria(conditionConfiguration.configuration.criteria); } this.trigger = conditionConfiguration.configuration.trigger; + this.unsubscribes = this.getTelemetrySubscriptions().map(id => { + this.on(`subscription:${id}`, this.handleReceivedTelemetry) + }); + } + + handleReceivedTelemetry(datum) { + if (!datum || !datum.id) { + console.log('no data received'); + return; + } + + this.criteria.filter(criterion => criterion.telemetryObjectIdAsString === datum.id) + .forEach(subscribingCriterion => { + subscribingCriterion.emit(`subscription`, datum) + }); } update(conditionConfiguration) { @@ -214,11 +229,8 @@ export default class ConditionClass extends EventEmitter { }); } - subscribe() { - // TODO it looks like on any single criterion update subscriptions fire for all criteria - this.criteria.forEach((criterion) => { - criterion.subscribe(); - }) + getTelemetrySubscriptions() { + return this.criteria.map(criterion => criterion.telemetryObjectIdAsString); } handleConditionUpdated(datum) { diff --git a/src/plugins/condition/ConditionManager.js b/src/plugins/condition/ConditionManager.js index c7906806af..72d10046d3 100644 --- a/src/plugins/condition/ConditionManager.js +++ b/src/plugins/condition/ConditionManager.js @@ -38,6 +38,8 @@ export default class ConditionManager extends EventEmitter { this.stopObservingForChanges = this.openmct.objects.observe(this.conditionSetDomainObject, '*', (newDomainObject) => { this.update(newDomainObject); }); + + this.subscribeToTelemetry(); } load() { @@ -255,6 +257,28 @@ export default class ConditionManager extends EventEmitter { }); } + subscribeToTelemetry() { + this.load().then((endpoints) => { + this.unsubscribes = endpoints.map(endpoint => { + this.openmct.telemetry.subscribe( + endpoint, + this.broadcastTelemetry + .bind(this, this.openmct.objects.makeKeyString(endpoint.identifier))); + }); + }); + } + + broadcastTelemetry(id, datum) { + this.conditionClassCollection.filter(condition => { + return condition.getTelemetrySubscriptions().includes(id); + }).forEach(subscribingCondition => { + subscribingCondition.emit( + `subscription:${id}`, + Object.assign({}, datum, {id: id}) + ); + }); + } + persistConditions() { this.openmct.objects.mutate(this.conditionSetDomainObject, 'configuration.conditionCollection', this.conditionSetDomainObject.configuration.conditionCollection); } diff --git a/src/plugins/condition/criterion/TelemetryCriterion.js b/src/plugins/condition/criterion/TelemetryCriterion.js index f9b2350211..19501f63f2 100644 --- a/src/plugins/condition/criterion/TelemetryCriterion.js +++ b/src/plugins/condition/criterion/TelemetryCriterion.js @@ -44,16 +44,17 @@ export default class TelemetryCriterion extends EventEmitter { this.operation = telemetryDomainObjectDefinition.operation; this.input = telemetryDomainObjectDefinition.input; this.metadata = telemetryDomainObjectDefinition.metadata; - this.subscription = null; - this.telemetryObjectIdAsString = null; - this.objectAPI.get(this.objectAPI.makeKeyString(this.telemetry)).then((obj) => this.initialize(obj)); + // this.subscription = null; + this.telemetryObjectIdAsString = this.objectAPI.makeKeyString(this.telemetry); + this.on('subscription', this.handleSubscription); + // this.objectAPI.get(this.objectAPI.makeKeyString(this.telemetry)).then((obj) => this.initialize(obj)); } - initialize(obj) { - this.telemetryObject = obj; - this.telemetryObjectIdAsString = this.objectAPI.makeKeyString(this.telemetryObject.identifier); - this.emitEvent('criterionUpdated', this); - } + // initialize(obj) { + // this.telemetryObject = obj; + // this.telemetryObjectIdAsString = this.objectAPI.makeKeyString(this.telemetryObject.identifier); + // this.emitEvent('criterionUpdated', this); + // } formatData(data) { const datum = { @@ -70,7 +71,9 @@ export default class TelemetryCriterion extends EventEmitter { } handleSubscription(data) { - this.emitEvent('criterionResultUpdated', this.formatData(data)); + if(this.isValid()) { + this.emitEvent('criterionResultUpdated', this.formatData(data)); + } } findOperation(operation) { @@ -106,7 +109,7 @@ export default class TelemetryCriterion extends EventEmitter { } isValid() { - return this.telemetryObject && this.metadata && this.operation; + return this.metadata && this.operation; } requestLAD(options) { @@ -120,7 +123,7 @@ export default class TelemetryCriterion extends EventEmitter { return this.objectAPI.get(this.objectAPI.makeKeyString(this.telemetry)) .then((obj) => { - if (!obj || !this.metadata || !this.operation) { + if (!obj || !this.isValid()) { return this.formatData({}); } return this.telemetryAPI.request( @@ -136,36 +139,9 @@ export default class TelemetryCriterion extends EventEmitter { }); } - /** - * Subscribes to the telemetry object and returns an unsubscribe function - * If the telemetry is not valid, returns nothing - */ - subscribe() { - if (this.isValid()) { - this.unsubscribe(); - this.subscription = this.telemetryAPI.subscribe(this.telemetryObject, (datum) => { - this.handleSubscription(datum); - }); - } else { - this.handleSubscription(); - } - } - - /** - * Calls an unsubscribe function returned by subscribe() and deletes any initialized data - */ - unsubscribe() { - //unsubscribe from telemetry source - if (typeof this.subscription === 'function') { - this.subscription(); - } - delete this.subscription; - } - destroy() { - this.unsubscribe(); + this.off('receivedTelemetry', this.handleSubscription); this.emitEvent('criterionRemoved'); delete this.telemetryObjectIdAsString; - delete this.telemetryObject; } } From 243b9cac2493e7bff70ca6bc0f9fe7afa3a3ea4a Mon Sep 17 00:00:00 2001 From: David Tsay Date: Wed, 18 Mar 2020 10:21:53 -0700 Subject: [PATCH 17/32] subscribe to telemetry --- src/plugins/condition/Condition.js | 1 + src/plugins/condition/ConditionManager.js | 53 ++++++++++++++++++----- 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/plugins/condition/Condition.js b/src/plugins/condition/Condition.js index 6c5ebfa92e..92f48fbec5 100644 --- a/src/plugins/condition/Condition.js +++ b/src/plugins/condition/Condition.js @@ -67,6 +67,7 @@ export default class ConditionClass extends EventEmitter { } handleReceivedTelemetry(datum) { + console.log(`received datum`); if (!datum || !datum.id) { console.log('no data received'); return; diff --git a/src/plugins/condition/ConditionManager.js b/src/plugins/condition/ConditionManager.js index ed71527960..cad5c02ea3 100644 --- a/src/plugins/condition/ConditionManager.js +++ b/src/plugins/condition/ConditionManager.js @@ -32,14 +32,41 @@ export default class ConditionManager extends EventEmitter { this.timeAPI = this.openmct.time; this.latestTimestamp = {}; this.composition = this.openmct.composition.get(conditionSetDomainObject); + this.composition.on('add', this.addTelemetry, this) + this.composition.on('remove', this.removeTelemetry, this) + this.loaded = this.composition.load(); + this.subscriptions = {}; this.initialize(); this.stopObservingForChanges = this.openmct.objects.observe(this.conditionSetDomainObject, '*', (newDomainObject) => { this.conditionSetDomainObject = newDomainObject; }); + } - this.subscribeToTelemetry(); + addTelemetry(endpoint) { + const id = this.openmct.objects.makeKeyString(endpoint.identifier); + if (this.subscriptions[id]) { + console.log('subscription already exists'); + return; + } + + this.subscriptions[id] = this.openmct.telemetry.subscribe( + endpoint, + this.broadcastTelemetry + .bind(this, id) + ); + } + + removeTelemetry(endpointIdentifier) { + const id = this.openmct.objects.makeKeyString(endpointIdentifier); + if (!this.subscriptions[id]) { + console.log('no subscription to remove'); + return; + } + + this.subscriptions[id](); + delete this.subscriptions[id]; } load() { @@ -248,18 +275,20 @@ export default class ConditionManager extends EventEmitter { }); } - subscribeToTelemetry() { - this.load().then((endpoints) => { - this.unsubscribes = endpoints.map(endpoint => { - this.openmct.telemetry.subscribe( - endpoint, - this.broadcastTelemetry - .bind(this, this.openmct.objects.makeKeyString(endpoint.identifier))); - }); - }); - } + // subscribeToTelemetry() { + + // this.load().then((endpoints) => { + // this.unsubscribes = endpoints.map(endpoint => { + // this.openmct.telemetry.subscribe( + // endpoint, + // this.broadcastTelemetry + // .bind(this, this.openmct.objects.makeKeyString(endpoint.identifier))); + // }); + // }); + // } broadcastTelemetry(id, datum) { + console.log(this.conditionClassCollection); this.conditionClassCollection.filter(condition => { return condition.getTelemetrySubscriptions().includes(id); }).forEach(subscribingCondition => { @@ -275,6 +304,8 @@ export default class ConditionManager extends EventEmitter { } destroy() { + this.composition.off('add', this.addTelemetry, this) + this.composition.off('remove', this.removeTelemetry, this) if(this.stopObservingForChanges) { this.stopObservingForChanges(); } From 00d1b5e69f384ca50dcdd167844aa5014c1bf59c Mon Sep 17 00:00:00 2001 From: David Tsay Date: Thu, 19 Mar 2020 10:18:57 -0700 Subject: [PATCH 18/32] avoid multiple instantiations of condtionManager if possible --- src/plugins/condition/Condition.js | 2 -- src/plugins/condition/ConditionManager.js | 29 ++++++------------- .../ConditionSetTelemetryProvider.js | 7 +++-- .../components/ConditionCollection.vue | 12 +++++--- 4 files changed, 21 insertions(+), 29 deletions(-) diff --git a/src/plugins/condition/Condition.js b/src/plugins/condition/Condition.js index 92f48fbec5..7098d63fbc 100644 --- a/src/plugins/condition/Condition.js +++ b/src/plugins/condition/Condition.js @@ -67,12 +67,10 @@ export default class ConditionClass extends EventEmitter { } handleReceivedTelemetry(datum) { - console.log(`received datum`); if (!datum || !datum.id) { console.log('no data received'); return; } - this.criteria.filter(criterion => criterion.telemetryObjectIdAsString === datum.id) .forEach(subscribingCriterion => { subscribingCriterion.emit(`subscription`, datum) diff --git a/src/plugins/condition/ConditionManager.js b/src/plugins/condition/ConditionManager.js index e00d6ca3c1..e33ff3741b 100644 --- a/src/plugins/condition/ConditionManager.js +++ b/src/plugins/condition/ConditionManager.js @@ -32,8 +32,8 @@ export default class ConditionManager extends EventEmitter { this.timeAPI = this.openmct.time; this.latestTimestamp = {}; this.composition = this.openmct.composition.get(conditionSetDomainObject); - this.composition.on('add', this.addTelemetry, this) - this.composition.on('remove', this.removeTelemetry, this) + this.composition.on('add', this.addTelemetry, this); + this.composition.on('remove', this.removeTelemetry, this); this.loaded = this.composition.load(); this.subscriptions = {}; @@ -53,8 +53,7 @@ export default class ConditionManager extends EventEmitter { this.subscriptions[id] = this.openmct.telemetry.subscribe( endpoint, - this.broadcastTelemetry - .bind(this, id) + this.broadcastTelemetry.bind(this, id) ); } @@ -212,7 +211,6 @@ export default class ConditionManager extends EventEmitter { // update conditions results and then calculate the current condition this.updateConditionResults(resultObj); const currentCondition = this.getCurrentCondition(); - this.emit('conditionSetResultUpdated', Object.assign( { @@ -264,20 +262,7 @@ export default class ConditionManager extends EventEmitter { }); } - // subscribeToTelemetry() { - - // this.load().then((endpoints) => { - // this.unsubscribes = endpoints.map(endpoint => { - // this.openmct.telemetry.subscribe( - // endpoint, - // this.broadcastTelemetry - // .bind(this, this.openmct.objects.makeKeyString(endpoint.identifier))); - // }); - // }); - // } - broadcastTelemetry(id, datum) { - console.log(this.conditionClassCollection); this.conditionClassCollection.filter(condition => { return condition.getTelemetrySubscriptions().includes(id); }).forEach(subscribingCondition => { @@ -293,11 +278,15 @@ export default class ConditionManager extends EventEmitter { } destroy() { - this.composition.off('add', this.addTelemetry, this) - this.composition.off('remove', this.removeTelemetry, this) + this.composition.off('add', this.addTelemetry, this); + this.composition.off('remove', this.removeTelemetry, this); + Object.values(this.subscriptions).forEach(unsubscribe => unsubscribe()); + this.subscriptions = undefined; + if(this.stopObservingForChanges) { this.stopObservingForChanges(); } + this.conditionClassCollection.forEach((condition) => { condition.off('conditionResultUpdated', this.handleConditionResult); condition.destroy(); diff --git a/src/plugins/condition/ConditionSetTelemetryProvider.js b/src/plugins/condition/ConditionSetTelemetryProvider.js index f1ca0ec12f..3e4022d8e2 100644 --- a/src/plugins/condition/ConditionSetTelemetryProvider.js +++ b/src/plugins/condition/ConditionSetTelemetryProvider.js @@ -40,7 +40,7 @@ export default class ConditionSetTelemetryProvider { } request(domainObject, options) { - let conditionManager = new ConditionManager(domainObject, this.openmct); + let conditionManager = options.conditionManager || new ConditionManager(domainObject, this.openmct); return conditionManager.requestLADConditionSetOutput() .then(latestOutput => { @@ -50,8 +50,9 @@ export default class ConditionSetTelemetryProvider { }); } - subscribe(domainObject, callback) { - let conditionManager = new ConditionManager(domainObject, this.openmct); + subscribe(domainObject, callback, options) { + let conditionManager = options.conditionManager || new ConditionManager(domainObject, this.openmct); + conditionManager.on('conditionSetResultUpdated', callback); return function unsubscribe() { diff --git a/src/plugins/condition/components/ConditionCollection.vue b/src/plugins/condition/components/ConditionCollection.vue index 853f2e2f49..4afac0dac5 100644 --- a/src/plugins/condition/components/ConditionCollection.vue +++ b/src/plugins/condition/components/ConditionCollection.vue @@ -121,11 +121,15 @@ export default { this.conditionCollection = this.domainObject.configuration.conditionCollection; this.observeForChanges(); this.conditionManager = new ConditionManager(this.domainObject, this.openmct); - this.conditionManager.requestLADConditionSetOutput() + console.log(`collection condition manager: ${this.conditionManager.id}`); + + let options = { conditionManager: this.conditionManager }; + this.openmct.telemetry.request(this.domainObject, options) .then(data => this.$emit('conditionSetResultUpdated', data[0])); - this.conditionManager.on('conditionSetResultUpdated', (data) => { - this.$emit('conditionSetResultUpdated', data); - }); + this.unsubscribe = this.openmct.telemetry.subscribe( + this.domainObject, + (data) => { this.$emit('conditionSetResultUpdated', data); }, + options); }, methods: { observeForChanges() { From 3f61db206731e52787e79724b04a6a03c38a36c2 Mon Sep 17 00:00:00 2001 From: David Tsay Date: Thu, 19 Mar 2020 17:30:02 -0700 Subject: [PATCH 19/32] pass telemetry down to criteria. criteria listens to corresponding endpoints. --- src/plugins/condition/Condition.js | 19 ++++++------ src/plugins/condition/ConditionManager.js | 11 ++----- .../ConditionSetTelemetryProvider.js | 30 ++++++++++++------- .../components/ConditionCollection.vue | 14 ++++----- .../condition/criterion/TelemetryCriterion.js | 14 ++++----- 5 files changed, 43 insertions(+), 45 deletions(-) diff --git a/src/plugins/condition/Condition.js b/src/plugins/condition/Condition.js index 7098d63fbc..be4bb982eb 100644 --- a/src/plugins/condition/Condition.js +++ b/src/plugins/condition/Condition.js @@ -48,33 +48,32 @@ export default class ConditionClass extends EventEmitter { * @param conditionConfiguration: {id: uuid,trigger: enum, criteria: Array of {id: uuid, operation: enum, input: Array, metaDataKey: string, key: {domainObject.identifier} } * @param openmct */ - constructor(conditionConfiguration, openmct) { + constructor(conditionConfiguration, openmct, conditionManager) { super(); this.openmct = openmct; + this.conditionManager = conditionManager; this.id = conditionConfiguration.id; this.criteria = []; this.criteriaResults = {}; this.result = undefined; this.latestTimestamp = {}; + if (conditionConfiguration.configuration.criteria) { this.createCriteria(conditionConfiguration.configuration.criteria); } this.trigger = conditionConfiguration.configuration.trigger; - this.unsubscribes = this.getTelemetrySubscriptions().map(id => { - this.on(`subscription:${id}`, this.handleReceivedTelemetry) - }); + this.conditionManager.on('broadcastTelemetry', this.handleBroadcastTelemetry, this); } - handleReceivedTelemetry(datum) { + handleBroadcastTelemetry(datum) { if (!datum || !datum.id) { console.log('no data received'); return; } - this.criteria.filter(criterion => criterion.telemetryObjectIdAsString === datum.id) - .forEach(subscribingCriterion => { - subscribingCriterion.emit(`subscription`, datum) - }); + this.criteria.forEach(criterion => { + criterion.emit(`subscription:${datum.id}`, datum); + }); } update(conditionConfiguration) { @@ -187,7 +186,7 @@ export default class ConditionClass extends EventEmitter { let found = this.findCriterion(criterion.id); if (found) { this.criteria[found.index] = criterion.data; - this.subscribe(); + // this.subscribe(); // TODO nothing is listening to this this.emitEvent('conditionUpdated', { trigger: this.trigger, diff --git a/src/plugins/condition/ConditionManager.js b/src/plugins/condition/ConditionManager.js index e33ff3741b..69b34b2940 100644 --- a/src/plugins/condition/ConditionManager.js +++ b/src/plugins/condition/ConditionManager.js @@ -90,7 +90,7 @@ export default class ConditionManager extends EventEmitter { } initCondition(conditionConfiguration, index) { - let condition = new Condition(conditionConfiguration, this.openmct); + let condition = new Condition(conditionConfiguration, this.openmct, this); condition.on('conditionResultUpdated', this.handleConditionResult.bind(this)); if (index !== undefined) { this.conditionClassCollection.splice(index + 1, 0, condition); @@ -263,14 +263,7 @@ export default class ConditionManager extends EventEmitter { } broadcastTelemetry(id, datum) { - this.conditionClassCollection.filter(condition => { - return condition.getTelemetrySubscriptions().includes(id); - }).forEach(subscribingCondition => { - subscribingCondition.emit( - `subscription:${id}`, - Object.assign({}, datum, {id: id}) - ); - }); + this.emit(`broadcastTelemetry`, Object.assign({}, datum, {id: id})); } persistConditions() { diff --git a/src/plugins/condition/ConditionSetTelemetryProvider.js b/src/plugins/condition/ConditionSetTelemetryProvider.js index 3e4022d8e2..6706cb160a 100644 --- a/src/plugins/condition/ConditionSetTelemetryProvider.js +++ b/src/plugins/condition/ConditionSetTelemetryProvider.js @@ -40,25 +40,35 @@ export default class ConditionSetTelemetryProvider { } request(domainObject, options) { - let conditionManager = options.conditionManager || new ConditionManager(domainObject, this.openmct); + let conditionManager = options.conditionManager; + let newConditionManager = false; + if (!conditionManager) { + newConditionManager = true; + conditionManager = new ConditionManager(domainObject, this.openmct); + } return conditionManager.requestLADConditionSetOutput() .then(latestOutput => { - conditionManager.destroy(); - conditionManager = undefined; + if (newConditionManager) { + conditionManager.destroy(); + conditionManager = undefined; + } return latestOutput ? [latestOutput] : []; }); } subscribe(domainObject, callback, options) { - let conditionManager = options.conditionManager || new ConditionManager(domainObject, this.openmct); + let conditionManager = options.conditionManager; + if (!conditionManager) { + conditionManager = new ConditionManager(domainObject, this.openmct); + conditionManager.on('conditionSetResultUpdated', callback); + return function unsubscribe() { + conditionManager.off('conditionSetResultUpdated'); + conditionManager.destroy(); + conditionManager = undefined; + }; + } conditionManager.on('conditionSetResultUpdated', callback); - - return function unsubscribe() { - conditionManager.off('conditionSetResultUpdated'); - conditionManager.destroy(); - conditionManager = undefined; - }; } } diff --git a/src/plugins/condition/components/ConditionCollection.vue b/src/plugins/condition/components/ConditionCollection.vue index 4afac0dac5..9b2ae28eb0 100644 --- a/src/plugins/condition/components/ConditionCollection.vue +++ b/src/plugins/condition/components/ConditionCollection.vue @@ -107,6 +107,7 @@ export default { this.composition.off('add', this.addTelemetryObject); this.composition.off('remove', this.removeTelemetryObject); if(this.conditionManager) { + this.conditionManager.off('conditionSetResultUpdated', this.handleConditionSetResultUpdated); this.conditionManager.destroy(); } if (this.stopObservingForChanges) { @@ -121,17 +122,12 @@ export default { this.conditionCollection = this.domainObject.configuration.conditionCollection; this.observeForChanges(); this.conditionManager = new ConditionManager(this.domainObject, this.openmct); - console.log(`collection condition manager: ${this.conditionManager.id}`); - - let options = { conditionManager: this.conditionManager }; - this.openmct.telemetry.request(this.domainObject, options) - .then(data => this.$emit('conditionSetResultUpdated', data[0])); - this.unsubscribe = this.openmct.telemetry.subscribe( - this.domainObject, - (data) => { this.$emit('conditionSetResultUpdated', data); }, - options); + this.conditionManager.on('conditionSetResultUpdated', this.handleConditionSetResultUpdated); }, methods: { + handleConditionSetResultUpdated(data) { + this.$emit('conditionSetResultUpdated', data) + }, observeForChanges() { this.stopObservingForChanges = this.openmct.objects.observe(this.domainObject, 'configuration.conditionCollection', (newConditionCollection) => { this.conditionCollection = newConditionCollection; diff --git a/src/plugins/condition/criterion/TelemetryCriterion.js b/src/plugins/condition/criterion/TelemetryCriterion.js index 19501f63f2..351f51e06d 100644 --- a/src/plugins/condition/criterion/TelemetryCriterion.js +++ b/src/plugins/condition/criterion/TelemetryCriterion.js @@ -46,15 +46,15 @@ export default class TelemetryCriterion extends EventEmitter { this.metadata = telemetryDomainObjectDefinition.metadata; // this.subscription = null; this.telemetryObjectIdAsString = this.objectAPI.makeKeyString(this.telemetry); - this.on('subscription', this.handleSubscription); - // this.objectAPI.get(this.objectAPI.makeKeyString(this.telemetry)).then((obj) => this.initialize(obj)); + + this.on(`subscription:${this.telemetryObjectIdAsString}`, this.handleSubscription); + this.objectAPI.get(this.telemetryObjectIdAsString).then((obj) => this.initialize(obj)); } - // initialize(obj) { - // this.telemetryObject = obj; - // this.telemetryObjectIdAsString = this.objectAPI.makeKeyString(this.telemetryObject.identifier); - // this.emitEvent('criterionUpdated', this); - // } + initialize(obj) { + this.telemetryObject = obj; + this.emitEvent('criterionUpdated', this); + } formatData(data) { const datum = { From ecf3e19f16414140e0a6b3b7a7d771149e0bdefb Mon Sep 17 00:00:00 2001 From: David Tsay Date: Thu, 19 Mar 2020 20:30:27 -0700 Subject: [PATCH 20/32] remove listener on destroy --- src/plugins/condition/Condition.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/condition/Condition.js b/src/plugins/condition/Condition.js index be4bb982eb..b9c775c959 100644 --- a/src/plugins/condition/Condition.js +++ b/src/plugins/condition/Condition.js @@ -277,6 +277,7 @@ export default class ConditionClass extends EventEmitter { } destroy() { + this.conditionManager.off('broadcastTelemetry', this.handleBroadcastTelemetry, this); if (typeof this.stopObservingForChanges === 'function') { this.stopObservingForChanges(); } From b38a9ad4cef07e9a9a9668248951a9fe2f848a4d Mon Sep 17 00:00:00 2001 From: David Tsay Date: Fri, 20 Mar 2020 10:12:02 -0700 Subject: [PATCH 21/32] exclude default condition when requesting telemetry --- src/plugins/condition/ConditionManager.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/condition/ConditionManager.js b/src/plugins/condition/ConditionManager.js index 69b34b2940..3fb712c77d 100644 --- a/src/plugins/condition/ConditionManager.js +++ b/src/plugins/condition/ConditionManager.js @@ -240,7 +240,9 @@ export default class ConditionManager extends EventEmitter { return this.load().then(() => { const ladConditionResults = this.conditionClassCollection - .filter(condition => !condition.isDefault) + .filter((condition, index) => { + return !this.conditionSetDomainObject.configuration.conditionCollection[index].isDefault + }) .map(condition => condition.requestLADConditionResult()); return Promise.all(ladConditionResults) From cbeb25c583b8871d40837088dc7a2091f7dfb1d4 Mon Sep 17 00:00:00 2001 From: David Tsay Date: Fri, 20 Mar 2020 10:16:02 -0700 Subject: [PATCH 22/32] request telemetry from all conditions if conditions have no criteria (isDefault) then nothing will be requested --- src/plugins/condition/ConditionManager.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/plugins/condition/ConditionManager.js b/src/plugins/condition/ConditionManager.js index 3fb712c77d..1c0c941c2d 100644 --- a/src/plugins/condition/ConditionManager.js +++ b/src/plugins/condition/ConditionManager.js @@ -240,9 +240,6 @@ export default class ConditionManager extends EventEmitter { return this.load().then(() => { const ladConditionResults = this.conditionClassCollection - .filter((condition, index) => { - return !this.conditionSetDomainObject.configuration.conditionCollection[index].isDefault - }) .map(condition => condition.requestLADConditionResult()); return Promise.all(ladConditionResults) From aed5377ad260c6509259367566a0c0b3a07b7458 Mon Sep 17 00:00:00 2001 From: David Tsay Date: Fri, 20 Mar 2020 11:44:05 -0700 Subject: [PATCH 23/32] use existing var instead of recalculating on listener should be off in destroy() --- src/plugins/condition/criterion/TelemetryCriterion.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/plugins/condition/criterion/TelemetryCriterion.js b/src/plugins/condition/criterion/TelemetryCriterion.js index 22f9c72256..ea4a86d459 100644 --- a/src/plugins/condition/criterion/TelemetryCriterion.js +++ b/src/plugins/condition/criterion/TelemetryCriterion.js @@ -45,7 +45,6 @@ export default class TelemetryCriterion extends EventEmitter { this.input = telemetryDomainObjectDefinition.input; this.metadata = telemetryDomainObjectDefinition.metadata; this.telemetryObjectIdAsString = this.objectAPI.makeKeyString(this.telemetry); - this.on(`subscription:${this.telemetryObjectIdAsString}`, this.handleSubscription); this.objectAPI.get(this.telemetryObjectIdAsString).then((obj) => this.initialize(obj)); } @@ -129,7 +128,7 @@ export default class TelemetryCriterion extends EventEmitter { } ); - return this.objectAPI.get(this.objectAPI.makeKeyString(this.telemetry)) + return this.objectAPI.get(this.telemetryObjectIdAsString) .then((obj) => { if (!obj || !this.isValid()) { return this.formatData({}); @@ -148,7 +147,7 @@ export default class TelemetryCriterion extends EventEmitter { } destroy() { - this.on(`subscription:${this.telemetryObjectIdAsString}`, this.handleSubscription); + this.off(`subscription:${this.telemetryObjectIdAsString}`, this.handleSubscription); this.emitEvent('criterionRemoved'); delete this.telemetryObjectIdAsString; delete this.telemetryObject; From d51dd8b7d04ec3945bd08df20f05f0762611d694 Mon Sep 17 00:00:00 2001 From: David Tsay Date: Fri, 20 Mar 2020 15:00:24 -0700 Subject: [PATCH 24/32] fix broken tests --- src/plugins/condition/ConditionManagerSpec.js | 16 +++++++++----- src/plugins/condition/ConditionSpec.js | 22 ++++++++++++++----- .../criterion/TelemetryCriterionSpec.js | 22 ++++--------------- 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/src/plugins/condition/ConditionManagerSpec.js b/src/plugins/condition/ConditionManagerSpec.js index a2e5152702..cc5b12f441 100644 --- a/src/plugins/condition/ConditionManagerSpec.js +++ b/src/plugins/condition/ConditionManagerSpec.js @@ -76,7 +76,7 @@ describe('ConditionManager', () => { beforeEach(function () { mockAngularComponents(); - + mockListener = jasmine.createSpy('mockListener'); loader = {}; loader.promise = new Promise(function (resolve, reject) { loader.resolve = resolve; @@ -84,7 +84,9 @@ describe('ConditionManager', () => { }); mockComposition = jasmine.createSpyObj('compositionCollection', [ - 'load' + 'load', + 'on', + 'off' ]); mockComposition.load.and.callFake(() => { setTimeout(() => { @@ -92,6 +94,8 @@ describe('ConditionManager', () => { }); return loader.promise; }); + mockComposition.on('add', mockListener); + mockComposition.on('remove', mockListener); openmct.composition = jasmine.createSpyObj('compositionAPI', [ 'get' ]); @@ -108,15 +112,15 @@ describe('ConditionManager', () => { openmct.objects.mutate.and.returnValue(function () {}); conditionMgr = new ConditionManager(conditionSetDomainObject, openmct); - mockListener = jasmine.createSpy('mockListener'); conditionMgr.on('conditionSetResultUpdated', mockListener); + conditionMgr.on('broadcastTelemetry', mockListener); }); it('creates a conditionCollection with a default condition', function () { - expect(conditionMgr.conditionSetDomainObject.configuration.conditionCollection.length).toEqual(1); - let defaultConditionId = conditionMgr.conditionClassCollection[0].id; - expect(defaultConditionId).toEqual(mockCondition.id); + expect(conditionMgr.conditionSetDomainObject.configuration.conditionCollection.length).toEqual(1); + let defaultConditionId = conditionMgr.conditionClassCollection[0].id; + expect(defaultConditionId).toEqual(mockCondition.id); }); }); diff --git a/src/plugins/condition/ConditionSpec.js b/src/plugins/condition/ConditionSpec.js index cd8253cf50..d3375eadba 100644 --- a/src/plugins/condition/ConditionSpec.js +++ b/src/plugins/condition/ConditionSpec.js @@ -28,11 +28,19 @@ let openmct = {}, mockListener, testConditionDefinition, testTelemetryObject, - conditionObj; + conditionObj, + conditionManager, + mockBroadcastTelemetry; describe("The condition", function () { beforeEach (() => { + conditionManager = jasmine.createSpyObj('conditionManager', + ['on'] + ); + mockBroadcastTelemetry = jasmine.createSpy('listener'); + conditionManager.on('broadcastTelemetry', mockBroadcastTelemetry); + mockListener = jasmine.createSpy('listener'); testTelemetryObject = { identifier:{ namespace: "", key: "test-object"}, @@ -66,11 +74,14 @@ describe("The condition", function () { testConditionDefinition = { id: '123-456', configuration: { + name: 'mock condition', + output: 'mock output', trigger: TRIGGER.ANY, criteria: [ { + id: '1234-5678-9999-0000', operation: 'equalTo', - input: false, + input: ['0'], metadata: 'value', telemetry: testTelemetryObject.identifier } @@ -80,14 +91,14 @@ describe("The condition", function () { conditionObj = new Condition( testConditionDefinition, - openmct + openmct, + conditionManager ); conditionObj.on('conditionUpdated', mockListener); - }); - it("generates criteria with an id", function () { + it("generates criteria with the correct properties", function () { const testCriterion = testConditionDefinition.configuration.criteria[0]; let criterion = conditionObj.generateCriterion(testCriterion); expect(criterion.id).toBeDefined(); @@ -98,6 +109,7 @@ describe("The condition", function () { }); it("initializes with an id", function () { + console.log(conditionObj); expect(conditionObj.id).toBeDefined(); }); diff --git a/src/plugins/condition/criterion/TelemetryCriterionSpec.js b/src/plugins/condition/criterion/TelemetryCriterionSpec.js index 93ad86e164..a1f6bd1501 100644 --- a/src/plugins/condition/criterion/TelemetryCriterionSpec.js +++ b/src/plugins/condition/criterion/TelemetryCriterionSpec.js @@ -78,7 +78,9 @@ describe("The telemetry criterion", function () { testCriterionDefinition = { id: 'test-criterion-id', - telemetry: openmct.objects.makeKeyString(testTelemetryObject.identifier) + telemetry: openmct.objects.makeKeyString(testTelemetryObject.identifier), + operation: 'lessThan', + metadata: 'sin' }; mockListener = jasmine.createSpy('listener'); @@ -102,12 +104,7 @@ describe("The telemetry criterion", function () { expect(mockListener2).toHaveBeenCalled(); }); - it("subscribes to telemetry providers", function () { - telemetryCriterion.subscribe(); - expect(telemetryCriterion.subscription).toBeDefined(); - }); - - it("emits update event on new data from telemetry providers", function () { + it("updates and emits event on new data from telemetry providers", function () { telemetryCriterion.initialize(testTelemetryObject); spyOn(telemetryCriterion, 'emitEvent').and.callThrough(); telemetryCriterion.handleSubscription({ @@ -115,16 +112,5 @@ describe("The telemetry criterion", function () { utc: 'Hi' }); expect(telemetryCriterion.emitEvent).toHaveBeenCalled(); - expect(mockListener).toHaveBeenCalled(); }); - - it("un-subscribes from telemetry providers", function () { - telemetryCriterion.subscribe(); - expect(telemetryCriterion.subscription).toBeDefined(); - telemetryCriterion.destroy(); - expect(telemetryCriterion.subscription).toBeUndefined(); - expect(telemetryCriterion.telemetryObjectIdAsString).toBeUndefined(); - expect(telemetryCriterion.telemetryObject).toBeUndefined(); - }); - }); From e4a6c211018cff1fb8b6dc5f4155f90e088e61f8 Mon Sep 17 00:00:00 2001 From: David Tsay Date: Fri, 20 Mar 2020 15:08:45 -0700 Subject: [PATCH 25/32] load composition using less code --- src/plugins/condition/ConditionManager.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/plugins/condition/ConditionManager.js b/src/plugins/condition/ConditionManager.js index 1c0c941c2d..e18705bab9 100644 --- a/src/plugins/condition/ConditionManager.js +++ b/src/plugins/condition/ConditionManager.js @@ -34,8 +34,6 @@ export default class ConditionManager extends EventEmitter { this.composition = this.openmct.composition.get(conditionSetDomainObject); this.composition.on('add', this.addTelemetry, this); this.composition.on('remove', this.removeTelemetry, this); - - this.loaded = this.composition.load(); this.subscriptions = {}; this.initialize(); @@ -68,10 +66,6 @@ export default class ConditionManager extends EventEmitter { delete this.subscriptions[id]; } - load() { - return this.loaded; - } - initialize() { this.conditionResults = {}; this.conditionClassCollection = []; @@ -238,7 +232,7 @@ export default class ConditionManager extends EventEmitter { return Promise.resolve([]); } - return this.load().then(() => { + return this.composition.load().then(() => { const ladConditionResults = this.conditionClassCollection .map(condition => condition.requestLADConditionResult()); From 26ffe8efdeb953add671618ac342c888572e889c Mon Sep 17 00:00:00 2001 From: David Tsay <3614296+davetsay@users.noreply.github.com> Date: Mon, 23 Mar 2020 13:05:48 -0700 Subject: [PATCH 26/32] remove comment --- src/plugins/condition/Condition.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/condition/Condition.js b/src/plugins/condition/Condition.js index b9c775c959..23dd342cd2 100644 --- a/src/plugins/condition/Condition.js +++ b/src/plugins/condition/Condition.js @@ -186,7 +186,6 @@ export default class ConditionClass extends EventEmitter { let found = this.findCriterion(criterion.id); if (found) { this.criteria[found.index] = criterion.data; - // this.subscribe(); // TODO nothing is listening to this this.emitEvent('conditionUpdated', { trigger: this.trigger, From f13714e0c43ebd0cfabc2dd4230271bfc271fb6a Mon Sep 17 00:00:00 2001 From: David Tsay Date: Mon, 23 Mar 2020 13:53:19 -0700 Subject: [PATCH 27/32] rename telemetry subscription calls --- src/plugins/condition/ConditionManager.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/plugins/condition/ConditionManager.js b/src/plugins/condition/ConditionManager.js index e18705bab9..3d8b08e941 100644 --- a/src/plugins/condition/ConditionManager.js +++ b/src/plugins/condition/ConditionManager.js @@ -32,8 +32,8 @@ export default class ConditionManager extends EventEmitter { this.timeAPI = this.openmct.time; this.latestTimestamp = {}; this.composition = this.openmct.composition.get(conditionSetDomainObject); - this.composition.on('add', this.addTelemetry, this); - this.composition.on('remove', this.removeTelemetry, this); + this.composition.on('add', this.subscribeToTelemetry, this); + this.composition.on('remove', this.unsubscribeFromTelemetry, this); this.subscriptions = {}; this.initialize(); @@ -42,7 +42,7 @@ export default class ConditionManager extends EventEmitter { }); } - addTelemetry(endpoint) { + subscribeToTelemetry(endpoint) { const id = this.openmct.objects.makeKeyString(endpoint.identifier); if (this.subscriptions[id]) { console.log('subscription already exists'); @@ -55,7 +55,7 @@ export default class ConditionManager extends EventEmitter { ); } - removeTelemetry(endpointIdentifier) { + unsubscribeFromTelemetry(endpointIdentifier) { const id = this.openmct.objects.makeKeyString(endpointIdentifier); if (!this.subscriptions[id]) { console.log('no subscription to remove'); @@ -264,8 +264,8 @@ export default class ConditionManager extends EventEmitter { } destroy() { - this.composition.off('add', this.addTelemetry, this); - this.composition.off('remove', this.removeTelemetry, this); + this.composition.off('add', this.subscribeToTelemetry, this); + this.composition.off('remove', this.unsubscribeFromTelemetry, this); Object.values(this.subscriptions).forEach(unsubscribe => unsubscribe()); this.subscriptions = undefined; From 77b705ecc832e60a3fd02b86e37f3d2f20d01712 Mon Sep 17 00:00:00 2001 From: David Tsay Date: Mon, 23 Mar 2020 15:21:51 -0700 Subject: [PATCH 28/32] add telemetry object back for criterion --- .../condition/criterion/TelemetryCriterion.js | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/plugins/condition/criterion/TelemetryCriterion.js b/src/plugins/condition/criterion/TelemetryCriterion.js index ea4a86d459..82d6cb474d 100644 --- a/src/plugins/condition/criterion/TelemetryCriterion.js +++ b/src/plugins/condition/criterion/TelemetryCriterion.js @@ -44,14 +44,16 @@ export default class TelemetryCriterion extends EventEmitter { this.operation = telemetryDomainObjectDefinition.operation; this.input = telemetryDomainObjectDefinition.input; this.metadata = telemetryDomainObjectDefinition.metadata; - this.telemetryObjectIdAsString = this.objectAPI.makeKeyString(this.telemetry); - this.on(`subscription:${this.telemetryObjectIdAsString}`, this.handleSubscription); - this.objectAPI.get(this.telemetryObjectIdAsString).then((obj) => this.initialize(obj)); + this.telemetryObjectIdAsString = undefined; + this.objectAPI.get(this.objectAPI.makeKeyString(this.telemetry)).then((obj) => this.initialize(obj)); } initialize(obj) { this.telemetryObject = obj; this.telemetryMetaData = this.openmct.telemetry.getMetadata(obj).valueMetadatas; + this.telemetryObjectIdAsString = this.objectAPI.makeKeyString(this.telemetry); + console.log(`subscription:${this.telemetryObjectIdAsString}`); + this.on(`subscription:${this.telemetryObjectIdAsString}`, this.handleSubscription); this.emitEvent('criterionUpdated', this); } @@ -128,22 +130,20 @@ export default class TelemetryCriterion extends EventEmitter { } ); - return this.objectAPI.get(this.telemetryObjectIdAsString) - .then((obj) => { - if (!obj || !this.isValid()) { - return this.formatData({}); - } - return this.telemetryAPI.request( - obj, - options - ).then(results => { - const latestDatum = results.length ? results[results.length - 1] : {}; - return { - id: this.id, - data: this.formatData(latestDatum) - }; - }); - }); + if (!this.isValid()) { + return this.formatData({}); + } + + 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() { From d42bd444858afe0381bf3e4108c9e2486d875aaf Mon Sep 17 00:00:00 2001 From: David Tsay Date: Mon, 23 Mar 2020 15:24:24 -0700 Subject: [PATCH 29/32] remove logging statement --- src/plugins/condition/criterion/TelemetryCriterion.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/condition/criterion/TelemetryCriterion.js b/src/plugins/condition/criterion/TelemetryCriterion.js index 82d6cb474d..bfe6954728 100644 --- a/src/plugins/condition/criterion/TelemetryCriterion.js +++ b/src/plugins/condition/criterion/TelemetryCriterion.js @@ -52,7 +52,6 @@ export default class TelemetryCriterion extends EventEmitter { this.telemetryObject = obj; this.telemetryMetaData = this.openmct.telemetry.getMetadata(obj).valueMetadatas; this.telemetryObjectIdAsString = this.objectAPI.makeKeyString(this.telemetry); - console.log(`subscription:${this.telemetryObjectIdAsString}`); this.on(`subscription:${this.telemetryObjectIdAsString}`, this.handleSubscription); this.emitEvent('criterionUpdated', this); } From a5a197680d0aee68693a252b90df8455d1188a0b Mon Sep 17 00:00:00 2001 From: David Tsay Date: Mon, 23 Mar 2020 15:58:01 -0700 Subject: [PATCH 30/32] remove debug --- src/plugins/condition/ConditionManager.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/plugins/condition/ConditionManager.js b/src/plugins/condition/ConditionManager.js index 3d8b08e941..4d761b0667 100644 --- a/src/plugins/condition/ConditionManager.js +++ b/src/plugins/condition/ConditionManager.js @@ -241,8 +241,6 @@ export default class ConditionManager extends EventEmitter { results.forEach(resultObj => { this.updateConditionResults(resultObj); }); const currentCondition = this.getCurrentCondition(); - // uncomment to see output of lad request (before subscriptions kick in) - // console.log(obj.configuration.output); return Object.assign( { output: currentCondition.configuration.output, From 78487a48f687cf255b2d3c678c5b60fc52e408e7 Mon Sep 17 00:00:00 2001 From: David Tsay Date: Mon, 23 Mar 2020 16:04:37 -0700 Subject: [PATCH 31/32] restrict conditionManager instances to one per domainObject --- .../ConditionSetTelemetryProvider.js | 54 +++++++++++-------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/src/plugins/condition/ConditionSetTelemetryProvider.js b/src/plugins/condition/ConditionSetTelemetryProvider.js index 6706cb160a..052406be0d 100644 --- a/src/plugins/condition/ConditionSetTelemetryProvider.js +++ b/src/plugins/condition/ConditionSetTelemetryProvider.js @@ -25,6 +25,7 @@ import ConditionManager from './ConditionManager' export default class ConditionSetTelemetryProvider { constructor(openmct) { this.openmct = openmct; + this.conditionManagerPool = {}; } isTelemetryObject(domainObject) { @@ -39,36 +40,45 @@ export default class ConditionSetTelemetryProvider { return domainObject.type === 'conditionSet'; } - request(domainObject, options) { - let conditionManager = options.conditionManager; - let newConditionManager = false; - if (!conditionManager) { - newConditionManager = true; - conditionManager = new ConditionManager(domainObject, this.openmct); - } + request(domainObject) { + let conditionManager = this.getConditionManager(domainObject); return conditionManager.requestLADConditionSetOutput() .then(latestOutput => { - if (newConditionManager) { - conditionManager.destroy(); - conditionManager = undefined; - } return latestOutput ? [latestOutput] : []; }); } - subscribe(domainObject, callback, options) { - let conditionManager = options.conditionManager; - if (!conditionManager) { - conditionManager = new ConditionManager(domainObject, this.openmct); - conditionManager.on('conditionSetResultUpdated', callback); - return function unsubscribe() { - conditionManager.off('conditionSetResultUpdated'); - conditionManager.destroy(); - conditionManager = undefined; - }; - } + subscribe(domainObject, callback) { + let conditionManager = this.getConditionManager(domainObject); conditionManager.on('conditionSetResultUpdated', callback); + + return this.destroyConditionManager.bind(this, this.openmct.objects.makeKeyString(domainObject.identifier)); + } + + /** + * returns conditionManager instance for corresponding domain object + * creates the instance if it is not yet created + * @private + */ + getConditionManager(domainObject) { + const id = this.openmct.objects.makeKeyString(domainObject.identifier); + + if (!this.conditionManagerPool[id]) { + this.conditionManagerPool[id] = new ConditionManager(domainObject, this.openmct); + } + + return this.conditionManagerPool[id]; + } + + /** + * cleans up and destroys conditionManager instance for corresponding domain object id + * can be called manually for views that only request but do not subscribe to data + */ + destroyConditionManager(id) { + this.conditionManagerPool[id].off('conditionSetResultUpdated'); + this.conditionManagerPool[id].destroy(); + delete this.conditionManagerPool[id]; } } From 437e8a0263fad8e5b8320be062abf07c0af0c5fe Mon Sep 17 00:00:00 2001 From: David Tsay Date: Tue, 24 Mar 2020 11:15:58 -0700 Subject: [PATCH 32/32] always load composition --- src/plugins/condition/ConditionManager.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/condition/ConditionManager.js b/src/plugins/condition/ConditionManager.js index 4d761b0667..c401e6610d 100644 --- a/src/plugins/condition/ConditionManager.js +++ b/src/plugins/condition/ConditionManager.js @@ -34,6 +34,7 @@ export default class ConditionManager extends EventEmitter { this.composition = this.openmct.composition.get(conditionSetDomainObject); this.composition.on('add', this.subscribeToTelemetry, this); this.composition.on('remove', this.unsubscribeFromTelemetry, this); + this.compositionLoad = this.composition.load(); this.subscriptions = {}; this.initialize(); @@ -232,7 +233,7 @@ export default class ConditionManager extends EventEmitter { return Promise.resolve([]); } - return this.composition.load().then(() => { + return this.compositionLoad.then(() => { const ladConditionResults = this.conditionClassCollection .map(condition => condition.requestLADConditionResult());