From 395436a361b75ba5a33bd31e6cdb6fe0beede2fc Mon Sep 17 00:00:00 2001 From: Scott Bell Date: Wed, 9 Oct 2024 09:32:44 +0200 Subject: [PATCH] works --- src/api/telemetry/TelemetryCollection.js | 19 ------- src/plugins/comps/CompsManager.js | 53 +++++++++++++------- src/plugins/comps/CompsMathWorker.js | 39 +++++++++++--- src/plugins/comps/CompsMetadataProvider.js | 1 + src/plugins/comps/CompsTelemetryProvider.js | 7 +-- src/plugins/comps/components/CompsView.vue | 42 ++++++++++++++++ src/plugins/plot/configuration/PlotSeries.js | 8 ++- 7 files changed, 121 insertions(+), 48 deletions(-) diff --git a/src/api/telemetry/TelemetryCollection.js b/src/api/telemetry/TelemetryCollection.js index addfa008f1..d3999753c8 100644 --- a/src/api/telemetry/TelemetryCollection.js +++ b/src/api/telemetry/TelemetryCollection.js @@ -93,9 +93,6 @@ export default class TelemetryCollection extends EventEmitter { if (this.options.end) { this.lastBounds.end = this.options.end; } - console.debug( - `🫙 Bounds for collection are start ${new Date(this.lastBounds.start).toISOString()} and end ${new Date(this.lastBounds.end).toISOString()}` - ); this._watchBounds(); this._watchTimeSystem(); this._watchTimeModeChange(); @@ -140,9 +137,6 @@ export default class TelemetryCollection extends EventEmitter { * @private */ async _requestHistoricalTelemetry() { - console.debug( - `🫙 Requesting historical telemetry with start ${new Date(this.lastBounds.start).toISOString()} and end ${new Date(this.lastBounds.end).toISOString()}}` - ); let options = this.openmct.telemetry.standardizeRequestOptions({ ...this.options }); const historicalProvider = this.openmct.telemetry.findRequestProvider( this.domainObject, @@ -243,19 +237,6 @@ export default class TelemetryCollection extends EventEmitter { beforeStartOfBounds = parsedValue < boundsToUse.start; afterEndOfBounds = parsedValue > boundsToUse.end; - if (beforeStartOfBounds) { - console.debug( - `🫙 Datum is BEFORE start of bounds: ${new Date(parsedValue).toISOString()} < ${new Date(this.lastBounds.start).toISOString()}`, - this.options - ); - } - if (afterEndOfBounds) { - console.debug( - `🫙 Datum is AFTER start of bounds: ${new Date(parsedValue).toISOString()} < ${new Date(this.lastBounds.start).toISOString()}`, - this.options - ); - } - if ( !afterEndOfBounds && (!beforeStartOfBounds || (this.isStrategyLatest && this.openmct.telemetry.greedyLAD())) diff --git a/src/plugins/comps/CompsManager.js b/src/plugins/comps/CompsManager.js index 6d912ef397..b23f8071cd 100644 --- a/src/plugins/comps/CompsManager.js +++ b/src/plugins/comps/CompsManager.js @@ -59,7 +59,8 @@ export default class CompsManager extends EventEmitter { name: `${this.#getNextAlphabeticalParameterName()}`, valueToUse, testValue: 0, - timeMetaData + timeMetaData, + accumulateValues: false }); this.emit('parameterAdded', this.#domainObject); } @@ -173,27 +174,45 @@ export default class CompsManager extends EventEmitter { } } - getFullDataFrame(newTelemetry) { - const dataFrame = {}; - // can assume on data item - const newTelemetryKey = Object.keys(newTelemetry)[0]; - const newTelemetryData = newTelemetry[newTelemetryKey]; - const otherTelemetryKeys = Object.keys(this.#telemetryCollections).filter( - (keyString) => keyString !== newTelemetryKey + #getParameterForKeyString(keyString) { + return this.#domainObject.configuration.comps.parameters.find( + (parameter) => parameter.keyString === keyString ); - // initialize the data frame with the new telemetry data - dataFrame[newTelemetryKey] = newTelemetryData; - // initialize the other telemetry data + } + + getTelemetryForComps(newTelemetry) { + const telemetryForComps = {}; + const newTelemetryKey = Object.keys(newTelemetry)[0]; + const newTelemetryParameter = this.#getParameterForKeyString(newTelemetryKey); + const newTelemetryData = newTelemetry[newTelemetryKey]; + const otherTelemetryKeys = Object.keys(this.#telemetryCollections).slice(0); + if (newTelemetryParameter.accumulateValues) { + telemetryForComps[newTelemetryKey] = this.#telemetryCollections[newTelemetryKey].getAll(); + } else { + telemetryForComps[newTelemetryKey] = newTelemetryData; + } otherTelemetryKeys.forEach((keyString) => { - dataFrame[keyString] = []; + telemetryForComps[keyString] = []; }); - // march through the new telemetry data and add data to the frame from the other telemetry objects - // using LOCF + const otherTelemetryKeysNotAccumulating = otherTelemetryKeys.filter( + (keyString) => !this.#getParameterForKeyString(keyString).accumulateValues + ); + const otherTelemetryKeysAccumulating = otherTelemetryKeys.filter( + (keyString) => this.#getParameterForKeyString(keyString).accumulateValues + ); + // if we're accumulating, just add all the data + otherTelemetryKeysAccumulating.forEach((keyString) => { + telemetryForComps[keyString] = this.#telemetryCollections[keyString].getAll(); + }); + + // for the others, march through the new telemetry data and add data to the frame from the other telemetry objects + // using LOCF newTelemetryData.forEach((newDatum) => { - otherTelemetryKeys.forEach((otherKeyString) => { + otherTelemetryKeysNotAccumulating.forEach((otherKeyString) => { const otherCollection = this.#telemetryCollections[otherKeyString]; + // otherwise we need to find the closest datum to the new datum let insertionPointForNewData = otherCollection._sortedIndex(newDatum); const otherCollectionData = otherCollection.getAll(); if (insertionPointForNewData && insertionPointForNewData >= otherCollectionData.length) { @@ -202,11 +221,11 @@ export default class CompsManager extends EventEmitter { // get the closest datum to the new datum const closestDatum = otherCollectionData[insertionPointForNewData]; if (closestDatum) { - dataFrame[otherKeyString].push(closestDatum); + telemetryForComps[otherKeyString].push(closestDatum); } }); }); - return dataFrame; + return telemetryForComps; } #removeTelemetryObject = (telemetryObjectIdentifier) => { diff --git a/src/plugins/comps/CompsMathWorker.js b/src/plugins/comps/CompsMathWorker.js index adec37f357..29c2ba4fe2 100644 --- a/src/plugins/comps/CompsMathWorker.js +++ b/src/plugins/comps/CompsMathWorker.js @@ -5,7 +5,8 @@ onconnect = function (e) { const port = e.ports[0]; port.onmessage = function (event) { - const { type, callbackID, telemetryForComps, expression, parameters } = event.data; + const { type, callbackID, telemetryForComps, expression, parameters, newTelemetry } = + event.data; let responseType = 'unknown'; let error = null; let result = []; @@ -15,7 +16,7 @@ onconnect = function (e) { result = calculateRequest(telemetryForComps, parameters, expression); } else if (type === 'calculateSubscription') { responseType = 'calculationSubscriptionResult'; - result = calculateSubscription(telemetryForComps, parameters, expression); + result = calculateSubscription(telemetryForComps, newTelemetry, parameters, expression); } else if (type === 'init') { port.postMessage({ type: 'ready' }); return; @@ -40,9 +41,16 @@ function getFullDataFrame(telemetryForComps, parameters) { return dataFrame; } -function calculateSubscription(telemetryForComps, parameters, expression) { +function calculateSubscription(telemetryForComps, newTelemetry, parameters, expression) { const dataFrame = getFullDataFrame(telemetryForComps, parameters); - return calculate(dataFrame, parameters, expression); + const calculation = calculate(dataFrame, parameters, expression); + const newTelemetryKey = Object.keys(newTelemetry)[0]; + const newTelemetrySize = newTelemetry[newTelemetryKey].length; + let trimmedCalculation = calculation; + if (calculation.length > newTelemetrySize) { + trimmedCalculation = calculation.slice(calculation.length - newTelemetrySize); + } + return trimmedCalculation; } function calculateRequest(telemetryForComps, parameters, expression) { @@ -56,14 +64,28 @@ function calculate(dataFrame, parameters, expression) { if (!expression) { return sumResults; } + // set up accumulated data structure + const accumulatedData = {}; + parameters.forEach((parameter) => { + if (parameter.accumulateValues) { + accumulatedData[parameter.name] = []; + } + }); + // take the first parameter keyString as the reference const referenceParameter = parameters[0]; const otherParameters = parameters.slice(1); // iterate over the reference telemetry data const referenceTelemetry = dataFrame[referenceParameter.keyString]; referenceTelemetry?.forEach((referenceTelemetryItem) => { + let referenceValue = referenceTelemetryItem[referenceParameter.valueToUse]; + if (referenceParameter.accumulateValues) { + accumulatedData[referenceParameter.name].push(referenceValue); + referenceValue = accumulatedData[referenceParameter.name]; + } + const scope = { - [referenceParameter.name]: referenceTelemetryItem[referenceParameter.valueToUse] + [referenceParameter.name]: referenceValue }; const referenceTime = referenceTelemetryItem[referenceParameter.timeKey]; // iterate over the other parameters to set the scope @@ -75,7 +97,12 @@ function calculate(dataFrame, parameters, expression) { missingData = true; return; } - scope[parameter.name] = otherTelemetry[parameter.valueToUse]; + let otherValue = otherTelemetry[parameter.valueToUse]; + if (parameter.accumulateValues) { + accumulatedData[parameter.name].push(referenceValue); + otherValue = accumulatedData[referenceParameter.name]; + } + scope[parameter.name] = otherValue; }); if (missingData) { return; diff --git a/src/plugins/comps/CompsMetadataProvider.js b/src/plugins/comps/CompsMetadataProvider.js index b12fc34ef2..690b2c999b 100644 --- a/src/plugins/comps/CompsMetadataProvider.js +++ b/src/plugins/comps/CompsMetadataProvider.js @@ -61,6 +61,7 @@ export default class CompsMetadataProvider { key: 'compsOutput', source: 'compsOutput', name: 'Output', + derived: true, formatString: specificCompsManager.getOutputFormat(), hints: { range: 1 diff --git a/src/plugins/comps/CompsTelemetryProvider.js b/src/plugins/comps/CompsTelemetryProvider.js index bf069fd36d..cb75afe847 100644 --- a/src/plugins/comps/CompsTelemetryProvider.js +++ b/src/plugins/comps/CompsTelemetryProvider.js @@ -95,7 +95,7 @@ export default class CompsTelemetryProvider { return; } const expression = specificCompsManager.getExpression(); - const telemetryForComps = specificCompsManager.getFullDataFrame(newTelemetry); + const telemetryForComps = specificCompsManager.getTelemetryForComps(newTelemetry); const parameters = JSON.parse(JSON.stringify(specificCompsManager.getParameters())); if (!expression || !parameters) { return; @@ -103,6 +103,7 @@ export default class CompsTelemetryProvider { const payload = { type: 'calculateSubscription', telemetryForComps, + newTelemetry, expression, parameters, callbackID @@ -134,10 +135,6 @@ export default class CompsTelemetryProvider { ); return () => { delete this.#subscriptionCallbacks[callbackID]; - console.debug( - `🛑 Stopping subscription for ${domainObject.name} with callback ID ${callbackID}. We now have ${Object.keys(this.#subscriptionCallbacks).length} subscribers`, - this.#subscriptionCallbacks - ); specificCompsManager.stopListeningToUnderlyingTelemetry(); specificCompsManager.off('underlyingTelemetryUpdated', boundComputeOnNewTelemetry); }; diff --git a/src/plugins/comps/components/CompsView.vue b/src/plugins/comps/components/CompsView.vue index ec8f1abeab..d75ee003e0 100644 --- a/src/plugins/comps/components/CompsView.vue +++ b/src/plugins/comps/components/CompsView.vue @@ -95,6 +95,25 @@
{{ parameter.valueToUse }}
+
+ +
Test value @@ -235,6 +254,15 @@ function updateParameters() { applyTestData(); } +function updateAccumulateValues(parameter) { + if (parameter.accumulateValues) { + parameter.testValue = ['']; + } else { + parameter.testValue = ''; + } + updateParameters(); +} + function toggleTestData() { testDataApplied.value = !testDataApplied.value; if (testDataApplied.value) { @@ -270,6 +298,20 @@ function applyTestData() { } return acc; }, {}); + + // see which parameters are misconfigured as non-arrays + const misconfiguredParameterNames = parameters.value + .filter((parameter) => { + return parameter.accumulateValues && !Array.isArray(scope[parameter.name]); + }) + .map((parameter) => parameter.name); + if (misconfiguredParameterNames.length) { + const misconfiguredParameterNamesString = misconfiguredParameterNames.join(', '); + currentTestOutput.value = null; + expressionOutput.value = `Reference "${misconfiguredParameterNamesString}" set to accumulating, but test values aren't arrays.`; + return; + } + try { const testOutput = evaluate(expression.value, scope); const formattedData = getValueFormatter().format(testOutput); diff --git a/src/plugins/plot/configuration/PlotSeries.js b/src/plugins/plot/configuration/PlotSeries.js index 9f4f8329ea..34a1dec1ab 100644 --- a/src/plugins/plot/configuration/PlotSeries.js +++ b/src/plugins/plot/configuration/PlotSeries.js @@ -225,7 +225,13 @@ export default class PlotSeries extends Model { try { const points = await this.openmct.telemetry.request(this.domainObject, options); - const data = this.getSeriesData(); + // if derived, we can't use the old data + let data = this.getSeriesData(); + + if (this.metadata.value(this.get('yKey')).derived) { + data = []; + } + // eslint-disable-next-line you-dont-need-lodash-underscore/concat const newPoints = _(data) .concat(points)