Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
joeyhage committed Nov 12, 2021
2 parents 97ebb25 + 40c9abf commit 0a11b9e
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 24 deletions.
24 changes: 24 additions & 0 deletions lambda/datetime-util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@

export function formatDate(date: Date, timezoneCode?: string): string {
console.log(date, timezoneCode);
return new Intl.DateTimeFormat("default", {
month: "short",
day: "numeric",
hour: "numeric",
minute: "numeric",
hour12: true,
timeZone: timezoneCode,
timeZoneName: "short",
}).format(date);
}

export function determineThresholdDatetime(eventDate: Date): Date {
const thresholdHours = Number(process.env.NOTIFICATION_THRESHOLD_HRS);
const thresholdDatetime = new Date(eventDate.getTime());
thresholdDatetime.setHours(eventDate.getHours() + thresholdHours);
return thresholdDatetime;
}

export function hasThresholdTimePassed(thresholdDatetime: Date): boolean {
return Date.now() > thresholdDatetime.getTime();
}
34 changes: 12 additions & 22 deletions lambda/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { DeviceType } from "homebridge-lg-thinq/dist/lib/constants";
import { Device } from "homebridge-lg-thinq/dist/lib/Device";
import { URL } from "url";
import { ThinQApi } from "./api";
import { determineThresholdDatetime, formatDate, hasThresholdTimePassed } from "./datetime-util";

