mirror of
https://github.com/nasa/openmct.git
synced 2025-03-23 12:35:48 +00:00
can take arbitrary expressions
This commit is contained in:
parent
0326e38f5d
commit
413338d3e2
@ -29,10 +29,27 @@ export default class CompsManager extends EventEmitter {
|
||||
this.persist();
|
||||
}
|
||||
|
||||
getDomainObjectForParameter(keyString) {
|
||||
getParameters() {
|
||||
const parameters = this.#domainObject.configuration.comps.parameters;
|
||||
const parametersWithTimeKey = parameters.map((parameter) => {
|
||||
return {
|
||||
...parameter,
|
||||
timeKey: this.#telemetryCollections[parameter.keyString]?.timeKey
|
||||
};
|
||||
});
|
||||
return parametersWithTimeKey;
|
||||
}
|
||||
|
||||
getTelemetryObjectForParameter(keyString) {
|
||||
return this.#telemetryObjects[keyString];
|
||||
}
|
||||
|
||||
getMetaDataValuesForParameter(keyString) {
|
||||
const telemetryObject = this.getTelemetryObjectForParameter(keyString);
|
||||
const metaData = this.#openmct.telemetry.getMetadata(telemetryObject);
|
||||
return metaData.valueMetadatas;
|
||||
}
|
||||
|
||||
deleteParameter(keyString) {
|
||||
this.#domainObject.configuration.comps.parameters =
|
||||
this.#domainObject.configuration.comps.parameters.filter(
|
||||
@ -54,6 +71,10 @@ export default class CompsManager extends EventEmitter {
|
||||
'configuration.comps',
|
||||
this.#domainObject.configuration.comps
|
||||
);
|
||||
console.debug(
|
||||
`📦 CompsManager: persisted domain object`,
|
||||
this.#domainObject.configuration.comps
|
||||
);
|
||||
}
|
||||
|
||||
async load() {
|
||||
@ -170,7 +191,7 @@ export default class CompsManager extends EventEmitter {
|
||||
}
|
||||
|
||||
getExpression() {
|
||||
return this.#domainObject.configuration.expression;
|
||||
return this.#domainObject.configuration.comps.expression;
|
||||
}
|
||||
|
||||
#waitForDebounce() {
|
||||
|
@ -8,12 +8,12 @@ onconnect = function (e) {
|
||||
port.onmessage = function (event) {
|
||||
console.debug('🧮 Comps Math Worker message:', event);
|
||||
try {
|
||||
const { type, callbackID, telemetryForComps, expression } = event.data;
|
||||
const { type, callbackID, telemetryForComps, expression, parameters } = event.data;
|
||||
if (type === 'calculateRequest') {
|
||||
const result = calculateRequest(telemetryForComps, expression);
|
||||
const result = calculateRequest(telemetryForComps, parameters, expression);
|
||||
port.postMessage({ type: 'calculationRequestResult', callbackID, result });
|
||||
} else if (type === 'calculateSubscription') {
|
||||
const result = calculateSubscription(telemetryForComps, expression);
|
||||
const result = calculateSubscription(telemetryForComps, parameters, expression);
|
||||
if (result.length) {
|
||||
port.postMessage({ type: 'calculationSubscriptionResult', callbackID, result });
|
||||
}
|
||||
@ -38,31 +38,48 @@ function getFullDataFrame(telemetryForComps) {
|
||||
return dataFrame;
|
||||
}
|
||||
|
||||
function calculateSubscription(telemetryForComps, expression) {
|
||||
function calculateSubscription(telemetryForComps, parameters, expression) {
|
||||
const dataFrame = getFullDataFrame(telemetryForComps);
|
||||
return calculate(dataFrame, expression);
|
||||
return calculate(dataFrame, parameters, expression);
|
||||
}
|
||||
|
||||
function calculateRequest(telemetryForComps, expression) {
|
||||
function calculateRequest(telemetryForComps, parameters, expression) {
|
||||
const dataFrame = getFullDataFrame(telemetryForComps);
|
||||
return calculate(dataFrame, expression);
|
||||
return calculate(dataFrame, parameters, expression);
|
||||
}
|
||||
|
||||
function calculate(dataFrame, expression) {
|
||||
function calculate(dataFrame, parameters, expression) {
|
||||
const sumResults = [];
|
||||
// Iterate over the first dataset and check for matching utc in the other dataset
|
||||
const firstDataSet = Object.values(dataFrame)[0];
|
||||
const secondDataSet = Object.values(dataFrame)[1];
|
||||
if (!firstDataSet || !secondDataSet) {
|
||||
// ensure all parameter keyStrings have corresponding telemetry data
|
||||
if (!expression) {
|
||||
return sumResults;
|
||||
}
|
||||
|
||||
for (const [utc, item1] of firstDataSet.entries()) {
|
||||
if (secondDataSet.has(utc)) {
|
||||
const item2 = secondDataSet.get(utc);
|
||||
const output = evaluate(expression, { a: item1.sin, b: item2.sin });
|
||||
sumResults.push({ utc, output });
|
||||
// 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) => {
|
||||
const scope = {
|
||||
[referenceParameter.name]: referenceTelemetryItem[referenceParameter.valueToUse]
|
||||
};
|
||||
const referenceTime = referenceTelemetryItem[referenceParameter.timeKey];
|
||||
// iterate over the other parameters to set the scope
|
||||
let missingData = false;
|
||||
otherParameters.forEach((parameter) => {
|
||||
const otherDataFrame = dataFrame[parameter.keyString];
|
||||
const otherTelemetry = otherDataFrame.get(referenceTime);
|
||||
if (!otherTelemetry) {
|
||||
missingData = true;
|
||||
return;
|
||||
}
|
||||
scope[parameter.name] = otherTelemetry[parameter.valueToUse];
|
||||
});
|
||||
if (missingData) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const output = evaluate(expression, scope);
|
||||
sumResults.push({ [referenceParameter.timeKey]: referenceTime, output });
|
||||
});
|
||||
return sumResults;
|
||||
}
|
||||
|
@ -59,21 +59,16 @@ export default class CompsTelemetryProvider {
|
||||
this.#compsManagerPool
|
||||
);
|
||||
specificCompsManager.load().then(() => {
|
||||
console.debug('📚 specific comp is ready');
|
||||
const callbackID = this.#getCallbackID();
|
||||
const telemetryForComps = specificCompsManager.requestUnderlyingTelemetry();
|
||||
const expression = specificCompsManager.getExpression();
|
||||
console.debug('🏟️ 1 Telemetry for comps:', telemetryForComps);
|
||||
console.debug(
|
||||
'🏟️ 2 Telemetry for comps:',
|
||||
specificCompsManager.requestUnderlyingTelemetry()
|
||||
);
|
||||
console.debug('🏟️ expression:', expression);
|
||||
const parameters = specificCompsManager.getParameters();
|
||||
this.#requestPromises[callbackID] = { resolve, reject };
|
||||
this.#sharedWorker.port.postMessage({
|
||||
type: 'calculateRequest',
|
||||
telemetryForComps,
|
||||
expression,
|
||||
parameters,
|
||||
callbackID
|
||||
});
|
||||
});
|
||||
@ -83,11 +78,12 @@ export default class CompsTelemetryProvider {
|
||||
#computeOnNewTelemetry(specificCompsManager, newTelemetry, callbackID) {
|
||||
const expression = specificCompsManager.getExpression();
|
||||
const telemetryForComps = specificCompsManager.getFullDataFrame(newTelemetry);
|
||||
// console.debug('🏟️ created new Data frame:', telemetryForComps);
|
||||
const parameters = specificCompsManager.getParameters();
|
||||
this.#sharedWorker.port.postMessage({
|
||||
type: 'calculateSubscription',
|
||||
telemetryForComps,
|
||||
expression,
|
||||
parameters,
|
||||
callbackID
|
||||
});
|
||||
}
|
||||
@ -120,7 +116,6 @@ export default class CompsTelemetryProvider {
|
||||
this.#sharedWorker.port.onmessageerror = this.onSharedWorkerMessageError.bind(this);
|
||||
this.#sharedWorker.port.start();
|
||||
|
||||
// send an initial message to the worker
|
||||
this.#sharedWorker.port.postMessage({ type: 'init' });
|
||||
|
||||
this.#openmct.on('destroy', () => {
|
||||
@ -131,10 +126,10 @@ export default class CompsTelemetryProvider {
|
||||
onSharedWorkerMessage(event) {
|
||||
const { type, result, callbackID } = event.data;
|
||||
if (type === 'calculationSubscriptionResult' && this.#subscriptionCallbacks[callbackID]) {
|
||||
console.log('📝 Shared worker subscription message:', event.data);
|
||||
console.debug('📝 Shared worker subscription message:', event.data);
|
||||
this.#subscriptionCallbacks[callbackID](result);
|
||||
} else if (type === 'calculationRequestResult' && this.#requestPromises[callbackID]) {
|
||||
console.log('📝 Shared worker request message:', event.data);
|
||||
console.debug('📝 Shared worker request message:', event.data);
|
||||
this.#requestPromises[callbackID].resolve(result);
|
||||
delete this.#requestPromises[callbackID];
|
||||
} else if (type === 'error') {
|
||||
|
@ -55,30 +55,26 @@
|
||||
:class="{ 's-status-icon-warning-lo': !domainObject.configuration.comps.parameters }"
|
||||
>
|
||||
<div v-for="parameter in parameters" :key="parameter.name">
|
||||
<div class="c-cs__telemetry-reference">
|
||||
<input
|
||||
v-model="parameter.name"
|
||||
class="c-cs__telemetry-reference__label"
|
||||
@change="compsManager.persist"
|
||||
/>
|
||||
<div>
|
||||
Reference
|
||||
<input v-model="parameter.name" @change="compsManager.persist" />
|
||||
<ObjectPath
|
||||
:domain-object="compsManager.getDomainObjectForParameter(parameter.keyString)"
|
||||
:domain-object="compsManager.getTelemetryObjectForParameter(parameter.keyString)"
|
||||
/>
|
||||
{{ compsManager.getDomainObjectForParameter(parameter.keyString).name }}
|
||||
{{ compsManager.getTelemetryObjectForParameter(parameter.keyString).name }}
|
||||
<!-- drop down to select value from telemetry -->
|
||||
<select
|
||||
v-model="parameter.value"
|
||||
class="c-cs__telemetry-reference__value"
|
||||
@change="compsManager.persist"
|
||||
>
|
||||
<select v-model="parameter.valueToUse" @change="persistParameters">
|
||||
<option
|
||||
v-for="parameterValueOption in compsManager.getDomainObjectForParameter(
|
||||
v-for="parameterValueOption in compsManager.getMetaDataValuesForParameter(
|
||||
parameter.keyString
|
||||
)"
|
||||
:key="parameterValueOption"
|
||||
:value="parameterValueOption"
|
||||
/>
|
||||
:key="parameterValueOption.key"
|
||||
:value="parameterValueOption.key"
|
||||
>
|
||||
{{ parameterValueOption.name }}
|
||||
</option>
|
||||
</select>
|
||||
<input v-model="parameter.testValue" @change="compsManager.persist" />
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="!domainObject.configuration.comps.parameters"
|
||||
@ -92,13 +88,12 @@
|
||||
<div class="c-cs__header-label c-section__label">Expression</div>
|
||||
</div>
|
||||
<div class="c-cs__content">
|
||||
<div v-if="!isEditing">{{ domainObject.configuration.comps.expression }}</div>
|
||||
<div v-else>
|
||||
<div>
|
||||
<textarea
|
||||
v-model="domainObject.configuration.comps.expression"
|
||||
v-model="expression"
|
||||
class="c-cs__expression__input"
|
||||
placeholder="Enter an expression"
|
||||
@change="compsManager.persist"
|
||||
@change="persistExpression"
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
@ -119,6 +114,7 @@ const compsManager = CompsManager.getCompsManager(domainObject, openmct, compsMa
|
||||
const currentCompOutput = ref(null);
|
||||
const testDataApplied = ref(false);
|
||||
const parameters = ref(null);
|
||||
const expression = ref(null);
|
||||
|
||||
let outputTelemetryCollection;
|
||||
|
||||
@ -135,9 +131,20 @@ onBeforeMount(async () => {
|
||||
outputTelemetryCollection.on('clear', clearData);
|
||||
await outputTelemetryCollection.load();
|
||||
await compsManager.load();
|
||||
parameters.value = domainObject.configuration.comps.parameters;
|
||||
parameters.value = compsManager.getParameters();
|
||||
expression.value = compsManager.getExpression();
|
||||
});
|
||||
|
||||
function persistParameters() {
|
||||
domainObject.configuration.comps.parameters = parameters.value;
|
||||
compsManager.persist();
|
||||
}
|
||||
|
||||
function persistExpression() {
|
||||
domainObject.configuration.comps.expression = expression.value;
|
||||
compsManager.persist();
|
||||
}
|
||||
|
||||
function applyTestData() {}
|
||||
|
||||
function telemetryProcessor(data) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user