Compare commits

...

5 Commits

Author SHA1 Message Date
Jamie Vigliotta
d20df25893 merging in main branch changes 2021-01-20 10:41:26 -08:00
Jamie Vigliotta
c236444a05 added options for request 2021-01-19 19:51:55 -08:00
Jamie Vigliotta
39c1eb1d5b added revised functionality for getting related telemetry data with examples and local testing settings as well 2021-01-19 19:49:22 -08:00
Jamie Vigliotta
0500b3967e wip 2021-01-19 15:00:50 -08:00
Jamie Vigliotta
4633436cbd added get imageMetadataValue method for getting necessary values for new image enhancements, has temporary local testing code as well for dev 2021-01-13 15:16:03 -08:00
3 changed files with 267 additions and 8 deletions

View File

@@ -1,7 +1,7 @@
import ImageryViewLayout from './components/ImageryViewLayout.vue';
import Vue from 'vue';
export default function ImageryViewProvider(openmct) {
export default function ImageryViewProvider(openmct, configuration) {
const type = 'example.imagery';
function hasImageTelemetry(domainObject) {
@@ -32,7 +32,8 @@ export default function ImageryViewProvider(openmct) {
},
provide: {
openmct,
domainObject
domainObject,
configuration
},
template: '<imagery-view-layout ref="ImageryLayout"></imagery-view-layout>'
});

View File

@@ -61,11 +61,25 @@
<div class="c-imagery__control-bar">
<div class="c-imagery__time">
<div class="c-imagery__timestamp u-style-receiver js-style-receiver">{{ time }}</div>
<!-- Imagery Age Freshness -->
<div
v-if="canTrackDuration"
:class="{'c-imagery--new': isImageNew && !refreshCSS}"
class="c-imagery__age icon-timer"
>{{ formattedDuration }}</div>
<!-- Rover Position Freshness -->
<div>isFresh {{ roverPositionIsFresh }}</div>
<div
v-if="roverPositionIsFresh !== undefined"
:class="{'c-imagery--new': roverPositionIsFresh}"
class="c-imagery__age icon-timer"
>{{ roverPositionIsFresh ? 'ROVER' : '' }}</div>
<!-- Rover Camera Position Freshness -->
<div
v-if="cameraPositionIsFresh !== undefined"
:class="{'c-imagery--new': cameraPositionIsFresh && !refreshCSS}"
class="c-imagery__age icon-timer"
>{{ formattedDuration }}</div>
</div>
<div class="h-local-controls">
<button
@@ -116,7 +130,7 @@ const ARROW_RIGHT = 39;
const ARROW_LEFT = 37;
export default {
inject: ['openmct', 'domainObject'],
inject: ['openmct', 'domainObject', 'configuration'],
data() {
let timeSystem = this.openmct.time.timeSystem();
@@ -137,7 +151,14 @@ export default {
refreshCSS: false,
keyString: undefined,
focusedImageIndex: undefined,
numericDuration: undefined
numericDuration: undefined,
metadataEndpoints: {},
roverPositionIsFresh: undefined,
cameraPositionIsFresh: undefined,
roverPositionState: {},
cameraPositionState: {},
canTrackRoverPositionFreshness: undefined,
canTrackCameraPositionFreshness: undefined
};
},
computed: {
@@ -201,9 +222,11 @@ export default {
focusedImageIndex() {
this.trackDuration();
this.resetAgeCSS();
this.determineRoverFreshness();
this.determineCameraPositionFreshness();
}
},
mounted() {
async mounted() {
// listen
this.openmct.time.on('bounds', this.boundsChange);
this.openmct.time.on('timeSystem', this.timeSystemChange);
@@ -212,16 +235,34 @@ export default {
// set
this.keyString = this.openmct.objects.makeKeyString(this.domainObject.identifier);
this.metadata = this.openmct.telemetry.getMetadata(this.domainObject);
this.imageHints = this.metadata.valuesForHints(['image'])[0];
this.durationFormatter = this.getFormatter(this.timeSystem.durationFormat || DEFAULT_DURATION_FORMATTER);
this.imageFormatter = this.openmct.telemetry.getValueFormatter(this.metadata.valuesForHints(['image'])[0]);
this.imageFormatter = this.openmct.telemetry.getValueFormatter(this.imageHints);
// DELETE WHEN DONE
this.temporaryForImageEnhancements();
// initialize
this.timeKey = this.timeSystem.key;
this.timeFormatter = this.getFormatter(this.timeKey);
this.roverPositionKeys = ['Rover Heading', 'Rover Roll', 'Rover Pitch', 'Rover Yaw'];
this.cameraPositionKeys = ['Camera Tilt', 'Camera Pan'];
// kickoff
this.subscribe();
this.requestHistory();
await this.initializeRelatedTelemetry();
// DELETE
// examples for requesting historical data for a relatedTelemetry key
// and for subscribing to a relatedTelemetry key
// example for 'Rover Heading'
// ***********************************************************************
// let results = await this.relatedTelemetry['Rover Heading'].request();
// this.relatedTelemetry['Rover Heading'].subscribe((data) => {
// console.log('subscribe test', data);
// });
// ***********************************************************************
},
updated() {
this.scrollToRight();
@@ -236,8 +277,148 @@ export default {
this.openmct.time.off('bounds', this.boundsChange);
this.openmct.time.off('timeSystem', this.timeSystemChange);
this.openmct.time.off('clock', this.clockChange);
// unsubscribe from related telemetry
if (this.hasRelatedTelemetry) {
for (let key of this.relatedTelemetry.keys) {
if (this.relatedTelemetry[key].unsubscribe) {
this.relatedTelemetry[key].unsubscribe();
}
}
}
},
methods: {
// for local dev, to be DELETED
temporaryForImageEnhancements() {
let roverKeys = ['Rover Heading', 'Rover Roll', 'Rover Yaw', 'Rover Pitch'];
let cameraKeys = ['Camera Pan', 'Camera Tilt'];
this.searchService = this.openmct.$injector.get('searchService');
this.temporaryDev = true;
// mock related telemetry metadata
this.imageHints.relatedTelemetry = {};
// populate temp keys in imageHints for local testing
[...roverKeys, ...cameraKeys].forEach(key => {
this.imageHints.relatedTelemetry[key] = {
dev: true,
realtime: key,
historical: key,
devInit: async () => {
const searchResults = await this.searchService.query(key);
const endpoint = searchResults.hits[0].id;
const domainObject = await this.openmct.objects.get(endpoint);
return domainObject;
}
};
});
},
async initializeRelatedTelemetry() {
if (this.imageHints.relatedTelemetry === undefined) {
this.hasRelatedTelemetry = false;
return;
}
// DELETE
if (this.temporaryDev) {
let searchIndexBuildDelay = new Promise((resolve, reject) => {
setTimeout(resolve, 3000);
});
await searchIndexBuildDelay;
}
let keys = Object.keys(this.imageHints.relatedTelemetry);
this.hasRelatedTelemetry = true;
this.relatedTelemetry = {
keys,
...this.imageHints.relatedTelemetry
};
// grab historical and subscribe to realtime
for (let key of keys) {
let historicalId = this.relatedTelemetry[key].historical;
let realtimeId = this.relatedTelemetry[key].realtime;
let sameId = false;
if (historicalId && realtimeId && historicalId === realtimeId) {
// DELETE temp
if (this.relatedTelemetry[key].dev) {
this.relatedTelemetry[key].historicalDomainObject = await this.relatedTelemetry[key].devInit();
delete this.relatedTelemetry[key].dev;
delete this.relatedTelemetry[key].devInit;
} else {
this.relatedTelemetry[key].historicalDomainObject = await this.openmct.objects.get(historicalId);
}
this.relatedTelemetry[key].realtimeDomainObject = this.relatedTelemetry[key].historicalDomainObject;
sameId = true;
}
if (historicalId) {
// check for on-telemetry data
if (historicalId[0] === '.') {
this.relatedTelemetry[key].valueOnTelemetry = true;
}
if (!sameId) {
this.relatedTelemetry[key].historicalDomainObject = await this.openmct.objects.get(historicalId);
}
this.relatedTelemetry[key].request = async (options) => {
let results = await this.openmct.telemetry
.request(this.relatedTelemetry[key].historicalDomainObject, options);
return results;
};
}
if (realtimeId) {
// set up listeners
this.relatedTelemetry[key].listeners = [];
this.relatedTelemetry[key].subscribe = (callback) => {
if (!this.relatedTelemetry[key].listeners.includes(callback)) {
this.relatedTelemetry[key].listeners.push(callback);
return () => {
this.relatedTelemetry[key].listeners.remove(callback);
};
} else {
return () => {};
}
};
if (!sameId) {
this.relatedTelemetry[key].realtimeDomainObject = await this.openmct.objects.get(realtimeId);
}
this.relatedTelemetry[key].unsubscribe = this.openmct.telemetry.subscribe(
this.relatedTelemetry[key].realtimeDomainObject,
datum => {
this.relatedTelemetry[key].latest = datum;
this.relatedTelemetry[key].listeners.forEach(callback => {
callback(datum);
});
}
);
}
}
},
async requestRelatedTelemetry(key) {
if (this.relatedTelemetry[key] && this.relatedTelemetry[key].historicalDomainObject) {
let data = await this.openmct.telemetry.request(this.relatedTelemetry[key].historicalDomainObject);
return data;
}
},
focusElement() {
this.$el.focus();
},
@@ -405,6 +586,83 @@ export default {
return valueFormatter;
},
roverPositionTrackingApplicable() {
let canTrack = false; // possibly false first, depending on if we need all or one
for (const key of this.roverPositionKeys) {
// do we need ALL to be available or will one work?
if (this.metadata.value(key)) {
canTrack = true;
}
}
// Force true, will remove
if (this.temporaryDev) {
return true;
}
return canTrack;
},
async determineRoverFreshness() {
if (this.canTrackRoverPositionFreshness === false) {
return;
}
let noChanges = true;
// set up state tracking
for (const key of this.roverPositionKeys) {
try {
let currentState = await this.getImageMetadataValue(key, this.focusedImage[this.timeKey]);
currentState = currentState.toFixed(1);
if (currentState !== this.roverPositionState[key]) {
this.roverPositionState[key] = currentState;
this.roverPositionIsFresh = false;
noChanges = false;
}
} catch (err) {
this.roverPositionIsFresh = undefined;
}
}
if (noChanges) {
this.roverPositionIsFresh = true;
}
console.log('roverPosition is fresh', this.roverPositionIsFresh);
},
trackRoverPosition() {
this.cancelRoverTrackingInterval = window.setInterval(this.determineRoverFreshness, this.roverTrackingInterval);
},
cameraPositionTrackingApplicable() {
let canTrack = false; // possibly false first, depending on if we need all or one
for (const key of this.cameraPositionKeys) {
// do we need ALL to be available or will one work?
if (this.metadata.value(key)) {
canTrack = true;
}
}
// will remove
if (this.temporaryDev) {
return true;
}
return canTrack;
},
determineCameraPositionFreshness() {
if (this.canTrackCameraPositionFreshness === false) {
return;
}
this.cameraPositionIsFresh = undefined;
},
trackCameraPosition() {
this.cancelCameraTrackingInterval = window.setInterval(this.determineCameraFreshness, this.cameraTrackingInterval);
},
trackDuration() {
if (this.canTrackDuration) {
this.stopDurationTracking();

View File

@@ -1,8 +1,8 @@
import ImageryViewProvider from './ImageryViewProvider';
export default function () {
export default function (configuration) {
return function install(openmct) {
openmct.objectViews.addProvider(new ImageryViewProvider(openmct));
openmct.objectViews.addProvider(new ImageryViewProvider(openmct, configuration));
};
}