diff --git a/demo/src/ha-demo.ts b/demo/src/ha-demo.ts index 0a9b131556..4b4d919d2b 100644 --- a/demo/src/ha-demo.ts +++ b/demo/src/ha-demo.ts @@ -17,6 +17,7 @@ import { energyEntities } from "./stubs/entities"; import { mockEntityRegistry } from "./stubs/entity_registry"; import { mockEvents } from "./stubs/events"; import { mockFrontend } from "./stubs/frontend"; +import { mockIcons } from "./stubs/icons"; import { mockHistory } from "./stubs/history"; import { mockLovelace } from "./stubs/lovelace"; import { mockMediaPlayer } from "./stubs/media_player"; @@ -57,6 +58,7 @@ export class HaDemo extends HomeAssistantAppEl { mockEvents(hass); mockMediaPlayer(hass); mockFrontend(hass); + mockIcons(hass); mockEnergy(hass); mockPersistentNotification(hass); mockConfigEntries(hass); diff --git a/demo/src/stubs/icons.ts b/demo/src/stubs/icons.ts new file mode 100644 index 0000000000..930a245d52 --- /dev/null +++ b/demo/src/stubs/icons.ts @@ -0,0 +1,33 @@ +import { IconCategory } from "../../../src/data/icons"; +import { ENTITY_COMPONENT_ICONS } from "../../../src/fake_data/entity_component_icons"; +import { MockHomeAssistant } from "../../../src/fake_data/provide_hass"; + +export const mockIcons = (hass: MockHomeAssistant) => { + hass.mockWS( + "frontend/get_icons", + async ({ + category, + integration, + }: { + category: IconCategory; + integration?: string; + }) => { + if (integration) { + try { + const response = await fetch( + `https://raw.githubusercontent.com/home-assistant/core/dev/homeassistant/components/${integration}/icons.json` + ).then((resp) => resp.json()); + return { resources: { [integration]: response[category] || {} } }; + } catch { + return { resources: {} }; + } + } + if (category === "entity_component") { + return { + resources: ENTITY_COMPONENT_ICONS, + }; + } + return { resources: {} }; + } + ); +}; diff --git a/gallery/src/pages/lovelace/alarm-panel-card.ts b/gallery/src/pages/lovelace/alarm-panel-card.ts index b55b1ca5d1..45a4c20b68 100644 --- a/gallery/src/pages/lovelace/alarm-panel-card.ts +++ b/gallery/src/pages/lovelace/alarm-panel-card.ts @@ -3,6 +3,7 @@ import { customElement, query } from "lit/decorators"; import { getEntity } from "../../../../src/fake_data/entity"; import { provideHass } from "../../../../src/fake_data/provide_hass"; import "../../components/demo-cards"; +import { mockIcons } from "../../../../demo/src/stubs/icons"; const ENTITIES = [ getEntity("alarm_control_panel", "alarm", "disarmed", { @@ -84,6 +85,7 @@ class DemoAlarmPanelEntity extends LitElement { hass.updateTranslations(null, "en"); hass.updateTranslations("lovelace", "en"); hass.addEntities(ENTITIES); + mockIcons(hass); } } diff --git a/gallery/src/pages/lovelace/area-card.ts b/gallery/src/pages/lovelace/area-card.ts index 30f98b07de..ea7afd7db9 100644 --- a/gallery/src/pages/lovelace/area-card.ts +++ b/gallery/src/pages/lovelace/area-card.ts @@ -3,6 +3,7 @@ import { customElement, query } from "lit/decorators"; import { getEntity } from "../../../../src/fake_data/entity"; import { provideHass } from "../../../../src/fake_data/provide_hass"; import "../../components/demo-cards"; +import { mockIcons } from "../../../../demo/src/stubs/icons"; const ENTITIES = [ getEntity("light", "bed_light", "on", { @@ -146,6 +147,7 @@ class DemoArea extends LitElement { entity_id: "binary_sensor.kitchen_door", }, ]); + mockIcons(hass); } } diff --git a/gallery/src/pages/lovelace/conditional-card.ts b/gallery/src/pages/lovelace/conditional-card.ts index bdaf093ed3..b59d5b3bad 100644 --- a/gallery/src/pages/lovelace/conditional-card.ts +++ b/gallery/src/pages/lovelace/conditional-card.ts @@ -3,6 +3,7 @@ import { customElement, query } from "lit/decorators"; import { getEntity } from "../../../../src/fake_data/entity"; import { provideHass } from "../../../../src/fake_data/provide_hass"; import "../../components/demo-cards"; +import { mockIcons } from "../../../../demo/src/stubs/icons"; const ENTITIES = [ getEntity("light", "controller_1", "on", { @@ -66,6 +67,7 @@ class DemoConditional extends LitElement { hass.updateTranslations(null, "en"); hass.updateTranslations("lovelace", "en"); hass.addEntities(ENTITIES); + mockIcons(hass); } } diff --git a/gallery/src/pages/lovelace/entities-card.ts b/gallery/src/pages/lovelace/entities-card.ts index aa6368878d..a7131557e6 100644 --- a/gallery/src/pages/lovelace/entities-card.ts +++ b/gallery/src/pages/lovelace/entities-card.ts @@ -3,6 +3,7 @@ import { customElement, query } from "lit/decorators"; import { getEntity } from "../../../../src/fake_data/entity"; import { provideHass } from "../../../../src/fake_data/provide_hass"; import "../../components/demo-cards"; +import { mockIcons } from "../../../../demo/src/stubs/icons"; const ENTITIES = [ getEntity("light", "bed_light", "on", { @@ -323,6 +324,7 @@ class DemoEntities extends LitElement { hass.updateTranslations(null, "en"); hass.updateTranslations("lovelace", "en"); hass.addEntities(ENTITIES); + mockIcons(hass); } } diff --git a/gallery/src/pages/lovelace/entity-button-card.ts b/gallery/src/pages/lovelace/entity-button-card.ts index a90f7c776d..daa6071571 100644 --- a/gallery/src/pages/lovelace/entity-button-card.ts +++ b/gallery/src/pages/lovelace/entity-button-card.ts @@ -3,6 +3,7 @@ import { customElement, query } from "lit/decorators"; import { getEntity } from "../../../../src/fake_data/entity"; import { provideHass } from "../../../../src/fake_data/provide_hass"; import "../../components/demo-cards"; +import { mockIcons } from "../../../../demo/src/stubs/icons"; const ENTITIES = [ getEntity("light", "bed_light", "on", { @@ -82,6 +83,7 @@ class DemoButtonEntity extends LitElement { hass.updateTranslations(null, "en"); hass.updateTranslations("lovelace", "en"); hass.addEntities(ENTITIES); + mockIcons(hass); } } diff --git a/gallery/src/pages/lovelace/entity-filter-card.ts b/gallery/src/pages/lovelace/entity-filter-card.ts index 879cf3bb71..86b0b9cb93 100644 --- a/gallery/src/pages/lovelace/entity-filter-card.ts +++ b/gallery/src/pages/lovelace/entity-filter-card.ts @@ -3,6 +3,7 @@ import { customElement, query } from "lit/decorators"; import { getEntity } from "../../../../src/fake_data/entity"; import { provideHass } from "../../../../src/fake_data/provide_hass"; import "../../components/demo-cards"; +import { mockIcons } from "../../../../demo/src/stubs/icons"; const ENTITIES = [ getEntity("device_tracker", "demo_paulus", "work", { @@ -123,6 +124,7 @@ class DemoEntityFilter extends LitElement { hass.updateTranslations(null, "en"); hass.updateTranslations("lovelace", "en"); hass.addEntities(ENTITIES); + mockIcons(hass); } } diff --git a/gallery/src/pages/lovelace/gauge-card.ts b/gallery/src/pages/lovelace/gauge-card.ts index ae99d1b1be..43d3e60d19 100644 --- a/gallery/src/pages/lovelace/gauge-card.ts +++ b/gallery/src/pages/lovelace/gauge-card.ts @@ -3,6 +3,7 @@ import { customElement, query } from "lit/decorators"; import { getEntity } from "../../../../src/fake_data/entity"; import { provideHass } from "../../../../src/fake_data/provide_hass"; import "../../components/demo-cards"; +import { mockIcons } from "../../../../demo/src/stubs/icons"; const ENTITIES = [ getEntity("sensor", "brightness", "12", {}), @@ -128,6 +129,7 @@ class DemoGaugeEntity extends LitElement { hass.updateTranslations(null, "en"); hass.updateTranslations("lovelace", "en"); hass.addEntities(ENTITIES); + mockIcons(hass); } } diff --git a/gallery/src/pages/lovelace/glance-card.ts b/gallery/src/pages/lovelace/glance-card.ts index c2a7c22ece..ab2f29d974 100644 --- a/gallery/src/pages/lovelace/glance-card.ts +++ b/gallery/src/pages/lovelace/glance-card.ts @@ -3,6 +3,7 @@ import { customElement, query } from "lit/decorators"; import { getEntity } from "../../../../src/fake_data/entity"; import { provideHass } from "../../../../src/fake_data/provide_hass"; import "../../components/demo-cards"; +import { mockIcons } from "../../../../demo/src/stubs/icons"; const ENTITIES = [ getEntity("device_tracker", "demo_paulus", "home", { @@ -238,6 +239,7 @@ class DemoGlanceEntity extends LitElement { hass.updateTranslations(null, "en"); hass.updateTranslations("lovelace", "en"); hass.addEntities(ENTITIES); + mockIcons(hass); } } diff --git a/gallery/src/pages/lovelace/grid-and-stack-card.ts b/gallery/src/pages/lovelace/grid-and-stack-card.ts index 9fc7d6f5e7..bac8a6f157 100644 --- a/gallery/src/pages/lovelace/grid-and-stack-card.ts +++ b/gallery/src/pages/lovelace/grid-and-stack-card.ts @@ -4,6 +4,7 @@ import { mockHistory } from "../../../../demo/src/stubs/history"; import { getEntity } from "../../../../src/fake_data/entity"; import { provideHass } from "../../../../src/fake_data/provide_hass"; import "../../components/demo-cards"; +import { mockIcons } from "../../../../demo/src/stubs/icons"; const ENTITIES = [ getEntity("light", "kitchen_lights", "on", { @@ -214,6 +215,7 @@ class DemoStack extends LitElement { hass.updateTranslations("lovelace", "en"); hass.addEntities(ENTITIES); mockHistory(hass); + mockIcons(hass); } } diff --git a/gallery/src/pages/lovelace/light-card.ts b/gallery/src/pages/lovelace/light-card.ts index 3b0fc01011..1590edce0f 100644 --- a/gallery/src/pages/lovelace/light-card.ts +++ b/gallery/src/pages/lovelace/light-card.ts @@ -3,6 +3,7 @@ import { customElement, query } from "lit/decorators"; import { getEntity } from "../../../../src/fake_data/entity"; import { provideHass } from "../../../../src/fake_data/provide_hass"; import "../../components/demo-cards"; +import { mockIcons } from "../../../../demo/src/stubs/icons"; const ENTITIES = [ getEntity("light", "bed_light", "on", { @@ -76,6 +77,7 @@ class DemoLightEntity extends LitElement { hass.updateTranslations(null, "en"); hass.updateTranslations("lovelace", "en"); hass.addEntities(ENTITIES); + mockIcons(hass); } } diff --git a/gallery/src/pages/lovelace/picture-elements-card.ts b/gallery/src/pages/lovelace/picture-elements-card.ts index 588d6be9bf..7f6b0c99cb 100644 --- a/gallery/src/pages/lovelace/picture-elements-card.ts +++ b/gallery/src/pages/lovelace/picture-elements-card.ts @@ -3,6 +3,7 @@ import { customElement, query } from "lit/decorators"; import { getEntity } from "../../../../src/fake_data/entity"; import { provideHass } from "../../../../src/fake_data/provide_hass"; import "../../components/demo-cards"; +import { mockIcons } from "../../../../demo/src/stubs/icons"; const ENTITIES = [ getEntity("light", "bed_light", "on", { @@ -138,6 +139,7 @@ class DemoPictureElements extends LitElement { hass.updateTranslations(null, "en"); hass.updateTranslations("lovelace", "en"); hass.addEntities(ENTITIES); + mockIcons(hass); } } diff --git a/gallery/src/pages/lovelace/picture-entity-card.ts b/gallery/src/pages/lovelace/picture-entity-card.ts index b88d97cbce..1573f0dbec 100644 --- a/gallery/src/pages/lovelace/picture-entity-card.ts +++ b/gallery/src/pages/lovelace/picture-entity-card.ts @@ -3,6 +3,7 @@ import { customElement, query } from "lit/decorators"; import { getEntity } from "../../../../src/fake_data/entity"; import { provideHass } from "../../../../src/fake_data/provide_hass"; import "../../components/demo-cards"; +import { mockIcons } from "../../../../demo/src/stubs/icons"; const ENTITIES = [ getEntity("light", "kitchen_lights", "on", { @@ -93,6 +94,7 @@ class DemoPictureEntity extends LitElement { hass.updateTranslations(null, "en"); hass.updateTranslations("lovelace", "en"); hass.addEntities(ENTITIES); + mockIcons(hass); } } diff --git a/gallery/src/pages/lovelace/picture-glance-card.ts b/gallery/src/pages/lovelace/picture-glance-card.ts index f698754ea6..dccc05e09b 100644 --- a/gallery/src/pages/lovelace/picture-glance-card.ts +++ b/gallery/src/pages/lovelace/picture-glance-card.ts @@ -3,6 +3,7 @@ import { customElement, query } from "lit/decorators"; import { getEntity } from "../../../../src/fake_data/entity"; import { provideHass } from "../../../../src/fake_data/provide_hass"; import "../../components/demo-cards"; +import { mockIcons } from "../../../../demo/src/stubs/icons"; const ENTITIES = [ getEntity("switch", "decorative_lights", "on", { @@ -134,6 +135,7 @@ class DemoPictureGlance extends LitElement { hass.updateTranslations(null, "en"); hass.updateTranslations("lovelace", "en"); hass.addEntities(ENTITIES); + mockIcons(hass); } } diff --git a/gallery/src/pages/lovelace/plant-card.ts b/gallery/src/pages/lovelace/plant-card.ts index 99b6780aee..6f04b474b3 100644 --- a/gallery/src/pages/lovelace/plant-card.ts +++ b/gallery/src/pages/lovelace/plant-card.ts @@ -3,6 +3,7 @@ import { customElement, query } from "lit/decorators"; import { provideHass } from "../../../../src/fake_data/provide_hass"; import "../../components/demo-cards"; import { createPlantEntities } from "../../data/plants"; +import { mockIcons } from "../../../../demo/src/stubs/icons"; const CONFIGS = [ { @@ -43,6 +44,7 @@ export class DemoPlantEntity extends LitElement { hass.updateTranslations(null, "en"); hass.updateTranslations("lovelace", "en"); hass.addEntities(createPlantEntities()); + mockIcons(hass); } } diff --git a/gallery/src/pages/lovelace/thermostat-card.ts b/gallery/src/pages/lovelace/thermostat-card.ts index 623adf5e34..1775a826e2 100644 --- a/gallery/src/pages/lovelace/thermostat-card.ts +++ b/gallery/src/pages/lovelace/thermostat-card.ts @@ -3,6 +3,7 @@ import { customElement, query } from "lit/decorators"; import { getEntity } from "../../../../src/fake_data/entity"; import { provideHass } from "../../../../src/fake_data/provide_hass"; import "../../components/demo-cards"; +import { mockIcons } from "../../../../demo/src/stubs/icons"; const ENTITIES = [ getEntity("climate", "ecobee", "auto", { @@ -116,6 +117,7 @@ class DemoThermostatEntity extends LitElement { hass.updateTranslations(null, "en"); hass.updateTranslations("lovelace", "en"); hass.addEntities(ENTITIES); + mockIcons(hass); } } diff --git a/gallery/src/pages/lovelace/tile-card.ts b/gallery/src/pages/lovelace/tile-card.ts index 7113f4d048..62ab5abd23 100644 --- a/gallery/src/pages/lovelace/tile-card.ts +++ b/gallery/src/pages/lovelace/tile-card.ts @@ -6,6 +6,7 @@ import { VacuumEntityFeature } from "../../../../src/data/vacuum"; import { getEntity } from "../../../../src/fake_data/entity"; import { provideHass } from "../../../../src/fake_data/provide_hass"; import "../../components/demo-cards"; +import { mockIcons } from "../../../../demo/src/stubs/icons"; const ENTITIES = [ getEntity("switch", "tv_outlet", "on", { @@ -184,6 +185,7 @@ class DemoTile extends LitElement { hass.updateTranslations(null, "en"); hass.updateTranslations("lovelace", "en"); hass.addEntities(ENTITIES); + mockIcons(hass); } } diff --git a/gallery/src/pages/lovelace/todo-list-card.ts b/gallery/src/pages/lovelace/todo-list-card.ts index 49a61a61a1..b03ffd1a93 100644 --- a/gallery/src/pages/lovelace/todo-list-card.ts +++ b/gallery/src/pages/lovelace/todo-list-card.ts @@ -4,6 +4,7 @@ import { provideHass } from "../../../../src/fake_data/provide_hass"; import "../../components/demo-cards"; import { getEntity } from "../../../../src/fake_data/entity"; import { mockTodo } from "../../../../demo/src/stubs/todo"; +import { mockIcons } from "../../../../demo/src/stubs/icons"; const ENTITIES = [ getEntity("todo", "shopping_list", "2", { @@ -47,6 +48,7 @@ class DemoTodoListEntity extends LitElement { hass.updateTranslations(null, "en"); hass.updateTranslations("lovelace", "en"); hass.addEntities(ENTITIES); + mockIcons(hass); mockTodo(hass); } diff --git a/gallery/src/pages/misc/entity-state.ts b/gallery/src/pages/misc/entity-state.ts index 4c2194c95c..e454553a4b 100644 --- a/gallery/src/pages/misc/entity-state.ts +++ b/gallery/src/pages/misc/entity-state.ts @@ -11,6 +11,7 @@ import "../../../../src/components/data-table/ha-data-table"; import type { DataTableColumnContainer } from "../../../../src/components/data-table/ha-data-table"; import "../../../../src/components/entity/state-badge"; import { provideHass } from "../../../../src/fake_data/provide_hass"; +import { mockIcons } from "../../../../demo/src/stubs/icons"; import { HomeAssistant } from "../../../../src/types"; const SENSOR_DEVICE_CLASSES = [ @@ -291,6 +292,7 @@ const ENTITIES: HassEntity[] = [ createEntity("water_heater.high_demand", "high_demand"), createEntity("water_heater.heat_pump", "heat_pump"), createEntity("water_heater.gas", "gas"), + createEntity("select.speed", "ridiculous_speed"), ]; function createEntity( @@ -397,6 +399,16 @@ export class DemoEntityState extends LitElement { protected firstUpdated(changedProps) { super.firstUpdated(changedProps); const hass = provideHass(this); + mockIcons(hass); + hass.updateHass({ + entities: { + "select.speed": { + entity_id: "select.speed", + translation_key: "speed", + platform: "demo", + }, + }, + }); hass.updateTranslations(null, "en"); hass.updateTranslations("config", "en"); } diff --git a/src/data/icons.ts b/src/data/icons.ts index dbb1a16515..dcb3952f55 100644 --- a/src/data/icons.ts +++ b/src/data/icons.ts @@ -9,6 +9,7 @@ import { EntityRegistryEntry, } from "./entity_registry"; import { isComponentLoaded } from "../common/config/is_component_loaded"; +import { atLeastVersion } from "../common/config/version"; const resources: { entity: Record>; @@ -46,10 +47,10 @@ interface PlatformIcons { }; } -interface ComponentIcons { +export interface ComponentIcons { [device_class: string]: { - state: Record; - state_attributes: Record< + state?: Record; + state_attributes?: Record< string, { state: Record; @@ -91,7 +92,10 @@ export const getPlatformIcons = async ( if (!force && integration in resources.entity) { return resources.entity[integration]; } - if (!isComponentLoaded(hass, integration)) { + if ( + !isComponentLoaded(hass, integration) || + !atLeastVersion(hass.connection.haVersion, 2024, 2) + ) { return undefined; } const result = getHassIcons(hass, "entity", integration).then( @@ -106,6 +110,16 @@ export const getComponentIcons = async ( domain: string, force = false ): Promise => { + // For Cast, old instances can connect to it. + if ( + __BACKWARDS_COMPAT__ && + !atLeastVersion(hass.connection.haVersion, 2024, 2) + ) { + return import("../fake_data/entity_component_icons") + .then((mod) => mod.ENTITY_COMPONENT_ICONS) + .then((res) => res[domain]); + } + if ( !force && resources.entity_component.resources && @@ -113,6 +127,7 @@ export const getComponentIcons = async ( ) { return resources.entity_component.resources.then((res) => res[domain]); } + if (!isComponentLoaded(hass, domain)) { return undefined; } diff --git a/src/fake_data/demo_config.ts b/src/fake_data/demo_config.ts index caaf1bb558..2d6a6fda15 100644 --- a/src/fake_data/demo_config.ts +++ b/src/fake_data/demo_config.ts @@ -14,7 +14,53 @@ export const demoConfig: HassConfig = { wind_speed: "m/s", accumulated_precipitation: "mm", }, - components: ["notify.html5", "history", "todo", "forecast_solar", "energy"], + components: [ + "notify.html5", + "history", + "forecast_solar", + "energy", + "person", + "number", + "select", + "tts", + "datetime", + "vacuum", + "wake_word", + "light", + "alarm_control_panel", + "text", + "lawn_mower", + "siren", + "input_boolean", + "lock", + "calendar", + "image", + "device_tracker", + "scene", + "script", + "todo", + "cover", + "switch", + "button", + "water_heater", + "binary_sensor", + "sensor", + "humidifier", + "valve", + "time", + "media_player", + "air_quality", + "camera", + "date", + "fan", + "automation", + "weather", + "climate", + "stt", + "update", + "event", + "demo", + ], time_zone: "America/Los_Angeles", config_dir: "/config", version: "DEMO", diff --git a/src/fake_data/entity_component_icons.ts b/src/fake_data/entity_component_icons.ts new file mode 100644 index 0000000000..595c01cd0f --- /dev/null +++ b/src/fake_data/entity_component_icons.ts @@ -0,0 +1,962 @@ +import { ComponentIcons } from "../data/icons"; + +export const ENTITY_COMPONENT_ICONS: Record = { + person: { + _: { + default: "mdi:account", + state: { + not_home: "mdi:account-arrow-right", + }, + }, + }, + number: { + _: { + default: "mdi:ray-vertex", + }, + apparent_power: { + default: "mdi:flash", + }, + aqi: { + default: "mdi:air-filter", + }, + atmospheric_pressure: { + default: "mdi:thermometer-lines", + }, + battery: { + default: "mdi:battery", + }, + carbon_dioxide: { + default: "mdi:molecule-co2", + }, + carbon_monoxide: { + default: "mdi:molecule-co", + }, + current: { + default: "mdi:current-ac", + }, + data_rate: { + default: "mdi:transmission-tower", + }, + data_size: { + default: "mdi:database", + }, + distance: { + default: "mdi:arrow-left-right", + }, + duration: { + default: "mdi:progress-clock", + }, + energy: { + default: "mdi:lightning-bolt", + }, + energy_storage: { + default: "mdi:car-battery", + }, + frequency: { + default: "mdi:sine-wave", + }, + gas: { + default: "mdi:meter-gas", + }, + humidity: { + default: "mdi:water-percent", + }, + illuminance: { + default: "mdi:brightness-5", + }, + irradiance: { + default: "mdi:sun-wireless", + }, + moisture: { + default: "mdi:water-percent", + }, + monetary: { + default: "mdi:cash", + }, + nitrogen_dioxide: { + default: "mdi:molecule", + }, + nitrogen_monoxide: { + default: "mdi:molecule", + }, + nitrous_oxide: { + default: "mdi:molecule", + }, + ozone: { + default: "mdi:molecule", + }, + ph: { + default: "mdi:ph", + }, + pm1: { + default: "mdi:molecule", + }, + pm10: { + default: "mdi:molecule", + }, + pm25: { + default: "mdi:molecule", + }, + power: { + default: "mdi:flash", + }, + power_factor: { + default: "mdi:angle-acute", + }, + precipitation: { + default: "mdi:weather-rainy", + }, + precipitation_intensity: { + default: "mdi:weather-pouring", + }, + pressure: { + default: "mdi:gauge", + }, + reactive_power: { + default: "mdi:flash", + }, + signal_strength: { + default: "mdi:wifi", + }, + sound_pressure: { + default: "mdi:ear-hearing", + }, + speed: { + default: "mdi:speedometer", + }, + sulfur_dioxide: { + default: "mdi:molecule", + }, + temperature: { + default: "mdi:thermometer", + }, + volatile_organic_compounds: { + default: "mdi:molecule", + }, + volatile_organic_compounds_parts: { + default: "mdi:molecule", + }, + voltage: { + default: "mdi:sine-wave", + }, + volume: { + default: "mdi:car-coolant-level", + }, + volume_storage: { + default: "mdi:storage-tank", + }, + water: { + default: "mdi:water", + }, + weight: { + default: "mdi:weight", + }, + wind_speed: { + default: "mdi:weather-windy", + }, + }, + select: { + _: { + default: "mdi:format-list-bulleted", + }, + }, + tts: { + _: { + default: "mdi:speaker-message", + }, + }, + datetime: { + _: { + default: "mdi:calendar-clock", + }, + }, + vacuum: { + _: { + default: "mdi:robot-vacuum", + }, + }, + wake_word: { + _: { + default: "mdi:chat-sleep", + }, + }, + light: { + _: { + default: "mdi:lightbulb", + }, + }, + alarm_control_panel: { + _: { + default: "mdi:shield", + state: { + armed_away: "mdi:shield-lock", + armed_custom_bypass: "mdi:security", + armed_home: "mdi:shield-home", + armed_night: "mdi:shield-moon", + armed_vacation: "mdi:shield-airplane", + disarmed: "mdi:shield-off", + pending: "mdi:shield-outline", + triggered: "mdi:bell-ring", + }, + }, + }, + text: { + _: { + default: "mdi:form-textbox", + }, + }, + lawn_mower: { + _: { + default: "mdi:robot-mower", + }, + }, + siren: { + _: { + default: "mdi:bullhorn", + }, + }, + input_boolean: { + _: { + default: "mdi:check-circle-outline", + state: { + off: "mdi:close-circle-outline", + }, + }, + }, + lock: { + _: { + default: "mdi:lock", + state: { + jammed: "mdi:lock-alert", + locking: "mdi:lock-clock", + unlocked: "mdi:lock-open", + unlocking: "mdi:lock-clock", + }, + }, + }, + calendar: { + _: { + default: "mdi:calendar", + state: { + on: "mdi:calendar-check", + off: "mdi:calendar-blank", + }, + }, + }, + image: { + _: { + default: "mdi:image", + }, + }, + device_tracker: { + _: { + default: "mdi:account", + state: { + not_home: "mdi:account-arrow-right", + }, + }, + }, + scene: { + _: { + default: "mdi:palette", + }, + }, + script: { + _: { + default: "mdi:script-text", + state: { + on: "mdi:script-text-play", + }, + }, + }, + todo: { + _: { + default: "mdi:clipboard-list", + }, + }, + cover: { + _: { + default: "mdi:window-open", + state: { + closed: "mdi:window-closed", + closing: "mdi:arrow-down-box", + opening: "mdi:arrow-up-box", + }, + }, + blind: { + default: "mdi:blinds-horizontal", + state: { + closed: "mdi:blinds-horizontal-closed", + closing: "mdi:arrow-down-box", + opening: "mdi:arrow-up-box", + }, + }, + curtain: { + default: "mdi:curtains", + state: { + closed: "mdi:curtains-closed", + closing: "mdi:arrow-collapse-horizontal", + opening: "mdi:arrow-split-vertical", + }, + }, + damper: { + default: "mdi:circle", + state: { + closed: "mdi:circle-slice-8", + }, + }, + door: { + default: "mdi:door-open", + state: { + closed: "mdi:door-closed", + }, + }, + garage: { + default: "mdi:garage-open", + state: { + closed: "mdi:garage", + closing: "mdi:arrow-down-box", + opening: "mdi:arrow-up-box", + }, + }, + gate: { + default: "mdi:gate-open", + state: { + closed: "mdi:gate", + closing: "mdi:arrow-right", + opening: "mdi:arrow-right", + }, + }, + shade: { + default: "mdi:roller-shade", + state: { + closed: "mdi:roller-shade-closed", + closing: "mdi:arrow-down-box", + opening: "mdi:arrow-up-box", + }, + }, + shutter: { + default: "mdi:window-shutter-open", + state: { + closed: "mdi:window-shutter", + closing: "mdi:arrow-down-box", + opening: "mdi:arrow-up-box", + }, + }, + window: { + default: "mdi:window-open", + state: { + closed: "mdi:window-closed", + closing: "mdi:arrow-down-box", + opening: "mdi:arrow-up-box", + }, + }, + }, + switch: { + _: { + default: "mdi:toggle-switch-variant", + }, + switch: { + default: "mdi:toggle-switch-variant", + state: { + off: "mdi:toggle-switch-variant-off", + }, + }, + outlet: { + default: "mdi:power-plug", + state: { + off: "mdi:power-plug-off", + }, + }, + }, + button: { + _: { + default: "mdi:button-pointer", + }, + restart: { + default: "mdi:restart", + }, + identify: { + default: "mdi:crosshairs-question", + }, + update: { + default: "mdi:package-up", + }, + }, + water_heater: { + _: { + default: "mdi:water-boiler", + state: { + off: "mdi:water-boiler-off", + }, + state_attributes: { + operation_mode: { + default: "mdi:circle-medium", + state: { + eco: "mdi:leaf", + electric: "mdi:lightning-bolt", + gas: "mdi:fire-circle", + heat_pump: "mdi:heat-wave", + high_demand: "mdi:finance", + off: "mdi:power", + performance: "mdi:rocket-launch", + }, + }, + }, + }, + }, + binary_sensor: { + _: { + default: "mdi:radiobox-blank", + state: { + on: "mdi:checkbox-marked-circle", + }, + }, + battery: { + default: "mdi:battery", + state: { + on: "mdi:battery-outline", + }, + }, + battery_charging: { + default: "mdi:battery", + state: { + on: "mdi:battery-charging", + }, + }, + carbon_monoxide: { + default: "mdi:smoke-detector", + state: { + on: "mdi:smoke-detector-alert", + }, + }, + cold: { + default: "mdi:thermometer", + state: { + on: "mdi:snowflake", + }, + }, + connectivity: { + default: "mdi:close-network-outline", + state: { + on: "mdi:check-network-outline", + }, + }, + door: { + default: "mdi:door-closed", + state: { + on: "mdi:door-open", + }, + }, + garage_door: { + default: "mdi:garage", + state: { + on: "mdi:garage-open", + }, + }, + gas: { + default: "mdi:check-circle", + state: { + on: "mdi:alert-circle", + }, + }, + heat: { + default: "mdi:thermometer", + state: { + on: "mdi:fire", + }, + }, + light: { + default: "mdi:brightness-5", + state: { + on: "mdi:brightness-7", + }, + }, + lock: { + default: "mdi:lock", + state: { + on: "mdi:lock-open", + }, + }, + moisture: { + default: "mdi:water-off", + state: { + on: "mdi:water", + }, + }, + motion: { + default: "mdi:motion-sensor-off", + state: { + on: "mdi:motion-sensor", + }, + }, + moving: { + default: "mdi:arrow-right", + state: { + on: "mdi:octagon", + }, + }, + occupancy: { + default: "mdi:home-outline", + state: { + on: "mdi:home", + }, + }, + opening: { + default: "mdi:square", + state: { + on: "mdi:square-outline", + }, + }, + plug: { + default: "mdi:power-plug-off", + state: { + on: "mdi:power-plug", + }, + }, + power: { + default: "mdi:power-plug-off", + state: { + on: "mdi:power-plug", + }, + }, + presence: { + default: "mdi:home-outline", + state: { + on: "mdi:home", + }, + }, + problem: { + default: "mdi:check-circle", + state: { + on: "mdi:alert-circle", + }, + }, + running: { + default: "mdi:stop", + state: { + on: "mdi:play", + }, + }, + safety: { + default: "mdi:check-circle", + state: { + on: "mdi:alert-circle", + }, + }, + smoke: { + default: "mdi:smoke-detector-variant", + state: { + on: "mdi:smoke-detector-variant-alert", + }, + }, + sound: { + default: "mdi:music-note-off", + state: { + on: "mdi:music-note", + }, + }, + tamper: { + default: "mdi:check-circle", + state: { + on: "mdi:alert-circle", + }, + }, + update: { + default: "mdi:package", + state: { + on: "mdi:package-up", + }, + }, + vibration: { + default: "mdi:crop-portrait", + state: { + on: "mdi:vibrate", + }, + }, + window: { + default: "mdi:window-closed", + state: { + on: "mdi:window-open", + }, + }, + }, + sensor: { + _: { + default: "mdi:eye", + }, + apparent_power: { + default: "mdi:flash", + }, + aqi: { + default: "mdi:air-filter", + }, + atmospheric_pressure: { + default: "mdi:thermometer-lines", + }, + carbon_dioxide: { + default: "mdi:molecule-co2", + }, + carbon_monoxide: { + default: "mdi:molecule-co", + }, + current: { + default: "mdi:current-ac", + }, + data_rate: { + default: "mdi:transmission-tower", + }, + data_size: { + default: "mdi:database", + }, + date: { + default: "mdi:calendar", + }, + distance: { + default: "mdi:arrow-left-right", + }, + duration: { + default: "mdi:progress-clock", + }, + energy: { + default: "mdi:lightning-bolt", + }, + energy_storage: { + default: "mdi:car-battery", + }, + enum: { + default: "mdi:eye", + }, + frequency: { + default: "mdi:sine-wave", + }, + gas: { + default: "mdi:meter-gas", + }, + humidity: { + default: "mdi:water-percent", + }, + illuminance: { + default: "mdi:brightness-5", + }, + irradiance: { + default: "mdi:sun-wireless", + }, + moisture: { + default: "mdi:water-percent", + }, + monetary: { + default: "mdi:cash", + }, + nitrogen_dioxide: { + default: "mdi:molecule", + }, + nitrogen_monoxide: { + default: "mdi:molecule", + }, + nitrous_oxide: { + default: "mdi:molecule", + }, + ozone: { + default: "mdi:molecule", + }, + ph: { + default: "mdi:ph", + }, + pm1: { + default: "mdi:molecule", + }, + pm10: { + default: "mdi:molecule", + }, + pm25: { + default: "mdi:molecule", + }, + power: { + default: "mdi:flash", + }, + power_factor: { + default: "mdi:angle-acute", + }, + precipitation: { + default: "mdi:weather-rainy", + }, + precipitation_intensity: { + default: "mdi:weather-pouring", + }, + pressure: { + default: "mdi:gauge", + }, + reactive_power: { + default: "mdi:flash", + }, + signal_strength: { + default: "mdi:wifi", + }, + sound_pressure: { + default: "mdi:ear-hearing", + }, + speed: { + default: "mdi:speedometer", + }, + sulfur_dioxide: { + default: "mdi:molecule", + }, + temperature: { + default: "mdi:thermometer", + }, + timestamp: { + default: "mdi:clock", + }, + volatile_organic_compounds: { + default: "mdi:molecule", + }, + volatile_organic_compounds_parts: { + default: "mdi:molecule", + }, + voltage: { + default: "mdi:sine-wave", + }, + volume: { + default: "mdi:car-coolant-level", + }, + volume_storage: { + default: "mdi:storage-tank", + }, + water: { + default: "mdi:water", + }, + weight: { + default: "mdi:weight", + }, + wind_speed: { + default: "mdi:weather-windy", + }, + }, + humidifier: { + _: { + default: "mdi:air-humidifier", + state: { + off: "mdi:air-humidifier-off", + }, + state_attributes: { + action: { + default: "mdi:circle-medium", + state: { + drying: "mdi:arrow-down-bold", + humidifying: "mdi:arrow-up-bold", + idle: "mdi:clock-outline", + off: "mdi:power", + }, + }, + mode: { + default: "mdi:circle-medium", + state: { + auto: "mdi:refresh-auto", + away: "mdi:account-arrow-right", + baby: "mdi:baby-carriage", + boost: "mdi:rocket-launch", + comfort: "mdi:sofa", + eco: "mdi:leaf", + home: "mdi:home", + normal: "mdi:water-percent", + sleep: "mdi:power-sleep", + }, + }, + }, + }, + }, + valve: { + _: { + default: "mdi:pipe-valve", + }, + gas: { + default: "mdi:meter-gas", + }, + water: { + default: "mdi:pipe-valve", + }, + }, + time: { + _: { + default: "mdi:clock", + }, + }, + media_player: { + _: { + default: "mdi:cast", + state: { + off: "mdi:cast-off", + paused: "mdi:cast-connected", + playing: "mdi:cast-connected", + }, + }, + receiver: { + default: "mdi:audio-video", + state: { + off: "mdi:audio-video-off", + }, + }, + speaker: { + default: "mdi:speaker", + state: { + off: "mdi:speaker-off", + paused: "mdi:speaker-pause", + playing: "mdi:speaker-play", + }, + }, + tv: { + default: "mdi:television", + state: { + off: "mdi:television-off", + paused: "mdi:television-pause", + playing: "mdi:television-play", + }, + }, + }, + air_quality: { + _: { + default: "mdi:air-filter", + }, + }, + camera: { + _: { + default: "mdi:video", + state: { + off: "mdi:video-off", + }, + }, + }, + date: { + _: { + default: "mdi:calendar", + }, + }, + fan: { + _: { + default: "mdi:fan", + state: { + off: "mdi:fan-off", + }, + state_attributes: { + direction: { + default: "mdi:rotate-right", + state: { + reverse: "mdi:rotate-left", + }, + }, + }, + }, + }, + automation: { + _: { + default: "mdi:robot", + state: { + off: "mdi:robot-off", + unavailable: "mdi:robot-confused", + }, + }, + }, + weather: { + _: { + default: "mdi:weather-partly-cloudy", + state: { + "clear-night": "mdi:weather-night", + cloudy: "mdi:weather-cloudy", + exceptional: "mdi:alert-circle-outline", + fog: "mdi:weather-fog", + hail: "mdi:weather-hail", + lightning: "mdi:weather-lightning", + "lightning-rainy": "mdi:weather-lightning-rainy", + pouring: "mdi:weather-pouring", + rainy: "mdi:weather-rainy", + snowy: "mdi:weather-snowy", + "snowy-rainy": "mdi:weather-snowy-rainy", + sunny: "mdi:weather-sunny", + windy: "mdi:weather-windy", + "windy-variant": "mdi:weather-windy-variant", + }, + }, + }, + climate: { + _: { + default: "mdi:thermostat", + state_attributes: { + fan_mode: { + default: "mdi:circle-medium", + state: { + diffuse: "mdi:weather-windy", + focus: "mdi:target", + high: "mdi:speedometer", + low: "mdi:speedometer-slow", + medium: "mdi:speedometer-medium", + middle: "mdi:speedometer-medium", + off: "mdi:fan-off", + on: "mdi:fan", + }, + }, + hvac_action: { + default: "mdi:circle-medium", + state: { + cooling: "mdi:snowflake", + drying: "mdi:water-percent", + fan: "mdi:fan", + heating: "mdi:fire", + idle: "mdi:clock-outline", + off: "mdi:power", + preheating: "mdi:heat-wave", + }, + }, + preset_mode: { + default: "mdi:circle-medium", + state: { + activity: "mdi:motion-sensor", + away: "mdi:account-arrow-right", + boost: "mdi:rocket-launch", + comfort: "mdi:sofa", + eco: "mdi:leaf", + home: "mdi:home", + sleep: "mdi:bed", + }, + }, + swing_mode: { + default: "mdi:circle-medium", + state: { + both: "mdi:arrow-all", + horizontal: "mdi:arrow-left-right", + off: "mdi:arrow-oscillating-off", + on: "mdi:arrow-oscillating", + vertical: "mdi:arrow-up-down", + }, + }, + }, + }, + }, + stt: { + _: { + default: "mdi:microphone-message", + }, + }, + update: { + _: { + default: "mdi:package-up", + state: { + off: "mdi:package", + }, + }, + }, + event: { + _: { + default: "mdi:eye-check", + }, + button: { + default: "mdi:gesture-tap-button", + }, + doorbell: { + default: "mdi:doorbell", + }, + motion: { + default: "mdi:motion-sensor", + }, + }, +};