mirror of
https://github.com/nasa/openmct.git
synced 2025-04-07 19:34:25 +00:00
[Code Style] Use prototypes in telemetry bundle
WTD-1482
This commit is contained in:
parent
1ea6f7620e
commit
2ccca016a5
@ -42,154 +42,147 @@ define(
|
||||
* at the specific data which is appropriate to the domain object.)
|
||||
*
|
||||
* @memberof platform/telemetry
|
||||
* @implements {Capability}
|
||||
* @constructor
|
||||
*/
|
||||
function TelemetryCapability($injector, $q, $log, domainObject) {
|
||||
var telemetryService,
|
||||
subscriptions = [],
|
||||
unsubscribeFunction;
|
||||
|
||||
// We could depend on telemetryService directly, but
|
||||
// there isn't a platform implementation of this;
|
||||
function getTelemetryService() {
|
||||
if (telemetryService === undefined) {
|
||||
try {
|
||||
telemetryService =
|
||||
$injector.get("telemetryService");
|
||||
} catch (e) {
|
||||
// $injector should throw if telemetryService
|
||||
// is unavailable or unsatisfiable.
|
||||
$log.warn("Telemetry service unavailable");
|
||||
telemetryService = null;
|
||||
}
|
||||
// there isn't a platform implementation of this.
|
||||
this.initializeTelemetryService = function () {
|
||||
try {
|
||||
return (this.telemetryService =
|
||||
$injector.get("telemetryService"));
|
||||
} catch (e) {
|
||||
// $injector should throw if telemetryService
|
||||
// is unavailable or unsatisfiable.
|
||||
$log.warn("Telemetry service unavailable");
|
||||
return (this.telemetryService = null);
|
||||
}
|
||||
return telemetryService;
|
||||
}
|
||||
|
||||
// Build a request object. This takes the request that was
|
||||
// passed to the capability, and adds source, id, and key
|
||||
// fields associated with the object (from its type definition
|
||||
// and/or its model)
|
||||
function buildRequest(request) {
|
||||
// Start with any "telemetry" field in type; use that as a
|
||||
// basis for the request.
|
||||
var type = domainObject.getCapability("type"),
|
||||
typeRequest = (type && type.getDefinition().telemetry) || {},
|
||||
modelTelemetry = domainObject.getModel().telemetry,
|
||||
fullRequest = Object.create(typeRequest);
|
||||
|
||||
// Add properties from the telemetry field of this
|
||||
// specific domain object.
|
||||
Object.keys(modelTelemetry).forEach(function (k) {
|
||||
fullRequest[k] = modelTelemetry[k];
|
||||
});
|
||||
|
||||
// Add properties from this specific requestData call.
|
||||
Object.keys(request).forEach(function (k) {
|
||||
fullRequest[k] = request[k];
|
||||
});
|
||||
|
||||
// Ensure an ID and key are present
|
||||
if (!fullRequest.id) {
|
||||
fullRequest.id = domainObject.getId();
|
||||
}
|
||||
if (!fullRequest.key) {
|
||||
fullRequest.key = domainObject.getId();
|
||||
}
|
||||
|
||||
return fullRequest;
|
||||
}
|
||||
|
||||
// Issue a request for telemetry data
|
||||
function requestTelemetry(request) {
|
||||
// Bring in any defaults from the object model
|
||||
var fullRequest = buildRequest(request || {}),
|
||||
source = fullRequest.source,
|
||||
key = fullRequest.key;
|
||||
|
||||
// Pull out the relevant field from the larger,
|
||||
// structured response.
|
||||
function getRelevantResponse(response) {
|
||||
return ((response || {})[source] || {})[key] ||
|
||||
EMPTY_SERIES;
|
||||
}
|
||||
|
||||
// Issue a request to the service
|
||||
function requestTelemetryFromService() {
|
||||
return telemetryService.requestTelemetry([fullRequest]);
|
||||
}
|
||||
|
||||
// If a telemetryService is not available,
|
||||
// getTelemetryService() should reject, and this should
|
||||
// bubble through subsequent then calls.
|
||||
return getTelemetryService() &&
|
||||
requestTelemetryFromService()
|
||||
.then(getRelevantResponse);
|
||||
}
|
||||
|
||||
// Listen for real-time and/or streaming updates
|
||||
function subscribe(callback, request) {
|
||||
var fullRequest = buildRequest(request || {});
|
||||
|
||||
// Unpack the relevant telemetry series
|
||||
function update(telemetries) {
|
||||
var source = fullRequest.source,
|
||||
key = fullRequest.key,
|
||||
result = ((telemetries || {})[source] || {})[key];
|
||||
if (result) {
|
||||
callback(result);
|
||||
}
|
||||
}
|
||||
|
||||
return getTelemetryService() &&
|
||||
telemetryService.subscribe(update, [fullRequest]);
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* Request telemetry data for this specific domain object.
|
||||
* @param {TelemetryRequest} [request] parameters for this
|
||||
* specific request
|
||||
* @returns {Promise} a promise for the resulting telemetry
|
||||
* object
|
||||
* @memberof platform/telemetry.TelemetryCapability#
|
||||
*/
|
||||
requestData: requestTelemetry,
|
||||
|
||||
/**
|
||||
* Get metadata about this domain object's associated
|
||||
* telemetry.
|
||||
* @memberof platform/telemetry.TelemetryCapability#
|
||||
*/
|
||||
getMetadata: function () {
|
||||
// metadata just looks like a request,
|
||||
// so use buildRequest to bring in both
|
||||
// type-level and object-level telemetry
|
||||
// properties
|
||||
return buildRequest({});
|
||||
},
|
||||
|
||||
/**
|
||||
* Subscribe to updates to telemetry data for this domain
|
||||
* object.
|
||||
* @param {Function} callback a function to call when new
|
||||
* data becomes available; the telemetry series
|
||||
* containing the data will be given as an argument.
|
||||
* @param {TelemetryRequest} [request] parameters for the
|
||||
* subscription request
|
||||
* @memberof platform/telemetry.TelemetryCapability#
|
||||
*/
|
||||
subscribe: subscribe
|
||||
};
|
||||
|
||||
|
||||
this.$q = $q;
|
||||
this.$log = $log;
|
||||
this.domainObject = domainObject;
|
||||
}
|
||||
|
||||
// Build a request object. This takes the request that was
|
||||
// passed to the capability, and adds source, id, and key
|
||||
// fields associated with the object (from its type definition
|
||||
// and/or its model)
|
||||
TelemetryCapability.prototype.buildRequest = function (request) {
|
||||
// Start with any "telemetry" field in type; use that as a
|
||||
// basis for the request.
|
||||
var domainObject = this.domainObject,
|
||||
type = domainObject.getCapability("type"),
|
||||
typeRequest = (type && type.getDefinition().telemetry) || {},
|
||||
modelTelemetry = domainObject.getModel().telemetry,
|
||||
fullRequest = Object.create(typeRequest);
|
||||
|
||||
// Add properties from the telemetry field of this
|
||||
// specific domain object.
|
||||
Object.keys(modelTelemetry).forEach(function (k) {
|
||||
fullRequest[k] = modelTelemetry[k];
|
||||
});
|
||||
|
||||
// Add properties from this specific requestData call.
|
||||
Object.keys(request).forEach(function (k) {
|
||||
fullRequest[k] = request[k];
|
||||
});
|
||||
|
||||
// Ensure an ID and key are present
|
||||
if (!fullRequest.id) {
|
||||
fullRequest.id = domainObject.getId();
|
||||
}
|
||||
if (!fullRequest.key) {
|
||||
fullRequest.key = domainObject.getId();
|
||||
}
|
||||
|
||||
return fullRequest;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Request telemetry data for this specific domain object.
|
||||
* @param {TelemetryRequest} [request] parameters for this
|
||||
* specific request
|
||||
* @returns {Promise} a promise for the resulting telemetry
|
||||
* object
|
||||
*/
|
||||
TelemetryCapability.prototype.requestData = function requestTelemetry(request) {
|
||||
// Bring in any defaults from the object model
|
||||
var fullRequest = this.buildRequest(request || {}),
|
||||
source = fullRequest.source,
|
||||
key = fullRequest.key,
|
||||
telemetryService = this.telemetryService ||
|
||||
this.initializeTelemetryService(); // Lazy initialization
|
||||
|
||||
// Pull out the relevant field from the larger,
|
||||
// structured response.
|
||||
function getRelevantResponse(response) {
|
||||
return ((response || {})[source] || {})[key] ||
|
||||
EMPTY_SERIES;
|
||||
}
|
||||
|
||||
// Issue a request to the service
|
||||
function requestTelemetryFromService() {
|
||||
return telemetryService.requestTelemetry([fullRequest]);
|
||||
}
|
||||
|
||||
// If a telemetryService is not available,
|
||||
// getTelemetryService() should reject, and this should
|
||||
// bubble through subsequent then calls.
|
||||
return telemetryService &&
|
||||
requestTelemetryFromService().then(getRelevantResponse);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get metadata about this domain object's associated
|
||||
* telemetry.
|
||||
* @returns {TelemetryMetadata} metadata about this object's telemetry
|
||||
*/
|
||||
TelemetryCapability.prototype.getMetadata = function () {
|
||||
// metadata just looks like a request,
|
||||
// so use buildRequest to bring in both
|
||||
// type-level and object-level telemetry
|
||||
// properties
|
||||
return (this.metadata = this.metadata || this.buildRequest({}));
|
||||
};
|
||||
|
||||
/**
|
||||
* Subscribe to updates to telemetry data for this domain
|
||||
* object.
|
||||
* @param {Function} callback a function to call when new
|
||||
* data becomes available; the telemetry series
|
||||
* containing the data will be given as an argument.
|
||||
* @param {TelemetryRequest} [request] parameters for the
|
||||
* subscription request
|
||||
*/
|
||||
TelemetryCapability.prototype.subscribe = function subscribe(callback, request) {
|
||||
var fullRequest = this.buildRequest(request || {}),
|
||||
telemetryService = this.telemetryService ||
|
||||
this.initializeTelemetryService(); // Lazy initialization
|
||||
|
||||
// Unpack the relevant telemetry series
|
||||
function update(telemetries) {
|
||||
var source = fullRequest.source,
|
||||
key = fullRequest.key,
|
||||
result = ((telemetries || {})[source] || {})[key];
|
||||
if (result) {
|
||||
callback(result);
|
||||
}
|
||||
}
|
||||
|
||||
return telemetryService &&
|
||||
telemetryService.subscribe(update, [fullRequest]);
|
||||
};
|
||||
|
||||
/**
|
||||
* The telemetry capability is applicable when a
|
||||
* domain object model has a "telemetry" field.
|
||||
*/
|
||||
TelemetryCapability.appliesTo = function (model) {
|
||||
return (model &&
|
||||
model.telemetry) ? true : false;
|
||||
return (model && model.telemetry) ? true : false;
|
||||
};
|
||||
|
||||
return TelemetryCapability;
|
||||
|
@ -36,6 +36,7 @@ define(
|
||||
*
|
||||
* @memberof platform/telemetry
|
||||
* @constructor
|
||||
* @deprecated use platform/telemetry.TelemetryHandler instead
|
||||
*/
|
||||
function TelemetryController($scope, $q, $timeout, $log) {
|
||||
|
||||
|
@ -33,37 +33,40 @@ define(
|
||||
* @memberof platform/telemetry
|
||||
*/
|
||||
function TelemetryDelegator($q) {
|
||||
return {
|
||||
/**
|
||||
* Promise telemetry-providing objects associated with
|
||||
* this domain object (either the domain object itself,
|
||||
* or the objects it delegates)
|
||||
* @returns {Promise.<DomainObject[]>} domain objects with
|
||||
* a telemetry capability
|
||||
* @memberof platform/telemetry.TelemetryDelegator#
|
||||
*/
|
||||
promiseTelemetryObjects: function (domainObject) {
|
||||
// If object has been cleared, there are no relevant
|
||||
// telemetry-providing domain objects.
|
||||
if (!domainObject) {
|
||||
return $q.when([]);
|
||||
}
|
||||
|
||||
// Otherwise, try delegation first, and attach the
|
||||
// object itself if it has a telemetry capability.
|
||||
return $q.when(domainObject.useCapability(
|
||||
"delegation",
|
||||
"telemetry"
|
||||
)).then(function (result) {
|
||||
var head = domainObject.hasCapability("telemetry") ?
|
||||
[ domainObject ] : [],
|
||||
tail = result || [];
|
||||
return head.concat(tail);
|
||||
});
|
||||
}
|
||||
};
|
||||
this.$q = $q;
|
||||
}
|
||||
|
||||
/**
|
||||
* Promise telemetry-providing objects associated with
|
||||
* this domain object (either the domain object itself,
|
||||
* or the objects it delegates)
|
||||
* @param {DomainObject} the domain object which may have
|
||||
* or delegate telemetry
|
||||
* @returns {Promise.<DomainObject[]>} domain objects with
|
||||
* a telemetry capability
|
||||
*/
|
||||
TelemetryDelegator.prototype.promiseTelemetryObjects = function (domainObject) {
|
||||
var $q = this.$q;
|
||||
|
||||
// If object has been cleared, there are no relevant
|
||||
// telemetry-providing domain objects.
|
||||
if (!domainObject) {
|
||||
return $q.when([]);
|
||||
}
|
||||
|
||||
// Otherwise, try delegation first, and attach the
|
||||
// object itself if it has a telemetry capability.
|
||||
return $q.when(domainObject.useCapability(
|
||||
"delegation",
|
||||
"telemetry"
|
||||
)).then(function (result) {
|
||||
var head = domainObject.hasCapability("telemetry") ?
|
||||
[ domainObject ] : [],
|
||||
tail = result || [];
|
||||
return head.concat(tail);
|
||||
});
|
||||
};
|
||||
|
||||
return TelemetryDelegator;
|
||||
}
|
||||
);
|
||||
|
@ -39,41 +39,35 @@ define(
|
||||
* @constructor
|
||||
*/
|
||||
function TelemetryFormatter() {
|
||||
function formatDomainValue(v, key) {
|
||||
return isNaN(v) ? "" : moment.utc(v).format(DATE_FORMAT);
|
||||
}
|
||||
|
||||
function formatRangeValue(v, key) {
|
||||
return isNaN(v) ? v : v.toFixed(3);
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* Format a domain value.
|
||||
* @param {number} v the domain value; a timestamp
|
||||
* in milliseconds since start of 1970
|
||||
* @param {string} [key] the key which identifies the
|
||||
* domain; if unspecified or unknown, this will
|
||||
* be treated as a standard timestamp.
|
||||
* @returns {string} a textual representation of the
|
||||
* data and time, suitable for display.
|
||||
* @memberof platform/telemetry.TelemetryFormatter#
|
||||
*/
|
||||
formatDomainValue: formatDomainValue,
|
||||
/**
|
||||
* Format a range value.
|
||||
* @param {number} v the range value; a numeric value
|
||||
* @param {string} [key] the key which identifies the
|
||||
* range; if unspecified or unknown, this will
|
||||
* be treated as a numeric value.
|
||||
* @returns {string} a textual representation of the
|
||||
* value, suitable for display.
|
||||
* @memberof platform/telemetry.TelemetryFormatter#
|
||||
*/
|
||||
formatRangeValue: formatRangeValue
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a domain value.
|
||||
* @param {number} v the domain value; a timestamp
|
||||
* in milliseconds since start of 1970
|
||||
* @param {string} [key] the key which identifies the
|
||||
* domain; if unspecified or unknown, this will
|
||||
* be treated as a standard timestamp.
|
||||
* @returns {string} a textual representation of the
|
||||
* data and time, suitable for display.
|
||||
*/
|
||||
TelemetryFormatter.prototype.formatDomainValue = function (v, key) {
|
||||
return isNaN(v) ? "" : moment.utc(v).format(DATE_FORMAT);
|
||||
};
|
||||
|
||||
/**
|
||||
* Format a range value.
|
||||
* @param {number} v the range value; a numeric value
|
||||
* @param {string} [key] the key which identifies the
|
||||
* range; if unspecified or unknown, this will
|
||||
* be treated as a numeric value.
|
||||
* @returns {string} a textual representation of the
|
||||
* value, suitable for display.
|
||||
*/
|
||||
TelemetryFormatter.prototype.formatRangeValue = function (v, key) {
|
||||
return isNaN(v) ? String(v) : v.toFixed(VALUE_FORMAT_DIGITS);
|
||||
};
|
||||
|
||||
return TelemetryFormatter;
|
||||
}
|
||||
);
|
||||
|
@ -36,19 +36,31 @@ define(
|
||||
* @param $q Angular's $q
|
||||
*/
|
||||
function TelemetryHandler($q, telemetrySubscriber) {
|
||||
return {
|
||||
handle: function (domainObject, callback, lossless) {
|
||||
var subscription = telemetrySubscriber.subscribe(
|
||||
domainObject,
|
||||
callback,
|
||||
lossless
|
||||
);
|
||||
|
||||
return new TelemetryHandle($q, subscription);
|
||||
}
|
||||
};
|
||||
this.$q = $q;
|
||||
this.telemetrySubscriber = telemetrySubscriber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start receiving telemetry associated with this domain object
|
||||
* (either directly, or via delegation.)
|
||||
* @param {DomainObject} domainObject the domain object
|
||||
* @param {Function} callback callback to invoke when new data is
|
||||
* available
|
||||
* @param {boolean} lossless true if the callback should be invoked
|
||||
* one separate time for each new latest value
|
||||
* @returns {TelemetryHandle} a handle to telemetry data
|
||||
* associated with this object
|
||||
*/
|
||||
TelemetryHandler.prototype.handle = function (domainObject, callback, lossless) {
|
||||
var subscription = this.telemetrySubscriber.subscribe(
|
||||
domainObject,
|
||||
callback,
|
||||
lossless
|
||||
);
|
||||
|
||||
return new TelemetryHandle(this.$q, subscription);
|
||||
};
|
||||
|
||||
return TelemetryHandler;
|
||||
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ define(
|
||||
* objects.)
|
||||
* @memberof platform/telemetry
|
||||
* @constructor
|
||||
* @implements {platform/telemetry.TelemetryPool}
|
||||
*/
|
||||
function TelemetryQueue() {
|
||||
// General approach here:
|
||||
@ -60,9 +61,37 @@ define(
|
||||
// 0 1 2 3 4
|
||||
// a * * * * *
|
||||
// b * * *
|
||||
// c * * *
|
||||
var queue = [],
|
||||
counts = {};
|
||||
// c * * *
|
||||
|
||||
this.queue = [];
|
||||
this.counts = {};
|
||||
}
|
||||
|
||||
|
||||
TelemetryQueue.prototype.isEmpty = function () {
|
||||
return this.queue.length < 1;
|
||||
};
|
||||
|
||||
TelemetryQueue.prototype.poll = function () {
|
||||
var counts = this.counts;
|
||||
|
||||
// Decrement counts for a specific key
|
||||
function decrementCount(key) {
|
||||
if (counts[key] < 2) {
|
||||
delete counts[key];
|
||||
} else {
|
||||
counts[key] -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Decrement counts for the object that will be popped
|
||||
Object.keys(counts).forEach(decrementCount);
|
||||
return this.queue.shift();
|
||||
};
|
||||
|
||||
TelemetryQueue.prototype.put = function (key, value) {
|
||||
var queue = this.queue,
|
||||
counts = this.counts;
|
||||
|
||||
// Look up an object in the queue that does not have a value
|
||||
// assigned to this key (or, add a new one)
|
||||
@ -71,7 +100,7 @@ define(
|
||||
|
||||
// Track the largest free position for this key
|
||||
counts[key] = index + 1;
|
||||
|
||||
|
||||
// If it's before the end of the queue, add it there
|
||||
if (index < queue.length) {
|
||||
return queue[index];
|
||||
@ -84,54 +113,9 @@ define(
|
||||
queue.push(object);
|
||||
return object;
|
||||
}
|
||||
|
||||
// Decrement counts for a specific key
|
||||
function decrementCount(key) {
|
||||
if (counts[key] < 2) {
|
||||
delete counts[key];
|
||||
} else {
|
||||
counts[key] -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Decrement all counts
|
||||
function decrementCounts() {
|
||||
Object.keys(counts).forEach(decrementCount);
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* Check if any value groups remain in this pool.
|
||||
* @return {boolean} true if value groups remain
|
||||
* @memberof platform/telemetry.TelemetryQueue#
|
||||
*/
|
||||
isEmpty: function () {
|
||||
return queue.length < 1;
|
||||
},
|
||||
/**
|
||||
* Retrieve the next value group from this pool.
|
||||
* This gives an object containing key-value pairs,
|
||||
* where keys and values correspond to the arguments
|
||||
* given to previous put functions.
|
||||
* @return {object} key-value pairs
|
||||
* @memberof platform/telemetry.TelemetryQueue#
|
||||
*/
|
||||
poll: function () {
|
||||
// Decrement counts for the object that will be popped
|
||||
decrementCounts();
|
||||
return queue.shift();
|
||||
},
|
||||
/**
|
||||
* Put a key-value pair into the pool.
|
||||
* @param {string} key the key to store the value under
|
||||
* @param {*} value the value to store
|
||||
* @memberof platform/telemetry.TelemetryQueue#
|
||||
*/
|
||||
put: function (key, value) {
|
||||
getFreeObject(key)[key] = value;
|
||||
}
|
||||
};
|
||||
}
|
||||
getFreeObject(key)[key] = value;
|
||||
};
|
||||
|
||||
return TelemetryQueue;
|
||||
}
|
||||
|
@ -44,39 +44,36 @@ define(
|
||||
* @param $timeout Angular's $timeout
|
||||
*/
|
||||
function TelemetrySubscriber($q, $timeout) {
|
||||
return {
|
||||
/**
|
||||
* Subscribe to streaming telemetry updates
|
||||
* associated with this domain object (either
|
||||
* directly or via capability delegation.)
|
||||
*
|
||||
* @param {DomainObject} domainObject the object whose
|
||||
* associated telemetry data is of interest
|
||||
* @param {Function} callback a function to invoke
|
||||
* when new data has become available.
|
||||
* @param {boolean} lossless flag to indicate whether the
|
||||
* callback should be notified for all values
|
||||
* (otherwise, multiple values in quick succession
|
||||
* will call back with only the latest value.)
|
||||
* @returns {TelemetrySubscription} the subscription,
|
||||
* which will provide access to latest values.
|
||||
*
|
||||
* @method
|
||||
* @memberof TelemetrySubscriber
|
||||
* @memberof platform/telemetry.TelemetrySubscriber#
|
||||
*/
|
||||
subscribe: function (domainObject, callback, lossless) {
|
||||
return new TelemetrySubscription(
|
||||
$q,
|
||||
$timeout,
|
||||
domainObject,
|
||||
callback,
|
||||
lossless
|
||||
);
|
||||
}
|
||||
};
|
||||
this.$q = $q;
|
||||
this.$timeout = $timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribe to streaming telemetry updates
|
||||
* associated with this domain object (either
|
||||
* directly or via capability delegation.)
|
||||
*
|
||||
* @param {DomainObject} domainObject the object whose
|
||||
* associated telemetry data is of interest
|
||||
* @param {Function} callback a function to invoke
|
||||
* when new data has become available.
|
||||
* @param {boolean} lossless flag to indicate whether the
|
||||
* callback should be notified for all values
|
||||
* (otherwise, multiple values in quick succession
|
||||
* will call back with only the latest value.)
|
||||
* @returns {platform/telemetry.TelemetrySubscription} the
|
||||
* subscription, which will provide access to latest values.
|
||||
*/
|
||||
TelemetrySubscriber.prototype.subscribe = function (domainObject, callback, lossless) {
|
||||
return new TelemetrySubscription(
|
||||
this.$q,
|
||||
this.$timeout,
|
||||
domainObject,
|
||||
callback,
|
||||
lossless
|
||||
);
|
||||
};
|
||||
|
||||
return TelemetrySubscriber;
|
||||
}
|
||||
);
|
||||
|
@ -26,6 +26,32 @@ define(
|
||||
function (TelemetryQueue, TelemetryTable, TelemetryDelegator) {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* A pool of telemetry values.
|
||||
* @interface platform/telemetry.TelemetryPool
|
||||
* @private
|
||||
*/
|
||||
/**
|
||||
* Check if any value groups remain in this pool.
|
||||
* @return {boolean} true if value groups remain
|
||||
* @method platform/telemetry.TelemetryPool#isEmpty
|
||||
*/
|
||||
/**
|
||||
* Retrieve the next value group from this pool.
|
||||
* This gives an object containing key-value pairs,
|
||||
* where keys and values correspond to the arguments
|
||||
* given to previous put functions.
|
||||
* @return {object} key-value pairs
|
||||
* @method platform/telemetry.TelemetryPool#poll
|
||||
*/
|
||||
/**
|
||||
* Put a key-value pair into the pool.
|
||||
* @param {string} key the key to store the value under
|
||||
* @param {*} value the value to store
|
||||
* @method platform/telemetry.TelemetryPool#put
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* A TelemetrySubscription tracks latest values for streaming
|
||||
* telemetry data and handles notifying interested observers.
|
||||
@ -52,14 +78,9 @@ define(
|
||||
* the callback once, with access to the latest data
|
||||
*/
|
||||
function TelemetrySubscription($q, $timeout, domainObject, callback, lossless) {
|
||||
var delegator = new TelemetryDelegator($q),
|
||||
unsubscribePromise,
|
||||
telemetryObjectPromise,
|
||||
latestValues = {},
|
||||
telemetryObjects = [],
|
||||
var self = this,
|
||||
delegator = new TelemetryDelegator($q),
|
||||
pool = lossless ? new TelemetryQueue() : new TelemetryTable(),
|
||||
metadatas,
|
||||
unlistenToMutation,
|
||||
updatePending;
|
||||
|
||||
// Look up domain objects which have telemetry capabilities.
|
||||
@ -72,7 +93,7 @@ define(
|
||||
function updateValuesFromPool() {
|
||||
var values = pool.poll();
|
||||
Object.keys(values).forEach(function (k) {
|
||||
latestValues[k] = values[k];
|
||||
self.latestValues[k] = values[k];
|
||||
});
|
||||
}
|
||||
|
||||
@ -165,8 +186,8 @@ define(
|
||||
// initial subscription chain; this allows `getTelemetryObjects()`
|
||||
// to return a non-Promise to simplify usage elsewhere.
|
||||
function cacheObjectReferences(objects) {
|
||||
telemetryObjects = objects;
|
||||
metadatas = objects.map(lookupMetadata);
|
||||
self.telemetryObjects = objects;
|
||||
self.metadatas = objects.map(lookupMetadata);
|
||||
// Fire callback, as this will be the first time that
|
||||
// telemetry objects are available, or these objects
|
||||
// will have changed.
|
||||
@ -176,14 +197,6 @@ define(
|
||||
return objects;
|
||||
}
|
||||
|
||||
function unsubscribeAll() {
|
||||
return unsubscribePromise.then(function (unsubscribes) {
|
||||
return $q.all(unsubscribes.map(function (unsubscribe) {
|
||||
return unsubscribe();
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
// Get a reference to relevant objects (those with telemetry
|
||||
// capabilities) and subscribe to their telemetry updates.
|
||||
@ -191,23 +204,23 @@ define(
|
||||
// will be unsubscribe functions. (This must be a promise
|
||||
// because delegation is supported, and retrieving delegate
|
||||
// telemetry-capable objects may be an asynchronous operation.)
|
||||
telemetryObjectPromise = promiseRelevantObjects(domainObject);
|
||||
unsubscribePromise = telemetryObjectPromise
|
||||
self.telemetryObjectPromise = promiseRelevantObjects(domainObject);
|
||||
self.unsubscribePromise = self.telemetryObjectPromise
|
||||
.then(cacheObjectReferences)
|
||||
.then(subscribeAll);
|
||||
}
|
||||
|
||||
function idsMatch(ids) {
|
||||
return ids.length === telemetryObjects.length &&
|
||||
return ids.length === self.telemetryObjects.length &&
|
||||
ids.every(function (id, index) {
|
||||
return telemetryObjects[index].getId() === id;
|
||||
return self.telemetryObjects[index].getId() === id;
|
||||
});
|
||||
}
|
||||
|
||||
function modelChange(model) {
|
||||
if (!idsMatch((model || {}).composition || [])) {
|
||||
// Reinitialize if composition has changed
|
||||
unsubscribeAll().then(initialize);
|
||||
self.unsubscribeAll().then(initialize);
|
||||
}
|
||||
}
|
||||
|
||||
@ -219,122 +232,126 @@ define(
|
||||
}
|
||||
}
|
||||
|
||||
initialize();
|
||||
unlistenToMutation = addMutationListener();
|
||||
this.$q = $q;
|
||||
this.latestValues = {};
|
||||
this.telemetryObjects = [];
|
||||
this.metadatas = [];
|
||||
|
||||
return {
|
||||
/**
|
||||
* Terminate all underlying subscriptions associated
|
||||
* with this object.
|
||||
* @method
|
||||
* @memberof TelemetrySubscription
|
||||
* @memberof platform/telemetry.TelemetrySubscription#
|
||||
*/
|
||||
unsubscribe: function () {
|
||||
if (unlistenToMutation) {
|
||||
unlistenToMutation();
|
||||
}
|
||||
return unsubscribeAll();
|
||||
},
|
||||
/**
|
||||
* Get the most recent domain value that has been observed
|
||||
* for the specified domain object. This will typically be
|
||||
* a timestamp.
|
||||
*
|
||||
* The domain object passed here should be one that is
|
||||
* subscribed-to here; that is, it should be one of the
|
||||
* domain objects returned by `getTelemetryObjects()`.
|
||||
*
|
||||
* @param {DomainObject} domainObject the object of interest
|
||||
* @returns the most recent domain value observed
|
||||
* @method
|
||||
* @memberof TelemetrySubscription
|
||||
* @memberof platform/telemetry.TelemetrySubscription#
|
||||
*/
|
||||
getDomainValue: function (domainObject) {
|
||||
var id = domainObject.getId();
|
||||
return (latestValues[id] || {}).domain;
|
||||
},
|
||||
/**
|
||||
* Get the most recent range value that has been observed
|
||||
* for the specified domain object. This will typically
|
||||
* be a numeric measurement.
|
||||
*
|
||||
* The domain object passed here should be one that is
|
||||
* subscribed-to here; that is, it should be one of the
|
||||
* domain objects returned by `getTelemetryObjects()`.
|
||||
*
|
||||
* @param {DomainObject} domainObject the object of interest
|
||||
* @returns the most recent range value observed
|
||||
* @method
|
||||
* @memberof TelemetrySubscription
|
||||
* @memberof platform/telemetry.TelemetrySubscription#
|
||||
*/
|
||||
getRangeValue: function (domainObject) {
|
||||
var id = domainObject.getId();
|
||||
return (latestValues[id] || {}).range;
|
||||
},
|
||||
/**
|
||||
* Get the latest telemetry datum for this domain object.
|
||||
*
|
||||
* @param {DomainObject} domainObject the object of interest
|
||||
* @returns {TelemetryDatum} the most recent datum
|
||||
* @memberof platform/telemetry.TelemetrySubscription#
|
||||
*/
|
||||
getDatum: function (domainObject) {
|
||||
var id = domainObject.getId();
|
||||
return (latestValues[id] || {}).datum;
|
||||
},
|
||||
/**
|
||||
* Get all telemetry-providing domain objects which are
|
||||
* being observed as part of this subscription.
|
||||
*
|
||||
* Capability delegation will be taken into account (so, if
|
||||
* a Telemetry Panel was passed in the constructor, this will
|
||||
* return its contents.) Capability delegation is resolved
|
||||
* asynchronously so the return value here may change over
|
||||
* time; while this resolution is pending, this method will
|
||||
* return an empty array.
|
||||
*
|
||||
* @returns {DomainObject[]} all subscribed-to domain objects
|
||||
* @method
|
||||
* @memberof TelemetrySubscription
|
||||
* @memberof platform/telemetry.TelemetrySubscription#
|
||||
*/
|
||||
getTelemetryObjects: function () {
|
||||
return telemetryObjects;
|
||||
},
|
||||
/**
|
||||
* Get all telemetry metadata associated with
|
||||
* telemetry-providing domain objects managed by
|
||||
* this controller.
|
||||
*
|
||||
* This will ordered in the
|
||||
* same manner as `getTelemetryObjects()` or
|
||||
* `getResponse()`; that is, the metadata at a
|
||||
* given index will correspond to the telemetry-providing
|
||||
* domain object at the same index.
|
||||
* @returns {Array} an array of metadata objects
|
||||
* @memberof platform/telemetry.TelemetrySubscription#
|
||||
*/
|
||||
getMetadata: function () {
|
||||
return metadatas;
|
||||
},
|
||||
/**
|
||||
* Get a promise for all telemetry-providing objects
|
||||
* associated with this subscription.
|
||||
* @returns {Promise.<DomainObject[]>} a promise for
|
||||
* telemetry-providing objects
|
||||
* @memberof platform/telemetry.TelemetrySubscription#
|
||||
*/
|
||||
promiseTelemetryObjects: function () {
|
||||
// Unsubscribe promise is available after objects
|
||||
// are loaded.
|
||||
return telemetryObjectPromise;
|
||||
}
|
||||
};
|
||||
initialize();
|
||||
this.unlistenToMutation = addMutationListener();
|
||||
}
|
||||
|
||||
TelemetrySubscription.prototype.unsubscribeAll = function () {
|
||||
var $q = this.$q;
|
||||
return this.unsubscribePromise.then(function (unsubscribes) {
|
||||
return $q.all(unsubscribes.map(function (unsubscribe) {
|
||||
return unsubscribe();
|
||||
}));
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Terminate all underlying subscriptions associated
|
||||
* with this object.
|
||||
*/
|
||||
TelemetrySubscription.prototype.unsubscribe = function () {
|
||||
if (this.unlistenToMutation) {
|
||||
this.unlistenToMutation();
|
||||
}
|
||||
return this.unsubscribeAll();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the most recent domain value that has been observed
|
||||
* for the specified domain object. This will typically be
|
||||
* a timestamp.
|
||||
*
|
||||
* The domain object passed here should be one that is
|
||||
* subscribed-to here; that is, it should be one of the
|
||||
* domain objects returned by `getTelemetryObjects()`.
|
||||
*
|
||||
* @param {DomainObject} domainObject the object of interest
|
||||
* @returns the most recent domain value observed
|
||||
*/
|
||||
TelemetrySubscription.prototype.getDomainValue = function (domainObject) {
|
||||
var id = domainObject.getId();
|
||||
return (this.latestValues[id] || {}).domain;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the most recent range value that has been observed
|
||||
* for the specified domain object. This will typically
|
||||
* be a numeric measurement.
|
||||
*
|
||||
* The domain object passed here should be one that is
|
||||
* subscribed-to here; that is, it should be one of the
|
||||
* domain objects returned by `getTelemetryObjects()`.
|
||||
*
|
||||
* @param {DomainObject} domainObject the object of interest
|
||||
* @returns the most recent range value observed
|
||||
*/
|
||||
TelemetrySubscription.prototype.getRangeValue = function (domainObject) {
|
||||
var id = domainObject.getId();
|
||||
return (this.latestValues[id] || {}).range;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the latest telemetry datum for this domain object.
|
||||
*
|
||||
* @param {DomainObject} domainObject the object of interest
|
||||
* @returns {TelemetryDatum} the most recent datum
|
||||
*/
|
||||
TelemetrySubscription.prototype.getDatum = function (domainObject) {
|
||||
var id = domainObject.getId();
|
||||
return (this.latestValues[id] || {}).datum;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get all telemetry-providing domain objects which are
|
||||
* being observed as part of this subscription.
|
||||
*
|
||||
* Capability delegation will be taken into account (so, if
|
||||
* a Telemetry Panel was passed in the constructor, this will
|
||||
* return its contents.) Capability delegation is resolved
|
||||
* asynchronously so the return value here may change over
|
||||
* time; while this resolution is pending, this method will
|
||||
* return an empty array.
|
||||
*
|
||||
* @returns {DomainObject[]} all subscribed-to domain objects
|
||||
*/
|
||||
TelemetrySubscription.prototype.getTelemetryObjects = function () {
|
||||
return this.telemetryObjects;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get all telemetry metadata associated with
|
||||
* telemetry-providing domain objects managed by
|
||||
* this controller.
|
||||
*
|
||||
* This will ordered in the
|
||||
* same manner as `getTelemetryObjects()` or
|
||||
* `getResponse()`; that is, the metadata at a
|
||||
* given index will correspond to the telemetry-providing
|
||||
* domain object at the same index.
|
||||
* @returns {TelemetryMetadata[]} an array of metadata objects
|
||||
*/
|
||||
TelemetrySubscription.prototype.getMetadata = function () {
|
||||
return this.metadatas;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a promise for all telemetry-providing objects
|
||||
* associated with this subscription.
|
||||
* @returns {Promise.<DomainObject[]>} a promise for
|
||||
* telemetry-providing objects
|
||||
* @memberof platform/telemetry.TelemetrySubscription#
|
||||
*/
|
||||
TelemetrySubscription.prototype.promiseTelemetryObjects = function () {
|
||||
// Unsubscribe promise is available after objects
|
||||
// are loaded.
|
||||
return this.telemetryObjectPromise;
|
||||
};
|
||||
|
||||
return TelemetrySubscription;
|
||||
|
||||
}
|
||||
|
@ -34,45 +34,26 @@ define(
|
||||
* values.
|
||||
* @memberof platform/telemetry
|
||||
* @constructor
|
||||
* @implements {platform/telemetry.TelemetryPool}
|
||||
*/
|
||||
function TelemetryTable() {
|
||||
var table;
|
||||
|
||||
return {
|
||||
/**
|
||||
* Check if any value groups remain in this pool.
|
||||
* @return {boolean} true if value groups remain
|
||||
* @memberof platform/telemetry.TelemetryTable#
|
||||
*/
|
||||
isEmpty: function () {
|
||||
return !table;
|
||||
},
|
||||
/**
|
||||
* Retrieve the next value group from this pool.
|
||||
* This gives an object containing key-value pairs,
|
||||
* where keys and values correspond to the arguments
|
||||
* given to previous put functions.
|
||||
* @return {object} key-value pairs
|
||||
* @memberof platform/telemetry.TelemetryTable#
|
||||
*/
|
||||
poll: function () {
|
||||
var t = table;
|
||||
table = undefined;
|
||||
return t;
|
||||
},
|
||||
/**
|
||||
* Put a key-value pair into the pool.
|
||||
* @param {string} key the key to store the value under
|
||||
* @param {*} value the value to store
|
||||
* @memberof platform/telemetry.TelemetryTable#
|
||||
*/
|
||||
put: function (key, value) {
|
||||
table = table || {};
|
||||
table[key] = value;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TelemetryTable.prototype.isEmpty = function () {
|
||||
return !this.table;
|
||||
};
|
||||
|
||||
TelemetryTable.prototype.poll = function () {
|
||||
var t = this.table;
|
||||
this.table = undefined;
|
||||
return t;
|
||||
};
|
||||
|
||||
TelemetryTable.prototype.put = function (key, value) {
|
||||
this.table = this.table || {};
|
||||
this.table[key] = value;
|
||||
};
|
||||
|
||||
return TelemetryTable;
|
||||
}
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user