diff --git a/src/common/entity/entity_filter.ts b/src/common/entity/entity_filter.ts index 072520d8a0..ae30422cc7 100644 --- a/src/common/entity/entity_filter.ts +++ b/src/common/entity/entity_filter.ts @@ -54,10 +54,7 @@ export const generateEntityFilter = ( } } if (deviceClasses) { - const dc = stateObj.attributes.device_class; - if (!dc) { - return false; - } + const dc = stateObj.attributes.device_class || "none"; if (!deviceClasses.has(dc)) { return false; } diff --git a/src/panels/lovelace/strategies/areas/area-view-strategy.ts b/src/panels/lovelace/strategies/areas/area-view-strategy.ts index 1fdc1d2f0e..4450451198 100644 --- a/src/panels/lovelace/strategies/areas/area-view-strategy.ts +++ b/src/panels/lovelace/strategies/areas/area-view-strategy.ts @@ -5,15 +5,10 @@ import type { LovelaceCardConfig } from "../../../../data/lovelace/config/card"; import type { LovelaceSectionRawConfig } from "../../../../data/lovelace/config/section"; import type { LovelaceViewConfig } from "../../../../data/lovelace/config/view"; import type { HomeAssistant } from "../../../../types"; -import { supportsAlarmModesCardFeature } from "../../card-features/hui-alarm-modes-card-feature"; -import { supportsCoverOpenCloseCardFeature } from "../../card-features/hui-cover-open-close-card-feature"; -import { supportsLightBrightnessCardFeature } from "../../card-features/hui-light-brightness-card-feature"; -import { supportsLockCommandsCardFeature } from "../../card-features/hui-lock-commands-card-feature"; -import { supportsTargetTemperatureCardFeature } from "../../card-features/hui-target-temperature-card-feature"; -import type { LovelaceCardFeatureConfig } from "../../card-features/types"; import { AREA_STRATEGY_GROUP_ICONS, AREA_STRATEGY_GROUP_LABELS, + computeAreaTileCardConfig, getAreaGroupedEntities, } from "./helpers/area-strategy-helper"; @@ -28,41 +23,6 @@ export interface AreaViewStrategyConfig { groups_options?: Record; } -const computeTileCardConfig = - (hass: HomeAssistant) => - (entity: string): LovelaceCardConfig => { - const stateObj = hass.states[entity]; - - let feature: LovelaceCardFeatureConfig | undefined; - if (supportsLightBrightnessCardFeature(stateObj)) { - feature = { - type: "light-brightness", - }; - } else if (supportsCoverOpenCloseCardFeature(stateObj)) { - feature = { - type: "cover-open-close", - }; - } else if (supportsTargetTemperatureCardFeature(stateObj)) { - feature = { - type: "target-temperature", - }; - } else if (supportsAlarmModesCardFeature(stateObj)) { - feature = { - type: "alarm-modes", - }; - } else if (supportsLockCommandsCardFeature(stateObj)) { - feature = { - type: "lock-commands", - }; - } - - return { - type: "tile", - entity: entity, - features: feature ? [feature] : undefined, - }; - }; - const computeHeadingCard = ( heading: string, icon: string @@ -114,9 +74,10 @@ export class AreaViewStrategy extends ReactiveElement { config.groups_options ); - const computeTileCard = computeTileCardConfig(hass); + const computeTileCard = computeAreaTileCardConfig(hass, area.name, true); - const { lights, climate, media_players, security } = groupedEntities; + const { lights, climate, media_players, security, others } = + groupedEntities; if (lights.length > 0) { sections.push({ @@ -170,6 +131,19 @@ export class AreaViewStrategy extends ReactiveElement { }); } + if (others.length > 0) { + sections.push({ + type: "grid", + cards: [ + computeHeadingCard( + AREA_STRATEGY_GROUP_LABELS.others, + AREA_STRATEGY_GROUP_ICONS.others + ), + ...others.map(computeTileCard), + ], + }); + } + return { type: "sections", header: { diff --git a/src/panels/lovelace/strategies/areas/areas-view-strategy.ts b/src/panels/lovelace/strategies/areas/areas-view-strategy.ts index 00a6b81bf8..e1cfc6f183 100644 --- a/src/panels/lovelace/strategies/areas/areas-view-strategy.ts +++ b/src/panels/lovelace/strategies/areas/areas-view-strategy.ts @@ -3,9 +3,12 @@ import { customElement } from "lit/decorators"; import type { LovelaceSectionConfig } from "../../../../data/lovelace/config/section"; import type { LovelaceViewConfig } from "../../../../data/lovelace/config/view"; import type { HomeAssistant } from "../../../../types"; -import { getAreaGroupedEntities } from "./helpers/area-strategy-helper"; -import { computeAreaPath, getAreas } from "./helpers/areas-strategy-helpers"; import type { EntitiesDisplay } from "./area-view-strategy"; +import { + computeAreaTileCardConfig, + getAreaGroupedEntities, +} from "./helpers/area-strategy-helper"; +import { computeAreaPath, getAreas } from "./helpers/areas-strategy-helpers"; interface AreaOptions { groups_options?: Record; @@ -49,8 +52,11 @@ export class AreasViewStrategy extends ReactiveElement { ...groups.climate, ...groups.media_players, ...groups.security, + ...groups.others, ]; + const computeTileCard = computeAreaTileCardConfig(hass, area.name); + return { type: "grid", cards: [ @@ -72,10 +78,7 @@ export class AreasViewStrategy extends ReactiveElement { }, }, ...(entities.length - ? entities.map((entity) => ({ - type: "tile", - entity: entity, - })) + ? entities.map(computeTileCard) : [ { type: "markdown", diff --git a/src/panels/lovelace/strategies/areas/helpers/area-strategy-helper.ts b/src/panels/lovelace/strategies/areas/helpers/area-strategy-helper.ts index ad560773c6..55fdcd7c2c 100644 --- a/src/panels/lovelace/strategies/areas/helpers/area-strategy-helper.ts +++ b/src/panels/lovelace/strategies/areas/helpers/area-strategy-helper.ts @@ -1,13 +1,25 @@ +import { computeDomain } from "../../../../../common/entity/compute_domain"; +import { computeStateName } from "../../../../../common/entity/compute_state_name"; import type { EntityFilterFunc } from "../../../../../common/entity/entity_filter"; import { generateEntityFilter } from "../../../../../common/entity/entity_filter"; +import { stripPrefixFromEntityName } from "../../../../../common/entity/strip_prefix_from_entity_name"; import { orderCompare } from "../../../../../common/string/compare"; +import type { LovelaceCardConfig } from "../../../../../data/lovelace/config/card"; import type { HomeAssistant } from "../../../../../types"; +import { supportsAlarmModesCardFeature } from "../../../card-features/hui-alarm-modes-card-feature"; +import { supportsCoverOpenCloseCardFeature } from "../../../card-features/hui-cover-open-close-card-feature"; +import { supportsLightBrightnessCardFeature } from "../../../card-features/hui-light-brightness-card-feature"; +import { supportsLockCommandsCardFeature } from "../../../card-features/hui-lock-commands-card-feature"; +import { supportsTargetTemperatureCardFeature } from "../../../card-features/hui-target-temperature-card-feature"; +import type { LovelaceCardFeatureConfig } from "../../../card-features/types"; +import type { TileCardConfig } from "../../../cards/types"; export const AREA_STRATEGY_GROUPS = [ "lights", "climate", "media_players", "security", + "others", ] as const; export const AREA_STRATEGY_GROUP_ICONS = { @@ -15,6 +27,7 @@ export const AREA_STRATEGY_GROUP_ICONS = { climate: "mdi:home-thermometer", media_players: "mdi:multimedia", security: "mdi:security", + others: "mdi:shape", }; // Todo be replace by translation when validated @@ -23,6 +36,7 @@ export const AREA_STRATEGY_GROUP_LABELS = { climate: "Climate", media_players: "Entertainment", security: "Security", + others: "Others", }; export type AreaStrategyGroup = (typeof AREA_STRATEGY_GROUPS)[number]; @@ -75,9 +89,15 @@ export const getAreaGroupedEntities = ( "shade", "shutter", "window", + "none", ], entity_category: "none", }), + generateEntityFilter(hass, { + domain: "fan", + area: area, + entity_category: "none", + }), generateEntityFilter(hass, { domain: "binary_sensor", area: area, @@ -109,6 +129,11 @@ export const getAreaGroupedEntities = ( area: area, entity_category: "none", }), + generateEntityFilter(hass, { + domain: "camera", + area: area, + entity_category: "none", + }), generateEntityFilter(hass, { domain: "binary_sensor", device_class: ["door", "garage_door"], @@ -116,6 +141,28 @@ export const getAreaGroupedEntities = ( entity_category: "none", }), ], + others: [ + generateEntityFilter(hass, { + domain: "vacuum", + area: area, + entity_category: "none", + }), + generateEntityFilter(hass, { + domain: "lawn_mower", + area: area, + entity_category: "none", + }), + generateEntityFilter(hass, { + domain: "valve", + area: area, + entity_category: "none", + }), + generateEntityFilter(hass, { + domain: "switch", + area: area, + entity_category: "none", + }), + ], }; return Object.fromEntries( @@ -147,3 +194,55 @@ export const getAreaGroupedEntities = ( }) ) as AreaEntitiesByGroup; }; + +export const computeAreaTileCardConfig = + (hass: HomeAssistant, prefix: string, includeFeature?: boolean) => + (entity: string): LovelaceCardConfig => { + const stateObj = hass.states[entity]; + + const additionalCardConfig: Partial = {}; + + const domain = computeDomain(entity); + if (domain === "camera") { + additionalCardConfig.show_entity_picture = true; + } + + let feature: LovelaceCardFeatureConfig | undefined; + if (includeFeature) { + if (supportsLightBrightnessCardFeature(stateObj)) { + feature = { + type: "light-brightness", + }; + } else if (supportsCoverOpenCloseCardFeature(stateObj)) { + feature = { + type: "cover-open-close", + }; + } else if (supportsTargetTemperatureCardFeature(stateObj)) { + feature = { + type: "target-temperature", + }; + } else if (supportsAlarmModesCardFeature(stateObj)) { + feature = { + type: "alarm-modes", + }; + } else if (supportsLockCommandsCardFeature(stateObj)) { + feature = { + type: "lock-commands", + }; + } + } + + if (feature) { + additionalCardConfig.features = [feature]; + } + + const name = computeStateName(stateObj); + const stripedName = stripPrefixFromEntityName(name, prefix.toLowerCase()); + + return { + type: "tile", + entity: entity, + name: stripedName, + ...additionalCardConfig, + }; + };