Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Imagery View does not discard old images when they fall out of bounds #5351

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
change to using telemetry collection
  • Loading branch information
scottbell committed Jun 15, 2022
commit 54b340e8842110ff9b7afd55292f4bb6a0cbf4eb
9 changes: 6 additions & 3 deletions example/imagery/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ function getImageUrlListFromConfig(configuration) {
}

function getImageLoadDelay(domainObject) {
const imageLoadDelay = domainObject.configuration.imageLoadDelayInMilliSeconds;
const imageLoadDelay = Math.trunc(Number(domainObject.configuration.imageLoadDelayInMilliSeconds));
if (!imageLoadDelay) {
openmctInstance.objects.mutate(domainObject, 'configuration.imageLoadDelayInMilliSeconds', DEFAULT_IMAGE_LOAD_DELAY_IN_MILISECONDS);

Expand All @@ -190,7 +190,9 @@ function getRealtimeProvider() {
subscribe: (domainObject, callback) => {
const delay = getImageLoadDelay(domainObject);
const interval = setInterval(() => {
callback(pointForTimestamp(Date.now(), domainObject.name, getImageSamples(domainObject.configuration), delay));
const imageSamples = getImageSamples(domainObject.configuration);
const datum = pointForTimestamp(Date.now(), domainObject.name, imageSamples, delay);
callback(datum);
}, delay);

return () => {
Expand Down Expand Up @@ -229,8 +231,9 @@ function getLadProvider() {
},
request: (domainObject, options) => {
const delay = getImageLoadDelay(domainObject);
const datum = pointForTimestamp(Date.now(), domainObject.name, getImageSamples(domainObject.configuration), delay);

return Promise.resolve([pointForTimestamp(Date.now(), domainObject.name, delay)]);
return Promise.resolve([datum]);
}
};
}
Expand Down
95 changes: 29 additions & 66 deletions src/plugins/imagery/mixins/imageryData.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default {
this.timeSystemChange = this.timeSystemChange.bind(this);
this.setDataTimeContext = this.setDataTimeContext.bind(this);
this.setDataTimeContext();
this.openmct.objectViews.on('clearData', this.clearData);
this.openmct.objectViews.on('clearData', this.dataCleared);

// set
this.keyString = this.openmct.objects.makeKeyString(this.domainObject.identifier);
Expand All @@ -44,8 +44,11 @@ export default {
this.timeKey = this.timeSystem.key;
this.timeFormatter = this.getFormatter(this.timeKey);

// kickoff
this.subscribe();
this.telemetryCollection = this.openmct.telemetry.requestCollection(this.domainObject, {});
this.telemetryCollection.on('add', this.dataAdded);
this.telemetryCollection.on('remove', this.dataRemoved);
this.telemetryCollection.on('clear', this.dataCleared);
this.telemetryCollection.load();
},
beforeDestroy() {
if (this.unsubscribe) {
Expand All @@ -54,9 +57,31 @@ export default {
}

this.stopFollowingDataTimeContext();
this.openmct.objectViews.off('clearData', this.clearData);
this.openmct.objectViews.off('clearData', this.dataCleared);

this.telemetryCollection.off('add', this.dataAdded);
this.telemetryCollection.off('remove', this.dataRemoved);
this.telemetryCollection.off('clear', this.dataCleared);

this.telemetryCollection.destroy();
},
methods: {
dataAdded(dataToAdd) {
const normalizedDataToAdd = dataToAdd.map(datum => this.normalizeDatum(datum));
this.imageHistory = this.imageHistory.concat(normalizedDataToAdd);
},
dataCleared() {
this.imageHistory.splice(0, this.imageHistory.length);
},
dataRemoved(dataToRemove) {
this.imageHistory = this.imageHistory.filter(existingDatum => {
const shouldKeep = dataToRemove.some(datumToRemove => {
return (existingDatum.utc !== datumToRemove.utc);
});

return shouldKeep;
});
},
setDataTimeContext() {
this.stopFollowingDataTimeContext();
this.timeContext = this.openmct.time.getContextForView(this.objectPath);
Expand All @@ -70,19 +95,6 @@ export default {
this.timeContext.off('timeSystem', this.timeSystemChange);
}
},
isDatumValid(datum) {
//TODO: Add a check to see if there are duplicate images (identical image timestamp and url subsequently)
if (!datum) {
return false;
}

const datumTimeCheck = this.parseTime(datum);
const bounds = this.timeContext.bounds();

const isOutOfBounds = datumTimeCheck < bounds.start || datumTimeCheck > bounds.end;

return !isOutOfBounds;
},
formatImageUrl(datum) {
if (!datum) {
return;
Expand Down Expand Up @@ -124,63 +136,14 @@ export default {
// forcibly reset the imageContainer size to prevent an aspect ratio distortion
delete this.imageContainerWidth;
delete this.imageContainerHeight;

return this.requestHistory();
},
async requestHistory() {
this.requestCount++;
const requestId = this.requestCount;
const bounds = this.timeContext.bounds();

const data = await this.openmct.telemetry
.request(this.domainObject, bounds) || [];
// wait until new request resolves to do comparison
if (this.requestCount !== requestId) {
return this.imageHistory = [];
}

const imagery = data.filter(this.isDatumValid).map(this.normalizeDatum);
this.imageHistory = imagery;
},
clearData(domainObjectToClear) {
// global clearData button is accepted therefore no truthy check on inputted param
const clearDataForObjectSelected = Boolean(domainObjectToClear);
if (clearDataForObjectSelected) {
const idsEqual = this.openmct.objects.areIdsEqual(
domainObjectToClear.identifier,
this.domainObject.identifier
);
if (!idsEqual) {
return;
}
}

// splice array to encourage garbage collection
this.imageHistory.splice(0, this.imageHistory.length);

},
timeSystemChange() {
this.timeSystem = this.timeContext.timeSystem();
this.timeKey = this.timeSystem.key;
this.timeFormatter = this.getFormatter(this.timeKey);
this.durationFormatter = this.getFormatter(this.timeSystem.durationFormat || DEFAULT_DURATION_FORMATTER);
},
subscribe() {
this.unsubscribe = this.openmct.telemetry
.subscribe(this.domainObject, (datum) => {
let parsedTimestamp = this.parseTime(datum);
let bounds = this.timeContext.bounds();
if (!(parsedTimestamp >= bounds.start && parsedTimestamp <= bounds.end)) {
return;
}

if (this.isDatumValid(datum)) {
this.imageHistory.push(this.normalizeDatum(datum));
}
});
},
normalizeDatum(datum) {

const formattedTime = this.formatTime(datum);
const url = this.formatImageUrl(datum);
const time = this.parseTime(formattedTime);
Expand Down
91 changes: 47 additions & 44 deletions src/plugins/imagery/pluginSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ describe("The Imagery View Layouts", () => {
let openmct;
let parent;
let child;
let historicalProvider;
let imageTelemetry = generateTelemetry(START - TEN_MINUTES, COUNT);
let imageryObject = {
identifier: {
Expand Down Expand Up @@ -122,50 +123,6 @@ describe("The Imagery View Layouts", () => {
"priority": 3
},
"source": "url"
// "relatedTelemetry": {
// "heading": {
// "comparisonFunction": comparisonFunction,
// "historical": {
// "telemetryObjectId": "heading",
// "valueKey": "value"
// }
// },
// "roll": {
// "comparisonFunction": comparisonFunction,
// "historical": {
// "telemetryObjectId": "roll",
// "valueKey": "value"
// }
// },
// "pitch": {
// "comparisonFunction": comparisonFunction,
// "historical": {
// "telemetryObjectId": "pitch",
// "valueKey": "value"
// }
// },
// "cameraPan": {
// "comparisonFunction": comparisonFunction,
// "historical": {
// "telemetryObjectId": "cameraPan",
// "valueKey": "value"
// }
// },
// "cameraTilt": {
// "comparisonFunction": comparisonFunction,
// "historical": {
// "telemetryObjectId": "cameraTilt",
// "valueKey": "value"
// }
// },
// "sunOrientation": {
// "comparisonFunction": comparisonFunction,
// "historical": {
// "telemetryObjectId": "sunOrientation",
// "valueKey": "value"
// }
// }
// }
},
{
"name": "Name",
Expand Down Expand Up @@ -209,6 +166,13 @@ describe("The Imagery View Layouts", () => {
telemetryPromiseResolve = resolve;
});

historicalProvider = {
request: () => {
return Promise.resolve(imageTelemetry);
}
};
spyOn(openmct.telemetry, 'findRequestProvider').and.returnValue(historicalProvider);

spyOn(openmct.telemetry, 'request').and.callFake(() => {
telemetryPromiseResolve(imageTelemetry);

Expand Down Expand Up @@ -584,6 +548,34 @@ describe("The Imagery View Layouts", () => {
expect(imageSizeAfter.width).toBeLessThan(imageSizeBefore.width);
done();
});

it('should reset the brightness and contrast when clicking the reset button', async () => {
const viewInstance = imageryView._getInstance();
await Vue.nextTick();

// Save the original brightness and contrast values
const origBrightness = viewInstance.$refs.ImageryContainer.filters.brightness;
const origContrast = viewInstance.$refs.ImageryContainer.filters.contrast;

// Change them to something else (default: 100)
viewInstance.$refs.ImageryContainer.setFilters({
brightness: 200,
contrast: 200
});
await Vue.nextTick();

// Verify that the values actually changed
expect(viewInstance.$refs.ImageryContainer.filters.brightness).toBe(200);
expect(viewInstance.$refs.ImageryContainer.filters.contrast).toBe(200);

// Click the reset button
parent.querySelector('.t-btn-reset').click();
await Vue.nextTick();

// Verify that the values were reset
expect(viewInstance.$refs.ImageryContainer.filters.brightness).toBe(origBrightness);
expect(viewInstance.$refs.ImageryContainer.filters.contrast).toBe(origContrast);
});
});

describe("imagery time strip view", () => {
Expand Down Expand Up @@ -652,5 +644,16 @@ describe("The Imagery View Layouts", () => {
});
});
});

it("should remove images when bounds change", async () => {
openmct.time.timeSystem('utc', {
start: START,
end: START + (5 * ONE_MINUTE)
});
await Vue.nextTick();
await Vue.nextTick();
const imageElements = parent.querySelectorAll('.c-imagery-tsv__image-wrapper');
expect(imageElements.length).toEqual(1);
});
});
});