mirror of
https://github.com/Matysh/houseplan-card
synced 2026-07-31 16:38:31 +00:00
feat v1.31.0: room cards — metrics line + proportional resize
- room label becomes a card: name on top, optional metrics below (temperature / humidity / avg zigbee / lights), four checkboxes in space settings, all off by default; lights render On/Off or '1 of 3' - areaHum + areaLightStats pure helpers (+3 unit tests, 90 total) - resize via corner handles in the Plan editor (hover), uniform 0.5-3x, scale stored as layout k next to the position; drag preserves it - fix latent v1.25 regression: draggable HTML labels were never rendered in the Plan editor (static SVG only) — real name-only cards now render there, draggable and resizable - repair merge/split smokes still calling removed _toggleMarkup - validation.py: 4 label_* bools; smoke_room_cards.mjs; docs same-commit
This commit is contained in:
@@ -343,6 +343,43 @@ export function areaLights(hass: any, devices: { area: string; entities: string[
|
||||
return seen ? 'off' : 'none';
|
||||
}
|
||||
|
||||
/** Average humidity across the area's climate-ish devices (integer %, or null). */
|
||||
export function areaHum(
|
||||
hass: any,
|
||||
devices: { area: string; icon?: string; entities: string[] }[],
|
||||
area: string,
|
||||
): number | null {
|
||||
const vals: number[] = [];
|
||||
for (const dv of devices) {
|
||||
if (dv.area !== area) continue;
|
||||
// same curation idea as areaTemp: climate sensors only, not fridges/plugs
|
||||
if (dv.icon !== 'mdi:thermometer' && dv.icon !== 'mdi:air-filter' && dv.icon !== 'mdi:water-percent') continue;
|
||||
const h = humFor(hass, dv.entities);
|
||||
if (h != null) vals.push(h);
|
||||
}
|
||||
if (!vals.length) return null;
|
||||
return Math.round(vals.reduce((a, b) => a + b, 0) / vals.length);
|
||||
}
|
||||
|
||||
/** How many of the area's lights are on: {on, total}, or null without lights. */
|
||||
export function areaLightStats(
|
||||
hass: any,
|
||||
devices: { area: string; entities: string[] }[],
|
||||
area: string,
|
||||
): { on: number; total: number } | null {
|
||||
const seen = new Set<string>();
|
||||
let on = 0;
|
||||
for (const dv of devices) {
|
||||
if (dv.area !== area) continue;
|
||||
for (const eid of dv.entities) {
|
||||
if (!eid.startsWith('light.') || seen.has(eid)) continue;
|
||||
seen.add(eid);
|
||||
if (hass.states[eid]?.state === 'on') on++;
|
||||
}
|
||||
}
|
||||
return seen.size ? { on, total: seen.size } : null;
|
||||
}
|
||||
|
||||
/** Average temperature across the area's devices (null when nothing reports one). */
|
||||
/** Average zigbee signal (LQI) across an area's non-virtual devices, or null. */
|
||||
export function areaLqi(hass: any, devices: { area: string; virtual?: boolean; entities: string[] }[], area: string): number | null {
|
||||
|
||||
Reference in New Issue
Block a user