export const handler = async (): Promise<void> => {
const region = process.env.AWS_REGION;
Expand All @@ -20,17 +21,18 @@ export const handler = async (): Promise<void> => {
const mostRecentEvent = events[0];
const eventDate = new Date(Number(mostRecentEvent.sendDate) * 1000);
const eventMessage = JSON.parse(mostRecentEvent.message) as EventMessage;
const formattedEventDate = formatDate(eventDate, dryer?.data.timezoneCode);
const formattedEventDate = formatDate(
eventDate,
dryer?.data.timezoneCode
);

const thresholdDatetime = determineThresholdDatetime(eventDate);
console.log(`Most recent event was at ${formattedEventDate}`);

const thresholdHours = Number(process.env.NOTIFICATION_THRESHOLD_HRS);
const thresholdTime = new Date();
thresholdTime.setHours(new Date().getHours() - thresholdHours);
console.log(`Threshold datetime is ${formatDate(thresholdDatetime, dryer?.data.timezoneCode)}`);

if (
eventDate < thresholdTime &&
shouldSendRepeatNotification(thresholdTime) &&
hasThresholdTimePassed(thresholdDatetime) &&
shouldSendRepeatNotification(thresholdDatetime) &&
isWasherCycleFinished(eventMessage) &&
!(await wasLatestWashTubClean(api, clientId, eventMessage))
) {
Expand All @@ -48,18 +50,6 @@ export const handler = async (): Promise<void> => {
}
};

function formatDate(date: Date, timezoneCode?: string): string {
return new Intl.DateTimeFormat("default", {
month: "short",
day: "numeric",
hour: "numeric",
minute: "numeric",
hour12: true,
timeZone: timezoneCode,
timeZoneName: "short",
}).format(date);
}

async function getAppSecrets(
region = "us-east-1"
): Promise<Record<string, string>> {
Expand Down Expand Up @@ -165,17 +155,17 @@ function isDryerOff(dryer?: Device): boolean {
);
}

function shouldSendRepeatNotification(thresholdTime: Date): boolean {
export function shouldSendRepeatNotification(thresholdDatetime: Date): boolean {
const notificationFreqHrs = Number(process.env.NOTIFICATION_FREQ_HRS);
const maxNotifications = Number(process.env.MAX_NOTIFICATIONS);

const msSinceThreshold = Date.now() - thresholdTime.getTime();
const msSinceThreshold = Date.now() - thresholdDatetime.getTime();
const hoursSinceThreshold = msSinceThreshold / (60 * 60 * 1000);

console.log({ hoursSinceThreshold, notificationFreqHrs, maxNotifications });
return (
hoursSinceThreshold % notificationFreqHrs < 1 &&
Math.floor(hoursSinceThreshold / notificationFreqHrs) <= maxNotifications
Math.floor(hoursSinceThreshold / notificationFreqHrs) < maxNotifications
);
}

Expand Down
15 changes: 15 additions & 0 deletions test/datetime-util.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { determineThresholdDatetime } from "../lambda/datetime-util";

describe("determineThresholdDatetime", () => {
test("should return `NOTIFICATION_THRESHOLD_HRS` after event date", async () => {
// given
process.env.NOTIFICATION_THRESHOLD_HRS = "3";
const eventDate = new Date("2021-11-01T12:00:00.000Z");

// when
const result = determineThresholdDatetime(eventDate);

// then
expect(result).toEqual(new Date("2021-11-01T15:00:00.000Z"));
});
});
87 changes: 87 additions & 0 deletions test/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { shouldSendRepeatNotification } from "../lambda/index";

describe("test shouldSendRepeatNotification given `NOTIFICATION_FREQ_HRS`=3 and `MAX_NOTIFICATIONS`=2", () => {

beforeEach(() => {
process.env.NOTIFICATION_FREQ_HRS = "3";
process.env.MAX_NOTIFICATIONS = "2";
});

test("should send repeat notification given washer finished 3 hours ago", async () => {
// given
const thresholdTime = new Date();
thresholdTime.setHours(thresholdTime.getHours() - 3);
thresholdTime.setMinutes(thresholdTime.getMinutes() - 20);

// when
const result = shouldSendRepeatNotification(thresholdTime);

// then
expect(result).toBe(true);
});

test("should send repeat notification given washer finished 6 hours ago", async () => {
// given
const thresholdTime = new Date();
thresholdTime.setHours(thresholdTime.getHours() - 6);
thresholdTime.setMinutes(thresholdTime.getMinutes() - 20);

// when
const result = shouldSendRepeatNotification(thresholdTime);

// then
expect(result).toBe(true);
});

test("should not send repeat notification given washer finished 9 hours ago", async () => {
// given
const thresholdTime = new Date();
thresholdTime.setHours(thresholdTime.getHours() - 9);
thresholdTime.setMinutes(thresholdTime.getMinutes() - 20);

// when
const result = shouldSendRepeatNotification(thresholdTime);

// then
expect(result).toBe(false);
});

test("should not send repeat notification given washer finished 9 hours ago", async () => {
// given
const thresholdTime = new Date();
thresholdTime.setHours(thresholdTime.getHours() - 9);
thresholdTime.setMinutes(thresholdTime.getMinutes() - 20);

// when
const result = shouldSendRepeatNotification(thresholdTime);

// then
expect(result).toBe(false);
});

test("should not send repeat notification given washer finished 4 hours ago", async () => {
// given
const thresholdTime = new Date();
thresholdTime.setHours(thresholdTime.getHours() - 4);
thresholdTime.setMinutes(thresholdTime.getMinutes() - 20);

// when
const result = shouldSendRepeatNotification(thresholdTime);

// then
expect(result).toBe(false);
});

test("should not send repeat notification given washer finished 7 hours ago", async () => {
// given
const thresholdTime = new Date();
thresholdTime.setHours(thresholdTime.getHours() - 7);
thresholdTime.setMinutes(thresholdTime.getMinutes() - 20);

// when
const result = shouldSendRepeatNotification(thresholdTime);

// then
expect(result).toBe(false);
});
});
12 changes: 10 additions & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,18 @@
"strictPropertyInitialization": false,
"typeRoots": [
"./node_modules/@types"
]
],
"skipLibCheck": true
},
"include": [
"bin/**/*.ts",
"lambda/**/*.ts",
"lib/**/*.ts",
"test/**/*.ts"
],
"exclude": [
"node_modules",
"cdk.out"
"cdk.out",
".github"
]
}

0 comments on commit 0a11b9e

Please sign in to comment.