mirror of
https://github.com/nasa/openmct.git
synced 2025-05-10 20:43:00 +00:00
* Bump d3-selection from 1.3.2 to 3.0.0 Bumps [d3-selection](https://github.com/d3/d3-selection) from 1.3.2 to 3.0.0. - [Release notes](https://github.com/d3/d3-selection/releases) - [Commits](https://github.com/d3/d3-selection/compare/v1.3.2...v3.0.0) --- updated-dependencies: - dependency-name: d3-selection dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * Remove snapshot * Fix imagery filter slider drag in flexible layouts (#5326) (#5350) * Dont' mutate a stacked plot unless its user initiated (#5357) * Port grid icons and imagery test to release 2.0.5 from master (#5360) * Port grid icons to release 2.0.5 from master * Port imagery test to release/2.0.5 * Restrict timestrip composition to time based plots, plans and imagery (#5161) * Restrict timestrip composition to time based plots, plans and imagery * Adds unit tests for timeline composition policy * Addresses review comments Improves tests * Reuse test objects Co-authored-by: Jamie V <jamie.j.vigliotta@nasa.gov> * Include objectStyles reference to conditionSetIdentifier in imports (#5354) * Include objectStyles reference to conditionSetIdentifier in imports * Add tests for export * Refactored some code and removed console log * Remove workarounds for chrome 'scrollTop' issue (#5375) * Fix naming of method (#5368) * Imagery View does not discard old images when they fall out of bounds (#5351) * change to using telemetry collection * fix tests * added more unit tests * Cherrypicked commits (#5390) Co-authored-by: unlikelyzero <jchill2@gmail.com> * [Timer] Update 3dot menu actions appropriately (#5387) * Call `removeAllListeners()` after emit * Manually show/hide actions if within a view * remove sneaky `console.log()` * Add Timer e2e test * Add to comments * Avoid hard waits in Timer e2e test - Assert against timer view state instead of menu options * Let's also test actions from the Timer view * 5391 Add preview and drag support to Grand Search (#5394) * add preview and drag actions * added unit test, simplified remove action * do not hide search results in preview mode when clicking outside search results * add semantic aria labels to enable e2e tests * readd preview * add e2e test * remove commented out url * add percy snapshot and add search to ci * make percy stuff work * linting * fix percy again * move percy snapshots to a visual test * added separate visual test and changed test to fixtures * fix fixtures path * addressing review comments * 5361 tags not persisting locally (#5408) * fixed typo * remove unneeded lookup * fix tags adding and deleting * more reliable way to remove tags * break tests up for parallel execution * fixed notebook tagging test * enable e2e tests * made schedule index comment more clear and fix uppercase/lowercase issue * address e2e changes * add unit test to bump coverage * fix typo * need to check on annotation creation if provider exists or not * added fixtures * undo silly couchdb commit * Plot progress bar fix for 2.0.5 (#5386) * Add .bind(this) to stopLoading() in loadMoreData() * Replace load spinner with progress bar for plots * Add loading delay prop to swg * fix linting errors * match load order * Update accessibility * Add Math.max to timeout to handle negative inputs * Moved math.max to load delay variable * Add loading fix for stacked plots * Move loadingUpdate func into plot item for update * Merge conflict resolve * Check if delay is 0 and send, put post in a func * Put obj directly to model, removed computed prop * Lint fix * Fix template where legend was not displayed * Remove commented out template * Fixed failing test Co-authored-by: unlikelyzero <jchill2@gmail.com> * Make plans non editable. (#5377) * Make plans non editable. * Add unit test for fix * [CouchDB] Better determination of indicator status (#5415) * Add unknown state, remove maintenance state * Handle all CouchDB status codes - Set unknown status if we receive an unhandled code * Include status code in error messages * SharedWorker can send unknown status * Add test for unknown status * Gauge fixes for Firefox and units display (#5369) * Closes #5323, #5325. Parent branch is release/2.0.5. - Significant work refactoring SVG markup and CSS for dial gauge; - Fixed missing `v-if` to control display of units for #5325; - Fixed bad `.length` test for limit properties; * Closes #5323, #5325 - Add 'value out of range' indicator * Closes #5323, #5325 - More accurate element naming; - Fix cross-browser problems with current value display in dial gauge; - Refinements to "out of range" indicator approach; - Fixed size of "Amplitude" input in Sine Wave Generator; * Closes #5323, #5325 - Styles and stubbed in code to support needle meter type; * Closes #5323, #5325 - Stubbed in markup and CSS for needle-style meter; * Closes #5323, #5325 - Fixed missing `js-*` classes that were failing npm run test; * Closes #5323, #5325 - Fix to not display meter value bar unless a data value is expected; * Addressing PR comments - Renamed method for clarity; - Added null value check in method `valueExpected`; * [Static Root] Return leafValue if null/undefined/false (#5416) * Return leafValue if null/undefined/false * Added a null to the test json * Show a better default poll question (#5425) * 5361 Tags not persisting when several notebook entries are created at once (#5428) * add end to end test to catch multiple entry errors * click expansion triangle instead * fix race condition between annotation creation and mutation * make sure notebook tags run in e2e * address PR comments * Handle missing objects gracefully (#5399) * Handle missing object errors for display layouts * Handle missing object errors for Overlay Plots * Add check for this.config * Add try/catch statement & check if obj is missing * Changed console.error to console.warn * Lint fix * Fix for this.metadata.value is undefined * Add e2e test * Update comment text * Add reload check and @private, verify console.warn * Redid assignment and metadata check * Fix typo * Changed assignment and metadata check * Redid checks for isMissing(object) * Lint fix * Backmerge e2e code coverage changes and fixes into release/2.0.5 (#5431) * [Telemetry Collections] Respect "Latest" Strategy Option (#5421) * Respect latest strategy in Telemetry Collections to limit potential memory growth. * fix sourcemaps (#5373) Co-authored-by: John Hill <john.c.hill@nasa.gov> * Debounce status summary (#5448) Co-authored-by: John Hill <john.c.hill@nasa.gov> * No gauge (#5451) * Installed gauge plugin by default * Make gauge part of standard install in e2e suite and add restrictednotebook Co-authored-by: Andrew Henry <akhenry@gmail.com> * [CouchDB] Always subscribe to the CouchDB changes feed (#5434) * Add unknown state, remove maintenance state * Handle all CouchDB status codes - Set unknown status if we receive an unhandled code * Include status code in error messages * SharedWorker can send unknown status * Add test for unknown status * Always subscribe to CouchDB changes feed - Always subscribe to the CouchDB changes feed, even if there are no observable objects, since we are also checking the status of CouchDB via this feed. * Update indicator status if not using SharedWorker * Start listening to changes feed on first request * fix test * adjust test to hopefully avoid race condition * lint Co-authored-by: John Hill <john.c.hill@nasa.gov> Co-authored-by: Andrew Henry <akhenry@gmail.com> Co-authored-by: Scott Bell <scott@traclabs.com> * Fix for Fault Management Visual Bugs (#5376) * Closes #5365 * General visual improvements Co-authored-by: Charles Hacskaylo <charlesh88@gmail.com> Co-authored-by: Andrew Henry <akhenry@gmail.com> * fix pathing (#5452) Co-authored-by: Jesse Mazzella <ozyx@users.noreply.github.com> * [Static Root] Static Root Plugin not loading (#5455) * Log if hitting falsy leafValue * Add some logging * Remove logs and specify null/undefined Co-authored-by: Jesse Mazzella <ozyx@users.noreply.github.com> * Allow endpoints with a single enum metadata value in Bar/Line graphs (#5443) * If there is only 1 metadata value, set yKey to none. Also, fix bug for determining the name of a metadata value * Update tests for enum metadata values Co-authored-by: John Hill <john.c.hill@nasa.gov> Co-authored-by: Andrew Henry <akhenry@gmail.com> * [Remote Clock] Wait for first tick and recalculate historical request bounds (#5433) * Updated to ES6 class * added request intercept functionality to telemetry api, added a request interceptor for remote clock * add remoteClock e2e test stub Co-authored-by: Jamie V <jamie.j.vigliotta@nasa.gov> Co-authored-by: Andrew Henry <akhenry@gmail.com> * Fix for missing object for LADTableSet (#5458) * Handle missing object errors for display layouts Co-authored-by: Andrew Henry <akhenry@gmail.com> * removing the call for default import now that TelemetryAPI is an ES6 class (#5461) * [Remote Clock] Fix requestInterceptor typo (#5462) * Fix typo in telemetry request interceptor Co-authored-by: Jamie V <jamie.j.vigliotta@nasa.gov> Co-authored-by: Andrew Henry <akhenry@gmail.com> * Lock model (#5457) * Lock event Model to prevent reactification * de-reactify all the things * Make API properties writable to allow test mocks to override them * Fix merge conflict * Added plot interceptor for missing series config (#5422) Co-authored-by: Andrew Henry <akhenry@gmail.com> Co-authored-by: Shefali Joshi <simplyrender@gmail.com> * Remove performance marks (#5465) * Remove performance marks * Retain performance mark in view large. It doesn't happen very often and it's needed for an automated performance test * Use timeKey for time comparison (#5471) * Fix couchdb no response (#5474) * Update the creation date only when the document is created for the first time * If there is no response from a bulk get, couch db has issues * Check the response - if it's null, don't apply interceptors * Fix shelved alarms (#5479) * Fix the logic around shelved alarms * Remove application router listener * Release 2.0.5 UI and Gauge fixes (#5470) * Various UI fixes - Tweak to Gauge properties form for clarity and usability. - Fix Gauge 'dial' type not obeying "Show units" property setting, closes #5325. - Tweaks to Operator Status UI label and layout for clarity. - Changed name and description of Graph object for clarity and consistency. - Fixed CSS classing that was coloring Export menu items text incorrectly. - Fixed icon-to-text vertical alignment in `.c-object-label`. - Fix for broken layout in imagery local controls (brightness, layers, magnification). Co-authored-by: Andrew Henry <akhenry@gmail.com> * Stacked plot interceptor rename (#5468) * Rename stacked plot interceptor and move to folder Co-authored-by: Andrew Henry <akhenry@gmail.com> * Clear data when time bounds are changed (#5482) * Clear data when time bounds are changed Also react to clear data action Ensure that the yKey is set to 'none' if there is no range with array Values * Refactor trace updates to a method * get rid of root (#5483) * Do not pass onPartialResponse option on to upstream telemetry (#5486) * Fix all of the e2e tests (#5477) * Fix timer test * be explicit about the warnings text * add full suite to CI to enable CircleCI Checks * add back in devtool=false for CI env so firefox tests run * add framework suite * Don't install webpack HMR in CI * Fix playwright version installs * exclude HMR if running tests in any environment - use NODE_ENV=TEST to exclude webpack HMR - deparameterize some of the playwright configs * use lower-case 'test' * timer hover fix * conditionally skip for firefox due to missing console events * increase timeouts to give time for mutation * no need to close save banner * remove devtool setting * revert * update snapshots * disable video to save some resources * use one worker * more timeouts :) * Remove `browser.close()` and `page.close()` as it was breaking other tests * Remove unnecessary awaits and fix func call syntax * Fix image reset test * fix restrictedNotebook tests * revert playwright-ci.config settings * increase timeout for polling imagery test * remove unnecessary waits * disable notebook lock test for chrome-beta as its unreliable - remove some unnecessary 'wait for save banner' logic - remove unused await - mark imagery test as slow in chrome-beta * LINT!! *shakes fist* * don't run full e2e suite per commit * disable video in all configs * add flakey zoom comment * exclude webpack HMR in non-development modes Co-authored-by: Jesse Mazzella <jesse.d.mazzella@nasa.gov> Co-authored-by: Jesse Mazzella <ozyx@users.noreply.github.com> * lint fix Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Joshi <simplyrender@gmail.com> Co-authored-by: Jesse Mazzella <ozyx@users.noreply.github.com> Co-authored-by: Jamie V <jamie.j.vigliotta@nasa.gov> Co-authored-by: Andrew Henry <akhenry@gmail.com> Co-authored-by: Scott Bell <scott@traclabs.com> Co-authored-by: unlikelyzero <jchill2@gmail.com> Co-authored-by: Alize Nguyen <alizenguyen@gmail.com> Co-authored-by: Charles Hacskaylo <charlesh88@gmail.com> Co-authored-by: Khalid Adil <khalidadil29@gmail.com> Co-authored-by: rukmini-bose <48999852+rukmini-bose@users.noreply.github.com> Co-authored-by: Jesse Mazzella <jesse.d.mazzella@nasa.gov>
455 lines
17 KiB
JavaScript
455 lines
17 KiB
JavaScript
/*****************************************************************************
|
|
* Open MCT, Copyright (c) 2014-2022, United States Government
|
|
* as represented by the Administrator of the National Aeronautics and Space
|
|
* Administration. All rights reserved.
|
|
*
|
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
* Open MCT includes source code licensed under additional open source
|
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
|
* this source code distribution or the Licensing information page available
|
|
* at runtime from the About dialog for additional information.
|
|
*****************************************************************************/
|
|
|
|
import Condition from "./Condition";
|
|
import { getLatestTimestamp } from './utils/time';
|
|
import { v4 as uuid } from 'uuid';
|
|
import EventEmitter from 'EventEmitter';
|
|
|
|
export default class ConditionManager extends EventEmitter {
|
|
constructor(conditionSetDomainObject, openmct) {
|
|
super();
|
|
this.openmct = openmct;
|
|
this.conditionSetDomainObject = conditionSetDomainObject;
|
|
this.timeSystems = this.openmct.time.getAllTimeSystems();
|
|
this.composition = this.openmct.composition.get(conditionSetDomainObject);
|
|
this.composition.on('add', this.subscribeToTelemetry, this);
|
|
this.composition.on('remove', this.unsubscribeFromTelemetry, this);
|
|
|
|
this.shouldEvaluateNewTelemetry = this.shouldEvaluateNewTelemetry.bind(this);
|
|
|
|
this.compositionLoad = this.composition.load();
|
|
this.subscriptions = {};
|
|
this.telemetryObjects = {};
|
|
this.testData = {
|
|
conditionTestInputs: this.conditionSetDomainObject.configuration.conditionTestData,
|
|
applied: false
|
|
};
|
|
this.initialize();
|
|
|
|
this.stopObservingForChanges = this.openmct.objects.observe(this.conditionSetDomainObject, '*', (newDomainObject) => {
|
|
this.conditionSetDomainObject = newDomainObject;
|
|
});
|
|
|
|
}
|
|
|
|
subscribeToTelemetry(endpoint) {
|
|
const id = this.openmct.objects.makeKeyString(endpoint.identifier);
|
|
if (this.subscriptions[id]) {
|
|
console.log('subscription already exists');
|
|
|
|
return;
|
|
}
|
|
|
|
const metadata = this.openmct.telemetry.getMetadata(endpoint);
|
|
|
|
this.telemetryObjects[id] = Object.assign({}, endpoint, {telemetryMetaData: metadata ? metadata.valueMetadatas : []});
|
|
this.subscriptions[id] = this.openmct.telemetry.subscribe(
|
|
endpoint,
|
|
this.telemetryReceived.bind(this, endpoint)
|
|
);
|
|
this.updateConditionTelemetryObjects();
|
|
}
|
|
|
|
unsubscribeFromTelemetry(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];
|
|
delete this.telemetryObjects[id];
|
|
this.removeConditionTelemetryObjects();
|
|
|
|
//force re-computation of condition set result as we might be in a state where
|
|
// there is no telemetry datum coming in for a while or at all.
|
|
let latestTimestamp = getLatestTimestamp(
|
|
{},
|
|
{},
|
|
this.timeSystems,
|
|
this.openmct.time.timeSystem()
|
|
);
|
|
this.updateConditionResults({id: id});
|
|
this.updateCurrentCondition(latestTimestamp);
|
|
}
|
|
|
|
initialize() {
|
|
this.conditions = [];
|
|
if (this.conditionSetDomainObject.configuration.conditionCollection.length) {
|
|
this.conditionSetDomainObject.configuration.conditionCollection.forEach((conditionConfiguration, index) => {
|
|
this.initCondition(conditionConfiguration, index);
|
|
});
|
|
}
|
|
}
|
|
|
|
updateConditionTelemetryObjects() {
|
|
this.conditions.forEach((condition) => {
|
|
condition.updateTelemetryObjects();
|
|
let index = this.conditionSetDomainObject.configuration.conditionCollection.findIndex(item => item.id === condition.id);
|
|
if (index > -1) {
|
|
//Only assign the summary, don't mutate the domain object
|
|
this.conditionSetDomainObject.configuration.conditionCollection[index].summary = this.updateConditionDescription(condition);
|
|
}
|
|
});
|
|
}
|
|
|
|
removeConditionTelemetryObjects() {
|
|
let conditionsChanged = false;
|
|
this.conditionSetDomainObject.configuration.conditionCollection.forEach((conditionConfiguration, conditionIndex) => {
|
|
let conditionChanged = false;
|
|
conditionConfiguration.configuration.criteria.forEach((criterion, index) => {
|
|
const isAnyAllTelemetry = criterion.telemetry && (criterion.telemetry === 'any' || criterion.telemetry === 'all');
|
|
if (!isAnyAllTelemetry) {
|
|
const found = Object.values(this.telemetryObjects).find((telemetryObject) => {
|
|
return this.openmct.objects.areIdsEqual(telemetryObject.identifier, criterion.telemetry);
|
|
});
|
|
if (!found) {
|
|
criterion.telemetry = '';
|
|
criterion.metadata = '';
|
|
criterion.input = [];
|
|
criterion.operation = '';
|
|
conditionChanged = true;
|
|
}
|
|
} else {
|
|
conditionChanged = true;
|
|
}
|
|
});
|
|
if (conditionChanged) {
|
|
this.updateCondition(conditionConfiguration, conditionIndex);
|
|
conditionsChanged = true;
|
|
}
|
|
});
|
|
if (conditionsChanged) {
|
|
this.persistConditions();
|
|
}
|
|
}
|
|
|
|
updateConditionDescription(condition) {
|
|
condition.updateDescription();
|
|
|
|
return condition.summary;
|
|
}
|
|
|
|
updateCondition(conditionConfiguration) {
|
|
let condition = this.findConditionById(conditionConfiguration.id);
|
|
if (condition) {
|
|
condition.update(conditionConfiguration);
|
|
conditionConfiguration.summary = this.updateConditionDescription(condition);
|
|
}
|
|
|
|
let index = this.conditionSetDomainObject.configuration.conditionCollection.findIndex(item => item.id === conditionConfiguration.id);
|
|
if (index > -1) {
|
|
this.conditionSetDomainObject.configuration.conditionCollection[index] = conditionConfiguration;
|
|
this.persistConditions();
|
|
}
|
|
}
|
|
|
|
initCondition(conditionConfiguration, index) {
|
|
let condition = new Condition(conditionConfiguration, this.openmct, this);
|
|
conditionConfiguration.summary = this.updateConditionDescription(condition);
|
|
|
|
if (index !== undefined) {
|
|
this.conditions.splice(index + 1, 0, condition);
|
|
} else {
|
|
this.conditions.unshift(condition);
|
|
}
|
|
}
|
|
|
|
createCondition(conditionConfiguration) {
|
|
let conditionObj;
|
|
if (conditionConfiguration) {
|
|
conditionObj = {
|
|
...conditionConfiguration,
|
|
id: uuid(),
|
|
configuration: {
|
|
...conditionConfiguration.configuration,
|
|
name: `Copy of ${conditionConfiguration.configuration.name}`
|
|
}
|
|
};
|
|
} else {
|
|
conditionObj = {
|
|
id: uuid(),
|
|
configuration: {
|
|
name: 'Unnamed Condition',
|
|
output: 'false',
|
|
trigger: 'all',
|
|
criteria: [{
|
|
id: uuid(),
|
|
telemetry: '',
|
|
operation: '',
|
|
input: [],
|
|
metadata: ''
|
|
}]
|
|
},
|
|
summary: ''
|
|
};
|
|
}
|
|
|
|
return conditionObj;
|
|
}
|
|
|
|
addCondition() {
|
|
this.createAndSaveCondition();
|
|
}
|
|
|
|
cloneCondition(conditionConfiguration, index) {
|
|
let clonedConfig = JSON.parse(JSON.stringify(conditionConfiguration));
|
|
clonedConfig.configuration.criteria.forEach((criterion) => criterion.id = uuid());
|
|
this.createAndSaveCondition(index, clonedConfig);
|
|
}
|
|
|
|
createAndSaveCondition(index, conditionConfiguration) {
|
|
const newCondition = this.createCondition(conditionConfiguration);
|
|
if (index !== undefined) {
|
|
this.conditionSetDomainObject.configuration.conditionCollection.splice(index + 1, 0, newCondition);
|
|
} else {
|
|
this.conditionSetDomainObject.configuration.conditionCollection.unshift(newCondition);
|
|
}
|
|
|
|
this.initCondition(newCondition, index);
|
|
this.persistConditions();
|
|
}
|
|
|
|
removeCondition(id) {
|
|
let index = this.conditions.findIndex(item => item.id === id);
|
|
if (index > -1) {
|
|
this.conditions[index].destroy();
|
|
this.conditions.splice(index, 1);
|
|
}
|
|
|
|
let conditionCollectionIndex = this.conditionSetDomainObject.configuration.conditionCollection.findIndex(item => item.id === id);
|
|
if (conditionCollectionIndex > -1) {
|
|
this.conditionSetDomainObject.configuration.conditionCollection.splice(conditionCollectionIndex, 1);
|
|
this.persistConditions();
|
|
}
|
|
}
|
|
|
|
findConditionById(id) {
|
|
return this.conditions.find(condition => condition.id === id);
|
|
}
|
|
|
|
reorderConditions(reorderPlan) {
|
|
let oldConditions = Array.from(this.conditionSetDomainObject.configuration.conditionCollection);
|
|
let newCollection = [];
|
|
reorderPlan.forEach((reorderEvent) => {
|
|
let item = oldConditions[reorderEvent.oldIndex];
|
|
newCollection.push(item);
|
|
});
|
|
this.conditionSetDomainObject.configuration.conditionCollection = newCollection;
|
|
this.persistConditions();
|
|
}
|
|
|
|
getCurrentCondition() {
|
|
const conditionCollection = this.conditionSetDomainObject.configuration.conditionCollection;
|
|
let currentCondition = conditionCollection[conditionCollection.length - 1];
|
|
|
|
for (let i = 0; i < conditionCollection.length - 1; i++) {
|
|
const condition = this.findConditionById(conditionCollection[i].id);
|
|
if (condition.result) {
|
|
//first condition to be true wins
|
|
currentCondition = conditionCollection[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
return currentCondition;
|
|
}
|
|
|
|
getCurrentConditionLAD(conditionResults) {
|
|
const conditionCollection = this.conditionSetDomainObject.configuration.conditionCollection;
|
|
let currentCondition = conditionCollection[conditionCollection.length - 1];
|
|
|
|
for (let i = 0; i < conditionCollection.length - 1; i++) {
|
|
if (conditionResults[conditionCollection[i].id]) {
|
|
//first condition to be true wins
|
|
currentCondition = conditionCollection[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
return currentCondition;
|
|
}
|
|
|
|
requestLADConditionSetOutput(options) {
|
|
if (!this.conditions.length) {
|
|
return Promise.resolve([]);
|
|
}
|
|
|
|
return this.compositionLoad.then(() => {
|
|
let latestTimestamp;
|
|
let conditionResults = {};
|
|
let nextLegOptions = {...options};
|
|
delete nextLegOptions.onPartialResponse;
|
|
|
|
const conditionRequests = this.conditions
|
|
.map(condition => condition.requestLADConditionResult(nextLegOptions));
|
|
|
|
return Promise.all(conditionRequests)
|
|
.then((results) => {
|
|
results.forEach(resultObj => {
|
|
const { id, data, data: { result } } = resultObj;
|
|
if (this.findConditionById(id)) {
|
|
conditionResults[id] = Boolean(result);
|
|
}
|
|
|
|
latestTimestamp = getLatestTimestamp(
|
|
latestTimestamp,
|
|
data,
|
|
this.timeSystems,
|
|
this.openmct.time.timeSystem()
|
|
);
|
|
});
|
|
|
|
if (!Object.values(latestTimestamp).some(timeSystem => timeSystem)) {
|
|
return [];
|
|
}
|
|
|
|
const currentCondition = this.getCurrentConditionLAD(conditionResults);
|
|
const currentOutput = Object.assign(
|
|
{
|
|
output: currentCondition.configuration.output,
|
|
id: this.conditionSetDomainObject.identifier,
|
|
conditionId: currentCondition.id
|
|
},
|
|
latestTimestamp
|
|
);
|
|
|
|
return [currentOutput];
|
|
});
|
|
});
|
|
}
|
|
|
|
isTelemetryUsed(endpoint) {
|
|
const id = this.openmct.objects.makeKeyString(endpoint.identifier);
|
|
|
|
for (let condition of this.conditions) {
|
|
if (condition.isTelemetryUsed(id)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
shouldEvaluateNewTelemetry(currentTimestamp) {
|
|
return this.openmct.time.bounds().end >= currentTimestamp;
|
|
}
|
|
|
|
telemetryReceived(endpoint, datum) {
|
|
if (!this.isTelemetryUsed(endpoint)) {
|
|
return;
|
|
}
|
|
|
|
const normalizedDatum = this.createNormalizedDatum(datum, endpoint);
|
|
const timeSystemKey = this.openmct.time.timeSystem().key;
|
|
let timestamp = {};
|
|
const currentTimestamp = normalizedDatum[timeSystemKey];
|
|
timestamp[timeSystemKey] = currentTimestamp;
|
|
if (this.shouldEvaluateNewTelemetry(currentTimestamp)) {
|
|
this.updateConditionResults(normalizedDatum);
|
|
this.updateCurrentCondition(timestamp);
|
|
}
|
|
}
|
|
|
|
updateConditionResults(normalizedDatum) {
|
|
//We want to stop when the first condition evaluates to true.
|
|
this.conditions.some((condition) => {
|
|
condition.updateResult(normalizedDatum);
|
|
|
|
return condition.result === true;
|
|
});
|
|
}
|
|
|
|
updateCurrentCondition(timestamp) {
|
|
const currentCondition = this.getCurrentCondition();
|
|
|
|
this.emit('conditionSetResultUpdated',
|
|
Object.assign(
|
|
{
|
|
output: currentCondition.configuration.output,
|
|
id: this.conditionSetDomainObject.identifier,
|
|
conditionId: currentCondition.id
|
|
},
|
|
timestamp
|
|
)
|
|
);
|
|
}
|
|
|
|
getTestData(metadatum) {
|
|
let data = undefined;
|
|
if (this.testData.applied) {
|
|
const found = this.testData.conditionTestInputs.find((testInput) => (testInput.metadata === metadatum.source));
|
|
if (found) {
|
|
data = found.value;
|
|
}
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
createNormalizedDatum(telemetryDatum, endpoint) {
|
|
const id = this.openmct.objects.makeKeyString(endpoint.identifier);
|
|
const metadata = this.openmct.telemetry.getMetadata(endpoint).valueMetadatas;
|
|
|
|
const normalizedDatum = Object.values(metadata).reduce((datum, metadatum) => {
|
|
const testValue = this.getTestData(metadatum);
|
|
const formatter = this.openmct.telemetry.getValueFormatter(metadatum);
|
|
datum[metadatum.key] = testValue !== undefined ? formatter.parse(testValue) : formatter.parse(telemetryDatum[metadatum.source]);
|
|
|
|
return datum;
|
|
}, {});
|
|
|
|
normalizedDatum.id = id;
|
|
|
|
return normalizedDatum;
|
|
}
|
|
|
|
updateTestData(testData) {
|
|
if (!_.isEqual(testData, this.testData)) {
|
|
this.testData = testData;
|
|
this.openmct.objects.mutate(this.conditionSetDomainObject, 'configuration.conditionTestData', this.testData.conditionTestInputs);
|
|
}
|
|
}
|
|
|
|
persistConditions() {
|
|
this.openmct.objects.mutate(this.conditionSetDomainObject, 'configuration.conditionCollection', this.conditionSetDomainObject.configuration.conditionCollection);
|
|
}
|
|
|
|
destroy() {
|
|
this.composition.off('add', this.subscribeToTelemetry, this);
|
|
this.composition.off('remove', this.unsubscribeFromTelemetry, this);
|
|
Object.values(this.subscriptions).forEach(unsubscribe => unsubscribe());
|
|
delete this.subscriptions;
|
|
|
|
if (this.stopObservingForChanges) {
|
|
this.stopObservingForChanges();
|
|
}
|
|
|
|
this.conditions.forEach((condition) => {
|
|
condition.destroy();
|
|
});
|
|
}
|
|
}
|