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 @@