diff --git a/src/homepage/service.ts b/src/homepage/service.ts index 381a541..f6dcd00 100644 --- a/src/homepage/service.ts +++ b/src/homepage/service.ts @@ -1,21 +1,22 @@ import { - type API_HA_DeskPosition, - BaseService, - type ComponentUpdate, - type FullInformation, - type GristRecord_PersonalGoals, - type HomeAssistantDeskPositionResult, - type ServiceResult, - type TidalGetCurrent, - type WsService, - createComponentUpdate, - StatusComponent, + type API_HA_DeskPosition, + BaseService, + type ComponentUpdate, + createComponentUpdate, + type FullInformation, + type GristRecord_PersonalGoals, + type HomeAssistantDeskPositionResult, + type ServiceResult, + StatusComponent, + type TidalGetCurrent, + type WsService, } from "@dpu/shared"; import { logInfo, logWarning } from "@dpu/shared/dist/logger.js"; +import { DateTime } from "luxon"; +import type { WebSocket } from "ws"; import type { GristService } from "../grist/service"; import type { HomeAssistantService } from "../homeassistant/service"; import type { TidalService } from "../tidal/service"; -import type { WebSocket } from "ws"; export class HomepageService extends BaseService { private gristService: GristService; @@ -42,6 +43,34 @@ export class HomepageService extends BaseService { this.wsService = wsService; } + scheduleMidnightGristUpdate(): void { + const now = DateTime.now().setZone("Europe/Berlin"); + const nextMidnight = now.plus({ days: 1 }).startOf("day"); + + setTimeout(async () => { + await this.fetchAndBroadcastGrist(); + this.scheduleMidnightGristUpdate(); + }, nextMidnight.diff(now).toMillis()); + } + + private async fetchAndBroadcastGrist(): Promise { + try { + if (this.wsService.getClientCount() > 0) { + const updates: ComponentUpdate[] = []; + this.updateGristPG(await this._getGristPG(), updates); + + if (updates.length > 0) { + this.wsService.broadcast({ + type: "update", + data: updates, + }); + } + } + } catch (error) { + logWarning("Error fetching midnight Grist update", error); + } + } + async sendFullInformationToSocket(socket: WebSocket): Promise { try { const [desk, temp, tidal, personal_goals] = await this._getAll(); @@ -49,12 +78,17 @@ export class HomepageService extends BaseService { createComponentUpdate(StatusComponent.HA_DESK_POSITION, desk), createComponentUpdate(StatusComponent.HA_TEMP, temp), createComponentUpdate(StatusComponent.TIDAL_CURRENT, tidal), - createComponentUpdate(StatusComponent.GRIST_PERSONAL_GOALS, personal_goals) + createComponentUpdate( + StatusComponent.GRIST_PERSONAL_GOALS, + personal_goals, + ), ]; - socket.send(JSON.stringify({ - type: "update", - data: updates - })) + socket.send( + JSON.stringify({ + type: "update", + data: updates, + }), + ); } catch (error) { logWarning("error getting all information for socket update.", error); } @@ -184,7 +218,12 @@ export class HomepageService extends BaseService { new_ha_desk_position?.is_standing ) { this.lastPoll.ha_desk_position = new_ha_desk_position; - updates.push(createComponentUpdate(StatusComponent.HA_DESK_POSITION, new_ha_desk_position)); + updates.push( + createComponentUpdate( + StatusComponent.HA_DESK_POSITION, + new_ha_desk_position, + ), + ); } } @@ -206,7 +245,9 @@ export class HomepageService extends BaseService { this.lastPoll.tidal_current?.volume !== new_tidal_current?.volume ) { this.lastPoll.tidal_current = new_tidal_current; - updates.push(createComponentUpdate(StatusComponent.TIDAL_CURRENT, new_tidal_current)); + updates.push( + createComponentUpdate(StatusComponent.TIDAL_CURRENT, new_tidal_current), + ); } } @@ -231,7 +272,12 @@ export class HomepageService extends BaseService { new_grist_personal_goals?.stairs ) { this.lastPoll.grist_personal_goals = new_grist_personal_goals; - updates.push(createComponentUpdate(StatusComponent.GRIST_PERSONAL_GOALS, new_grist_personal_goals)); + updates.push( + createComponentUpdate( + StatusComponent.GRIST_PERSONAL_GOALS, + new_grist_personal_goals, + ), + ); } } } diff --git a/src/index.ts b/src/index.ts index d48ea98..f9ce505 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,17 +3,17 @@ import { logError } from "@dpu/shared/dist/logger.js"; import fastifyCors, { type FastifyCorsOptions } from "@fastify/cors"; import fastifySwagger, { type SwaggerOptions } from "@fastify/swagger"; import fastifySwaggerUi, { - type FastifySwaggerUiOptions, + type FastifySwaggerUiOptions, } from "@fastify/swagger-ui"; import fastifyWebsocket from "@fastify/websocket"; import type { FastifyReply, FastifyRequest } from "fastify"; import Fastify from "fastify"; import fastifyAxios, { type FastifyAxiosOptions } from "fastify-axios"; import { - jsonSchemaTransform, - serializerCompiler, - validatorCompiler, - type ZodTypeProvider, + jsonSchemaTransform, + serializerCompiler, + validatorCompiler, + type ZodTypeProvider, } from "fastify-type-provider-zod"; import type { OpenAPIV3 } from "openapi-types"; import { SwaggerTheme, SwaggerThemeNameEnum } from "swagger-themes"; @@ -154,6 +154,8 @@ const hpService = new HomepageService( wsService, ); +hpService.scheduleMidnightGristUpdate(); + async function verifyAPIKey( request: FastifyRequest, reply: FastifyReply,