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

feat: customizable resolutions #23

Merged
merged 2 commits into from
Dec 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const barChartSpecPage = async (propOverrides: Partial<Components.IotBarChart> =
isEditing: false,
query: {
source: 'test-mock',
assets: [{ assetId: 'some-asset-id', propertyIds: ['some-property-id'] }],
assets: [{ assetId: 'some-asset-id', properties: [{ propertyId: 'some-property-id' }] }],
} as SiteWiseDataStreamQuery,
viewport,
...propOverrides,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ it('provides data streams', async () => {
renderFunc,
query: {
source: 'test-mock',
assets: [{ assetId, propertyIds: [propertyId] }],
assets: [{ assetId, properties: [{ propertyId }] }],
} as SiteWiseDataStreamQuery,
});

Expand Down Expand Up @@ -87,7 +87,7 @@ it('updates with new query', async () => {

connector.query = {
source: 'test-mock',
assets: [{ assetId, propertyIds: [propertyId] }],
assets: [{ assetId, properties: [{ propertyId }] }],
} as SiteWiseDataStreamQuery;

await page.waitForChanges();
Expand Down
2 changes: 1 addition & 1 deletion packages/components/src/components/iot-kpi/iot-kpi.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const kpiSpecPage = async (propOverrides: Partial<Components.IotKpi> = {}) => {
isEditing: false,
query: {
source: 'test-mock',
assets: [{ assetId: 'some-asset-id', propertyIds: ['some-property-id'] }],
assets: [{ assetId: 'some-asset-id', properties: [{ propertyId: 'some-property-id' }] }],
} as SiteWiseDataStreamQuery, // static casting because of legacy sw
viewport,
...propOverrides,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const lineChartSpecPage = async (propOverrides: Partial<Components.IotKpi> = {})
isEditing: false,
query: {
source: 'test-mock',
assets: [{ assetId: 'some-asset-id', propertyIds: ['some-property-id'] }],
assets: [{ assetId: 'some-asset-id', properties: [{ propertyId: 'some-property-id' }] }],
} as SiteWiseDataStreamQuery, // static casting because of legacy sw
viewport,
...propOverrides,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const scatterChartSpecPage = async (propOverrides: Partial<Components.IotScatter
isEditing: false,
query: {
source: 'test-mock',
assets: [{ assetId: 'some-asset-id', propertyIds: ['some-property-id'] }],
assets: [{ assetId: 'some-asset-id', properties: [{ propertyId: 'some-property-id' }] }],
} as SiteWiseDataStreamQuery, // static casting because of legacy sw
viewport,
...propOverrides,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const statusGridSpecPage = async (propOverrides: Partial<Components.IotKpi> = {}
isEditing: false,
query: {
source: 'test-mock',
assets: [{ assetId: 'some-asset-id', propertyIds: ['some-property-id'] }],
assets: [{ assetId: 'some-asset-id', properties: [{ propertyId: 'some-property-id' }] }],
} as SiteWiseDataStreamQuery, // static casting because of legacy sw
viewport,
...propOverrides,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const statusTimelineSpecPage = async (propOverrides: Partial<Components.IotStatu
isEditing: false,
query: {
source: 'test-mock',
assets: [{ assetId: 'some-asset-id', propertyIds: ['some-property-id'] }],
assets: [{ assetId: 'some-asset-id', properties: [{ propertyId: 'some-property-id' }] }],
} as SiteWiseDataStreamQuery, // static casting because of legacy sw
viewport,
...propOverrides,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const tableSpecPage = async (propOverrides: Partial<Components.IotKpi> = {}) =>
isEditing: false,
query: {
source: 'test-mock',
assets: [{ assetId: 'some-asset-id', propertyIds: ['some-property-id'] }],
assets: [{ assetId: 'some-asset-id', properties: [{ propertyId: 'some-property-id' }] }],
} as SiteWiseDataStreamQuery, // static casting because of legacy sw
viewport,
...propOverrides,
Expand Down
2 changes: 1 addition & 1 deletion packages/components/src/testing/createMockSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { toDataStreamId } from './dataStreamId';

const dataStreamIds = (query: SiteWiseDataStreamQuery) =>
query.assets
.map(({ assetId, propertyIds }) => propertyIds.map((propertyId) => toDataStreamId({ assetId, propertyId })))
.map(({ assetId, properties }) => properties.map(({ propertyId }) => toDataStreamId({ assetId, propertyId })))
.flat();

export const createMockSource = (dataStreams: DataStream[]): DataSource => ({
Expand Down
13 changes: 10 additions & 3 deletions packages/components/src/testing/testing-ground/siteWiseQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const DEMO_TURBINE_ASSET_1_PROPERTY_4 = '8d9ed440-a8dd-48bd-a35f-70db6f2e

export const STRING_QUERY = {
source: 'site-wise',
assets: [{ assetId: STRING_ASSET_ID, propertyIds: [STRING_PROPERTY_ID] }],
assets: [{ assetId: STRING_ASSET_ID, properties: [{ propertyId: STRING_PROPERTY_ID }] }],
};

export const ASSET_DETAILS_QUERY = {
Expand All @@ -22,17 +22,24 @@ export const NUMBER_QUERY = {
assets: [
{
assetId: DEMO_TURBINE_ASSET_1,
propertyIds: [DEMO_TURBINE_ASSET_1_PROPERTY_1, DEMO_TURBINE_ASSET_1_PROPERTY_4],
properties: [{ propertyId: DEMO_TURBINE_ASSET_1_PROPERTY_1 }, { propertyId: DEMO_TURBINE_ASSET_1_PROPERTY_4 }],
},
],
};

const AGGREGATED_DATA_ASSET = '099b1330-83ff-4fec-b165-c7186ec8eb23';
const AGGREGATED_DATA_PROPERTY = '05c5c47f-fd92-4823-828e-09ce63b90569';
const AGGREGATED_DATA_PROPERTY_2 = '11d2599a-2547-451d-ab79-a47f878dbbe3';

export const AGGREGATED_DATA_QUERY = {
source: 'site-wise',
assets: [{ assetId: AGGREGATED_DATA_ASSET, propertyIds: [AGGREGATED_DATA_PROPERTY] }],
assets: [{
assetId: AGGREGATED_DATA_ASSET,
properties: [
{ propertyId: AGGREGATED_DATA_PROPERTY },
{ propertyId: AGGREGATED_DATA_PROPERTY_2, resolution: '1m' }
]
}],
};

// From demo turbine asset, found at https://p-rlvy2rj8.app.iotsitewise.aws/
Expand Down
42 changes: 36 additions & 6 deletions packages/components/src/testing/testing-ground/testing-ground.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Component, h } from '@stencil/core';
import { initialize, DataModule } from '@iot-app-kit/core';
import { Component, State, h } from '@stencil/core';
import { initialize, DataModule, ResolutionConfig } from '@iot-app-kit/core';
import {
ASSET_DETAILS_QUERY,
DEMO_TURBINE_ASSET_1,
Expand All @@ -15,7 +15,7 @@ const VIEWPORT = { duration: '5m' };

const THREE_MINUTES = 1000 * 60 * 3;

const resolutionMapping = {
const DEFAULT_RESOLUTION_MAPPING = {
[THREE_MINUTES]: '1m',
}

Expand All @@ -24,10 +24,30 @@ const resolutionMapping = {
styleUrl: 'testing-ground.css',
})
export class TestingGround {
@State() resolution: ResolutionConfig = DEFAULT_RESOLUTION_MAPPING;
@State() viewport: { duration: string } = VIEWPORT;
private dataModule: DataModule;

componentWillLoad() {
this.dataModule = initialize({ awsCredentials: getEnvCredentials(), awsRegion: 'us-west-2' });
this.dataModule = initialize({ awsCredentials: getEnvCredentials(), awsRegion: 'us-east-1' });
}

private changeResolution = (ev: Event) => {
const resolution = (ev.target as HTMLSelectElement)?.value;

if (resolution === 'auto'){
this.resolution = DEFAULT_RESOLUTION_MAPPING;
} else if (resolution === '0') {
this.resolution = {};
} else {
this.resolution = resolution;
}
}

private changeDuration = (ev: Event) => {
const duration = `${(ev.target as HTMLSelectElement)?.value}m`;

this.viewport = { duration };
}

render() {
Expand Down Expand Up @@ -86,12 +106,22 @@ export class TestingGround {
/>
</div>
</div>
resolution: <select onChange={this.changeResolution}>
<option value={'0'}>raw</option>
<option value={'1m'}>1m</option>
<option selected value={'auto'}>auto</option>
</select>
viewport: <select onChange={this.changeDuration}>
<option value={'1'}>1 minute</option>
<option value={'3'}>3 minutes</option>
<option selected value={'5'}>5 minutes</option>
</select>
<div style={{ width: '400px', height: '500px' }}>
<iot-line-chart
appKit={this.dataModule}
query={AGGREGATED_DATA_QUERY}
viewport={VIEWPORT}
requestConfig={{ resolutionMapping, fetchAggregatedData: true }}
viewport={this.viewport}
requestConfig={{ resolution: this.resolution, fetchAggregatedData: true }}
/>
</div>
<iot-asset-details query={ASSET_DETAILS_QUERY} />
Expand Down
11 changes: 6 additions & 5 deletions packages/core/src/data-module/IotAppKitDataModule.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const DATA_STREAM_QUERY: SiteWiseDataStreamQuery = {
assets: [
{
assetId: ASSET_ID,
propertyIds: [PROPERTY_ID],
properties: [{ propertyId: PROPERTY_ID }],
},
],
};
Expand All @@ -39,8 +39,8 @@ const createMockSiteWiseDataSource = (
initiateRequest: jest.fn(({ onSuccess }: DataSourceRequest<SiteWiseDataStreamQuery>) => onSuccess(dataStreams)),
getRequestsFromQuery: ({ query }) =>
query.assets
.map(({ assetId, propertyIds }) =>
propertyIds.map((propertyId) => ({
.map(({ assetId, properties }) =>
properties.map(({ propertyId }) => ({
id: toDataStreamId({ assetId, propertyId }),
resolution,
}))
Expand Down Expand Up @@ -183,7 +183,7 @@ it('subscribes to a single data stream', async () => {
assets: [
{
assetId,
propertyIds: [propertyId],
properties: [{ propertyId }],
},
],
},
Expand Down Expand Up @@ -233,7 +233,7 @@ it('requests data from a custom data source', () => {
dataModule.subscribeToDataStreams(
{
query: {
assets: [{ assetId, propertyIds: [propertyId] }],
assets: [{ assetId, properties: [{ propertyId }] }],
source: customSource.name,
},
requestInfo: {
Expand Down Expand Up @@ -778,3 +778,4 @@ it('requests data range with buffer', () => {

unsubscribe();
});

6 changes: 4 additions & 2 deletions packages/core/src/data-module/data-cache/requestTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@ export type OnRequestData = (opts: {
dataStreamId: string;
}) => void;

export type ResolutionMapping ={
export type ResolutionMapping = {
[viewportDuration: number]: number | string;
};

export type ResolutionConfig = ResolutionMapping | string;

export interface RequestConfig {
fetchMostRecentBeforeStart?: boolean;
requestBuffer?: number;
fetchAggregatedData?: boolean;
resolutionMapping?: ResolutionMapping;
resolution?: ResolutionConfig;
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ it('updates subscription', () => {

const query = {
source: SITEWISE_DATA_SOURCE,
assets: [{ assetId: '123', propertyIds: ['prop1', 'prop2'] }],
assets: [{ assetId: '123', properties: [{ propertyId: 'prop1' }, { propertyId: 'prop2' }] }],
};

subscriptionStore.addSubscription(SUBSCRIPTION_ID, MOCK_SUBSCRIPTION);
Expand Down
40 changes: 34 additions & 6 deletions packages/core/src/data-sources/site-wise/client/client.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe('getHistoricalPropertyDataPoints', () => {
const onError = jest.fn();
const query: SiteWiseDataStreamQuery = {
source: SITEWISE_DATA_SOURCE,
assets: [{ assetId, propertyIds: [propertyId] }],
assets: [{ assetId, properties: [{ propertyId }] }],
};

const client = new SiteWiseClient(createSiteWiseSDK({ getAssetPropertyValueHistory }));
Expand All @@ -47,7 +47,7 @@ describe('getHistoricalPropertyDataPoints', () => {
const onError = jest.fn();
const query: SiteWiseDataStreamQuery = {
source: SITEWISE_DATA_SOURCE,
assets: [{ assetId, propertyIds: [propertyId] }],
assets: [{ assetId, properties: [{ propertyId }] }],
};

const client = new SiteWiseClient(createSiteWiseSDK({ getAssetPropertyValueHistory }));
Expand Down Expand Up @@ -91,7 +91,7 @@ describe('getLatestPropertyDataPoint', () => {
const onError = jest.fn();
const query: SiteWiseDataStreamQuery = {
source: SITEWISE_DATA_SOURCE,
assets: [{ assetId, propertyIds: [propertyId] }],
assets: [{ assetId, properties: [{ propertyId }] }],
};

const client = new SiteWiseClient(createSiteWiseSDK({ getAssetPropertyValue }));
Expand Down Expand Up @@ -126,7 +126,7 @@ describe('getLatestPropertyDataPoint', () => {
const onError = jest.fn();
const query: SiteWiseDataStreamQuery = {
source: SITEWISE_DATA_SOURCE,
assets: [{ assetId, propertyIds: [propertyId] }],
assets: [{ assetId, properties: [{ propertyId }] }],
};

await client.getLatestPropertyDataPoint({ query, onSuccess, onError });
Expand All @@ -147,7 +147,7 @@ describe('getAggregatedPropertyDataPoints', () => {
const onError = jest.fn();
const query: SiteWiseDataStreamQuery = {
source: SITEWISE_DATA_SOURCE,
assets: [{ assetId, propertyIds: [propertyId] }],
assets: [{ assetId, properties: [{ propertyId }] }],
};

const client = new SiteWiseClient(createSiteWiseSDK({ getAssetPropertyAggregates }));
Expand All @@ -170,6 +170,34 @@ describe('getAggregatedPropertyDataPoints', () => {
expect(onError).toBeCalled();
});

it('throws error when no resolution specified', async () => {
const getAssetPropertyAggregates = jest.fn().mockResolvedValue(AGGREGATE_VALUES);
const assetId = 'some-asset-id';
const propertyId = 'some-property-id';

const onSuccess = jest.fn();
const onError = jest.fn();
const query: SiteWiseDataStreamQuery = {
source: SITEWISE_DATA_SOURCE,
assets: [{ assetId, properties: [{ propertyId }] }],
};

const client = new SiteWiseClient(createSiteWiseSDK({ getAssetPropertyAggregates }));

const startDate = new Date(2000, 0, 0);
const endDate = new Date(2001, 0, 0);
const aggregateTypes = [AggregateType.AVERAGE];

await expect(async () => { await client.getAggregatedPropertyDataPoints({
query,
onSuccess,
onError,
start: startDate,
end: endDate,
aggregateTypes,
})}).rejects.toThrowError();
});

it('returns data point on success', async () => {
const assetId = 'some-asset-id';
const propertyId = 'some-property-id';
Expand All @@ -178,7 +206,7 @@ describe('getAggregatedPropertyDataPoints', () => {
const onError = jest.fn();
const query: SiteWiseDataStreamQuery = {
source: SITEWISE_DATA_SOURCE,
assets: [{ assetId, propertyIds: [propertyId] }],
assets: [{ assetId, properties: [{ propertyId }] }],
};
const getAssetPropertyAggregates = jest.fn().mockResolvedValue(AGGREGATE_VALUES);

Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/data-sources/site-wise/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ export class SiteWiseClient {
query: SiteWiseDataStreamQuery;
start: Date;
end: Date;
resolution: string;
resolution?: string;
aggregateTypes: AggregateType[];
maxResults?: number;
onError: Function;
onError: ErrorCallback;
onSuccess: DataStreamCallback;
}): Promise<void> {
return getAggregatedPropertyDataPoints({ client: this.siteWiseSdk, ...options });
Expand Down
Loading