Skip to content

Commit

Permalink
feat(alarms): integrate alarms into bar charts
Browse files Browse the repository at this point in the history
  • Loading branch information
corteggiano committed Sep 25, 2024
1 parent 068ebd3 commit 8056660
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 13 deletions.
56 changes: 44 additions & 12 deletions packages/react-components/src/components/bar-chart/barChart.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useMemo } from 'react';
import {
StyleSettingsMap,
Threshold,
Expand All @@ -17,12 +17,15 @@ import {
DEFAULT_VIEWPORT,
ECHARTS_GESTURE,
} from '../../common/constants';
import type {
import { getAlarmQueries, getTimeSeriesQueries } from '../../utils/queries';
import {
AxisSettings,
ChartSize,
ComponentQuery,
} from '../../common/chartTypes';
import { getTimeSeriesQueries } from '../../utils/queries';
import { useAlarms } from '../../hooks/useAlarms';
import { convertAlarmQueryToAlarmRequest } from '../../queries/utils/convertAlarmQueryToAlarmRequest';
import { transformAlarmsToThreshold } from '../../utils/transformAlarmsToThreshold';

const HOUR_IN_MS = 1000 * 60 * 60;
const DAY_IN_MS = HOUR_IN_MS * 24;
Expand Down Expand Up @@ -56,9 +59,38 @@ export const BarChart = (props: BarChartProps) => {
...rest
} = props;

const { viewport, setViewport, group, lastUpdatedBy } = useViewport();

// if using echarts then echarts gesture overrides passed in viewport
// else explicitly passed in viewport overrides viewport group
const utilizedViewport =
(lastUpdatedBy === ECHARTS_GESTURE
? viewport
: passedInViewport || viewport) ?? DEFAULT_VIEWPORT;

const alarmQueries = getAlarmQueries(queries);
const timeSeriesQueries = getTimeSeriesQueries(queries);

const mapAlarmQueriesToRequests = alarmQueries.flatMap((query) =>
convertAlarmQueryToAlarmRequest(query)
);

const transformedAlarms = useAlarms({
iotSiteWiseClient: alarmQueries.at(0)?.iotSiteWiseClient,
iotEventsClient: alarmQueries.at(0)?.iotEventsClient,
requests: mapAlarmQueriesToRequests,
viewport: utilizedViewport,
settings: {
fetchThresholds: true,
refreshRate: alarmQueries.at(0)?.query.requestSettings?.refreshRate,
},
transform: transformAlarmsToThreshold,
});
const filteredAlarms = transformedAlarms.filter((alarm) => !!alarm);

const { dataStreams, thresholds: queryThresholds } = useTimeSeriesData({
viewport: passedInViewport,
queries: getTimeSeriesQueries(queries),
queries: timeSeriesQueries,
settings: {
fetchFromStartToEnd: true,
fetchMostRecentBeforeStart: true,
Expand All @@ -72,15 +104,15 @@ export const BarChart = (props: BarChartProps) => {
},
styles,
});
const { viewport, setViewport, group, lastUpdatedBy } = useViewport();
const allThresholds = [...queryThresholds, ...thresholds];

// if using echarts then echarts gesture overrides passed in viewport
// else explicitly passed in viewport overrides viewport group
const utilizedViewport =
(lastUpdatedBy === ECHARTS_GESTURE
? viewport
: passedInViewport || viewport) ?? DEFAULT_VIEWPORT;
const allThresholds = useMemo(
() => [...queryThresholds, ...thresholds, ...filteredAlarms],
[
JSON.stringify(queryThresholds),
JSON.stringify(thresholds),
JSON.stringify(filteredAlarms),
]
);

return (
<BarChartBase
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { AlarmDataQuery } from '@iot-app-kit/source-iotsitewise';
import { AlarmCompositeModelRequest } from '../../hooks/useAlarms';

export const convertAlarmQueryToAlarmRequest = (
alarmQuery: AlarmDataQuery
): AlarmCompositeModelRequest[] => {
return (
alarmQuery.query.alarms?.reduce((results, alarm) => {
alarm.alarmComponents.map((component) => {
results.push({
assetId: alarm.assetId,
assetCompositeModelId: component.assetCompositeModelId,
});
});
return results;
}, [] as AlarmCompositeModelRequest[]) ?? []
);
};
61 changes: 61 additions & 0 deletions packages/react-components/src/utils/transformAlarmsToThreshold.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Threshold } from '@iot-app-kit/core';
import { AlarmData } from '../hooks/useAlarms';
import { IoTEventsToSynchroChartsComparisonOperator } from '@iot-app-kit/source-iotsitewise';
import { COMPARATOR_MAP, COMPARISON_OPERATOR } from '../common/constants';

const createThreshold = ({
thresholdValue,
severity,
labelText,
comparisonOperator,
}: {
thresholdValue: number;
severity: number | undefined;
labelText: string;
comparisonOperator: COMPARISON_OPERATOR;
}): Threshold => {
return {
color: 'red',
value: thresholdValue,
severity: severity,
showValue: false,
label: {
text: labelText,
show: true,
},
comparisonOperator: comparisonOperator,
};
};

export const transformAlarmsToThreshold = (
alarm: AlarmData
): Threshold | undefined => {
const { models, inputProperty, thresholds, status } = alarm;
const modelsFound = models && models.length !== 0;
const thresholdsFound = thresholds && thresholds?.length !== 0;

if (status.isSuccess) {
if (modelsFound && thresholdsFound) {
const model = models[0];
const threshold = thresholds[thresholds.length - 1];

const thresholdValue =
threshold.value?.doubleValue ?? threshold.value?.integerValue;
const comparisonOperator =
model.alarmRule?.simpleRule?.comparisonOperator;

if (thresholdValue && comparisonOperator && inputProperty) {
const scComparisonOperator = IoTEventsToSynchroChartsComparisonOperator[
comparisonOperator
] as COMPARISON_OPERATOR;

return createThreshold({
labelText: `${inputProperty[0].name} ${COMPARATOR_MAP[scComparisonOperator]} ${thresholdValue}`,
thresholdValue: thresholdValue,
severity: model.severity,
comparisonOperator: scComparisonOperator,
});
}
}
}
};
5 changes: 4 additions & 1 deletion packages/source-iotsitewise/src/alarms/iotevents/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@ export * from './types';
export * from './siteWiseAlarmModule';
export { parseAlarmData } from './util/parseAlarmData';
export { constructAlarmThresholds } from './util/constructAlarmThresholds';
export { SOURCE } from './constants';
export {
SOURCE,
IoTEventsToSynchroChartsComparisonOperator,
} from './constants';
1 change: 1 addition & 0 deletions packages/source-iotsitewise/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export * from './__mocks__';
export { initialize } from './initialize';
export { BranchReference } from './asset-modules/sitewise-asset-tree/types';
export { toId, fromId } from './time-series-data/util/dataStreamId';
export { IoTEventsToSynchroChartsComparisonOperator } from './alarms/iotevents';
export type {
SiteWiseDataSourceInitInputs,
SiteWiseQuery,
Expand Down

0 comments on commit 8056660

Please sign in to comment.