diff --git a/hacs.json b/hacs.json index e7c66434b..262521982 100644 --- a/hacs.json +++ b/hacs.json @@ -1,6 +1,6 @@ { "name": "Mushroom", "filename": "mushroom.js", - "homeassistant": "2022.4.0", + "homeassistant": "2022.11.0", "render_readme": true } diff --git a/src/cards/chips-card/chips/alarm-control-panel-chip.ts b/src/cards/chips-card/chips/alarm-control-panel-chip.ts index aa6f182a9..3fbdfed35 100644 --- a/src/cards/chips-card/chips/alarm-control-panel-chip.ts +++ b/src/cards/chips-card/chips/alarm-control-panel-chip.ts @@ -73,7 +73,12 @@ export class AlarmControlPanelChip extends LitElement implements LovelaceChip { const iconColor = getStateColor(entity.state); const iconPulse = shouldPulse(entity.state); - const stateDisplay = computeStateDisplay(this.hass.localize, entity, this.hass.locale); + const stateDisplay = computeStateDisplay( + this.hass.localize, + entity, + this.hass.locale, + this.hass.entities + ); const iconStyle = {}; if (iconColor) { diff --git a/src/cards/chips-card/chips/entity-chip.ts b/src/cards/chips-card/chips/entity-chip.ts index d1e1b6ddc..30a843e43 100644 --- a/src/cards/chips-card/chips/entity-chip.ts +++ b/src/cards/chips-card/chips/entity-chip.ts @@ -66,7 +66,12 @@ export class EntityChip extends LitElement implements LovelaceChip { const picture = this._config.use_entity_picture ? getEntityPicture(entity) : undefined; - const stateDisplay = computeStateDisplay(this.hass.localize, entity, this.hass.locale); + const stateDisplay = computeStateDisplay( + this.hass.localize, + entity, + this.hass.locale, + this.hass.entities + ); const active = isActive(entity); diff --git a/src/cards/chips-card/chips/light-chip.ts b/src/cards/chips-card/chips/light-chip.ts index 94cbc56df..e18af0093 100644 --- a/src/cards/chips-card/chips/light-chip.ts +++ b/src/cards/chips-card/chips/light-chip.ts @@ -72,7 +72,12 @@ export class LightChip extends LitElement implements LovelaceChip { const name = this._config.name || entity.attributes.friendly_name || ""; const icon = this._config.icon || stateIcon(entity); - const stateDisplay = computeStateDisplay(this.hass.localize, entity, this.hass.locale); + const stateDisplay = computeStateDisplay( + this.hass.localize, + entity, + this.hass.locale, + this.hass.entities + ); const active = isActive(entity); diff --git a/src/cards/chips-card/chips/weather-chip.ts b/src/cards/chips-card/chips/weather-chip.ts index f1e6eca4e..44bf11bd9 100644 --- a/src/cards/chips-card/chips/weather-chip.ts +++ b/src/cards/chips-card/chips/weather-chip.ts @@ -61,7 +61,12 @@ export class WeatherChip extends LitElement implements LovelaceChip { const displayLabels: string[] = []; if (this._config.show_conditions) { - const stateDisplay = computeStateDisplay(this.hass.localize, entity, this.hass.locale); + const stateDisplay = computeStateDisplay( + this.hass.localize, + entity, + this.hass.locale, + this.hass.entities + ); displayLabels.push(stateDisplay); } diff --git a/src/cards/climate-card/climate-card.ts b/src/cards/climate-card/climate-card.ts index 258bc0e35..6d6ddb0d4 100644 --- a/src/cards/climate-card/climate-card.ts +++ b/src/cards/climate-card/climate-card.ts @@ -145,7 +145,12 @@ export class ClimateCard extends MushroomBaseCard implements LovelaceCard { const appearance = computeAppearance(this._config); const picture = computeEntityPicture(entity, appearance.icon_type); - let stateDisplay = computeStateDisplay(this.hass.localize, entity, this.hass.locale); + let stateDisplay = computeStateDisplay( + this.hass.localize, + entity, + this.hass.locale, + this.hass.entities + ); if (entity.attributes.current_temperature !== null) { const temperature = formatNumber( entity.attributes.current_temperature, diff --git a/src/cards/cover-card/cover-card.ts b/src/cards/cover-card/cover-card.ts index 7a45968d7..2ac2a1584 100644 --- a/src/cards/cover-card/cover-card.ts +++ b/src/cards/cover-card/cover-card.ts @@ -160,7 +160,12 @@ export class CoverCard extends MushroomBaseCard implements LovelaceCard { const appearance = computeAppearance(this._config); const picture = computeEntityPicture(entity, appearance.icon_type); - let stateDisplay = computeStateDisplay(this.hass.localize, entity, this.hass.locale); + let stateDisplay = computeStateDisplay( + this.hass.localize, + entity, + this.hass.locale, + this.hass.entities + ); if (this.position) { stateDisplay += ` - ${this.position}%`; } diff --git a/src/cards/fan-card/fan-card.ts b/src/cards/fan-card/fan-card.ts index 67b7bd823..53932f9f5 100644 --- a/src/cards/fan-card/fan-card.ts +++ b/src/cards/fan-card/fan-card.ts @@ -119,7 +119,12 @@ export class FanCard extends MushroomBaseCard implements LovelaceCard { const appearance = computeAppearance(this._config); const picture = computeEntityPicture(entity, appearance.icon_type); - let stateDisplay = computeStateDisplay(this.hass.localize, entity, this.hass.locale); + let stateDisplay = computeStateDisplay( + this.hass.localize, + entity, + this.hass.locale, + this.hass.entities + ); if (this.percentage != null) { stateDisplay = `${this.percentage}%`; } diff --git a/src/cards/humidifier-card/humidifier-card.ts b/src/cards/humidifier-card/humidifier-card.ts index 77803aa6a..7811fee7d 100644 --- a/src/cards/humidifier-card/humidifier-card.ts +++ b/src/cards/humidifier-card/humidifier-card.ts @@ -101,7 +101,12 @@ export class HumidifierCard extends MushroomBaseCard implements LovelaceCard { const appearance = computeAppearance(this._config); const picture = computeEntityPicture(entity, appearance.icon_type); - let stateDisplay = computeStateDisplay(this.hass.localize, entity, this.hass.locale); + let stateDisplay = computeStateDisplay( + this.hass.localize, + entity, + this.hass.locale, + this.hass.entities + ); if (this.humidity) { stateDisplay = `${this.humidity} %`; } diff --git a/src/cards/light-card/light-card.ts b/src/cards/light-card/light-card.ts index b27239443..ec3113f11 100644 --- a/src/cards/light-card/light-card.ts +++ b/src/cards/light-card/light-card.ts @@ -174,7 +174,12 @@ export class LightCard extends MushroomBaseCard implements LovelaceCard { const appearance = computeAppearance(this._config); const picture = computeEntityPicture(entity, appearance.icon_type); - let stateDisplay = computeStateDisplay(this.hass.localize, entity, this.hass.locale); + let stateDisplay = computeStateDisplay( + this.hass.localize, + entity, + this.hass.locale, + this.hass.entities + ); if (this.brightness != null) { stateDisplay = `${this.brightness}%`; } diff --git a/src/cards/media-player-card/utils.ts b/src/cards/media-player-card/utils.ts index ba725cd17..348bc46e3 100644 --- a/src/cards/media-player-card/utils.ts +++ b/src/cards/media-player-card/utils.ts @@ -51,7 +51,7 @@ export function computeMediaStateDisplay( entity: MediaPlayerEntity, hass: HomeAssistant ): string { - let state = computeStateDisplay(hass.localize, entity, hass.locale); + let state = computeStateDisplay(hass.localize, entity, hass.locale, hass.entities); if (![UNAVAILABLE, UNKNOWN, OFF].includes(entity.state) && config.use_media_info) { return computeMediaDescription(entity) || state; } diff --git a/src/ha/common/entity/compute-state-display.ts b/src/ha/common/entity/compute-state-display.ts index 456b0a639..cd6c9401c 100644 --- a/src/ha/common/entity/compute-state-display.ts +++ b/src/ha/common/entity/compute-state-display.ts @@ -2,6 +2,7 @@ import { HassEntity } from "home-assistant-js-websocket"; import { UNAVAILABLE, UNKNOWN } from "../../data/entity"; import { FrontendLocaleData } from "../../data/translation"; import { updateIsInstalling, UpdateEntity, UPDATE_SUPPORT_PROGRESS } from "../../data/update"; +import { EntityRegistryEntry, HomeAssistant } from "../../types"; import { formatDate } from "../datetime/format_date"; import { formatDateTime } from "../datetime/format_date_time"; import { formatTime } from "../datetime/format_time"; @@ -14,6 +15,7 @@ export const computeStateDisplay = ( localize: LocalizeFunc, stateObj: HassEntity, locale: FrontendLocaleData, + entities: HomeAssistant["entities"], state?: string ): string => { const compareState = state !== undefined ? state : stateObj.state; @@ -148,7 +150,13 @@ export const computeStateDisplay = ( : localize("ui.card.update.up_to_date"); } + const entity = entities[stateObj.entity_id] as EntityRegistryEntry | undefined; + return ( + (entity?.translation_key && + localize( + `component.${entity.platform}.entity.${domain}.${entity.translation_key}.state.${compareState}` + )) || // Return device class translation (stateObj.attributes.device_class && localize( diff --git a/src/ha/types.ts b/src/ha/types.ts index f6c275e2a..2cbcab678 100644 --- a/src/ha/types.ts +++ b/src/ha/types.ts @@ -49,6 +49,48 @@ declare global { } } +export interface EntityRegistryEntry { + id: string; + entity_id: string; + name: string | null; + icon: string | null; + platform: string; + config_entry_id: string | null; + device_id: string | null; + area_id: string | null; + disabled_by: "user" | "device" | "integration" | "config_entry" | null; + hidden_by: Exclude; + entity_category: "config" | "diagnostic" | null; + has_entity_name: boolean; + original_name?: string; + unique_id: string; + translation_key?: string; +} + +export interface DeviceRegistryEntry { + id: string; + config_entries: string[]; + connections: Array<[string, string]>; + identifiers: Array<[string, string]>; + manufacturer: string | null; + model: string | null; + name: string | null; + sw_version: string | null; + hw_version: string | null; + via_device_id: string | null; + area_id: string | null; + name_by_user: string | null; + entry_type: "service" | null; + disabled_by: "user" | "integration" | "config_entry" | null; + configuration_url: string | null; +} + +export interface AreaRegistryEntry { + area_id: string; + name: string; + picture: string | null; +} + export interface ThemeSettings { theme: string; // Radio box selection for theme picker. Do not use in Lovelace rendering as @@ -130,6 +172,9 @@ export interface HomeAssistant { connection: Connection; connected: boolean; states: HassEntities; + entities: { [id: string]: EntityRegistryEntry }; + devices: { [id: string]: DeviceRegistryEntry }; + areas: { [id: string]: AreaRegistryEntry }; services: HassServices; config: HassConfig; themes: Themes; diff --git a/src/utils/base-card.ts b/src/utils/base-card.ts index 93c4a4deb..262638772 100644 --- a/src/utils/base-card.ts +++ b/src/utils/base-card.ts @@ -55,7 +55,12 @@ export class MushroomBaseCard extends MushroomBaseElement { name: string, state?: string ): TemplateResult | null { - const defaultState = computeStateDisplay(this.hass.localize, entity, this.hass.locale); + const defaultState = computeStateDisplay( + this.hass.localize, + entity, + this.hass.locale, + this.hass.entities + ); const displayState = state ?? defaultState; const primary = computeInfoDisplay(