Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nasa/openmct.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Bell <scott@traclabs.com>2022-10-21 21:25:24 +0300
committerGitHub <noreply@github.com>2022-10-21 21:25:24 +0300
commit9e23f79bc8b1b8cc702be3ede097f4f860024190 (patch)
tree5b8ee979dcdcef105d25065250df3d6039c8053c
parentbd1e869f6a9864bdec75641bdce88360d5842020 (diff)
Add time context to telemetry requests (#5887)
* add time context to telemetry requests * change to empty array * refactor telemetry api to use time context * removed unused function * add tests * add test, rename function * make function public
-rw-r--r--src/api/telemetry/TelemetryAPI.js88
-rw-r--r--src/api/telemetry/TelemetryAPISpec.js230
-rw-r--r--src/api/time/TimeAPISpec.js19
-rw-r--r--src/api/time/TimeContext.js12
-rw-r--r--src/plugins/LADTable/components/LADRow.vue5
-rw-r--r--src/plugins/displayLayout/components/TelemetryView.vue5
6 files changed, 185 insertions, 174 deletions
diff --git a/src/api/telemetry/TelemetryAPI.js b/src/api/telemetry/TelemetryAPI.js
index 15cef5b19..c2a392d18 100644
--- a/src/api/telemetry/TelemetryAPI.js
+++ b/src/api/telemetry/TelemetryAPI.js
@@ -27,7 +27,6 @@ import TelemetryMetadataManager from './TelemetryMetadataManager';
import TelemetryValueFormatter from './TelemetryValueFormatter';
import DefaultMetadataProvider from './DefaultMetadataProvider';
import objectUtils from 'objectUtils';
-import _ from 'lodash';
export default class TelemetryAPI {
@@ -73,7 +72,7 @@ export default class TelemetryAPI {
* @returns {boolean} true if the object is a telemetry object.
*/
isTelemetryObject(domainObject) {
- return Boolean(this.findMetadataProvider(domainObject));
+ return Boolean(this.#findMetadataProvider(domainObject));
}
/**
@@ -87,7 +86,7 @@ export default class TelemetryAPI {
* @memberof module:openmct.TelemetryAPI~TelemetryProvider#
*/
canProvideTelemetry(domainObject) {
- return Boolean(this.findSubscriptionProvider(domainObject))
+ return Boolean(this.#findSubscriptionProvider(domainObject))
|| Boolean(this.findRequestProvider(domainObject));
}
@@ -120,7 +119,7 @@ export default class TelemetryAPI {
/**
* @private
*/
- findSubscriptionProvider() {
+ #findSubscriptionProvider() {
const args = Array.prototype.slice.apply(arguments);
function supportsDomainObject(provider) {
return provider.supportsSubscribe.apply(provider, args);
@@ -130,9 +129,10 @@ export default class TelemetryAPI {
}
/**
- * @private
+ * Returns a telemetry request provider that supports
+ * a given domain object and options.
*/
- findRequestProvider(domainObject) {
+ findRequestProvider() {
const args = Array.prototype.slice.apply(arguments);
function supportsDomainObject(provider) {
return provider.supportsRequest.apply(provider, args);
@@ -144,7 +144,7 @@ export default class TelemetryAPI {
/**
* @private
*/
- findMetadataProvider(domainObject) {
+ #findMetadataProvider(domainObject) {
return this.metadataProviders.filter(function (p) {
return p.supportsMetadata(domainObject);
})[0];
@@ -153,7 +153,7 @@ export default class TelemetryAPI {
/**
* @private
*/
- findLimitEvaluator(domainObject) {
+ #findLimitEvaluator(domainObject) {
return this.limitProviders.filter(function (p) {
return p.supportsLimits(domainObject);
})[0];
@@ -161,6 +161,7 @@ export default class TelemetryAPI {
/**
* @private
+ * Though used in TelemetryCollection as well
*/
standardizeRequestOptions(options) {
if (!Object.prototype.hasOwnProperty.call(options, 'start')) {
@@ -174,6 +175,10 @@ export default class TelemetryAPI {
if (!Object.prototype.hasOwnProperty.call(options, 'domain')) {
options.domain = this.openmct.time.timeSystem().key;
}
+
+ if (!Object.prototype.hasOwnProperty.call(options, 'timeContext')) {
+ options.timeContext = this.openmct.time;
+ }
}
/**
@@ -241,7 +246,7 @@ export default class TelemetryAPI {
/**
* Request historical telemetry for a domain object.
* The `options` argument allows you to specify filters
- * (start, end, etc.), sort order, and strategies for retrieving
+ * (start, end, etc.), sort order, time context, and strategies for retrieving
* telemetry (aggregation, latest available, etc.).
*
* @method request
@@ -255,7 +260,7 @@ export default class TelemetryAPI {
*/
async request(domainObject) {
if (this.noRequestProviderForAllObjects) {
- return Promise.resolve([]);
+ return [];
}
if (arguments.length === 1) {
@@ -273,22 +278,24 @@ export default class TelemetryAPI {
if (!provider) {
this.requestAbortControllers.delete(abortController);
- return this.handleMissingRequestProvider(domainObject);
+ return this.#handleMissingRequestProvider(domainObject);
}
arguments[1] = await this.applyRequestInterceptors(domainObject, arguments[1]);
+ try {
+ const telemetry = await provider.request(...arguments);
+
+ return telemetry;
+ } catch (error) {
+ if (error.name !== 'AbortError') {
+ this.openmct.notifications.error('Error requesting telemetry data, see console for details');
+ console.error(error);
+ }
- return provider.request.apply(provider, arguments)
- .catch((rejected) => {
- if (rejected.name !== 'AbortError') {
- this.openmct.notifications.error('Error requesting telemetry data, see console for details');
- console.error(rejected);
- }
-
- return Promise.reject(rejected);
- }).finally(() => {
- this.requestAbortControllers.delete(abortController);
- });
+ throw new Error(error);
+ } finally {
+ this.requestAbortControllers.delete(abortController);
+ }
}
/**
@@ -306,7 +313,7 @@ export default class TelemetryAPI {
* the subscription
*/
subscribe(domainObject, callback, options) {
- const provider = this.findSubscriptionProvider(domainObject);
+ const provider = this.#findSubscriptionProvider(domainObject);
if (!this.subscribeCache) {
this.subscribeCache = {};
@@ -353,7 +360,7 @@ export default class TelemetryAPI {
*/
getMetadata(domainObject) {
if (!this.metadataCache.has(domainObject)) {
- const metadataProvider = this.findMetadataProvider(domainObject);
+ const metadataProvider = this.#findMetadataProvider(domainObject);
if (!metadataProvider) {
return;
}
@@ -370,33 +377,6 @@ export default class TelemetryAPI {
}
/**
- * Return an array of valueMetadatas that are common to all supplied
- * telemetry objects and match the requested hints.
- *
- */
- commonValuesForHints(metadatas, hints) {
- const options = metadatas.map(function (metadata) {
- const values = metadata.valuesForHints(hints);
-
- return _.keyBy(values, 'key');
- }).reduce(function (a, b) {
- const results = {};
- Object.keys(a).forEach(function (key) {
- if (Object.prototype.hasOwnProperty.call(b, key)) {
- results[key] = a[key];
- }
- });
-
- return results;
- });
- const sortKeys = hints.map(function (h) {
- return 'hints.' + h;
- });
-
- return _.sortBy(options, sortKeys);
- }
-
- /**
* Get a value formatter for a given valueMetadata.
*
* @returns {TelemetryValueFormatter}
@@ -450,7 +430,7 @@ export default class TelemetryAPI {
*
* @returns Promise
*/
- handleMissingRequestProvider(domainObject) {
+ #handleMissingRequestProvider(domainObject) {
this.noRequestProviderForAllObjects = this.requestProviders.every(requestProvider => {
const supportsRequest = requestProvider.supportsRequest.apply(requestProvider, arguments);
const hasRequestProvider = Object.prototype.hasOwnProperty.call(requestProvider, 'request') && typeof requestProvider.request === 'function';
@@ -540,7 +520,7 @@ export default class TelemetryAPI {
* @memberof module:openmct.TelemetryAPI~TelemetryProvider#
*/
getLimitEvaluator(domainObject) {
- const provider = this.findLimitEvaluator(domainObject);
+ const provider = this.#findLimitEvaluator(domainObject);
if (!provider) {
return {
evaluate: function () {}
@@ -578,7 +558,7 @@ export default class TelemetryAPI {
* @memberof module:openmct.TelemetryAPI~TelemetryProvider#
*/
getLimits(domainObject) {
- const provider = this.findLimitEvaluator(domainObject);
+ const provider = this.#findLimitEvaluator(domainObject);
if (!provider || !provider.getLimits) {
return {
limits: function () {
diff --git a/src/api/telemetry/TelemetryAPISpec.js b/src/api/telemetry/TelemetryAPISpec.js
index 5af944009..1362ec0ae 100644
--- a/src/api/telemetry/TelemetryAPISpec.js
+++ b/src/api/telemetry/TelemetryAPISpec.js
@@ -23,11 +23,11 @@ import { createOpenMct, resetApplicationState } from 'utils/testing';
import TelemetryAPI from './TelemetryAPI';
import TelemetryCollection from './TelemetryCollection';
-describe('Telemetry API', function () {
+describe('Telemetry API', () => {
let openmct;
let telemetryAPI;
- beforeEach(function () {
+ beforeEach(() => {
openmct = {
time: jasmine.createSpyObj('timeAPI', [
'timeSystem',
@@ -47,11 +47,11 @@ describe('Telemetry API', function () {
});
- describe('telemetry providers', function () {
+ describe('telemetry providers', () => {
let telemetryProvider;
let domainObject;
- beforeEach(function () {
+ beforeEach(() => {
telemetryProvider = jasmine.createSpyObj('telemetryProvider', [
'supportsSubscribe',
'subscribe',
@@ -73,19 +73,16 @@ describe('Telemetry API', function () {
};
});
- it('provides consistent results without providers', function (done) {
+ it('provides consistent results without providers', async () => {
const unsubscribe = telemetryAPI.subscribe(domainObject);
expect(unsubscribe).toEqual(jasmine.any(Function));
- telemetryAPI.request(domainObject)
- .then((data) => {
- expect(data).toEqual([]);
- })
- .finally(done);
+ const data = await telemetryAPI.request(domainObject);
+ expect(data).toEqual([]);
});
- it('skips providers that do not match', function (done) {
+ it('skips providers that do not match', async () => {
telemetryProvider.supportsSubscribe.and.returnValue(false);
telemetryProvider.supportsRequest.and.returnValue(false);
telemetryProvider.request.and.returnValue(Promise.resolve([]));
@@ -98,14 +95,13 @@ describe('Telemetry API', function () {
expect(telemetryProvider.subscribe).not.toHaveBeenCalled();
expect(unsubscribe).toEqual(jasmine.any(Function));
- telemetryAPI.request(domainObject).then((response) => {
- expect(telemetryProvider.supportsRequest)
- .toHaveBeenCalledWith(domainObject, jasmine.any(Object));
- expect(telemetryProvider.request).not.toHaveBeenCalled();
- }).finally(done);
+ await telemetryAPI.request(domainObject);
+ expect(telemetryProvider.supportsRequest)
+ .toHaveBeenCalledWith(domainObject, jasmine.any(Object));
+ expect(telemetryProvider.request).not.toHaveBeenCalled();
});
- it('sends subscribe calls to matching providers', function () {
+ it('sends subscribe calls to matching providers', () => {
const unsubFunc = jasmine.createSpy('unsubscribe');
telemetryProvider.subscribe.and.returnValue(unsubFunc);
telemetryProvider.supportsSubscribe.and.returnValue(true);
@@ -133,7 +129,7 @@ describe('Telemetry API', function () {
expect(callback).not.toHaveBeenCalledWith('otherValue');
});
- it('subscribes once per object', function () {
+ it('subscribes once per object', () => {
const unsubFunc = jasmine.createSpy('unsubscribe');
telemetryProvider.subscribe.and.returnValue(unsubFunc);
telemetryProvider.supportsSubscribe.and.returnValue(true);
@@ -164,7 +160,7 @@ describe('Telemetry API', function () {
expect(callbacktwo).not.toHaveBeenCalledWith('anotherValue');
});
- it('only deletes subscription cache when there are no more subscribers', function () {
+ it('only deletes subscription cache when there are no more subscribers', () => {
const unsubFunc = jasmine.createSpy('unsubscribe');
telemetryProvider.subscribe.and.returnValue(unsubFunc);
telemetryProvider.supportsSubscribe.and.returnValue(true);
@@ -187,7 +183,7 @@ describe('Telemetry API', function () {
unsubscribeThree();
});
- it('does subscribe/unsubscribe', function () {
+ it('does subscribe/unsubscribe', () => {
const unsubFunc = jasmine.createSpy('unsubscribe');
telemetryProvider.subscribe.and.returnValue(unsubFunc);
telemetryProvider.supportsSubscribe.and.returnValue(true);
@@ -203,7 +199,7 @@ describe('Telemetry API', function () {
unsubscribe();
});
- it('subscribes for different object', function () {
+ it('subscribes for different object', () => {
const unsubFuncs = [];
const notifiers = [];
telemetryProvider.supportsSubscribe.and.returnValue(true);
@@ -243,120 +239,120 @@ describe('Telemetry API', function () {
expect(unsubFuncs[1]).toHaveBeenCalled();
});
- it('sends requests to matching providers', function (done) {
+ it('sends requests to matching providers', async () => {
const telemPromise = Promise.resolve([]);
telemetryProvider.supportsRequest.and.returnValue(true);
telemetryProvider.request.and.returnValue(telemPromise);
telemetryAPI.addProvider(telemetryProvider);
- telemetryAPI.request(domainObject).then(() => {
- expect(telemetryProvider.supportsRequest).toHaveBeenCalledWith(
- domainObject,
- jasmine.any(Object)
- );
- expect(telemetryProvider.request).toHaveBeenCalledWith(
- domainObject,
- jasmine.any(Object)
- );
- }).finally(done);
+ await telemetryAPI.request(domainObject);
+ expect(telemetryProvider.supportsRequest).toHaveBeenCalledWith(
+ domainObject,
+ jasmine.any(Object)
+ );
+ expect(telemetryProvider.request).toHaveBeenCalledWith(
+ domainObject,
+ jasmine.any(Object)
+ );
});
- it('generates default request options', function (done) {
+ it('generates default request options', async () => {
telemetryProvider.supportsRequest.and.returnValue(true);
telemetryProvider.request.and.returnValue(Promise.resolve([]));
telemetryAPI.addProvider(telemetryProvider);
- telemetryAPI.request(domainObject).then(() => {
- const { signal } = new AbortController();
- expect(telemetryProvider.supportsRequest).toHaveBeenCalledWith(
- jasmine.any(Object),
- {
- signal,
- start: 0,
- end: 1,
- domain: 'system'
- }
- );
-
- expect(telemetryProvider.request).toHaveBeenCalledWith(
- jasmine.any(Object),
- {
- signal,
- start: 0,
- end: 1,
- domain: 'system'
- }
- );
-
- telemetryProvider.supportsRequest.calls.reset();
- telemetryProvider.request.calls.reset();
-
- telemetryAPI.request(domainObject, {}).then(() => {
- expect(telemetryProvider.supportsRequest).toHaveBeenCalledWith(
- jasmine.any(Object),
- {
- signal,
- start: 0,
- end: 1,
- domain: 'system'
- }
- );
-
- expect(telemetryProvider.request).toHaveBeenCalledWith(
- jasmine.any(Object),
- {
- signal,
- start: 0,
- end: 1,
- domain: 'system'
- }
- );
- });
- }).finally(done);
+ await telemetryAPI.request(domainObject);
+ const { signal } = new AbortController();
+ expect(telemetryProvider.supportsRequest).toHaveBeenCalledWith(
+ jasmine.any(Object),
+ {
+ signal,
+ start: 0,
+ end: 1,
+ domain: 'system',
+ timeContext: jasmine.any(Object)
+ }
+ );
+
+ expect(telemetryProvider.request).toHaveBeenCalledWith(
+ jasmine.any(Object),
+ {
+ signal,
+ start: 0,
+ end: 1,
+ domain: 'system',
+ timeContext: jasmine.any(Object)
+ }
+ );
+
+ telemetryProvider.supportsRequest.calls.reset();
+ telemetryProvider.request.calls.reset();
+
+ await telemetryAPI.request(domainObject, {});
+ expect(telemetryProvider.supportsRequest).toHaveBeenCalledWith(
+ jasmine.any(Object),
+ {
+ signal,
+ start: 0,
+ end: 1,
+ domain: 'system',
+ timeContext: jasmine.any(Object)
+ }
+ );
+ expect(telemetryProvider.request).toHaveBeenCalledWith(
+ jasmine.any(Object),
+ {
+ signal,
+ start: 0,
+ end: 1,
+ domain: 'system',
+ timeContext: jasmine.any(Object)
+ }
+ );
});
- it('do not overwrite existing request options', function (done) {
+ it('do not overwrite existing request options', async () => {
telemetryProvider.supportsRequest.and.returnValue(true);
telemetryProvider.request.and.returnValue(Promise.resolve([]));
telemetryAPI.addProvider(telemetryProvider);
- telemetryAPI.request(domainObject, {
+ await telemetryAPI.request(domainObject, {
start: 20,
end: 30,
domain: 'someDomain'
- }).then(() => {
- const { signal } = new AbortController();
- expect(telemetryProvider.supportsRequest).toHaveBeenCalledWith(
- jasmine.any(Object),
- {
- start: 20,
- end: 30,
- domain: 'someDomain',
- signal
- }
- );
-
- expect(telemetryProvider.request).toHaveBeenCalledWith(
- jasmine.any(Object),
- {
- start: 20,
- end: 30,
- domain: 'someDomain',
- signal
- }
- );
+ });
+ const { signal } = new AbortController();
+ expect(telemetryProvider.supportsRequest).toHaveBeenCalledWith(
+ jasmine.any(Object),
+ {
+ start: 20,
+ end: 30,
+ domain: 'someDomain',
+ signal,
+ timeContext: jasmine.any(Object)
+ }
+ );
- }).finally(done);
+ expect(telemetryProvider.request).toHaveBeenCalledWith(
+ jasmine.any(Object),
+ {
+ start: 20,
+ end: 30,
+ domain: 'someDomain',
+ signal,
+ timeContext: jasmine.any(Object)
+ }
+ );
});
});
- describe('metadata', function () {
+ describe('metadata', () => {
let mockMetadata = {};
let mockObjectType = {
definition: {}
};
- beforeEach(function () {
+ beforeEach(() => {
telemetryAPI.addProvider({
key: 'mockMetadataProvider',
supportsMetadata() {
@@ -369,7 +365,7 @@ describe('Telemetry API', function () {
openmct.types.get.and.returnValue(mockObjectType);
});
- it('respects explicit priority', function () {
+ it('respects explicit priority', () => {
mockMetadata.values = [
{
key: "name",
@@ -408,7 +404,7 @@ describe('Telemetry API', function () {
expect(value.hints.priority).toBe(index + 1);
});
});
- it('if no explicit priority, defaults to order defined', function () {
+ it('if no explicit priority, defaults to order defined', () => {
mockMetadata.values = [
{
key: "name",
@@ -435,7 +431,7 @@ describe('Telemetry API', function () {
expect(value.key).toBe(mockMetadata.values[index].key);
});
});
- it('respects domain priority', function () {
+ it('respects domain priority', () => {
mockMetadata.values = [
{
key: "name",
@@ -477,7 +473,7 @@ describe('Telemetry API', function () {
expect(values[0].key).toBe('timestamp-local');
expect(values[1].key).toBe('timestamp-utc');
});
- it('respects range priority', function () {
+ it('respects range priority', () => {
mockMetadata.values = [
{
key: "name",
@@ -519,7 +515,7 @@ describe('Telemetry API', function () {
expect(values[0].key).toBe('cos');
expect(values[1].key).toBe('sin');
});
- it('respects priority and domain ordering', function () {
+ it('respects priority and domain ordering', () => {
mockMetadata.values = [
{
key: "id",
@@ -588,7 +584,7 @@ describe('Telemetry API', function () {
definition: {}
};
- beforeEach(function () {
+ beforeEach(() => {
openmct.telemetry = telemetryAPI;
telemetryAPI.addProvider({
key: 'mockMetadataProvider',
@@ -644,16 +640,14 @@ describe('Telemetery', () => {
return resetApplicationState(openmct);
});
- it('should not abort request without navigation', function (done) {
+ it('should not abort request without navigation', async () => {
telemetryAPI.addProvider(telemetryProvider);
- telemetryAPI.request({}).finally(() => {
- expect(watchedSignal.aborted).toBe(false);
- done();
- });
+ await telemetryAPI.request({});
+ expect(watchedSignal.aborted).toBe(false);
});
- it('should abort request on navigation', function (done) {
+ it('should abort request on navigation', (done) => {
telemetryAPI.addProvider(telemetryProvider);
telemetryAPI.request({}).finally(() => {
diff --git a/src/api/time/TimeAPISpec.js b/src/api/time/TimeAPISpec.js
index c7dea1081..5108cf449 100644
--- a/src/api/time/TimeAPISpec.js
+++ b/src/api/time/TimeAPISpec.js
@@ -229,6 +229,25 @@ describe("The Time API", function () {
expect(api.clock()).toBeUndefined();
});
+ it('Provides a default time context', () => {
+ const timeContext = api.getContextForView([]);
+ expect(timeContext).not.toBe(null);
+ });
+
+ it("Without a clock, is in fixed time mode", () => {
+ const timeContext = api.getContextForView([]);
+ expect(timeContext.isRealTime()).toBe(false);
+ });
+
+ it("Provided a clock, is in real-time mode", () => {
+ const timeContext = api.getContextForView([]);
+ timeContext.clock('mts', {
+ start: 0,
+ end: 1
+ });
+ expect(timeContext.isRealTime()).toBe(true);
+ });
+
});
it("on tick, observes offsets, and indicates tick in bounds callback", function () {
diff --git a/src/api/time/TimeContext.js b/src/api/time/TimeContext.js
index 29f95b72a..520540b2b 100644
--- a/src/api/time/TimeContext.js
+++ b/src/api/time/TimeContext.js
@@ -362,6 +362,18 @@ class TimeContext extends EventEmitter {
this.boundsVal = newBounds;
this.emit('bounds', this.boundsVal, true);
}
+
+ /**
+ * Checks if this time context is in real-time mode or not.
+ * @returns {boolean} true if this context is in real-time mode, false if not
+ */
+ isRealTime() {
+ if (this.clock()) {
+ return true;
+ }
+
+ return false;
+ }
}
export default TimeContext;
diff --git a/src/plugins/LADTable/components/LADRow.vue b/src/plugins/LADTable/components/LADRow.vue
index 929a4e201..3468c870b 100644
--- a/src/plugins/LADTable/components/LADRow.vue
+++ b/src/plugins/LADTable/components/LADRow.vue
@@ -114,6 +114,8 @@ export default {
this.formats = this.openmct.telemetry.getFormatMap(this.metadata);
this.keyString = this.openmct.objects.makeKeyString(this.domainObject.identifier);
+ this.timeContext = this.openmct.time.getContextForView(this.objectPath);
+
this.limitEvaluator = this.openmct
.telemetry
.limitEvaluator(this.domainObject);
@@ -134,7 +136,8 @@ export default {
this.telemetryCollection = this.openmct.telemetry.requestCollection(this.domainObject, {
size: 1,
- strategy: 'latest'
+ strategy: 'latest',
+ timeContext: this.timeContext
});
this.telemetryCollection.on('add', this.setLatestValues);
this.telemetryCollection.on('clear', this.resetValues);
diff --git a/src/plugins/displayLayout/components/TelemetryView.vue b/src/plugins/displayLayout/components/TelemetryView.vue
index 8ae30d913..24bd7bce0 100644
--- a/src/plugins/displayLayout/components/TelemetryView.vue
+++ b/src/plugins/displayLayout/components/TelemetryView.vue
@@ -282,12 +282,15 @@ export default {
this.limitEvaluator = this.openmct.telemetry.limitEvaluator(this.domainObject);
this.formats = this.openmct.telemetry.getFormatMap(this.metadata);
+ this.timeContext = this.openmct.time.getContextForView(this.objectPath);
+
const valueMetadata = this.metadata ? this.metadata.value(this.item.value) : {};
this.customStringformatter = this.openmct.telemetry.customStringFormatter(valueMetadata, this.item.format);
this.telemetryCollection = this.openmct.telemetry.requestCollection(this.domainObject, {
size: 1,
- strategy: 'latest'
+ strategy: 'latest',
+ timeContext: this.timeContext
});
this.telemetryCollection.on('add', this.setLatestValues);
this.telemetryCollection.on('clear', this.refreshData);