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>
This commit is contained in:
35
web/src/lib/shutter.ts
Normal file
35
web/src/lib/shutter.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
/** 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`;
|
||||
}
|
||||
Reference in New Issue
Block a user