Files
musicmouse/web/src/lib/shutter.ts
Martin Bauer a8ed350aec Add "Mein Zimmer" room-control page (Home Assistant, proxied through the backend)
Implements the room-control page from the design mockup: a scenes row above cards
for shutters, color lamps, and brightness-only lamps, all driven by a new
`general.ha` config section (server URL, token, ordered device/scene lists).

The backend proxies every Home Assistant call server-side (GET/POST /api/ha/...)
rather than the browser calling Home Assistant directly, so the long-lived token
never leaves the LAN device and Home Assistant's own CORS settings don't need to
know about musicmouse at all. Card kind (shutter/color/brightness-only) is
inferred at runtime from what Home Assistant reports about each entity, not
configured explicitly.

Also stops tracking python-backend/config.yml, which had drifted into the repo
despite its own header saying it shouldn't be - it now carries real credentials
locally and needs to stay untracked.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-27 23:45:29 +02:00

36 lines
1.3 KiB
TypeScript

/** Conversions between the room UI's shutter model and Home Assistant's `cover.*`
* convention. Home Assistant's `current_position`/`position` are percent *open* (100 =
* fully open, 0 = fully closed); the UI (following the design mockup) thinks in percent
* *closed*. Kept pure and separate because that inversion is easy to get backwards. */
export interface ShutterPreset {
label: string;
/** Percent closed: 0 = fully open, 100 = fully closed. */
closedPercent: number;
}
export const SHUTTER_PRESETS: ShutterPreset[] = [
{ label: "Offen", closedPercent: 0 },
{ label: "Halb zu", closedPercent: 50 },
{ label: "Fast zu", closedPercent: 85 },
{ label: "Ganz zu", closedPercent: 100 },
];
/** HA's `current_position` -> the UI's "how closed" percent. */
export function closedPercentFromPosition(position: number): number {
return 100 - position;
}
/** The UI's "how closed" percent -> the `position` `cover.set_cover_position` expects. */
export function positionFromClosedPercent(closedPercent: number): number {
return 100 - closedPercent;
}
export function closedLabelFor(closedPercent: number): string {
if (closedPercent <= 1) return "Offen";
if (closedPercent >= 99) return "Ganz zu";
if (closedPercent >= 80) return "Fast zu";
if (closedPercent >= 40) return "Halb zu";
return `${Math.round(closedPercent)}% zu`;
}