import { type API_HA_DeskPosition, BaseService, type HomeAssistantDeskPositionResult, type HomeAssistantEntity, type ServiceResult, } from "@dpu/shared"; import { calculateSecondsBetween } from "@dpu/shared/dist/timehelper.js"; import { Config } from "../config.js"; import type { HomeAssistantClient } from "./client.js"; export class HomeAssistantService extends BaseService { async startStandingAutomation(): Promise> { try { const positionResult = await this.getDeskPosition(); if (!positionResult.successful) { throw Error(positionResult.result as string); } const position = positionResult.result as HomeAssistantDeskPositionResult; if (position.as_boolean) { throw Error( `desk is already in standing position and has been for ${position.last_changed.toReadable(true)}`, ); } if (position.last_changed.seconds < 300) { throw Error("desk has moved too recently"); } const result = await this.getClient().triggerWebhook( Config.homeassistant.id_webhook_stand, ); return this.getSuccessfulResult(result); } catch (error) { return this.getErrorResult("error starting stand automation.", error); } } async getDeskPosition(): Promise< ServiceResult > { try { const raw = await this.getClient().getEntityState( Config.homeassistant.id_sensor_desk_binary, ); return this.getSuccessfulResult(this.convertHaEntityToPosResult(raw)); } catch (error) { return this.getErrorResult("error getting desk position.", error); } } convertHaEntityToPosResult( raw: HomeAssistantEntity, ): HomeAssistantDeskPositionResult { const position = Number(raw.state); return { raw, as_boolean: position === 1, last_changed: calculateSecondsBetween( new Date(raw.last_changed).getTime(), Date.now(), ), }; } convertPosResultToApiAnswer( position: HomeAssistantDeskPositionResult, ): API_HA_DeskPosition { return { is_standing: position.as_boolean, last_changed: position.last_changed.toReadable(true), last_changed_seconds: position.last_changed.seconds, }; } async getTemperature(): Promise> { try { const entity = await this.getClient().getEntityState( Config.homeassistant.id_sensor_roomtemp, ); return this.getSuccessfulResult(entity.state); } catch (error) { return this.getErrorResult("error getting temperature.", error); } } }