mirror of
https://github.com/nasa/openmct.git
synced 2025-06-01 07:00:49 +00:00
worker ready
This commit is contained in:
parent
0dd04426f5
commit
ff814544c6
@ -3,46 +3,79 @@ import { EventEmitter } from 'eventemitter3';
|
|||||||
export default class CompsManager extends EventEmitter {
|
export default class CompsManager extends EventEmitter {
|
||||||
#openmct;
|
#openmct;
|
||||||
#domainObject;
|
#domainObject;
|
||||||
|
#composition;
|
||||||
#telemetryObjects = {};
|
#telemetryObjects = {};
|
||||||
#telemetryCollections = {};
|
#telemetryCollections = {};
|
||||||
|
#managerLoadedPromise;
|
||||||
|
|
||||||
constructor(openmct, domainObject) {
|
constructor(openmct, domainObject) {
|
||||||
super();
|
super();
|
||||||
this.#openmct = openmct;
|
this.#openmct = openmct;
|
||||||
this.#domainObject = domainObject;
|
this.#domainObject = domainObject;
|
||||||
|
|
||||||
|
// Load the composition
|
||||||
|
this.#managerLoadedPromise = this.#loadComposition();
|
||||||
}
|
}
|
||||||
|
|
||||||
#removeTelemetryObject(telemetryObject) {
|
load() {
|
||||||
|
return this.#managerLoadedPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
async #loadComposition() {
|
||||||
|
this.#composition = this.#openmct.composition.get(this.#domainObject);
|
||||||
|
if (this.#composition) {
|
||||||
|
this.#composition.on('add', this.#addTelemetryObject);
|
||||||
|
this.#composition.on('remove', this.#removeTelemetryObject);
|
||||||
|
await this.#composition.load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#removeTelemetryObject = (telemetryObject) => {
|
||||||
|
console.debug('❌ CompsManager: removeTelemetryObject', telemetryObject);
|
||||||
const keyString = this.#openmct.objects.makeKeyString(telemetryObject.identifier);
|
const keyString = this.#openmct.objects.makeKeyString(telemetryObject.identifier);
|
||||||
delete this.#telemetryObjects[keyString];
|
delete this.#telemetryObjects[keyString];
|
||||||
this.#telemetryCollections[keyString]?.destroy();
|
this.#telemetryCollections[keyString]?.destroy();
|
||||||
delete this.#telemetryCollections[keyString];
|
delete this.#telemetryCollections[keyString];
|
||||||
|
};
|
||||||
|
|
||||||
|
requestUnderlyingTelemetry() {
|
||||||
|
const underlyingTelemetry = {};
|
||||||
|
Object.keys(this.#telemetryCollections).forEach((collectionKey) => {
|
||||||
|
const collection = this.#telemetryCollections[collectionKey];
|
||||||
|
underlyingTelemetry[collectionKey] = collection.getAll();
|
||||||
|
});
|
||||||
|
return underlyingTelemetry;
|
||||||
}
|
}
|
||||||
|
|
||||||
telemetryProcessor(telemetryObjects) {
|
#telemetryProcessor(telemetryObjects) {
|
||||||
console.debug('Telemetry Processor', telemetryObjects);
|
this.emit('underlyingTelemetryUpdated', telemetryObjects);
|
||||||
}
|
}
|
||||||
|
|
||||||
clearData() {
|
#clearData() {
|
||||||
console.debug('Clear Data');
|
console.debug('Clear Data');
|
||||||
}
|
}
|
||||||
|
|
||||||
#addTelemetryObject(telemetryObject) {
|
getExpression() {
|
||||||
|
return 'a + b';
|
||||||
|
}
|
||||||
|
|
||||||
|
#addTelemetryObject = (telemetryObject) => {
|
||||||
|
console.debug('📢 CompsManager: #addTelemetryObject', telemetryObject);
|
||||||
const keyString = this.#openmct.objects.makeKeyString(telemetryObject.identifier);
|
const keyString = this.#openmct.objects.makeKeyString(telemetryObject.identifier);
|
||||||
this.#telemetryObjects[keyString] = telemetryObject;
|
this.#telemetryObjects[keyString] = telemetryObject;
|
||||||
this.#telemetryCollections[keyString] =
|
this.#telemetryCollections[keyString] =
|
||||||
this.#openmct.telemetry.requestCollection(telemetryObject);
|
this.#openmct.telemetry.requestCollection(telemetryObject);
|
||||||
|
|
||||||
this.#telemetryCollections[keyString].on('add', this.telemetryProcessor);
|
this.#telemetryCollections[keyString].on('add', this.#telemetryProcessor);
|
||||||
this.#telemetryCollections[keyString].on('clear', this.clearData);
|
this.#telemetryCollections[keyString].on('clear', this.#clearData);
|
||||||
this.#telemetryCollections[keyString].load();
|
this.#telemetryCollections[keyString].load();
|
||||||
}
|
};
|
||||||
|
|
||||||
static getCompsManager(domainObject, openmct, compsManagerPool) {
|
static getCompsManager(domainObject, openmct, compsManagerPool) {
|
||||||
const id = openmct.objects.makeKeyString(domainObject.identifier);
|
const id = openmct.objects.makeKeyString(domainObject.identifier);
|
||||||
|
|
||||||
if (!compsManagerPool[id]) {
|
if (!compsManagerPool[id]) {
|
||||||
compsManagerPool[id] = new CompsManager(domainObject, this.openmct);
|
compsManagerPool[id] = new CompsManager(openmct, domainObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
return compsManagerPool[id];
|
return compsManagerPool[id];
|
||||||
|
@ -6,21 +6,26 @@ onconnect = function (e) {
|
|||||||
|
|
||||||
port.onmessage = function (event) {
|
port.onmessage = function (event) {
|
||||||
console.debug('🧮 Comps Math Worker message:', event);
|
console.debug('🧮 Comps Math Worker message:', event);
|
||||||
const { type, id, data, expression } = event.data;
|
const { type, callbackID, telemetryForComps, expression } = event.data;
|
||||||
if (type === 'calculate') {
|
if (type === 'calculateRequest' || type === 'calculateSubscription') {
|
||||||
try {
|
try {
|
||||||
const result = data.map((point) => {
|
// the reply type is different for request and subscription
|
||||||
|
const replyType =
|
||||||
|
type === 'calculateRequest'
|
||||||
|
? 'calculationRequestResult'
|
||||||
|
: 'calculationSubscriptionResult';
|
||||||
|
const result = telemetryForComps.map((point) => {
|
||||||
// Using Math.js to evaluate the expression against the data
|
// Using Math.js to evaluate the expression against the data
|
||||||
return { ...point, value: evaluate(expression, point) };
|
return { ...point, value: evaluate(expression, point) };
|
||||||
});
|
});
|
||||||
port.postMessage({ type: 'response', id, result });
|
port.postMessage({ type: replyType, callbackID, result });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
port.postMessage({ type: 'error', id, error: error.message });
|
port.postMessage({ type: 'error', callbackID, error: error.message });
|
||||||
}
|
}
|
||||||
} else if (type === 'init') {
|
} else if (type === 'init') {
|
||||||
port.postMessage({ type: 'ready' });
|
port.postMessage({ type: 'ready' });
|
||||||
} else {
|
} else {
|
||||||
port.postMessage({ type: 'error', id, error: 'Invalid message type' });
|
port.postMessage({ type: 'error', callbackID, error: 'Invalid message type' });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -19,23 +19,20 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
import CompsManager from './CompsManager.js';
|
||||||
|
|
||||||
export default class CompsTelemetryProvider {
|
export default class CompsTelemetryProvider {
|
||||||
#telemetryObjects = {};
|
|
||||||
#telemetryCollections = {};
|
|
||||||
#composition = [];
|
|
||||||
#openmct = null;
|
#openmct = null;
|
||||||
#sharedWorker = null;
|
#sharedWorker = null;
|
||||||
|
#compsManagerPool = null;
|
||||||
|
#lastUniqueID = 1;
|
||||||
|
#requestPromises = {};
|
||||||
|
#subscriptionCallbacks = {};
|
||||||
|
|
||||||
constructor(openmct) {
|
constructor(openmct, compsManagerPool) {
|
||||||
this.#openmct = openmct;
|
this.#openmct = openmct;
|
||||||
}
|
this.#compsManagerPool = compsManagerPool;
|
||||||
|
this.#startSharedWorker();
|
||||||
#removeTelemetryObject(telemetryObject) {
|
|
||||||
const keyString = this.openmct.objects.makeKeyString(telemetryObject.identifier);
|
|
||||||
delete this.#telemetryObjects[keyString];
|
|
||||||
this.#telemetryCollections[keyString]?.destroy();
|
|
||||||
delete this.#telemetryCollections[keyString];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isTelemetryObject(domainObject) {
|
isTelemetryObject(domainObject) {
|
||||||
@ -50,26 +47,55 @@ export default class CompsTelemetryProvider {
|
|||||||
return domainObject.type === 'comps';
|
return domainObject.type === 'comps';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#getCallbackID() {
|
||||||
|
return this.#lastUniqueID++;
|
||||||
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line require-await
|
// eslint-disable-next-line require-await
|
||||||
async request(domainObject, options) {
|
async request(domainObject, options) {
|
||||||
// get the telemetry from the collections
|
const specificCompsManager = CompsManager.getCompsManager(
|
||||||
const telmetryToSend = {};
|
|
||||||
Object.keys(this.#telemetryCollections).forEach((keyString) => {
|
|
||||||
telmetryToSend[keyString] = this.#telemetryCollections[keyString].getAll(
|
|
||||||
domainObject,
|
domainObject,
|
||||||
options
|
this.#openmct,
|
||||||
|
this.#compsManagerPool
|
||||||
);
|
);
|
||||||
});
|
await specificCompsManager.load();
|
||||||
|
const telemetryForComps = specificCompsManager.requestUnderlyingTelemetry();
|
||||||
|
console.debug('🏟️ Telemetry for comps:', telemetryForComps);
|
||||||
|
const expression = specificCompsManager.getExpression();
|
||||||
|
// need to create callbackID with a promise for future execution
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const callbackID = this.#getCallbackID();
|
||||||
|
this.#requestPromises[callbackID] = { resolve, reject };
|
||||||
this.#sharedWorker.port.postMessage({
|
this.#sharedWorker.port.postMessage({
|
||||||
type: 'calculate',
|
type: 'calculateRequest',
|
||||||
data: telmetryToSend,
|
telemetryForComps,
|
||||||
expression: 'a + b'
|
expression,
|
||||||
|
callbackID
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribe(domainObject, callback) {
|
subscribe(domainObject, callback) {
|
||||||
// TODO: add to listener list and return a function to remove it
|
const specificCompsManager = CompsManager.getCompsManager(
|
||||||
return () => {};
|
domainObject,
|
||||||
|
this.#openmct,
|
||||||
|
this.#compsManagerPool
|
||||||
|
);
|
||||||
|
const callbackID = this.#getCallbackID();
|
||||||
|
this.#subscriptionCallbacks[callbackID] = callback;
|
||||||
|
specificCompsManager.on('underlyingTelemetryUpdated', (newTelemetry) => {
|
||||||
|
const expression = specificCompsManager.getExpression();
|
||||||
|
this.#sharedWorker.port.postMessage({
|
||||||
|
type: 'calculateSubscription',
|
||||||
|
telemetryForComps: newTelemetry,
|
||||||
|
expression,
|
||||||
|
callbackID
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return () => {
|
||||||
|
specificCompsManager.off('calculationUpdated', callback);
|
||||||
|
delete this.#subscriptionCallbacks[callbackID];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#startSharedWorker() {
|
#startSharedWorker() {
|
||||||
@ -86,13 +112,6 @@ export default class CompsTelemetryProvider {
|
|||||||
// send an initial message to the worker
|
// send an initial message to the worker
|
||||||
this.#sharedWorker.port.postMessage({ type: 'init' });
|
this.#sharedWorker.port.postMessage({ type: 'init' });
|
||||||
|
|
||||||
// for testing, try a message adding two numbers
|
|
||||||
this.#sharedWorker.port.postMessage({
|
|
||||||
type: 'calculate',
|
|
||||||
data: [{ a: 1, b: 2 }],
|
|
||||||
expression: 'a + b'
|
|
||||||
});
|
|
||||||
|
|
||||||
this.#openmct.on('destroy', () => {
|
this.#openmct.on('destroy', () => {
|
||||||
this.#sharedWorker.port.close();
|
this.#sharedWorker.port.close();
|
||||||
});
|
});
|
||||||
@ -100,6 +119,15 @@ export default class CompsTelemetryProvider {
|
|||||||
|
|
||||||
onSharedWorkerMessage(event) {
|
onSharedWorkerMessage(event) {
|
||||||
console.log('📝 Shared worker message:', event.data);
|
console.log('📝 Shared worker message:', event.data);
|
||||||
|
const { type, result, callbackID } = event.data;
|
||||||
|
if (type === 'calculationSubscriptionResult') {
|
||||||
|
this.#subscriptionCallbacks[callbackID](result);
|
||||||
|
} else if (type === 'calculationRequestResult') {
|
||||||
|
this.#requestPromises[callbackID].resolve(result);
|
||||||
|
delete this.#requestPromises[callbackID];
|
||||||
|
} else if (type === 'error') {
|
||||||
|
console.error('❌ Shared worker error:', event.data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onSharedWorkerMessageError(event) {
|
onSharedWorkerMessageError(event) {
|
||||||
|
@ -33,33 +33,10 @@ const openmct = inject('openmct');
|
|||||||
const domainObject = inject('domainObject');
|
const domainObject = inject('domainObject');
|
||||||
const compsManagerPool = inject('compsManagerPool');
|
const compsManagerPool = inject('compsManagerPool');
|
||||||
const compsManager = CompsManager.getCompsManager(domainObject, openmct, compsManagerPool);
|
const compsManager = CompsManager.getCompsManager(domainObject, openmct, compsManagerPool);
|
||||||
const composition = openmct.composition.get(domainObject);
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
loadComposition();
|
|
||||||
console.debug('🚀 CompsView: onMounted with compsManager', compsManager);
|
console.debug('🚀 CompsView: onMounted with compsManager', compsManager);
|
||||||
});
|
});
|
||||||
|
|
||||||
async function loadComposition() {
|
onBeforeUnmount(() => {});
|
||||||
if (composition) {
|
|
||||||
composition.on('add', addTelemetryObject);
|
|
||||||
composition.on('remove', removeTelemetryObject);
|
|
||||||
await composition.load();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function addTelemetryObject(object) {
|
|
||||||
console.debug('📢 CompsView: addTelemetryObject', object);
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeTelemetryObject(object) {
|
|
||||||
console.debug('❌ CompsView: removeTelemetryObject', object);
|
|
||||||
}
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
if (composition) {
|
|
||||||
composition.off('add', addTelemetryObject);
|
|
||||||
composition.off('remove', removeTelemetryObject);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -40,7 +40,10 @@ export default function CompsPlugin() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
openmct.composition.addPolicy((parent, child) => {
|
openmct.composition.addPolicy((parent, child) => {
|
||||||
return openmct.telemetry.isTelemetryObject(child);
|
if (parent.type === 'comps' && !openmct.telemetry.isTelemetryObject(child)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
openmct.telemetry.addProvider(new CompsTelemetryProvider(openmct, compsManagerPool));
|
openmct.telemetry.addProvider(new CompsTelemetryProvider(openmct, compsManagerPool));
|
||||||
openmct.objectViews.addProvider(new CompsViewProvider(openmct, compsManagerPool));
|
openmct.objectViews.addProvider(new CompsViewProvider(openmct, compsManagerPool));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user