mirror of
https://github.com/nasa/openmct.git
synced 2024-12-19 13:17:53 +00:00
[Telemetry] Update TelemetryProvider API
Based on feedback from tutorial sprint, update provider API, formatter API, and legacy adapter code. Providers can now implement separate checks for providing realtime and historical data, and providers are not registered with a specific strategy. Strategy is instead intended to be an attribute in the request options. Removed unused code in the telemetry API and simplify limitEvaluators.
This commit is contained in:
parent
8e13819e1e
commit
d9f8622459
@ -29,7 +29,8 @@ define([
|
||||
* @implements module:openmct.TelemetryAPI~TelemetryProvider
|
||||
* @constructor
|
||||
*/
|
||||
function LegacyTelemetryProvider(instantiate) {
|
||||
function LegacyTelemetryProvider(openmct, instantiate) {
|
||||
this.telemetryApi = openmct.telemetry;
|
||||
this.instantiate = instantiate;
|
||||
}
|
||||
|
||||
@ -44,23 +45,33 @@ define([
|
||||
utils.makeKeyString(domainObject.identifier)).hasCapability("telemetry");
|
||||
};
|
||||
|
||||
LegacyTelemetryProvider.prototype.supportsRequest =
|
||||
LegacyTelemetryProvider.prototype.supportsSubscribe =
|
||||
LegacyTelemetryProvider.prototype.canProvideTelemetry;
|
||||
|
||||
function createDatum(domainObject, metadata, legacySeries, i) {
|
||||
var datum;
|
||||
|
||||
if (legacySeries.getDatum) {
|
||||
return legacySeries.getDatum(i);
|
||||
datum = legacySeries.getDatum(i);
|
||||
} else {
|
||||
datum = {};
|
||||
metadata.valuesForHints(['x']).forEach(function (metadatum) {
|
||||
datum[metadatum.key] = legacySeries.getDomainValue(i, metadatum.key);
|
||||
});
|
||||
|
||||
metadata.valuesForHints(['y']).forEach(function (metadatum) {
|
||||
datum[metadatum.key] = legacySeries.getRangeValue(i, metadatum.key);
|
||||
});
|
||||
}
|
||||
var datum = {};
|
||||
|
||||
metadata.domains.reduce(function (d, domain) {
|
||||
d[domain.key] = legacySeries.getDomainValue(i, domain.key);
|
||||
return d;
|
||||
}, datum);
|
||||
|
||||
metadata.ranges.reduce(function (d, range) {
|
||||
d[range.key] = legacySeries.getRangeValue(i, range.key);
|
||||
return d;
|
||||
}, datum);
|
||||
|
||||
datum.name = domainObject.name;
|
||||
/**
|
||||
* If telemetry metadata defines a 'name' field, and one is not present
|
||||
* on the datum, add it.
|
||||
*/
|
||||
if (metadata.value('name') !== undefined && datum.name === undefined) {
|
||||
datum.name = domainObject.name;
|
||||
}
|
||||
|
||||
return datum;
|
||||
}
|
||||
@ -93,11 +104,12 @@ define([
|
||||
* telemetry data.
|
||||
*/
|
||||
LegacyTelemetryProvider.prototype.request = function (domainObject, request) {
|
||||
var metadata = this.telemetryApi.getMetadata(domainObject);
|
||||
var oldObject = this.instantiate(utils.toOldFormat(domainObject), utils.makeKeyString(domainObject.identifier));
|
||||
var capability = oldObject.getCapability("telemetry");
|
||||
|
||||
return capability.requestData(request).then(function (telemetrySeries) {
|
||||
return Promise.resolve(adaptSeries(domainObject, capability.getMetadata(), telemetrySeries));
|
||||
return Promise.resolve(adaptSeries(domainObject, metadata, telemetrySeries));
|
||||
}).catch(function (error) {
|
||||
return Promise.reject(error);
|
||||
});
|
||||
@ -118,11 +130,12 @@ define([
|
||||
* @returns {platform|telemetry.TelemetrySubscription|*}
|
||||
*/
|
||||
LegacyTelemetryProvider.prototype.subscribe = function (domainObject, callback, request) {
|
||||
var metadata = this.telemetryApi.getMetadata(domainObject);
|
||||
var oldObject = this.instantiate(utils.toOldFormat(domainObject), utils.makeKeyString(domainObject.identifier));
|
||||
var capability = oldObject.getCapability("telemetry");
|
||||
|
||||
function callbackWrapper(series) {
|
||||
callback(createDatum(domainObject, capability.getMetadata(), series, series.getPointCount() - 1));
|
||||
callback(createDatum(domainObject, metadata, series, series.getPointCount() - 1));
|
||||
}
|
||||
|
||||
return capability.subscribe(callbackWrapper, request);
|
||||
@ -134,6 +147,10 @@ define([
|
||||
utils.makeKeyString(domainObject.identifier));
|
||||
var limitEvaluator = oldObject.getCapability("limit");
|
||||
|
||||
if (!limitEvaluator) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
evaluate: function (datum, property) {
|
||||
return limitEvaluator.evaluate(datum, property.key);
|
||||
@ -142,10 +159,11 @@ define([
|
||||
};
|
||||
|
||||
return function (openmct, instantiate) {
|
||||
// Push onto the start of the default providers array so that it's
|
||||
// always the last resort
|
||||
openmct.telemetry.defaultProviders.unshift(
|
||||
new LegacyTelemetryProvider(instantiate));
|
||||
// Legacy provider should always be the fallback.
|
||||
var provider = new LegacyTelemetryProvider(openmct, instantiate);
|
||||
openmct.telemetry.legacyProvider = provider;
|
||||
openmct.telemetry.requestProviders.push(provider);
|
||||
openmct.telemetry.subscriptionProviders.push(provider);
|
||||
};
|
||||
|
||||
});
|
||||
|
@ -74,34 +74,6 @@ define([
|
||||
* @memberof module:openmct.TelemetryAPI~TelemetryFormatter#
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
// format map is a placeholder until we figure out format service.
|
||||
var FORMAT_MAP = {
|
||||
generic: function (range) {
|
||||
return function (datum) {
|
||||
return datum[range.key];
|
||||
};
|
||||
},
|
||||
enum: function (range) {
|
||||
var enumMap = _.indexBy(range.enumerations, 'value');
|
||||
return function (datum) {
|
||||
try {
|
||||
return enumMap[datum[range.valueKey]].text;
|
||||
} catch (e) {
|
||||
return datum[range.valueKey];
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
FORMAT_MAP.number =
|
||||
FORMAT_MAP.float =
|
||||
FORMAT_MAP.integer =
|
||||
FORMAT_MAP.ascii =
|
||||
FORMAT_MAP.generic;
|
||||
|
||||
/**
|
||||
* Describes a property which would be found in a datum of telemetry
|
||||
* associated with a particular domain object.
|
||||
@ -161,8 +133,8 @@ define([
|
||||
*/
|
||||
function TelemetryAPI(MCT) {
|
||||
this.MCT = MCT;
|
||||
this.providersByStrategy = {};
|
||||
this.defaultProviders = [];
|
||||
this.requestProviders = [];
|
||||
this.subscriptionProviders = [];
|
||||
this.metadataCache = new WeakMap();
|
||||
this.formatMapCache = new WeakMap();
|
||||
this.valueFormatterCache = new WeakMap();
|
||||
@ -179,9 +151,8 @@ define([
|
||||
* @memberof module:openmct.TelemetryAPI~TelemetryProvider#
|
||||
*/
|
||||
TelemetryAPI.prototype.canProvideTelemetry = function (domainObject) {
|
||||
return this.defaultProviders.some(function (provider) {
|
||||
return provider.canProvideTelemetry(domainObject);
|
||||
});
|
||||
return !!this.findSubscriptionProvider(domainObject) ||
|
||||
!!this.findRequestProvider(domainObject);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -191,39 +162,36 @@ define([
|
||||
* @memberof module:openmct.TelemetryAPI#
|
||||
* @param {module:openmct.TelemetryAPI~TelemetryProvider} provider the new
|
||||
* telemetry provider
|
||||
* @param {string} [strategy] the request strategy supported by
|
||||
* this provider. If omitted, this will be used as a
|
||||
* default provider (when no strategy is requested or no
|
||||
* matching strategy is found.)
|
||||
*/
|
||||
TelemetryAPI.prototype.addProvider = function (provider, strategy) {
|
||||
if (!strategy) {
|
||||
this.defaultProviders.push(provider);
|
||||
} else {
|
||||
this.providersByStrategy[strategy] =
|
||||
this.providersByStrategy[strategy] || [];
|
||||
this.providersByStrategy[strategy].push(provider);
|
||||
TelemetryAPI.prototype.addProvider = function (provider) {
|
||||
if (provider.supportsRequest) {
|
||||
this.requestProviders.unshift(provider);
|
||||
}
|
||||
if (provider.supportsSubscribe) {
|
||||
this.subscriptionProviders.unshift(provider);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
TelemetryAPI.prototype.findProvider = function (domainObject, strategy) {
|
||||
TelemetryAPI.prototype.findSubscriptionProvider = function (domainObject) {
|
||||
function supportsDomainObject(provider) {
|
||||
return provider.canProvideTelemetry(domainObject);
|
||||
return provider.supportsSubscribe(domainObject);
|
||||
}
|
||||
|
||||
if (strategy) {
|
||||
var eligibleProviders =
|
||||
(this.providersByStrategy[strategy] || [])
|
||||
.filter(supportsDomainObject);
|
||||
if (eligibleProviders.length > 0) {
|
||||
return eligibleProviders[0];
|
||||
}
|
||||
return this.subscriptionProviders.filter(supportsDomainObject)[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
TelemetryAPI.prototype.findRequestProvider = function (domainObject, options) {
|
||||
function supportsDomainObject(provider) {
|
||||
return provider.supportsRequest(domainObject);
|
||||
}
|
||||
|
||||
return this.defaultProviders.filter(supportsDomainObject)[0];
|
||||
return this.requestProviders.filter(supportsDomainObject)[0];
|
||||
};
|
||||
|
||||
/**
|
||||
@ -242,10 +210,29 @@ define([
|
||||
* telemetry data
|
||||
*/
|
||||
TelemetryAPI.prototype.request = function (domainObject, options) {
|
||||
var provider = this.findProvider(domainObject, options.strategy);
|
||||
return provider ?
|
||||
provider.request(domainObject, options) :
|
||||
Promise.reject([]);
|
||||
var provider = this.findRequestProvider.apply(this, arguments);
|
||||
return provider.request.apply(provider, arguments);
|
||||
};
|
||||
|
||||
/**
|
||||
* Subscribe to realtime telemetry for a specific domain object.
|
||||
* The callback will be called whenever data is received from a
|
||||
* realtime provider.
|
||||
*
|
||||
* @method subscribe
|
||||
* @memberof module:openmct.TelemetryAPI~TelemetryProvider#
|
||||
* @param {module:openmct.DomainObject} domainObject the object
|
||||
* which has associated telemetry
|
||||
* @param {Function} callback the callback to invoke with new data, as
|
||||
* it becomes available
|
||||
* @param {module:openmct.TelemetryAPI~TelemetryRequest} options
|
||||
* options for this request
|
||||
* @returns {Function} a function which may be called to terminate
|
||||
* the subscription
|
||||
*/
|
||||
TelemetryAPI.prototype.subscribe = function (domainObject, callback, options) {
|
||||
var provider = this.findSubscriptionProvider.apply(this, arguments);
|
||||
return provider.subscribe.apply(provider, arguments);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -327,53 +314,6 @@ define([
|
||||
return this.formatMapCache.get(metadata);
|
||||
};
|
||||
|
||||
/**
|
||||
* Subscribe to realtime telemetry for a specific domain object.
|
||||
* The callback will be called whenever data is received from a
|
||||
* realtime provider.
|
||||
*
|
||||
* @method subscribe
|
||||
* @memberof module:openmct.TelemetryAPI~TelemetryProvider#
|
||||
* @param {module:openmct.DomainObject} domainObject the object
|
||||
* which has associated telemetry
|
||||
* @param {Function} callback the callback to invoke with new data, as
|
||||
* it becomes available
|
||||
* @param {module:openmct.TelemetryAPI~TelemetryRequest} options
|
||||
* options for this request
|
||||
* @returns {Function} a function which may be called to terminate
|
||||
* the subscription
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get a list of all telemetry properties defined for this
|
||||
* domain object.
|
||||
*
|
||||
* @param {module:openmct.DomainObject} domainObject the domain
|
||||
* object for which to request telemetry
|
||||
* @returns {module:openmct.TelemetryAPI~TelemetryProperty[]}
|
||||
* telemetry metadata
|
||||
* @method properties
|
||||
* @memberof module:openmct.TelemetryAPI~TelemetryProvider#
|
||||
*/
|
||||
|
||||
/**
|
||||
* Telemetry formatters help you format telemetry values for
|
||||
* display. Under the covers, they use telemetry metadata to
|
||||
* interpret your telemetry data, and then they use the format API
|
||||
* to format that data for display.
|
||||
*
|
||||
* This method is optional.
|
||||
* If a provider does not implement this method, it is presumed
|
||||
* that all telemetry associated with this domain object can
|
||||
* be formatted correctly by string coercion.
|
||||
*
|
||||
* @param {module:openmct.DomainObject} domainObject the domain
|
||||
* object for which to format telemetry
|
||||
* @returns {module:openmct.TelemetryAPI~TelemetryFormatter}
|
||||
* @method formatter
|
||||
* @memberof module:openmct.TelemetryAPI~TelemetryProvider#
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get a limit evaluator for this domain object.
|
||||
* Limit Evaluators help you evaluate limit and alarm status of individual telemetry datums for display purposes without having to interact directly with the Limit API.
|
||||
@ -388,19 +328,9 @@ define([
|
||||
* @method limitEvaluator
|
||||
* @memberof module:openmct.TelemetryAPI~TelemetryProvider#
|
||||
*/
|
||||
_.forEach({
|
||||
subscribe: undefined,
|
||||
properties: [],
|
||||
formatter: undefined,
|
||||
limitEvaluator: undefined
|
||||
}, function (defaultValue, method) {
|
||||
TelemetryAPI.prototype[method] = function (domainObject) {
|
||||
var provider = this.findProvider(domainObject);
|
||||
return provider ?
|
||||
provider[method].apply(provider, arguments) :
|
||||
defaultValue;
|
||||
};
|
||||
});
|
||||
TelemetryAPI.prototype.limitEvaluator = function () {
|
||||
return this.legacyProvider.limitEvaluator.apply(this.legacyProvider, arguments);
|
||||
};
|
||||
|
||||
return TelemetryAPI;
|
||||
});
|
||||
|
@ -28,6 +28,18 @@ define([
|
||||
|
||||
// TODO: needs reference to formatService;
|
||||
function TelemetryValueFormatter(valueMetadata, formatService) {
|
||||
var numberFormatter = {
|
||||
parse: function (x) {
|
||||
return Number(x);
|
||||
},
|
||||
format: function (x) {
|
||||
return x;
|
||||
},
|
||||
validate: function (x) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
this.valueMetadata = valueMetadata;
|
||||
this.parseCache = new WeakMap();
|
||||
this.formatCache = new WeakMap();
|
||||
@ -36,17 +48,7 @@ define([
|
||||
.getFormat(valueMetadata.format, valueMetadata);
|
||||
} catch (e) {
|
||||
// TODO: Better formatting
|
||||
this.formatter = {
|
||||
parse: function (x) {
|
||||
return Number(x);
|
||||
},
|
||||
format: function (x) {
|
||||
return x;
|
||||
},
|
||||
validate: function (x) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
this.formatter = numberFormatter;
|
||||
}
|
||||
|
||||
if (valueMetadata.type === 'enum') {
|
||||
|
Loading…
Reference in New Issue
Block a user