Skip to content

Commit

Permalink
fix(alarm threhsolds): filter values after viewport end
Browse files Browse the repository at this point in the history
  • Loading branch information
corteggiano committed Sep 25, 2024
1 parent fe430b1 commit 068ebd3
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ describe('useAlarmThreshold', () => {

expect(batchGetAssetPropertyValueMock).not.toHaveBeenCalled();

expect(batchGetAssetPropertyValueHistoryMock).toHaveBeenCalledOnce();
expect(batchGetAssetPropertyValueHistoryMock).toHaveBeenCalledTimes(2);
expect(result.current[0].thresholds).toEqual(
mockAssetProperty1Data.reverse()
);
Expand All @@ -248,14 +248,10 @@ describe('useAlarmThreshold', () => {
expect(result.current[1].status.isSuccess).toBe(true);
});

expect(batchGetAssetPropertyValueHistoryMock).toHaveBeenCalledTimes(2);
expect(batchGetAssetPropertyValueHistoryMock).toHaveBeenCalledTimes(4);

expect(result.current[0].thresholds).toEqual(
mockAssetProperty1Data.slice(2)
);
expect(result.current[1].thresholds).toEqual(
mockAssetProperty2Data.slice(2)
);
expect(result.current[0].thresholds).toEqual(mockAssetProperty1Data);
expect(result.current[1].thresholds).toEqual(mockAssetProperty2Data);
});

it('fetches the historical threshold asset properties within a live viewport.', async () => {
Expand Down Expand Up @@ -322,7 +318,7 @@ describe('useAlarmThreshold', () => {

expect(batchGetAssetPropertyValueMock).not.toHaveBeenCalled();

expect(batchGetAssetPropertyValueHistoryMock).toHaveBeenCalledOnce();
expect(batchGetAssetPropertyValueHistoryMock).toHaveBeenCalledTimes(2);
expect(result.current[0].thresholds).toEqual(
mockAssetProperty1Data.reverse()
);
Expand Down Expand Up @@ -353,7 +349,7 @@ describe('useAlarmThreshold', () => {
jest.advanceTimersByTime(TEST_ADVANCE_TIMERS_PAST_REFRESH_RATE);
});

expect(batchGetAssetPropertyValueHistoryMock).toHaveBeenCalledTimes(2);
expect(batchGetAssetPropertyValueHistoryMock).toHaveBeenCalledTimes(4);

jest.useRealTimers();
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { useMemo } from 'react';
import { IoTSiteWiseClient } from '@aws-sdk/client-iotsitewise';
import {
AssetPropertyValue,
IoTSiteWiseClient,
} from '@aws-sdk/client-iotsitewise';
import { Viewport } from '@iot-app-kit/core';
import { AlarmData } from '../types';
import {
Expand Down Expand Up @@ -82,7 +85,7 @@ export const useAlarmThreshold = ({
* Useful if there is no threshold data within the viewport.
*/
const mostRecentBeforeEndValueQueries = useHistoricalAssetPropertyValues({
enabled: enabled && queryMode === 'LATEST_IN_VIEWPORT',
enabled: enabled && queryMode !== 'LATEST',
iotSiteWiseClient,
requests,
viewport,
Expand Down Expand Up @@ -123,12 +126,13 @@ export const useAlarmThreshold = ({
? getStaticThresholdAsAssetPropertyValue(alarm.models[0])
: undefined;

let thresholdData = staticThresholdValue
const staticThresholdData = staticThresholdValue
? [staticThresholdValue]
: undefined;
: [];
let thresholdData: AssetPropertyValue[] = [];

// If there is no static value then the query may have data for the threshold
if (!thresholdData) {
if (!staticThresholdData.length) {
updateAlarmStatusForQueries(alarm, [
latestValueQuery,
mostRecentBeforeEndValueQuery,
Expand All @@ -144,7 +148,11 @@ export const useAlarmThreshold = ({
];
}

updateAlarmThresholdData(alarm, { data: thresholdData, viewport });
updateAlarmThresholdData(alarm, {
data: thresholdData,
viewport,
staticData: staticThresholdData,
});

return alarm;
}) ?? []
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Bisector } from 'd3-array';
import { Interval } from '../../../queries';

export const alarmThresholdValueFilterer =
<Point>(
bisector: Bisector<Point, Date>,
extractTime: (point: Point) => number
) =>
(points: Point[], { end }: Interval, includeBoundaryPoints = true) => {
if (points.length === 0) {
return [];
}

// If all data is after the view port
if (end.getTime() < extractTime(points[0])) {
return [];
}

// Otherwise return all the data before the end of the viewport
const startIndex = Math.max(0);
const endIndex = Math.min(
bisector.right(points, end) - (includeBoundaryPoints ? 0 : 1),
points.length - 1
);

return points.slice(startIndex, endIndex + 1);
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { AssetPropertyValue } from '@aws-sdk/client-iotsitewise';
import type { AlarmData } from '../types';
import { toTimestamp } from '../../../utils/time';
import { bisector } from 'd3-array';
import { Viewport, timeSeriesDataFilterer } from '../../../queries';
import { timeSeriesDataFilterer, Viewport } from '../../../queries';
import { viewportEndDate, viewportStartDate } from '@iot-app-kit/core';
import { alarmThresholdValueFilterer } from './alarmThresholdValueFilterer';

const assetPropertyValueTime = (assetPropertyValue: AssetPropertyValue) =>
toTimestamp(assetPropertyValue.timestamp);
Expand All @@ -17,6 +18,11 @@ const compareAssetPropertyValues = (

const assetPropertyValuesBisector = bisector(assetPropertyValueTime);

const filterAssetPropertyValuesForThreshold = alarmThresholdValueFilterer(
assetPropertyValuesBisector,
assetPropertyValueTime
);

const filterAssetPropertyValues = timeSeriesDataFilterer(
assetPropertyValuesBisector,
assetPropertyValueTime
Expand Down Expand Up @@ -81,7 +87,15 @@ export const updateAlarmStateData = (

export const updateAlarmThresholdData = (
alarm: AlarmData,
{ data, viewport }: { data: AssetPropertyValue[]; viewport?: Viewport }
{
data,
staticData,
viewport,
}: {
data: AssetPropertyValue[];
staticData: AssetPropertyValue[];
viewport?: Viewport;
}
): AlarmData => {
/**
* If there is no models property the queries will
Expand All @@ -90,9 +104,24 @@ export const updateAlarmThresholdData = (
if (!alarm.models) return alarm;

const currentData = alarm.thresholds ?? [];

/**
* If there is a static threshold then that should be used as the alarm threshold
**/
if (
staticData.length &&
shouldUpdateAlarmStateData(currentData, staticData)
) {
alarm.thresholds = staticData;
return alarm;
}

const updatedData = uniqueSortAssetPropertyValues([...currentData, ...data]);
const filteredData = viewport
? filterAssetPropertyValues(updatedData, viewportAsInterval(viewport))
? filterAssetPropertyValuesForThreshold(
updatedData,
viewportAsInterval(viewport)
)
: updatedData;

if (shouldUpdateAlarmStateData(currentData, filteredData)) {
Expand Down

0 comments on commit 068ebd3

Please sign in to comment.