mirror of
https://github.com/nasa/openmct.git
synced 2025-07-01 12:58:56 +00:00
Compare commits
2 Commits
omm-large-
...
fix-duplic
Author | SHA1 | Date | |
---|---|---|---|
d3825fc554 | |||
d42b2dd023 |
@ -23,5 +23,5 @@ module.exports = merge(common, {
|
||||
__OPENMCT_ROOT_RELATIVE__: '""'
|
||||
})
|
||||
],
|
||||
devtool: "source-map"
|
||||
devtool: "eval-source-map"
|
||||
});
|
||||
|
@ -1,138 +1,150 @@
|
||||
define(['lodash'], function (_) {
|
||||
var METADATA_BY_TYPE = {
|
||||
generator: {
|
||||
values: [
|
||||
{
|
||||
key: 'name',
|
||||
name: 'Name',
|
||||
format: 'string'
|
||||
define([
|
||||
'lodash'
|
||||
], function (
|
||||
_
|
||||
) {
|
||||
|
||||
var METADATA_BY_TYPE = {
|
||||
'generator': {
|
||||
values: [
|
||||
{
|
||||
key: "name",
|
||||
name: "Name",
|
||||
format: "string"
|
||||
},
|
||||
{
|
||||
key: "utc",
|
||||
name: "Time",
|
||||
format: "utc",
|
||||
hints: {
|
||||
domain: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "yesterday",
|
||||
name: "Yesterday",
|
||||
format: "utc",
|
||||
hints: {
|
||||
domain: 2
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "wavelengths",
|
||||
name: "Wavelength",
|
||||
unit: "nm",
|
||||
format: 'string[]',
|
||||
hints: {
|
||||
range: 4
|
||||
}
|
||||
},
|
||||
// Need to enable "LocalTimeSystem" plugin to make use of this
|
||||
// {
|
||||
// key: "local",
|
||||
// name: "Time",
|
||||
// format: "local-format",
|
||||
// source: "utc",
|
||||
// hints: {
|
||||
// domain: 3
|
||||
// }
|
||||
// },
|
||||
{
|
||||
key: "sin",
|
||||
name: "Sine",
|
||||
unit: "Hz",
|
||||
formatString: '%0.2f',
|
||||
hints: {
|
||||
range: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "cos",
|
||||
name: "Cosine",
|
||||
unit: "deg",
|
||||
formatString: '%0.2f',
|
||||
hints: {
|
||||
range: 2
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "intensities",
|
||||
name: "Intensities",
|
||||
format: 'number[]',
|
||||
hints: {
|
||||
range: 3
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: 'utc',
|
||||
name: 'Time',
|
||||
format: 'utc',
|
||||
hints: {
|
||||
domain: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'yesterday',
|
||||
name: 'Yesterday',
|
||||
format: 'utc',
|
||||
hints: {
|
||||
domain: 2
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'wavelengths',
|
||||
name: 'Wavelength',
|
||||
unit: 'nm',
|
||||
format: 'string[]',
|
||||
hints: {
|
||||
range: 4
|
||||
}
|
||||
},
|
||||
// Need to enable "LocalTimeSystem" plugin to make use of this
|
||||
// {
|
||||
// key: "local",
|
||||
// name: "Time",
|
||||
// format: "local-format",
|
||||
// source: "utc",
|
||||
// hints: {
|
||||
// domain: 3
|
||||
// }
|
||||
// },
|
||||
{
|
||||
key: 'sin',
|
||||
name: 'Sine',
|
||||
unit: 'Hz',
|
||||
formatString: '%0.2f',
|
||||
hints: {
|
||||
range: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'cos',
|
||||
name: 'Cosine',
|
||||
unit: 'deg',
|
||||
formatString: '%0.2f',
|
||||
hints: {
|
||||
range: 2
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'intensities',
|
||||
name: 'Intensities',
|
||||
format: 'number[]',
|
||||
hints: {
|
||||
range: 3
|
||||
}
|
||||
'example.state-generator': {
|
||||
values: [
|
||||
{
|
||||
key: "name",
|
||||
name: "Name",
|
||||
format: "string"
|
||||
},
|
||||
{
|
||||
key: "utc",
|
||||
name: "Time",
|
||||
format: "utc",
|
||||
hints: {
|
||||
domain: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "local",
|
||||
name: "Time",
|
||||
format: "utc",
|
||||
source: "utc",
|
||||
hints: {
|
||||
domain: 2
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "state",
|
||||
source: "value",
|
||||
name: "State",
|
||||
format: "enum",
|
||||
enumerations: [
|
||||
{
|
||||
value: 0,
|
||||
string: "OFF"
|
||||
},
|
||||
{
|
||||
value: 1,
|
||||
string: "ON"
|
||||
}
|
||||
],
|
||||
hints: {
|
||||
range: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "value",
|
||||
name: "Value",
|
||||
hints: {
|
||||
range: 2
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
'example.state-generator': {
|
||||
values: [
|
||||
{
|
||||
key: 'name',
|
||||
name: 'Name',
|
||||
format: 'string'
|
||||
},
|
||||
{
|
||||
key: 'utc',
|
||||
name: 'Time',
|
||||
format: 'utc',
|
||||
hints: {
|
||||
domain: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'local',
|
||||
name: 'Time',
|
||||
format: 'utc',
|
||||
source: 'utc',
|
||||
hints: {
|
||||
domain: 2
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'state',
|
||||
source: 'value',
|
||||
name: 'State',
|
||||
format: 'enum',
|
||||
enumerations: [
|
||||
{
|
||||
value: 0,
|
||||
string: 'OFF'
|
||||
},
|
||||
{
|
||||
value: 1,
|
||||
string: 'ON'
|
||||
}
|
||||
],
|
||||
hints: {
|
||||
range: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'value',
|
||||
name: 'Value',
|
||||
hints: {
|
||||
range: 2
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
function GeneratorMetadataProvider() {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
function GeneratorMetadataProvider() {}
|
||||
GeneratorMetadataProvider.prototype.supportsMetadata = function (domainObject) {
|
||||
return Object.prototype.hasOwnProperty.call(METADATA_BY_TYPE, domainObject.type);
|
||||
};
|
||||
|
||||
GeneratorMetadataProvider.prototype.supportsMetadata = function (domainObject) {
|
||||
return Object.prototype.hasOwnProperty.call(METADATA_BY_TYPE, domainObject.type);
|
||||
};
|
||||
GeneratorMetadataProvider.prototype.getMetadata = function (domainObject) {
|
||||
return Object.assign(
|
||||
{},
|
||||
domainObject.telemetry,
|
||||
METADATA_BY_TYPE[domainObject.type]
|
||||
);
|
||||
};
|
||||
|
||||
GeneratorMetadataProvider.prototype.getMetadata = function (domainObject) {
|
||||
return Object.assign({}, domainObject.telemetry, METADATA_BY_TYPE[domainObject.type]);
|
||||
};
|
||||
return GeneratorMetadataProvider;
|
||||
|
||||
return GeneratorMetadataProvider;
|
||||
});
|
||||
|
@ -20,86 +20,87 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(['./WorkerInterface'], function (WorkerInterface) {
|
||||
var REQUEST_DEFAULTS = {
|
||||
amplitude: 1,
|
||||
period: 10,
|
||||
offset: 0,
|
||||
dataRateInHz: 1,
|
||||
randomness: 0,
|
||||
phase: 0,
|
||||
loadDelay: 0,
|
||||
infinityValues: false,
|
||||
veryLargeValues: false
|
||||
};
|
||||
define([
|
||||
'./WorkerInterface'
|
||||
], function (
|
||||
WorkerInterface
|
||||
) {
|
||||
|
||||
function GeneratorProvider(openmct, StalenessProvider) {
|
||||
this.openmct = openmct;
|
||||
this.workerInterface = new WorkerInterface(openmct, StalenessProvider);
|
||||
}
|
||||
var REQUEST_DEFAULTS = {
|
||||
amplitude: 1,
|
||||
period: 10,
|
||||
offset: 0,
|
||||
dataRateInHz: 1,
|
||||
randomness: 0,
|
||||
phase: 0,
|
||||
loadDelay: 0,
|
||||
infinityValues: false
|
||||
};
|
||||
|
||||
GeneratorProvider.prototype.canProvideTelemetry = function (domainObject) {
|
||||
return domainObject.type === 'generator';
|
||||
};
|
||||
function GeneratorProvider(openmct, StalenessProvider) {
|
||||
this.openmct = openmct;
|
||||
this.workerInterface = new WorkerInterface(openmct, StalenessProvider);
|
||||
}
|
||||
|
||||
GeneratorProvider.prototype.supportsRequest = GeneratorProvider.prototype.supportsSubscribe =
|
||||
GeneratorProvider.prototype.canProvideTelemetry;
|
||||
GeneratorProvider.prototype.canProvideTelemetry = function (domainObject) {
|
||||
return domainObject.type === 'generator';
|
||||
};
|
||||
|
||||
GeneratorProvider.prototype.makeWorkerRequest = function (domainObject, request) {
|
||||
var props = [
|
||||
'amplitude',
|
||||
'period',
|
||||
'offset',
|
||||
'dataRateInHz',
|
||||
'randomness',
|
||||
'phase',
|
||||
'loadDelay',
|
||||
'infinityValues',
|
||||
'veryLargeValues'
|
||||
];
|
||||
GeneratorProvider.prototype.supportsRequest =
|
||||
GeneratorProvider.prototype.supportsSubscribe =
|
||||
GeneratorProvider.prototype.canProvideTelemetry;
|
||||
|
||||
request = request || {};
|
||||
GeneratorProvider.prototype.makeWorkerRequest = function (domainObject, request) {
|
||||
var props = [
|
||||
'amplitude',
|
||||
'period',
|
||||
'offset',
|
||||
'dataRateInHz',
|
||||
'randomness',
|
||||
'phase',
|
||||
'loadDelay',
|
||||
'infinityValues'
|
||||
];
|
||||
|
||||
var workerRequest = {};
|
||||
request = request || {};
|
||||
|
||||
props.forEach(function (prop) {
|
||||
if (
|
||||
domainObject.telemetry &&
|
||||
Object.prototype.hasOwnProperty.call(domainObject.telemetry, prop)
|
||||
) {
|
||||
workerRequest[prop] = domainObject.telemetry[prop];
|
||||
}
|
||||
var workerRequest = {};
|
||||
|
||||
if (request && Object.prototype.hasOwnProperty.call(request, prop)) {
|
||||
workerRequest[prop] = request[prop];
|
||||
}
|
||||
props.forEach(function (prop) {
|
||||
if (domainObject.telemetry && Object.prototype.hasOwnProperty.call(domainObject.telemetry, prop)) {
|
||||
workerRequest[prop] = domainObject.telemetry[prop];
|
||||
}
|
||||
|
||||
if (!Object.prototype.hasOwnProperty.call(workerRequest, prop)) {
|
||||
workerRequest[prop] = REQUEST_DEFAULTS[prop];
|
||||
}
|
||||
if (request && Object.prototype.hasOwnProperty.call(request, prop)) {
|
||||
workerRequest[prop] = request[prop];
|
||||
}
|
||||
|
||||
workerRequest[prop] = Number(workerRequest[prop]);
|
||||
});
|
||||
if (!Object.prototype.hasOwnProperty.call(workerRequest, prop)) {
|
||||
workerRequest[prop] = REQUEST_DEFAULTS[prop];
|
||||
}
|
||||
|
||||
workerRequest.id = this.openmct.objects.makeKeyString(domainObject.identifier);
|
||||
workerRequest.name = domainObject.name;
|
||||
workerRequest[prop] = Number(workerRequest[prop]);
|
||||
});
|
||||
|
||||
return workerRequest;
|
||||
};
|
||||
workerRequest.id = this.openmct.objects.makeKeyString(domainObject.identifier);
|
||||
workerRequest.name = domainObject.name;
|
||||
|
||||
GeneratorProvider.prototype.request = function (domainObject, request) {
|
||||
var workerRequest = this.makeWorkerRequest(domainObject, request);
|
||||
workerRequest.start = request.start;
|
||||
workerRequest.end = request.end;
|
||||
return workerRequest;
|
||||
};
|
||||
|
||||
return this.workerInterface.request(workerRequest);
|
||||
};
|
||||
GeneratorProvider.prototype.request = function (domainObject, request) {
|
||||
var workerRequest = this.makeWorkerRequest(domainObject, request);
|
||||
workerRequest.start = request.start;
|
||||
workerRequest.end = request.end;
|
||||
|
||||
GeneratorProvider.prototype.subscribe = function (domainObject, callback) {
|
||||
var workerRequest = this.makeWorkerRequest(domainObject, {});
|
||||
return this.workerInterface.request(workerRequest);
|
||||
};
|
||||
|
||||
return this.workerInterface.subscribe(workerRequest, callback);
|
||||
};
|
||||
GeneratorProvider.prototype.subscribe = function (domainObject, callback) {
|
||||
var workerRequest = this.makeWorkerRequest(domainObject, {});
|
||||
|
||||
return GeneratorProvider;
|
||||
return this.workerInterface.subscribe(workerRequest, callback);
|
||||
};
|
||||
|
||||
return GeneratorProvider;
|
||||
});
|
||||
|
@ -20,147 +20,155 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define([], function () {
|
||||
var PURPLE = {
|
||||
sin: 2.2,
|
||||
cos: 2.2
|
||||
},
|
||||
RED = {
|
||||
sin: 0.9,
|
||||
cos: 0.9
|
||||
},
|
||||
ORANGE = {
|
||||
sin: 0.7,
|
||||
cos: 0.7
|
||||
},
|
||||
YELLOW = {
|
||||
sin: 0.5,
|
||||
cos: 0.5
|
||||
},
|
||||
CYAN = {
|
||||
sin: 0.45,
|
||||
cos: 0.45
|
||||
},
|
||||
LIMITS = {
|
||||
rh: {
|
||||
cssClass: 'is-limit--upr is-limit--red',
|
||||
low: RED,
|
||||
high: Number.POSITIVE_INFINITY,
|
||||
name: 'Red High'
|
||||
},
|
||||
rl: {
|
||||
cssClass: 'is-limit--lwr is-limit--red',
|
||||
high: -RED,
|
||||
low: Number.NEGATIVE_INFINITY,
|
||||
name: 'Red Low'
|
||||
},
|
||||
yh: {
|
||||
cssClass: 'is-limit--upr is-limit--yellow',
|
||||
low: YELLOW,
|
||||
high: RED,
|
||||
name: 'Yellow High'
|
||||
},
|
||||
yl: {
|
||||
cssClass: 'is-limit--lwr is-limit--yellow',
|
||||
low: -RED,
|
||||
high: -YELLOW,
|
||||
name: 'Yellow Low'
|
||||
}
|
||||
define([
|
||||
|
||||
], function (
|
||||
|
||||
) {
|
||||
|
||||
var PURPLE = {
|
||||
sin: 2.2,
|
||||
cos: 2.2
|
||||
},
|
||||
RED = {
|
||||
sin: 0.9,
|
||||
cos: 0.9
|
||||
},
|
||||
ORANGE = {
|
||||
sin: 0.7,
|
||||
cos: 0.7
|
||||
},
|
||||
YELLOW = {
|
||||
sin: 0.5,
|
||||
cos: 0.5
|
||||
},
|
||||
CYAN = {
|
||||
sin: 0.45,
|
||||
cos: 0.45
|
||||
},
|
||||
LIMITS = {
|
||||
rh: {
|
||||
cssClass: "is-limit--upr is-limit--red",
|
||||
low: RED,
|
||||
high: Number.POSITIVE_INFINITY,
|
||||
name: "Red High"
|
||||
},
|
||||
rl: {
|
||||
cssClass: "is-limit--lwr is-limit--red",
|
||||
high: -RED,
|
||||
low: Number.NEGATIVE_INFINITY,
|
||||
name: "Red Low"
|
||||
},
|
||||
yh: {
|
||||
cssClass: "is-limit--upr is-limit--yellow",
|
||||
low: YELLOW,
|
||||
high: RED,
|
||||
name: "Yellow High"
|
||||
},
|
||||
yl: {
|
||||
cssClass: "is-limit--lwr is-limit--yellow",
|
||||
low: -RED,
|
||||
high: -YELLOW,
|
||||
name: "Yellow Low"
|
||||
}
|
||||
};
|
||||
|
||||
function SinewaveLimitProvider() {
|
||||
|
||||
}
|
||||
|
||||
SinewaveLimitProvider.prototype.supportsLimits = function (domainObject) {
|
||||
return domainObject.type === 'generator';
|
||||
};
|
||||
|
||||
function SinewaveLimitProvider() {}
|
||||
SinewaveLimitProvider.prototype.getLimitEvaluator = function (domainObject) {
|
||||
return {
|
||||
evaluate: function (datum, valueMetadata) {
|
||||
var range = valueMetadata && valueMetadata.key;
|
||||
|
||||
SinewaveLimitProvider.prototype.supportsLimits = function (domainObject) {
|
||||
return domainObject.type === 'generator';
|
||||
};
|
||||
if (datum[range] > RED[range]) {
|
||||
return LIMITS.rh;
|
||||
}
|
||||
|
||||
SinewaveLimitProvider.prototype.getLimitEvaluator = function (domainObject) {
|
||||
return {
|
||||
evaluate: function (datum, valueMetadata) {
|
||||
var range = valueMetadata && valueMetadata.key;
|
||||
if (datum[range] < -RED[range]) {
|
||||
return LIMITS.rl;
|
||||
}
|
||||
|
||||
if (datum[range] > RED[range]) {
|
||||
return LIMITS.rh;
|
||||
}
|
||||
if (datum[range] > YELLOW[range]) {
|
||||
return LIMITS.yh;
|
||||
}
|
||||
|
||||
if (datum[range] < -RED[range]) {
|
||||
return LIMITS.rl;
|
||||
}
|
||||
|
||||
if (datum[range] > YELLOW[range]) {
|
||||
return LIMITS.yh;
|
||||
}
|
||||
|
||||
if (datum[range] < -YELLOW[range]) {
|
||||
return LIMITS.yl;
|
||||
}
|
||||
}
|
||||
if (datum[range] < -YELLOW[range]) {
|
||||
return LIMITS.yl;
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
SinewaveLimitProvider.prototype.getLimits = function (domainObject) {
|
||||
return {
|
||||
limits: function () {
|
||||
return Promise.resolve({
|
||||
WATCH: {
|
||||
low: {
|
||||
color: 'cyan',
|
||||
sin: -CYAN.sin,
|
||||
cos: -CYAN.cos
|
||||
},
|
||||
high: {
|
||||
color: 'cyan',
|
||||
...CYAN
|
||||
SinewaveLimitProvider.prototype.getLimits = function (domainObject) {
|
||||
|
||||
return {
|
||||
limits: function () {
|
||||
return Promise.resolve({
|
||||
WATCH: {
|
||||
low: {
|
||||
color: "cyan",
|
||||
sin: -CYAN.sin,
|
||||
cos: -CYAN.cos
|
||||
},
|
||||
high: {
|
||||
color: "cyan",
|
||||
...CYAN
|
||||
}
|
||||
},
|
||||
WARNING: {
|
||||
low: {
|
||||
color: "yellow",
|
||||
sin: -YELLOW.sin,
|
||||
cos: -YELLOW.cos
|
||||
},
|
||||
high: {
|
||||
color: "yellow",
|
||||
...YELLOW
|
||||
}
|
||||
},
|
||||
DISTRESS: {
|
||||
low: {
|
||||
color: "orange",
|
||||
sin: -ORANGE.sin,
|
||||
cos: -ORANGE.cos
|
||||
},
|
||||
high: {
|
||||
color: "orange",
|
||||
...ORANGE
|
||||
}
|
||||
},
|
||||
CRITICAL: {
|
||||
low: {
|
||||
color: "red",
|
||||
sin: -RED.sin,
|
||||
cos: -RED.cos
|
||||
},
|
||||
high: {
|
||||
color: "red",
|
||||
...RED
|
||||
}
|
||||
},
|
||||
SEVERE: {
|
||||
low: {
|
||||
color: "purple",
|
||||
sin: -PURPLE.sin,
|
||||
cos: -PURPLE.cos
|
||||
},
|
||||
high: {
|
||||
color: "purple",
|
||||
...PURPLE
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
WARNING: {
|
||||
low: {
|
||||
color: 'yellow',
|
||||
sin: -YELLOW.sin,
|
||||
cos: -YELLOW.cos
|
||||
},
|
||||
high: {
|
||||
color: 'yellow',
|
||||
...YELLOW
|
||||
}
|
||||
},
|
||||
DISTRESS: {
|
||||
low: {
|
||||
color: 'orange',
|
||||
sin: -ORANGE.sin,
|
||||
cos: -ORANGE.cos
|
||||
},
|
||||
high: {
|
||||
color: 'orange',
|
||||
...ORANGE
|
||||
}
|
||||
},
|
||||
CRITICAL: {
|
||||
low: {
|
||||
color: 'red',
|
||||
sin: -RED.sin,
|
||||
cos: -RED.cos
|
||||
},
|
||||
high: {
|
||||
color: 'red',
|
||||
...RED
|
||||
}
|
||||
},
|
||||
SEVERE: {
|
||||
low: {
|
||||
color: 'purple',
|
||||
sin: -PURPLE.sin,
|
||||
cos: -PURPLE.cos
|
||||
},
|
||||
high: {
|
||||
color: 'purple',
|
||||
...PURPLE
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
return SinewaveLimitProvider;
|
||||
return SinewaveLimitProvider;
|
||||
});
|
||||
|
@ -23,135 +23,135 @@
|
||||
import EventEmitter from 'EventEmitter';
|
||||
|
||||
export default class SinewaveLimitProvider extends EventEmitter {
|
||||
#openmct;
|
||||
#observingStaleness;
|
||||
#watchingTheClock;
|
||||
#isRealTime;
|
||||
#openmct;
|
||||
#observingStaleness;
|
||||
#watchingTheClock;
|
||||
#isRealTime;
|
||||
|
||||
constructor(openmct) {
|
||||
super();
|
||||
constructor(openmct) {
|
||||
super();
|
||||
|
||||
this.#openmct = openmct;
|
||||
this.#observingStaleness = {};
|
||||
this.#watchingTheClock = false;
|
||||
this.#isRealTime = undefined;
|
||||
}
|
||||
|
||||
supportsStaleness(domainObject) {
|
||||
return domainObject.type === 'generator';
|
||||
}
|
||||
|
||||
isStale(domainObject, options) {
|
||||
if (!this.#providingStaleness(domainObject)) {
|
||||
return;
|
||||
this.#openmct = openmct;
|
||||
this.#observingStaleness = {};
|
||||
this.#watchingTheClock = false;
|
||||
this.#isRealTime = undefined;
|
||||
}
|
||||
|
||||
const id = this.#getObjectKeyString(domainObject);
|
||||
|
||||
if (!this.#observerExists(id)) {
|
||||
this.#createObserver(id);
|
||||
supportsStaleness(domainObject) {
|
||||
return domainObject.type === 'generator';
|
||||
}
|
||||
|
||||
return Promise.resolve({
|
||||
isStale: this.#observingStaleness[id].isStale,
|
||||
utc: Date.now()
|
||||
});
|
||||
}
|
||||
isStale(domainObject, options) {
|
||||
if (!this.#providingStaleness(domainObject)) {
|
||||
return;
|
||||
}
|
||||
|
||||
subscribeToStaleness(domainObject, callback) {
|
||||
const id = this.#getObjectKeyString(domainObject);
|
||||
const id = this.#getObjectKeyString(domainObject);
|
||||
|
||||
if (this.#isRealTime === undefined) {
|
||||
this.#updateRealTime(this.#openmct.time.getMode());
|
||||
if (!this.#observerExists(id)) {
|
||||
this.#createObserver(id);
|
||||
}
|
||||
|
||||
return Promise.resolve({
|
||||
isStale: this.#observingStaleness[id].isStale,
|
||||
utc: Date.now()
|
||||
});
|
||||
}
|
||||
|
||||
this.#handleClockUpdate();
|
||||
subscribeToStaleness(domainObject, callback) {
|
||||
const id = this.#getObjectKeyString(domainObject);
|
||||
|
||||
if (this.#observerExists(id)) {
|
||||
this.#addCallbackToObserver(id, callback);
|
||||
} else {
|
||||
this.#createObserver(id, callback);
|
||||
if (this.#isRealTime === undefined) {
|
||||
this.#updateRealTime(this.#openmct.time.clock());
|
||||
}
|
||||
|
||||
this.#handleClockUpdate();
|
||||
|
||||
if (this.#observerExists(id)) {
|
||||
this.#addCallbackToObserver(id, callback);
|
||||
} else {
|
||||
this.#createObserver(id, callback);
|
||||
}
|
||||
|
||||
const intervalId = setInterval(() => {
|
||||
if (this.#providingStaleness(domainObject)) {
|
||||
this.#updateStaleness(id, !this.#observingStaleness[id].isStale);
|
||||
}
|
||||
}, 10000);
|
||||
|
||||
return () => {
|
||||
clearInterval(intervalId);
|
||||
this.#updateStaleness(id, false);
|
||||
this.#handleClockUpdate();
|
||||
this.#destroyObserver(id);
|
||||
};
|
||||
}
|
||||
|
||||
const intervalId = setInterval(() => {
|
||||
if (this.#providingStaleness(domainObject)) {
|
||||
this.#updateStaleness(id, !this.#observingStaleness[id].isStale);
|
||||
}
|
||||
}, 10000);
|
||||
#handleClockUpdate() {
|
||||
let observers = Object.values(this.#observingStaleness).length > 0;
|
||||
|
||||
return () => {
|
||||
clearInterval(intervalId);
|
||||
this.#updateStaleness(id, false);
|
||||
this.#handleClockUpdate();
|
||||
this.#destroyObserver(id);
|
||||
};
|
||||
}
|
||||
|
||||
#handleClockUpdate() {
|
||||
let observers = Object.values(this.#observingStaleness).length > 0;
|
||||
|
||||
if (observers && !this.#watchingTheClock) {
|
||||
this.#watchingTheClock = true;
|
||||
this.#openmct.time.on('modeChanged', this.#updateRealTime, this);
|
||||
} else if (!observers && this.#watchingTheClock) {
|
||||
this.#watchingTheClock = false;
|
||||
this.#openmct.time.off('modeChanged', this.#updateRealTime, this);
|
||||
if (observers && !this.#watchingTheClock) {
|
||||
this.#watchingTheClock = true;
|
||||
this.#openmct.time.on('clock', this.#updateRealTime, this);
|
||||
} else if (!observers && this.#watchingTheClock) {
|
||||
this.#watchingTheClock = false;
|
||||
this.#openmct.time.off('clock', this.#updateRealTime, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#updateRealTime(mode) {
|
||||
this.#isRealTime = mode !== 'fixed';
|
||||
#updateRealTime(clock) {
|
||||
this.#isRealTime = clock !== undefined;
|
||||
|
||||
if (!this.#isRealTime) {
|
||||
Object.keys(this.#observingStaleness).forEach((id) => {
|
||||
this.#updateStaleness(id, false);
|
||||
});
|
||||
if (!this.#isRealTime) {
|
||||
Object.keys(this.#observingStaleness).forEach((id) => {
|
||||
this.#updateStaleness(id, false);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#updateStaleness(id, isStale) {
|
||||
this.#observingStaleness[id].isStale = isStale;
|
||||
this.#observingStaleness[id].utc = Date.now();
|
||||
this.#observingStaleness[id].callback({
|
||||
isStale: this.#observingStaleness[id].isStale,
|
||||
utc: this.#observingStaleness[id].utc
|
||||
});
|
||||
this.emit('stalenessEvent', {
|
||||
id,
|
||||
isStale: this.#observingStaleness[id].isStale
|
||||
});
|
||||
}
|
||||
|
||||
#createObserver(id, callback) {
|
||||
this.#observingStaleness[id] = {
|
||||
isStale: false,
|
||||
utc: Date.now()
|
||||
};
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
this.#addCallbackToObserver(id, callback);
|
||||
#updateStaleness(id, isStale) {
|
||||
this.#observingStaleness[id].isStale = isStale;
|
||||
this.#observingStaleness[id].utc = Date.now();
|
||||
this.#observingStaleness[id].callback({
|
||||
isStale: this.#observingStaleness[id].isStale,
|
||||
utc: this.#observingStaleness[id].utc
|
||||
});
|
||||
this.emit('stalenessEvent', {
|
||||
id,
|
||||
isStale: this.#observingStaleness[id].isStale
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#destroyObserver(id) {
|
||||
if (this.#observingStaleness[id]) {
|
||||
delete this.#observingStaleness[id];
|
||||
#createObserver(id, callback) {
|
||||
this.#observingStaleness[id] = {
|
||||
isStale: false,
|
||||
utc: Date.now()
|
||||
};
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
this.#addCallbackToObserver(id, callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#providingStaleness(domainObject) {
|
||||
return domainObject.telemetry?.staleness === true && this.#isRealTime;
|
||||
}
|
||||
#destroyObserver(id) {
|
||||
if (this.#observingStaleness[id]) {
|
||||
delete this.#observingStaleness[id];
|
||||
}
|
||||
}
|
||||
|
||||
#getObjectKeyString(object) {
|
||||
return this.#openmct.objects.makeKeyString(object.identifier);
|
||||
}
|
||||
#providingStaleness(domainObject) {
|
||||
return domainObject.telemetry?.staleness === true && this.#isRealTime;
|
||||
}
|
||||
|
||||
#addCallbackToObserver(id, callback) {
|
||||
this.#observingStaleness[id].callback = callback;
|
||||
}
|
||||
#getObjectKeyString(object) {
|
||||
return this.#openmct.objects.makeKeyString(object.identifier);
|
||||
}
|
||||
|
||||
#observerExists(id) {
|
||||
return this.#observingStaleness?.[id];
|
||||
}
|
||||
#addCallbackToObserver(id, callback) {
|
||||
this.#observingStaleness[id].callback = callback;
|
||||
}
|
||||
|
||||
#observerExists(id) {
|
||||
return this.#observingStaleness?.[id];
|
||||
}
|
||||
}
|
||||
|
@ -20,56 +20,64 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define([], function () {
|
||||
function StateGeneratorProvider() {}
|
||||
define([
|
||||
|
||||
function pointForTimestamp(timestamp, duration, name) {
|
||||
return {
|
||||
name: name,
|
||||
utc: Math.floor(timestamp / duration) * duration,
|
||||
value: Math.floor(timestamp / duration) % 2
|
||||
};
|
||||
}
|
||||
], function (
|
||||
|
||||
StateGeneratorProvider.prototype.supportsSubscribe = function (domainObject) {
|
||||
return domainObject.type === 'example.state-generator';
|
||||
};
|
||||
) {
|
||||
|
||||
StateGeneratorProvider.prototype.subscribe = function (domainObject, callback) {
|
||||
var duration = domainObject.telemetry.duration * 1000;
|
||||
function StateGeneratorProvider() {
|
||||
|
||||
var interval = setInterval(function () {
|
||||
var now = Date.now();
|
||||
var datum = pointForTimestamp(now, duration, domainObject.name);
|
||||
datum.value = String(datum.value);
|
||||
callback(datum);
|
||||
}, duration);
|
||||
|
||||
return function () {
|
||||
clearInterval(interval);
|
||||
};
|
||||
};
|
||||
|
||||
StateGeneratorProvider.prototype.supportsRequest = function (domainObject, options) {
|
||||
return domainObject.type === 'example.state-generator';
|
||||
};
|
||||
|
||||
StateGeneratorProvider.prototype.request = function (domainObject, options) {
|
||||
var start = options.start;
|
||||
var end = Math.min(Date.now(), options.end); // no future values
|
||||
var duration = domainObject.telemetry.duration * 1000;
|
||||
if (options.strategy === 'latest' || options.size === 1) {
|
||||
start = end;
|
||||
}
|
||||
|
||||
var data = [];
|
||||
while (start <= end && data.length < 5000) {
|
||||
data.push(pointForTimestamp(start, duration, domainObject.name));
|
||||
start += duration;
|
||||
function pointForTimestamp(timestamp, duration, name) {
|
||||
return {
|
||||
name: name,
|
||||
utc: Math.floor(timestamp / duration) * duration,
|
||||
value: Math.floor(timestamp / duration) % 2
|
||||
};
|
||||
}
|
||||
|
||||
return Promise.resolve(data);
|
||||
};
|
||||
StateGeneratorProvider.prototype.supportsSubscribe = function (domainObject) {
|
||||
return domainObject.type === 'example.state-generator';
|
||||
};
|
||||
|
||||
StateGeneratorProvider.prototype.subscribe = function (domainObject, callback) {
|
||||
var duration = domainObject.telemetry.duration * 1000;
|
||||
|
||||
var interval = setInterval(function () {
|
||||
var now = Date.now();
|
||||
var datum = pointForTimestamp(now, duration, domainObject.name);
|
||||
datum.value = String(datum.value);
|
||||
callback(datum);
|
||||
}, duration);
|
||||
|
||||
return function () {
|
||||
clearInterval(interval);
|
||||
};
|
||||
};
|
||||
|
||||
StateGeneratorProvider.prototype.supportsRequest = function (domainObject, options) {
|
||||
return domainObject.type === 'example.state-generator';
|
||||
};
|
||||
|
||||
StateGeneratorProvider.prototype.request = function (domainObject, options) {
|
||||
var start = options.start;
|
||||
var end = Math.min(Date.now(), options.end); // no future values
|
||||
var duration = domainObject.telemetry.duration * 1000;
|
||||
if (options.strategy === 'latest' || options.size === 1) {
|
||||
start = end;
|
||||
}
|
||||
|
||||
var data = [];
|
||||
while (start <= end && data.length < 5000) {
|
||||
data.push(pointForTimestamp(start, duration, domainObject.name));
|
||||
start += duration;
|
||||
}
|
||||
|
||||
return Promise.resolve(data);
|
||||
};
|
||||
|
||||
return StateGeneratorProvider;
|
||||
|
||||
return StateGeneratorProvider;
|
||||
});
|
||||
|
@ -20,88 +20,93 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(['uuid'], function ({ v4: uuid }) {
|
||||
function WorkerInterface(openmct, StalenessProvider) {
|
||||
// eslint-disable-next-line no-undef
|
||||
const workerUrl = `${openmct.getAssetPath()}${__OPENMCT_ROOT_RELATIVE__}generatorWorker.js`;
|
||||
this.StalenessProvider = StalenessProvider;
|
||||
this.worker = new Worker(workerUrl);
|
||||
this.worker.onmessage = this.onMessage.bind(this);
|
||||
this.callbacks = {};
|
||||
this.staleTelemetryIds = {};
|
||||
define([
|
||||
'uuid'
|
||||
], function (
|
||||
{ v4: uuid }
|
||||
) {
|
||||
function WorkerInterface(openmct, StalenessProvider) {
|
||||
// eslint-disable-next-line no-undef
|
||||
const workerUrl = `${openmct.getAssetPath()}${__OPENMCT_ROOT_RELATIVE__}generatorWorker.js`;
|
||||
this.StalenessProvider = StalenessProvider;
|
||||
this.worker = new Worker(workerUrl);
|
||||
this.worker.onmessage = this.onMessage.bind(this);
|
||||
this.callbacks = {};
|
||||
this.staleTelemetryIds = {};
|
||||
|
||||
this.watchStaleness();
|
||||
}
|
||||
|
||||
WorkerInterface.prototype.watchStaleness = function () {
|
||||
this.StalenessProvider.on('stalenessEvent', ({ id, isStale }) => {
|
||||
this.staleTelemetryIds[id] = isStale;
|
||||
});
|
||||
};
|
||||
|
||||
WorkerInterface.prototype.onMessage = function (message) {
|
||||
message = message.data;
|
||||
var callback = this.callbacks[message.id];
|
||||
if (callback) {
|
||||
callback(message);
|
||||
this.watchStaleness();
|
||||
}
|
||||
};
|
||||
|
||||
WorkerInterface.prototype.dispatch = function (request, data, callback) {
|
||||
var message = {
|
||||
request: request,
|
||||
data: data,
|
||||
id: uuid()
|
||||
WorkerInterface.prototype.watchStaleness = function () {
|
||||
this.StalenessProvider.on('stalenessEvent', ({ id, isStale}) => {
|
||||
this.staleTelemetryIds[id] = isStale;
|
||||
});
|
||||
};
|
||||
|
||||
if (callback) {
|
||||
this.callbacks[message.id] = callback;
|
||||
}
|
||||
WorkerInterface.prototype.onMessage = function (message) {
|
||||
message = message.data;
|
||||
var callback = this.callbacks[message.id];
|
||||
if (callback) {
|
||||
callback(message);
|
||||
}
|
||||
};
|
||||
|
||||
this.worker.postMessage(message);
|
||||
WorkerInterface.prototype.dispatch = function (request, data, callback) {
|
||||
var message = {
|
||||
request: request,
|
||||
data: data,
|
||||
id: uuid()
|
||||
};
|
||||
|
||||
return message.id;
|
||||
};
|
||||
if (callback) {
|
||||
this.callbacks[message.id] = callback;
|
||||
}
|
||||
|
||||
WorkerInterface.prototype.request = function (request) {
|
||||
var deferred = {};
|
||||
var promise = new Promise(function (resolve, reject) {
|
||||
deferred.resolve = resolve;
|
||||
deferred.reject = reject;
|
||||
});
|
||||
var messageId;
|
||||
this.worker.postMessage(message);
|
||||
|
||||
let self = this;
|
||||
function callback(message) {
|
||||
if (message.error) {
|
||||
deferred.reject(message.error);
|
||||
} else {
|
||||
deferred.resolve(message.data);
|
||||
}
|
||||
return message.id;
|
||||
};
|
||||
|
||||
delete self.callbacks[messageId];
|
||||
}
|
||||
WorkerInterface.prototype.request = function (request) {
|
||||
var deferred = {};
|
||||
var promise = new Promise(function (resolve, reject) {
|
||||
deferred.resolve = resolve;
|
||||
deferred.reject = reject;
|
||||
});
|
||||
var messageId;
|
||||
|
||||
messageId = this.dispatch('request', request, callback.bind(this));
|
||||
let self = this;
|
||||
function callback(message) {
|
||||
if (message.error) {
|
||||
deferred.reject(message.error);
|
||||
} else {
|
||||
deferred.resolve(message.data);
|
||||
}
|
||||
|
||||
return promise;
|
||||
};
|
||||
delete self.callbacks[messageId];
|
||||
|
||||
WorkerInterface.prototype.subscribe = function (request, cb) {
|
||||
const { id, loadDelay } = request;
|
||||
const messageId = this.dispatch('subscribe', request, (message) => {
|
||||
if (!this.staleTelemetryIds[id]) {
|
||||
setTimeout(() => cb(message.data), Math.max(loadDelay, 0));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return function () {
|
||||
this.dispatch('unsubscribe', {
|
||||
id: messageId
|
||||
});
|
||||
delete this.callbacks[messageId];
|
||||
}.bind(this);
|
||||
};
|
||||
messageId = this.dispatch('request', request, callback.bind(this));
|
||||
|
||||
return WorkerInterface;
|
||||
return promise;
|
||||
};
|
||||
|
||||
WorkerInterface.prototype.subscribe = function (request, cb) {
|
||||
const id = request.id;
|
||||
const messageId = this.dispatch('subscribe', request, (message) => {
|
||||
if (!this.staleTelemetryIds[id]) {
|
||||
cb(message.data);
|
||||
}
|
||||
});
|
||||
|
||||
return function () {
|
||||
this.dispatch('unsubscribe', {
|
||||
id: messageId
|
||||
});
|
||||
delete this.callbacks[messageId];
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
return WorkerInterface;
|
||||
});
|
||||
|
@ -21,254 +21,204 @@
|
||||
*****************************************************************************/
|
||||
|
||||
(function () {
|
||||
var FIFTEEN_MINUTES = 15 * 60 * 1000;
|
||||
|
||||
var handlers = {
|
||||
subscribe: onSubscribe,
|
||||
unsubscribe: onUnsubscribe,
|
||||
request: onRequest
|
||||
};
|
||||
var FIFTEEN_MINUTES = 15 * 60 * 1000;
|
||||
|
||||
var subscriptions = {};
|
||||
var handlers = {
|
||||
subscribe: onSubscribe,
|
||||
unsubscribe: onUnsubscribe,
|
||||
request: onRequest
|
||||
};
|
||||
|
||||
function workSubscriptions(timestamp) {
|
||||
var now = Date.now();
|
||||
var nextWork = Math.min.apply(
|
||||
Math,
|
||||
Object.values(subscriptions).map(function (subscription) {
|
||||
return subscription(now);
|
||||
})
|
||||
);
|
||||
var wait = nextWork - now;
|
||||
if (wait < 0) {
|
||||
wait = 0;
|
||||
}
|
||||
var subscriptions = {};
|
||||
|
||||
if (Number.isFinite(wait)) {
|
||||
setTimeout(workSubscriptions, wait);
|
||||
}
|
||||
}
|
||||
|
||||
function onSubscribe(message) {
|
||||
var data = message.data;
|
||||
|
||||
// Keep
|
||||
var start = Date.now();
|
||||
var step = 1000 / data.dataRateInHz;
|
||||
var nextStep = start - (start % step) + step;
|
||||
let work;
|
||||
if (data.spectra) {
|
||||
work = function (now) {
|
||||
while (nextStep < now) {
|
||||
const messageCopy = Object.create(message);
|
||||
message.data.start = nextStep - 60 * 1000;
|
||||
message.data.end = nextStep;
|
||||
onRequest(messageCopy);
|
||||
nextStep += step;
|
||||
function workSubscriptions(timestamp) {
|
||||
var now = Date.now();
|
||||
var nextWork = Math.min.apply(Math, Object.values(subscriptions).map(function (subscription) {
|
||||
return subscription(now);
|
||||
}));
|
||||
var wait = nextWork - now;
|
||||
if (wait < 0) {
|
||||
wait = 0;
|
||||
}
|
||||
|
||||
return nextStep;
|
||||
};
|
||||
} else {
|
||||
work = function (now) {
|
||||
while (nextStep < now) {
|
||||
self.postMessage({
|
||||
if (Number.isFinite(wait)) {
|
||||
setTimeout(workSubscriptions, wait);
|
||||
}
|
||||
}
|
||||
|
||||
function onSubscribe(message) {
|
||||
var data = message.data;
|
||||
|
||||
// Keep
|
||||
var start = Date.now();
|
||||
var step = 1000 / data.dataRateInHz;
|
||||
var nextStep = start - (start % step) + step;
|
||||
let work;
|
||||
if (data.spectra) {
|
||||
work = function (now) {
|
||||
while (nextStep < now) {
|
||||
const messageCopy = Object.create(message);
|
||||
message.data.start = nextStep - (60 * 1000);
|
||||
message.data.end = nextStep;
|
||||
onRequest(messageCopy);
|
||||
nextStep += step;
|
||||
}
|
||||
|
||||
return nextStep;
|
||||
};
|
||||
} else {
|
||||
work = function (now) {
|
||||
while (nextStep < now) {
|
||||
self.postMessage({
|
||||
id: message.id,
|
||||
data: {
|
||||
name: data.name,
|
||||
utc: nextStep,
|
||||
yesterday: nextStep - 60 * 60 * 24 * 1000,
|
||||
sin: sin(nextStep, data.period, data.amplitude, data.offset, data.phase, data.randomness, data.infinityValues),
|
||||
wavelengths: wavelengths(),
|
||||
intensities: intensities(),
|
||||
cos: cos(nextStep, data.period, data.amplitude, data.offset, data.phase, data.randomness, data.infinityValues)
|
||||
}
|
||||
});
|
||||
nextStep += step;
|
||||
}
|
||||
|
||||
return nextStep;
|
||||
};
|
||||
}
|
||||
|
||||
subscriptions[message.id] = work;
|
||||
workSubscriptions();
|
||||
}
|
||||
|
||||
function onUnsubscribe(message) {
|
||||
delete subscriptions[message.data.id];
|
||||
}
|
||||
|
||||
function onRequest(message) {
|
||||
var request = message.data;
|
||||
if (request.end === undefined) {
|
||||
request.end = Date.now();
|
||||
}
|
||||
|
||||
if (request.start === undefined) {
|
||||
request.start = request.end - FIFTEEN_MINUTES;
|
||||
}
|
||||
|
||||
var now = Date.now();
|
||||
var start = request.start;
|
||||
var end = request.end > now ? now : request.end;
|
||||
var amplitude = request.amplitude;
|
||||
var period = request.period;
|
||||
var offset = request.offset;
|
||||
var dataRateInHz = request.dataRateInHz;
|
||||
var phase = request.phase;
|
||||
var randomness = request.randomness;
|
||||
var loadDelay = Math.max(request.loadDelay, 0);
|
||||
var infinityValues = request.infinityValues;
|
||||
|
||||
var step = 1000 / dataRateInHz;
|
||||
var nextStep = start - (start % step) + step;
|
||||
|
||||
var data = [];
|
||||
|
||||
for (; nextStep < end && data.length < 5000; nextStep += step) {
|
||||
data.push({
|
||||
utc: nextStep,
|
||||
yesterday: nextStep - 60 * 60 * 24 * 1000,
|
||||
sin: sin(nextStep, period, amplitude, offset, phase, randomness, infinityValues),
|
||||
wavelengths: wavelengths(),
|
||||
intensities: intensities(),
|
||||
cos: cos(nextStep, period, amplitude, offset, phase, randomness, infinityValues)
|
||||
});
|
||||
}
|
||||
|
||||
if (loadDelay === 0) {
|
||||
postOnRequest(message, request, data);
|
||||
} else {
|
||||
setTimeout(() => postOnRequest(message, request, data), loadDelay);
|
||||
}
|
||||
}
|
||||
|
||||
function postOnRequest(message, request, data) {
|
||||
self.postMessage({
|
||||
id: message.id,
|
||||
data: {
|
||||
name: data.name,
|
||||
utc: nextStep,
|
||||
yesterday: nextStep - 60 * 60 * 24 * 1000,
|
||||
sin: sin(
|
||||
nextStep,
|
||||
data.period,
|
||||
data.amplitude,
|
||||
data.offset,
|
||||
data.phase,
|
||||
data.randomness,
|
||||
data.infinityValues,
|
||||
data.veryLargeValues
|
||||
),
|
||||
wavelengths: wavelengths(),
|
||||
intensities: intensities(),
|
||||
cos: cos(
|
||||
nextStep,
|
||||
data.period,
|
||||
data.amplitude,
|
||||
data.offset,
|
||||
data.phase,
|
||||
data.randomness,
|
||||
data.infinityValues,
|
||||
data.veryLargeValues
|
||||
)
|
||||
data: request.spectra ? {
|
||||
wavelength: data.map((item) => {
|
||||
return item.wavelength;
|
||||
}),
|
||||
cos: data.map((item) => {
|
||||
return item.cos;
|
||||
})
|
||||
} : data
|
||||
});
|
||||
}
|
||||
|
||||
function cos(timestamp, period, amplitude, offset, phase, randomness, infinityValues) {
|
||||
if (infinityValues && Math.random() > 0.5) {
|
||||
return Number.POSITIVE_INFINITY;
|
||||
}
|
||||
|
||||
return amplitude
|
||||
* Math.cos(phase + (timestamp / period / 1000 * Math.PI * 2)) + (amplitude * Math.random() * randomness) + offset;
|
||||
}
|
||||
|
||||
function sin(timestamp, period, amplitude, offset, phase, randomness, infinityValues) {
|
||||
if (infinityValues && Math.random() > 0.5) {
|
||||
return Number.POSITIVE_INFINITY;
|
||||
}
|
||||
|
||||
return amplitude
|
||||
* Math.sin(phase + (timestamp / period / 1000 * Math.PI * 2)) + (amplitude * Math.random() * randomness) + offset;
|
||||
}
|
||||
|
||||
function wavelengths() {
|
||||
let values = [];
|
||||
while (values.length < 5) {
|
||||
const randomValue = Math.random() * 100;
|
||||
if (!values.includes(randomValue)) {
|
||||
values.push(String(randomValue));
|
||||
}
|
||||
});
|
||||
nextStep += step;
|
||||
}
|
||||
|
||||
return nextStep;
|
||||
};
|
||||
return values;
|
||||
}
|
||||
|
||||
subscriptions[message.id] = work;
|
||||
workSubscriptions();
|
||||
}
|
||||
|
||||
function onUnsubscribe(message) {
|
||||
delete subscriptions[message.data.id];
|
||||
}
|
||||
|
||||
function onRequest(message) {
|
||||
var request = message.data;
|
||||
if (request.end === undefined) {
|
||||
request.end = Date.now();
|
||||
}
|
||||
|
||||
if (request.start === undefined) {
|
||||
request.start = request.end - FIFTEEN_MINUTES;
|
||||
}
|
||||
|
||||
var now = Date.now();
|
||||
var start = request.start;
|
||||
var end = request.end > now ? now : request.end;
|
||||
var amplitude = request.amplitude;
|
||||
var period = request.period;
|
||||
var offset = request.offset;
|
||||
var dataRateInHz = request.dataRateInHz;
|
||||
var phase = request.phase;
|
||||
var randomness = request.randomness;
|
||||
var loadDelay = Math.max(request.loadDelay, 0);
|
||||
var infinityValues = request.infinityValues;
|
||||
var veryLargeValues = request.veryLargeValues;
|
||||
|
||||
var step = 1000 / dataRateInHz;
|
||||
var nextStep = start - (start % step) + step;
|
||||
|
||||
var data = [];
|
||||
|
||||
for (; nextStep < end && data.length < 5000; nextStep += step) {
|
||||
data.push({
|
||||
utc: nextStep,
|
||||
yesterday: nextStep - 60 * 60 * 24 * 1000,
|
||||
sin: sin(nextStep, period, amplitude, offset, phase, randomness, infinityValues, veryLargeValues),
|
||||
wavelengths: wavelengths(),
|
||||
intensities: intensities(),
|
||||
cos: cos(nextStep, period, amplitude, offset, phase, randomness, infinityValues, veryLargeValues)
|
||||
});
|
||||
}
|
||||
|
||||
if (loadDelay === 0) {
|
||||
postOnRequest(message, request, data);
|
||||
} else {
|
||||
setTimeout(() => postOnRequest(message, request, data), loadDelay);
|
||||
}
|
||||
}
|
||||
|
||||
function postOnRequest(message, request, data) {
|
||||
self.postMessage({
|
||||
id: message.id,
|
||||
data: request.spectra
|
||||
? {
|
||||
wavelength: data.map((item) => {
|
||||
return item.wavelength;
|
||||
}),
|
||||
cos: data.map((item) => {
|
||||
return item.cos;
|
||||
})
|
||||
}
|
||||
: data
|
||||
});
|
||||
}
|
||||
|
||||
function cos(timestamp, period, amplitude, offset, phase, randomness, infinityValues, veryLargeValues) {
|
||||
const randomValue = Math.random();
|
||||
|
||||
if (infinityValues && veryLargeValues) {
|
||||
if (randomValue < 0.33) return Number.POSITIVE_INFINITY;
|
||||
if (randomValue < 0.66) return (randomValue > 0.5 ? -1 : 1) * 1e+177;
|
||||
// if neither condition is met, it just proceeds to the normal return value
|
||||
} else {
|
||||
if (infinityValues && randomValue > 0.5) {
|
||||
return Number.POSITIVE_INFINITY;
|
||||
function intensities() {
|
||||
let values = [];
|
||||
while (values.length < 5) {
|
||||
const randomValue = Math.random() * 10;
|
||||
if (!values.includes(randomValue)) {
|
||||
values.push(String(randomValue));
|
||||
}
|
||||
}
|
||||
if (veryLargeValues && randomValue > 0.5) {
|
||||
return (randomValue > 0.5 ? -1 : 1) * 1e+177;
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
function sendError(error, message) {
|
||||
self.postMessage({
|
||||
error: error.name + ': ' + error.message,
|
||||
message: message,
|
||||
id: message.id
|
||||
});
|
||||
}
|
||||
|
||||
self.onmessage = function handleMessage(event) {
|
||||
var message = event.data;
|
||||
var handler = handlers[message.request];
|
||||
|
||||
if (!handler) {
|
||||
sendError(new Error('unknown message type'), message);
|
||||
} else {
|
||||
try {
|
||||
handler(message);
|
||||
} catch (e) {
|
||||
sendError(e, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
amplitude * Math.cos(phase + (timestamp / period / 1000) * Math.PI * 2) +
|
||||
amplitude * Math.random() * randomness +
|
||||
offset
|
||||
);
|
||||
}
|
||||
|
||||
function sin(timestamp, period, amplitude, offset, phase, randomness, infinityValues, veryLargeValues) {
|
||||
const randomValue = Math.random();
|
||||
|
||||
if (infinityValues && veryLargeValues) {
|
||||
if (randomValue < 0.33) return Number.POSITIVE_INFINITY;
|
||||
if (randomValue < 0.66) return (randomValue > 0.5 ? -1 : 1) * 1e+177;
|
||||
// if neither condition is met, it just proceeds to the normal return value
|
||||
} else {
|
||||
if (infinityValues && randomValue > 0.5) {
|
||||
return Number.POSITIVE_INFINITY;
|
||||
}
|
||||
if (veryLargeValues && randomValue > 0.5) {
|
||||
return (randomValue > 0.5 ? -1 : 1) * 1e+177;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
amplitude * Math.sin(phase + (timestamp / period / 1000) * Math.PI * 2) +
|
||||
amplitude * Math.random() * randomness +
|
||||
offset
|
||||
);
|
||||
}
|
||||
|
||||
function wavelengths() {
|
||||
let values = [];
|
||||
while (values.length < 5) {
|
||||
const randomValue = Math.random() * 100;
|
||||
if (!values.includes(randomValue)) {
|
||||
values.push(String(randomValue));
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
function intensities() {
|
||||
let values = [];
|
||||
while (values.length < 5) {
|
||||
const randomValue = Math.random() * 10;
|
||||
if (!values.includes(randomValue)) {
|
||||
values.push(String(randomValue));
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
function sendError(error, message) {
|
||||
self.postMessage({
|
||||
error: error.name + ': ' + error.message,
|
||||
message: message,
|
||||
id: message.id
|
||||
});
|
||||
}
|
||||
|
||||
self.onmessage = function handleMessage(event) {
|
||||
var message = event.data;
|
||||
var handler = handlers[message.request];
|
||||
|
||||
if (!handler) {
|
||||
sendError(new Error('unknown message type'), message);
|
||||
} else {
|
||||
try {
|
||||
handler(message);
|
||||
} catch (e) {
|
||||
sendError(e, message);
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
||||
}());
|
||||
|
@ -20,142 +20,163 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
import GeneratorMetadataProvider from './GeneratorMetadataProvider';
|
||||
import GeneratorProvider from './GeneratorProvider';
|
||||
import SinewaveLimitProvider from './SinewaveLimitProvider';
|
||||
import SinewaveStalenessProvider from './SinewaveStalenessProvider';
|
||||
import StateGeneratorProvider from './StateGeneratorProvider';
|
||||
import GeneratorProvider from "./GeneratorProvider";
|
||||
import SinewaveLimitProvider from "./SinewaveLimitProvider";
|
||||
import SinewaveStalenessProvider from "./SinewaveStalenessProvider";
|
||||
import StateGeneratorProvider from "./StateGeneratorProvider";
|
||||
import GeneratorMetadataProvider from "./GeneratorMetadataProvider";
|
||||
|
||||
export default function (openmct) {
|
||||
openmct.types.addType('example.state-generator', {
|
||||
name: 'State Generator',
|
||||
description:
|
||||
'For development use. Generates example enumerated telemetry by cycling through a given set of states.',
|
||||
cssClass: 'icon-generator-telemetry',
|
||||
creatable: true,
|
||||
form: [
|
||||
{
|
||||
name: 'State Duration (seconds)',
|
||||
control: 'numberfield',
|
||||
cssClass: 'l-input-sm l-numeric',
|
||||
key: 'duration',
|
||||
required: true,
|
||||
property: ['telemetry', 'duration']
|
||||
}
|
||||
],
|
||||
initialize: function (object) {
|
||||
object.telemetry = {
|
||||
duration: 5
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
openmct.telemetry.addProvider(new StateGeneratorProvider());
|
||||
openmct.types.addType("example.state-generator", {
|
||||
name: "State Generator",
|
||||
description: "For development use. Generates example enumerated telemetry by cycling through a given set of states.",
|
||||
cssClass: "icon-generator-telemetry",
|
||||
creatable: true,
|
||||
form: [
|
||||
{
|
||||
name: "State Duration (seconds)",
|
||||
control: "numberfield",
|
||||
cssClass: "l-input-sm l-numeric",
|
||||
key: "duration",
|
||||
required: true,
|
||||
property: [
|
||||
"telemetry",
|
||||
"duration"
|
||||
]
|
||||
}
|
||||
],
|
||||
initialize: function (object) {
|
||||
object.telemetry = {
|
||||
duration: 5
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
openmct.types.addType('generator', {
|
||||
name: 'Sine Wave Generator',
|
||||
description:
|
||||
'For development use. Generates example streaming telemetry data using a simple sine wave algorithm.',
|
||||
cssClass: 'icon-generator-telemetry',
|
||||
creatable: true,
|
||||
form: [
|
||||
{
|
||||
name: 'Period',
|
||||
control: 'numberfield',
|
||||
cssClass: 'l-input-sm l-numeric',
|
||||
key: 'period',
|
||||
required: true,
|
||||
property: ['telemetry', 'period']
|
||||
},
|
||||
{
|
||||
name: 'Amplitude',
|
||||
control: 'numberfield',
|
||||
cssClass: 'l-numeric',
|
||||
key: 'amplitude',
|
||||
required: true,
|
||||
property: ['telemetry', 'amplitude']
|
||||
},
|
||||
{
|
||||
name: 'Offset',
|
||||
control: 'numberfield',
|
||||
cssClass: 'l-numeric',
|
||||
key: 'offset',
|
||||
required: true,
|
||||
property: ['telemetry', 'offset']
|
||||
},
|
||||
{
|
||||
name: 'Data Rate (hz)',
|
||||
control: 'numberfield',
|
||||
cssClass: 'l-input-sm l-numeric',
|
||||
key: 'dataRateInHz',
|
||||
required: true,
|
||||
property: ['telemetry', 'dataRateInHz']
|
||||
},
|
||||
{
|
||||
name: 'Phase (radians)',
|
||||
control: 'numberfield',
|
||||
cssClass: 'l-input-sm l-numeric',
|
||||
key: 'phase',
|
||||
required: true,
|
||||
property: ['telemetry', 'phase']
|
||||
},
|
||||
{
|
||||
name: 'Randomness',
|
||||
control: 'numberfield',
|
||||
cssClass: 'l-input-sm l-numeric',
|
||||
key: 'randomness',
|
||||
required: true,
|
||||
property: ['telemetry', 'randomness']
|
||||
},
|
||||
{
|
||||
name: 'Loading Delay (ms)',
|
||||
control: 'numberfield',
|
||||
cssClass: 'l-input-sm l-numeric',
|
||||
key: 'loadDelay',
|
||||
required: true,
|
||||
property: ['telemetry', 'loadDelay']
|
||||
},
|
||||
{
|
||||
name: 'Include Infinity Values',
|
||||
control: 'toggleSwitch',
|
||||
cssClass: 'l-input',
|
||||
key: 'infinityValues',
|
||||
property: ['telemetry', 'infinityValues']
|
||||
},
|
||||
{
|
||||
name: 'Include Very Large Values',
|
||||
control: 'toggleSwitch',
|
||||
cssClass: 'l-input',
|
||||
key: 'veryLargeValues',
|
||||
property: ['telemetry', 'veryLargeValues']
|
||||
},
|
||||
{
|
||||
name: 'Provide Staleness Updates',
|
||||
control: 'toggleSwitch',
|
||||
cssClass: 'l-input',
|
||||
key: 'staleness',
|
||||
property: ['telemetry', 'staleness']
|
||||
}
|
||||
],
|
||||
initialize: function (object) {
|
||||
object.telemetry = {
|
||||
period: 10,
|
||||
amplitude: 1,
|
||||
offset: 0,
|
||||
dataRateInHz: 1,
|
||||
phase: 0,
|
||||
randomness: 0,
|
||||
loadDelay: 0,
|
||||
infinityValues: false,
|
||||
veryLargeValues: false,
|
||||
staleness: false
|
||||
};
|
||||
}
|
||||
});
|
||||
const stalenessProvider = new SinewaveStalenessProvider(openmct);
|
||||
openmct.telemetry.addProvider(new StateGeneratorProvider());
|
||||
|
||||
openmct.telemetry.addProvider(new GeneratorProvider(openmct, stalenessProvider));
|
||||
openmct.telemetry.addProvider(new GeneratorMetadataProvider());
|
||||
openmct.telemetry.addProvider(new SinewaveLimitProvider());
|
||||
openmct.telemetry.addProvider(stalenessProvider);
|
||||
openmct.types.addType("generator", {
|
||||
name: "Sine Wave Generator",
|
||||
description: "For development use. Generates example streaming telemetry data using a simple sine wave algorithm.",
|
||||
cssClass: "icon-generator-telemetry",
|
||||
creatable: true,
|
||||
form: [
|
||||
{
|
||||
name: "Period",
|
||||
control: "numberfield",
|
||||
cssClass: "l-input-sm l-numeric",
|
||||
key: "period",
|
||||
required: true,
|
||||
property: [
|
||||
"telemetry",
|
||||
"period"
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Amplitude",
|
||||
control: "numberfield",
|
||||
cssClass: "l-numeric",
|
||||
key: "amplitude",
|
||||
required: true,
|
||||
property: [
|
||||
"telemetry",
|
||||
"amplitude"
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Offset",
|
||||
control: "numberfield",
|
||||
cssClass: "l-numeric",
|
||||
key: "offset",
|
||||
required: true,
|
||||
property: [
|
||||
"telemetry",
|
||||
"offset"
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Data Rate (hz)",
|
||||
control: "numberfield",
|
||||
cssClass: "l-input-sm l-numeric",
|
||||
key: "dataRateInHz",
|
||||
required: true,
|
||||
property: [
|
||||
"telemetry",
|
||||
"dataRateInHz"
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Phase (radians)",
|
||||
control: "numberfield",
|
||||
cssClass: "l-input-sm l-numeric",
|
||||
key: "phase",
|
||||
required: true,
|
||||
property: [
|
||||
"telemetry",
|
||||
"phase"
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Randomness",
|
||||
control: "numberfield",
|
||||
cssClass: "l-input-sm l-numeric",
|
||||
key: "randomness",
|
||||
required: true,
|
||||
property: [
|
||||
"telemetry",
|
||||
"randomness"
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Loading Delay (ms)",
|
||||
control: "numberfield",
|
||||
cssClass: "l-input-sm l-numeric",
|
||||
key: "loadDelay",
|
||||
required: true,
|
||||
property: [
|
||||
"telemetry",
|
||||
"loadDelay"
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Include Infinity Values",
|
||||
control: "toggleSwitch",
|
||||
cssClass: "l-input",
|
||||
key: "infinityValues",
|
||||
property: [
|
||||
"telemetry",
|
||||
"infinityValues"
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Provide Staleness Updates",
|
||||
control: "toggleSwitch",
|
||||
cssClass: "l-input",
|
||||
key: "staleness",
|
||||
property: [
|
||||
"telemetry",
|
||||
"staleness"
|
||||
]
|
||||
}
|
||||
],
|
||||
initialize: function (object) {
|
||||
object.telemetry = {
|
||||
period: 10,
|
||||
amplitude: 1,
|
||||
offset: 0,
|
||||
dataRateInHz: 1,
|
||||
phase: 0,
|
||||
randomness: 0,
|
||||
loadDelay: 0,
|
||||
infinityValues: false,
|
||||
staleness: false
|
||||
};
|
||||
}
|
||||
});
|
||||
const stalenessProvider = new SinewaveStalenessProvider(openmct);
|
||||
|
||||
openmct.telemetry.addProvider(new GeneratorProvider(openmct, stalenessProvider));
|
||||
openmct.telemetry.addProvider(new GeneratorMetadataProvider());
|
||||
openmct.telemetry.addProvider(new SinewaveLimitProvider());
|
||||
openmct.telemetry.addProvider(stalenessProvider);
|
||||
}
|
||||
|
@ -57,9 +57,7 @@ define([
|
||||
if (isIdentifier(keyString)) {
|
||||
// TODO REMOVE FOR OMM-RELEASE-5.0
|
||||
if (!keyString.namespace && keyString.key.includes(':')) {
|
||||
console.warn(`smushed key: ${keyString.key}`);
|
||||
|
||||
return parseKeyString(keyString.key);
|
||||
console.error(`smushed key: ${keyString.key}`);
|
||||
}
|
||||
|
||||
return keyString;
|
||||
|
@ -35,34 +35,34 @@ export default class DuplicateAction {
|
||||
}
|
||||
|
||||
invoke(objectPath) {
|
||||
this.object = objectPath[0];
|
||||
this.parent = objectPath[1];
|
||||
const object = objectPath[0];
|
||||
const parent = objectPath[1];
|
||||
|
||||
this.showForm(this.object, this.parent);
|
||||
this.showForm(object, parent);
|
||||
}
|
||||
|
||||
inNavigationPath() {
|
||||
inNavigationPath(object) {
|
||||
return this.openmct.router.path
|
||||
.some(objectInPath => this.openmct.objects.areIdsEqual(objectInPath.identifier, this.object.identifier));
|
||||
.some(objectInPath => this.openmct.objects.areIdsEqual(objectInPath.identifier, object.identifier));
|
||||
}
|
||||
|
||||
async onSave(changes) {
|
||||
async onSave(object, parent, changes) {
|
||||
this.startTransaction();
|
||||
|
||||
let inNavigationPath = this.inNavigationPath();
|
||||
let inNavigationPath = this.inNavigationPath(object);
|
||||
if (inNavigationPath && this.openmct.editor.isEditing()) {
|
||||
this.openmct.editor.save();
|
||||
}
|
||||
|
||||
let duplicationTask = new DuplicateTask(this.openmct);
|
||||
if (changes.name && (changes.name !== this.object.name)) {
|
||||
if (changes.name && (changes.name !== object.name)) {
|
||||
duplicationTask.changeName(changes.name);
|
||||
}
|
||||
|
||||
const parentDomainObjectpath = changes.location || [this.parent];
|
||||
const parent = parentDomainObjectpath[0];
|
||||
const parentDomainObjectpath = changes.location || [parent];
|
||||
const parentObject = parentDomainObjectpath[0];
|
||||
|
||||
await duplicationTask.duplicate(this.object, parent);
|
||||
await duplicationTask.duplicate(object, parentObject);
|
||||
|
||||
return this.saveTransaction();
|
||||
}
|
||||
@ -88,7 +88,7 @@ export default class DuplicateAction {
|
||||
control: "locator",
|
||||
required: true,
|
||||
parent: parentDomainObject,
|
||||
validate: this.validate(parentDomainObject),
|
||||
validate: this.validate(domainObject, parentDomainObject),
|
||||
key: 'location'
|
||||
}
|
||||
]
|
||||
@ -97,16 +97,19 @@ export default class DuplicateAction {
|
||||
};
|
||||
|
||||
this.openmct.forms.showForm(formStructure)
|
||||
.then(this.onSave.bind(this));
|
||||
.then(changes => {
|
||||
let onSave = this.onSave.bind(this);
|
||||
onSave(domainObject, parentDomainObject, changes);
|
||||
});
|
||||
}
|
||||
|
||||
validate(currentParent) {
|
||||
validate(domainObject, currentParent) {
|
||||
return (data) => {
|
||||
const parentCandidate = data.value[0];
|
||||
|
||||
let currentParentKeystring = this.openmct.objects.makeKeyString(currentParent.identifier);
|
||||
let parentCandidateKeystring = this.openmct.objects.makeKeyString(parentCandidate.identifier);
|
||||
let objectKeystring = this.openmct.objects.makeKeyString(this.object.identifier);
|
||||
let objectKeystring = this.openmct.objects.makeKeyString(domainObject.identifier);
|
||||
|
||||
if (!this.openmct.objects.isPersistable(parentCandidate.identifier)) {
|
||||
return false;
|
||||
@ -125,7 +128,7 @@ export default class DuplicateAction {
|
||||
return false;
|
||||
}
|
||||
|
||||
return parentCandidate && this.openmct.composition.checkPolicy(parentCandidate, this.object);
|
||||
return parentCandidate && this.openmct.composition.checkPolicy(parentCandidate, domainObject);
|
||||
};
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user