From 2aaae8e05c9a0367e95ae7620206afda2b58541f Mon Sep 17 00:00:00 2001 From: Darius Date: Sun, 16 Nov 2025 21:18:12 +0100 Subject: [PATCH] implement for desk control --- .env.example | 3 +-- src/commands/impl/position.ts | 8 ++++---- src/commands/impl/stand.ts | 35 ++++++++++++++++++++++++++------ src/config/config.ts | 4 ++-- src/util/api-homeassistant.ts | 38 ++++++++++++++++++++--------------- src/util/timespan.ts | 2 +- 6 files changed, 59 insertions(+), 31 deletions(-) diff --git a/.env.example b/.env.example index 62b0063..d6109a3 100644 --- a/.env.example +++ b/.env.example @@ -11,7 +11,6 @@ TIDAL_PORT=47836 NIGHT_TIME=01:00-08:00 HA_API_URL=http://homeassistant.com/api/states/ HA_API_TOKEN=Nina hätte hier jetzt ihr Token ausversehen stehen hihi -HA_DESK_SENSOR_ID=entityId -HA_DESK_SENSOR_TEXT=entityId HA_ROOMTEMP_SENSOR_IDS=entityId(,separated) HA_STANDING_WEBHOOK=webhookId +HA_DESK_SENSOR_BINARY=entityId diff --git a/src/commands/impl/position.ts b/src/commands/impl/position.ts index 0c38558..c0fddb0 100644 --- a/src/commands/impl/position.ts +++ b/src/commands/impl/position.ts @@ -1,5 +1,5 @@ import type { ChatMessage } from "@twurple/chat"; -import { getDeskPositionText } from "../../util/api-homeassistant.js"; +import { getDeskPosition } from "../../util/api-homeassistant.js"; import { calculateSecondsBetween } from "../../util/general.js"; import { logSuccess } from "../../util/logger.js"; import { BaseCommand } from "../base-command.js"; @@ -22,15 +22,15 @@ export class PositionCommand extends BaseCommand { msg: ChatMessage, ) => { logSuccess(`${channel} ${user} position command triggered`); - const position = await getDeskPositionText(); + const position = await getDeskPosition(); if (position) { const time = calculateSecondsBetween( - new Date(position.last_changed).getTime(), + new Date(position.raw.last_changed).getTime(), Date.now(), ).toReadable(true); this.chatClient.say( channel, - `darius has been ${position.state} for ${time}`, + `darius has been ${position.asText()} for ${time}`, { replyTo: msg, }, diff --git a/src/commands/impl/stand.ts b/src/commands/impl/stand.ts index 0b80fb4..60bfcf5 100644 --- a/src/commands/impl/stand.ts +++ b/src/commands/impl/stand.ts @@ -1,13 +1,14 @@ import type { ChatMessage } from "@twurple/chat"; -import { getDeskHeight, startStandingAutomation } from "../../util/api-homeassistant.js"; +import { getDeskPosition, startStandingAutomation } from "../../util/api-homeassistant.js"; import { logInfo, logSuccess } from "../../util/logger.js"; import { BaseCommand } from "../base-command.js"; import type { ICommandRequirements } from "../interface.ts"; import { Config } from "../../config/config.js"; +import { calculateSecondsBetween } from "../../util/general.js"; export class StandCommand extends BaseCommand { name = "stand"; - cooldown = 60; + cooldown = 300; enabled = true; requirements: ICommandRequirements = { @@ -23,11 +24,33 @@ export class StandCommand extends BaseCommand { ) => { logSuccess(`${channel} ${user} position command triggered`); - // const position = await getDeskHeight(); + const position = await getDeskPosition(); - // if (position?.state > 100) { + if (!position) { + this.chatClient.say(channel, `error: aborting operation`, { + replyTo: msg, + }); + return + } - // } + if (position.asBoolean) { + this.chatClient.say(channel, `desk already is in standing mode`, { + replyTo: msg, + }); + return + } + + const lastMoved = calculateSecondsBetween( + new Date(position.raw.last_changed).getTime(), + Date.now(), + ); + + if (60 > lastMoved.seconds) { + this.chatClient.say(channel, `desk has moved too recently. please wait`, { + replyTo: msg, + }); + return + } if (Config.night_time.contains()) { this.chatClient.say(channel, `command disabled during nighttime`, { @@ -39,7 +62,7 @@ export class StandCommand extends BaseCommand { const response = await startStandingAutomation(); logInfo(response) - this.chatClient.say(channel, `blabla`, { + this.chatClient.say(channel, `desk is now moving into standing position`, { replyTo: msg, }); }; diff --git a/src/config/config.ts b/src/config/config.ts index 8dacb63..00236aa 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -1,4 +1,5 @@ import dotenv from "dotenv"; +import { TimeSpan } from "../util/timespan"; dotenv.config(); @@ -20,8 +21,7 @@ export const Config = { api_url: process.env.HA_API_URL || "", api_token: process.env.HA_API_TOKEN || "", - id_desk_sensor: process.env.HA_DESK_SENSOR_ID || "", - id_desk_sensor_text: process.env.HA_DESK_SENSOR_TEXT || "", + id_desk_sensor_binary: process.env.HA_DESK_SENSOR_BINARY || "", id_room_sensors: process.env.HA_ROOMTEMP_SENSOR_IDS?.split(",") || [], id_webhook_stand: process.env.HA_STANDING_WEBHOOK || "" diff --git a/src/util/api-homeassistant.ts b/src/util/api-homeassistant.ts index 54a65c8..6810d29 100644 --- a/src/util/api-homeassistant.ts +++ b/src/util/api-homeassistant.ts @@ -22,6 +22,12 @@ type HomeAssistantEntity = { }; }; +interface DeskPositionResult { + raw: HomeAssistantEntity; + asBoolean: boolean; + asText: () => string; +} + // ACTIONS export async function startStandingAutomation(): Promise { try { @@ -36,26 +42,26 @@ export async function startStandingAutomation(): Promise { } // GETTER - -export async function getDeskPositionText(): Promise { +export async function getDeskPosition(): Promise { try { - const position = await sendRequestToHomeAssistantStates( - Config.homeassistant.id_desk_sensor_text, + const raw = await sendRequestToHomeAssistantStates( + Config.homeassistant.id_desk_sensor_binary, ); - return position; - } catch { - logWarning("error getting hoehe text from homeassistant"); + if (raw) { + const position = Number(raw.state); + return { + raw, + asBoolean: position === 1, + asText: () => { + if (position === 1) return 'standing'; + if (position === 0) return 'sitting'; + return 'unknown'; + } + }; + } return null; - } -} - -export async function getDeskHeight(): Promise { - try { - return await sendRequestToHomeAssistantStates( - Config.homeassistant.id_desk_sensor, - ); } catch { - logWarning("error getting hoehe from homeassistant"); + logWarning("error getting position from homeassistant"); return null; } } diff --git a/src/util/timespan.ts b/src/util/timespan.ts index c81bfef..c3aeb80 100644 --- a/src/util/timespan.ts +++ b/src/util/timespan.ts @@ -1,4 +1,4 @@ -class TimeSpan { +export class TimeSpan { private start: { hours: number; minutes: number }; private end: { hours: number; minutes: number };