Skip to content

Commit

Permalink
feat: Introduce alarms
Browse files Browse the repository at this point in the history
  • Loading branch information
NorbertNader committed Sep 7, 2022
1 parent e9760d4 commit 701d1bc
Show file tree
Hide file tree
Showing 84 changed files with 2,612 additions and 331 deletions.
33 changes: 33 additions & 0 deletions docs/AWSIoTSiteWiseSource.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,39 @@ Each asset contains the following fields:

Type: String

#### Alarms

AWS IoT SiteWise has a concept of [alarms](https://docs.aws.amazon.com/iot-sitewise/latest/userguide/industrial-alarms.html).

The source of alarms in IoT Application Kit is AWS IoT Events.

AWS IoT Events alarms are able to process and alarm on AWS IoT SiteWise data.

To query for an alarm you have to know the **AlarmState Property ID**. The **AlarmState Property ID** can be found in the AWS IoT SiteWise console on the **Models** page. Find the model which the alarm was created on. Then under the **Alarm definitions** tab you should see your alarm. Use the **AlarmState Property ID** as the `propertyId` in the asset property query.

```
query.timeSeriesData({
assets: [{
assetId: 'id',
properties: [{ propertyId: 'alarmStatePropertyId' }]
}]
})
```

What this entails:
- **streamType** for the **alarmStatePropertyId dataStream** will be set to `'ALARM'`.
- if the **inputPropertyId** is requested in the **AssetQuery** an **associatedStream** will be added to the **inputPropertyId dataStream**:
```
associatedStreams: [ ..., { id: toId({ assetId, propertyId: alarmStatePropertyId }), type: 'ALARM' } ]
```
- **thresholds** will be constructed to represent the alarm:
- A threshold for the **inputPropertyId dataStream**, used on charts with a y axis e.g. on `iot-line-chart`.
- Thresholds for every **AWS IoT Events AlarmState** for components that visualize alarms e.g. `iot-status-timeline`. More on alarm state [here](https://docs.aws.amazon.com/iotevents/latest/apireference/API_iotevents-data_AlarmState.html).

<img width="718" alt="188190555-e0d08ac4-216c-42bf-8b11-0d884a5d7e13" src="https://user-images.githubusercontent.com/6397726/188932778-48605d7a-226f-4c11-9692-5e2a78c3c530.png">
<img width="718" alt="188190551-6ac7b257-0401-4f40-805e-b624aae30792" src="https://user-images.githubusercontent.com/6397726/188932783-92c97a6c-8579-4a2d-bcd7-38dff11b3a32.png">
<img width="718" alt="188190546-63a1469c-cc60-464c-afe3-5a92ccae56fc" src="https://user-images.githubusercontent.com/6397726/188932785-61008e82-53b9-4158-832a-f32c26faa581.png">

### TimeSeriesDataSettings parameter

(Optional) Specifies how IoT Application Kit requests time series data. Learn more about how to configure TimeSeriesDataSettings, see TimeSeriesDataSettings under [Core](https://github.com/awslabs/iot-app-kit/tree/main/docs/Core.md).
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,6 @@
},
"resolutions": {
"@types/react": "^17.0.2",
"@types/react-dom": "^17.0.2"
"@types/react-dom": "^17.0.2"
}
}
2 changes: 2 additions & 0 deletions packages/components/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export namespace Components {
interface IotTestRoutes {
}
interface IotTimeSeriesConnector {
"annotations": Annotations;
"assignDefaultColors": boolean | undefined;
"initialViewport": Viewport;
"provider": Provider<TimeSeriesData[]>;
Expand Down Expand Up @@ -321,6 +322,7 @@ declare namespace LocalJSX {
interface IotTestRoutes {
}
interface IotTimeSeriesConnector {
"annotations"?: Annotations;
"assignDefaultColors"?: boolean | undefined;
"initialViewport"?: Viewport;
"provider"?: Provider<TimeSeriesData[]>;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
it('todo', () => {
// TODO
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Annotations } from '@synchro-charts/core';

export const combineAnnotations = (prev: Annotations, cur: Annotations): Annotations => {
return {
...prev,
y: [...(prev?.y || []), ...(cur?.y || [])],
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
it('todo', () => {
// TODO
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Annotations, YAnnotation } from '@synchro-charts/core';
import { DataStream } from '@iot-app-kit/core';

export const getAlarmStreamAnnotations = ({
annotations,
dataStreams,
}: {
annotations: Annotations;
dataStreams: DataStream[];
}): { y: YAnnotation[] | undefined } => ({
y: (annotations as Annotations).y?.filter((yAnnotation) => {
return (
'dataStreamIds' in yAnnotation &&
yAnnotation.dataStreamIds?.some((dataStreamId) =>
dataStreams.some((dataStream) => dataStream.streamType === 'ALARM' && dataStreamId === dataStream.id)
)
);
}),
});
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { newSpecPage } from '@stencil/core/testing';
import { MinimalLiveViewport } from '@synchro-charts/core';
import { IotBarChart } from './iot-bar-chart';
import { Components } from '../../components.d';
import { initialize } from '@iot-app-kit/source-iotsitewise';
import { initialize, createMockIoTEventsSDK } from '@iot-app-kit/source-iotsitewise';
import { IotTimeSeriesConnector } from '../iot-time-series-connector/iot-time-series-connector';
import { CustomHTMLElement } from '../../testing/types';
import { update } from '../../testing/update';
Expand All @@ -15,6 +15,7 @@ const viewport: MinimalLiveViewport = {
const barChartSpecPage = async (propOverrides: Partial<Components.IotBarChart> = {}) => {
const { query } = initialize({
iotSiteWiseClient: mockSiteWiseSDK,
iotEventsClient: createMockIoTEventsSDK(),
});

const page = await newSpecPage({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,11 @@ export class IotBarChart {
provider={this.provider}
styleSettings={this.styleSettings}
assignDefaultColors
renderFunc={({ dataStreams }) => (
annotations={this.annotations}
renderFunc={({ dataStreams, annotations }) => (
<sc-bar-chart
dataStreams={dataStreams as SynchroChartsDataStream[]}
annotations={this.annotations}
annotations={annotations}
viewport={this.viewport}
isEditing={this.isEditing}
widgetId={this.widgetId}
Expand Down
3 changes: 2 additions & 1 deletion packages/components/src/components/iot-kpi/iot-kpi.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { newSpecPage } from '@stencil/core/testing';
import { initialize } from '@iot-app-kit/source-iotsitewise';
import { initialize, createMockIoTEventsSDK } from '@iot-app-kit/source-iotsitewise';
import { MinimalLiveViewport } from '@synchro-charts/core';
import { IotKpi } from './iot-kpi';
import { Components } from '../../components.d';
Expand All @@ -15,6 +15,7 @@ const viewport: MinimalLiveViewport = {
const kpiSpecPage = async (propOverrides: Partial<Components.IotKpi> = {}) => {
const { query } = initialize({
iotSiteWiseClient: mockSiteWiseSDK,
iotEventsClient: createMockIoTEventsSDK(),
});

const page = await newSpecPage({
Expand Down
5 changes: 3 additions & 2 deletions packages/components/src/components/iot-kpi/iot-kpi.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,11 @@ export class IotKpi {
<iot-time-series-connector
provider={this.provider}
styleSettings={this.styleSettings}
renderFunc={({ dataStreams }) => (
annotations={this.annotations}
renderFunc={({ dataStreams, annotations }) => (
<sc-kpi
dataStreams={dataStreams as SynchroChartsDataStream[]}
annotations={this.annotations}
annotations={annotations}
viewport={this.viewport}
isEditing={this.isEditing}
widgetId={this.widgetId}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { MinimalLiveViewport } from '@synchro-charts/core';
import { IotLineChart } from './iot-line-chart';
import { Components } from '../../components.d';
import { CustomHTMLElement } from '../../testing/types';
import { initialize } from '@iot-app-kit/source-iotsitewise';
import { initialize, createMockIoTEventsSDK } from '@iot-app-kit/source-iotsitewise';
import { IotTimeSeriesConnector } from '../iot-time-series-connector/iot-time-series-connector';
import { update } from '../../testing/update';
import { mockSiteWiseSDK } from '../../testing/mocks/siteWiseSDK';
Expand All @@ -15,6 +15,7 @@ const viewport: MinimalLiveViewport = {
const lineChartSpecPage = async (propOverrides: Partial<Components.IotKpi> = {}) => {
const { query } = initialize({
iotSiteWiseClient: mockSiteWiseSDK,
iotEventsClient: createMockIoTEventsSDK(),
});

const page = await newSpecPage({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,12 @@ export class IotLineChart {
provider={this.provider}
styleSettings={this.styleSettings}
assignDefaultColors
renderFunc={({ dataStreams }) => {
annotations={this.annotations}
renderFunc={({ dataStreams, annotations }) => {
return (
<sc-line-chart
dataStreams={dataStreams as SynchroChartsDataStream[]}
annotations={this.annotations}
annotations={annotations}
viewport={this.viewport}
isEditing={this.isEditing}
widgetId={this.widgetId}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createMockSiteWiseSDK, initialize } from '@iot-app-kit/source-iotsitewise';
import { createMockSiteWiseSDK, createMockIoTEventsSDK, initialize } from '@iot-app-kit/source-iotsitewise';
import { newSpecPage } from '@stencil/core/testing';
import { IotResourceExplorer } from './iot-resource-explorer';
import { Components } from '../../components.d';
Expand All @@ -14,6 +14,7 @@ const resourceExplorerSpec = async (
) => {
const { query } = initialize({
iotSiteWiseClient: iotSiteWiseClient,
iotEventsClient: createMockIoTEventsSDK(),
});
const page = await newSpecPage({
components: [IotResourceExplorer],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { newSpecPage } from '@stencil/core/testing';
import { MinimalLiveViewport } from '@synchro-charts/core';
import { IotScatterChart } from './iot-scatter-chart';
import { Components } from '../../components.d';
import { initialize } from '@iot-app-kit/source-iotsitewise';
import { createMockIoTEventsSDK, initialize } from '@iot-app-kit/source-iotsitewise';
import { IotTimeSeriesConnector } from '../iot-time-series-connector/iot-time-series-connector';
import { CustomHTMLElement } from '../../testing/types';
import { update } from '../../testing/update';
Expand All @@ -15,6 +15,7 @@ const viewport: MinimalLiveViewport = {
const scatterChartSpecPage = async (propOverrides: Partial<Components.IotScatterChart> = {}) => {
const { query } = initialize({
iotSiteWiseClient: mockSiteWiseSDK,
iotEventsClient: createMockIoTEventsSDK(),
});

const page = await newSpecPage({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,12 @@ export class IotScatterChart {
provider={this.provider}
styleSettings={this.styleSettings}
assignDefaultColors
renderFunc={({ dataStreams }) => {
annotations={this.annotations}
renderFunc={({ dataStreams, annotations }) => {
return (
<sc-scatter-chart
dataStreams={dataStreams as SynchroChartsDataStream[]}
annotations={this.annotations}
annotations={annotations}
viewport={this.viewport}
isEditing={this.isEditing}
widgetId={this.widgetId}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { newSpecPage } from '@stencil/core/testing';
import { MinimalLiveViewport } from '@synchro-charts/core';
import { IotStatusGrid } from './iot-status-grid';
import { Components } from '../../components.d';
import { initialize } from '@iot-app-kit/source-iotsitewise';
import { createMockIoTEventsSDK, initialize } from '@iot-app-kit/source-iotsitewise';
import { IotTimeSeriesConnector } from '../iot-time-series-connector/iot-time-series-connector';
import { CustomHTMLElement } from '../../testing/types';
import { update } from '../../testing/update';
Expand All @@ -15,6 +15,7 @@ const viewport: MinimalLiveViewport = {
const statusGridSpecPage = async (propOverrides: Partial<Components.IotKpi> = {}) => {
const { query } = initialize({
iotSiteWiseClient: mockSiteWiseSDK,
iotEventsClient: createMockIoTEventsSDK(),
});

const page = await newSpecPage({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,11 @@ export class IotStatusGrid {
<iot-time-series-connector
provider={this.provider}
styleSettings={this.styleSettings}
renderFunc={({ dataStreams }) => (
annotations={this.annotations}
renderFunc={({ dataStreams, annotations }) => (
<sc-status-grid
dataStreams={dataStreams as SynchroChartsDataStream[]}
annotations={this.annotations}
annotations={annotations}
viewport={this.viewport}
isEditing={this.isEditing}
widgetId={this.widgetId}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { newSpecPage } from '@stencil/core/testing';
import { MinimalLiveViewport } from '@synchro-charts/core';
import { IotStatusTimeline } from './iot-status-timeline';
import { Components } from '../../components.d';
import { initialize } from '@iot-app-kit/source-iotsitewise';
import { createMockIoTEventsSDK, initialize } from '@iot-app-kit/source-iotsitewise';
import { IotTimeSeriesConnector } from '../iot-time-series-connector/iot-time-series-connector';
import { CustomHTMLElement } from '../../testing/types';
import { update } from '../../testing/update';
Expand All @@ -15,6 +15,7 @@ const viewport: MinimalLiveViewport = {
const statusTimelineSpecPage = async (propOverrides: Partial<Components.IotStatusTimeline> = {}) => {
const { query } = initialize({
iotSiteWiseClient: mockSiteWiseSDK,
iotEventsClient: createMockIoTEventsSDK(),
});

const page = await newSpecPage({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import {
combineProviders,
} from '@iot-app-kit/core';
import { v4 as uuidv4 } from 'uuid';
import { combineAnnotations } from '../common/combineAnnotations';
import { getAlarmStreamAnnotations } from '../common/getAlarmStreamAnnotations';

@Component({
tag: 'iot-status-timeline',
Expand Down Expand Up @@ -76,15 +78,24 @@ export class IotStatusTimeline {
provider={this.provider}
styleSettings={this.styleSettings}
assignDefaultColors
renderFunc={({ dataStreams }) => (
<sc-status-timeline
dataStreams={dataStreams as SynchroChartsDataStream[]}
annotations={this.annotations}
viewport={this.viewport}
isEditing={this.isEditing}
widgetId={this.widgetId}
/>
)}
annotations={this.annotations}
renderFunc={({ dataStreams, annotations }) => {
// Filter out the threshold generated for the input property stream
const newAnnotations = combineAnnotations(
this.annotations,
getAlarmStreamAnnotations({ annotations, dataStreams })
);

return (
<sc-status-timeline
dataStreams={dataStreams as SynchroChartsDataStream[]}
annotations={newAnnotations}
viewport={this.viewport}
isEditing={this.isEditing}
widgetId={this.widgetId}
/>
);
}}
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { newSpecPage } from '@stencil/core/testing';
import { MinimalLiveViewport } from '@synchro-charts/core';
import { IotTable } from './iot-table';
import { Components } from '../../components.d';
import { initialize } from '@iot-app-kit/source-iotsitewise';
import { createMockIoTEventsSDK, initialize } from '@iot-app-kit/source-iotsitewise';
import { IotTimeSeriesConnector } from '../iot-time-series-connector/iot-time-series-connector';
import { CustomHTMLElement } from '../../testing/types';
import { update } from '../../testing/update';
Expand All @@ -15,6 +15,7 @@ const viewport: MinimalLiveViewport = {
const tableSpecPage = async (propOverrides: Partial<Components.IotKpi> = {}) => {
const { query } = initialize({
iotSiteWiseClient: mockSiteWiseSDK,
iotEventsClient: createMockIoTEventsSDK(),
});

const page = await newSpecPage({
Expand Down
5 changes: 3 additions & 2 deletions packages/components/src/components/iot-table/iot-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,12 @@ export class IotTable {
<iot-time-series-connector
provider={this.provider}
styleSettings={this.styleSettings}
renderFunc={({ dataStreams }) => (
annotations={this.annotations}
renderFunc={({ dataStreams, annotations }) => (
<sc-table
dataStreams={dataStreams as SynchroChartsDataStream[]}
tableColumns={this.tableColumns}
annotations={this.annotations}
annotations={annotations}
viewport={this.viewport}
widgetId={this.widgetId}
/>
Expand Down
Loading

0 comments on commit 701d1bc

Please sign in to comment.