Improve state colors and add documentation for entity state (#14437)

* Add documentation for entity icons and colors

* Add domains

* Add domains

* improve colors

* Add fan color

* Change fan to cyan

* color rules adjustments
This commit is contained in:
Paul Bottein 2022-11-28 14:37:07 +01:00 committed by GitHub
parent 92e7254c54
commit aec0eb3c78
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 424 additions and 73 deletions

View File

@ -0,0 +1,3 @@
---
title: Entity State
---

View File

@ -0,0 +1,376 @@
import {
HassEntity,
HassEntityAttributeBase,
} from "home-assistant-js-websocket";
import { css, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import { styleMap } from "lit/directives/style-map";
import memoizeOne from "memoize-one";
import { computeDomain } from "../../../../src/common/entity/compute_domain";
import { computeStateDisplay } from "../../../../src/common/entity/compute_state_display";
import { stateColorCss } from "../../../../src/common/entity/state_color";
import { stateIconPath } from "../../../../src/common/entity/state_icon_path";
import "../../../../src/components/data-table/ha-data-table";
import type { DataTableColumnContainer } from "../../../../src/components/data-table/ha-data-table";
import "../../../../src/components/ha-chip";
import { provideHass } from "../../../../src/fake_data/provide_hass";
import { HomeAssistant } from "../../../../src/types";
const SENSOR_DEVICE_CLASSES = [
"apparent_power",
"aqi",
// "battery"
"carbon_dioxide",
"carbon_monoxide",
"current",
"date",
"distance",
"duration",
"energy",
"frequency",
"gas",
"humidity",
"illuminance",
"moisture",
"monetary",
"nitrogen_dioxide",
"nitrogen_monoxide",
"nitrous_oxide",
"ozone",
"pm1",
"pm10",
"pm25",
"power_factor",
"power",
"precipitation",
"precipitation_intensity",
"pressure",
"reactive_power",
"signal_strength",
"speed",
"sulphur_dioxide",
"temperature",
"timestamp",
"volatile_organic_compounds",
"voltage",
"volume",
"water",
"weight",
"wind_speed",
];
const BINARY_SENSOR_DEVICE_CLASSES = [
"battery",
"battery_charging",
"carbon_monoxide",
"cold",
"connectivity",
"door",
"garage_door",
"gas",
"heat",
"light",
"lock",
"moisture",
"motion",
"moving",
"occupancy",
"opening",
"plug",
"power",
"presence",
"problem",
"running",
"safety",
"smoke",
"sound",
"tamper",
"update",
"vibration",
"window",
];
const ENTITIES: HassEntity[] = [
// Alarm control panel
createEntity("alarm_control_panel.disarmed", "disarmed"),
createEntity("alarm_control_panel.armed_home", "armed_home"),
createEntity("alarm_control_panel.armed_away", "armed_away"),
createEntity("alarm_control_panel.armed_night", "armed_night"),
createEntity("alarm_control_panel.armed_vacation", "armed_vacation"),
createEntity(
"alarm_control_panel.armed_custom_bypass",
"armed_custom_bypass"
),
createEntity("alarm_control_panel.pending", "pending"),
createEntity("alarm_control_panel.arming", "arming"),
createEntity("alarm_control_panel.disarming", "disarming"),
createEntity("alarm_control_panel.triggered", "triggered"),
// Binary Sensor
...BINARY_SENSOR_DEVICE_CLASSES.map((dc) =>
createEntity(`binary_sensor.${dc}`, "on", dc)
),
// Button
createEntity("button.restart", "unknown", "restart"),
createEntity("button.update", "unknown", "update"),
// Calendar
createEntity("calendar.on", "on"),
createEntity("calendar.off", "off"),
// Climate
createEntity("climate.off", "off"),
createEntity("climate.heat", "heat"),
createEntity("climate.cool", "cool"),
createEntity("climate.heat_cool", "heat_cool"),
createEntity("climate.auto", "auto"),
createEntity("climate.dry", "dry"),
createEntity("climate.fan_only", "fan_only"),
// Cover
createEntity("cover.opening", "opening"),
createEntity("cover.open", "open"),
createEntity("cover.closing", "closing"),
createEntity("cover.closed", "closed"),
createEntity("cover.awning", "open", "awning"),
createEntity("cover.blind", "open", "blind"),
createEntity("cover.curtain", "open", "curtain"),
createEntity("cover.damper", "open", "damper"),
createEntity("cover.door", "open", "door"),
createEntity("cover.garage", "open", "garage"),
createEntity("cover.gate", "open", "gate"),
createEntity("cover.shade", "open", "shade"),
createEntity("cover.shutter", "open", "shutter"),
createEntity("cover.window", "open", "window"),
// Device tracker/person
createEntity("device_tracker.home", "home"),
createEntity("device_tracker.not_home", "not_home"),
createEntity("device_tracker.work", "work"),
createEntity("person.home", "home"),
createEntity("person.not_home", "not_home"),
createEntity("person.work", "work"),
// Fan
createEntity("fan.on", "on"),
createEntity("fan.off", "off"),
// Humidifier
createEntity("humidifier.on", "on"),
createEntity("humidifier.off", "off"),
// Light
createEntity("light.on", "on"),
createEntity("light.off", "off"),
// Locks
createEntity("lock.locked", "locked"),
createEntity("lock.unlocked", "unlocked"),
createEntity("lock.locking", "locking"),
createEntity("lock.unlocking", "unlocking"),
createEntity("lock.jammed", "jammed"),
// Media Player
createEntity("media_player.off", "off"),
createEntity("media_player.on", "on"),
createEntity("media_player.idle", "idle"),
createEntity("media_player.playing", "playing"),
createEntity("media_player.paused", "paused"),
createEntity("media_player.standby", "standby"),
createEntity("media_player.buffering", "buffering"),
createEntity("media_player.tv_off", "off", "tv"),
createEntity("media_player.tv_playing", "playing", "tv"),
createEntity("media_player.tv_paused", "paused", "tv"),
createEntity("media_player.tv_standby", "standby", "tv"),
createEntity("media_player.receiver_off", "off", "receiver"),
createEntity("media_player.receiver_playing", "playing", "receiver"),
createEntity("media_player.receiver_paused", "paused", "receiver"),
createEntity("media_player.receiver_standby", "standby", "receiver"),
createEntity("media_player.speaker_off", "off", "speaker"),
createEntity("media_player.speaker_playing", "playing", "speaker"),
createEntity("media_player.speaker_paused", "paused", "speaker"),
createEntity("media_player.speaker_standby", "standby", "speaker"),
// Sensor
...SENSOR_DEVICE_CLASSES.map((dc) => createEntity(`sensor.${dc}`, "10", dc)),
// Battery sensor
...[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100].map((value) =>
createEntity(`sensor.battery_${value}`, value.toString(), "battery")
),
// Siren
createEntity("siren.off", "off"),
createEntity("siren.on", "on"),
// Switch
createEntity("switch.off", "off"),
createEntity("switch.on", "on"),
createEntity("switch.outlet_off", "off", "outlet"),
createEntity("switch.outlet_on", "on", "outlet"),
createEntity("switch.switch_off", "off", "switch"),
createEntity("switch.switch_on", "on", "switch"),
// Vacuum
createEntity("vacuum.cleaning", "cleaning"),
createEntity("vacuum.docked", "docked"),
createEntity("vacuum.paused", "paused"),
createEntity("vacuum.idle", "idle"),
createEntity("vacuum.returning", "returning"),
createEntity("vacuum.error", "error"),
createEntity("vacuum.cleaning", "cleaning"),
createEntity("vacuum.off", "off"),
createEntity("vacuum.on", "on"),
// Update
createEntity("update.off", "off", undefined, {
installed_version: "1.0.0",
latest_version: "2.0.0",
}),
createEntity("update.on", "on", undefined, {
installed_version: "1.0.0",
latest_version: "2.0.0",
}),
createEntity("update.installing", "on", undefined, {
installed_version: "1.0.0",
latest_version: "2.0.0",
in_progress: true,
}),
createEntity("update.off", "off", "firmware", {
installed_version: "1.0.0",
latest_version: "2.0.0",
}),
createEntity("update.on", "on", "firmware", {
installed_version: "1.0.0",
latest_version: "2.0.0",
}),
];
function createEntity(
entity_id: string,
state: string,
device_class?: string,
attributes?: HassEntityAttributeBase | HassEntity["attributes"]
): HassEntity {
return {
entity_id,
state,
attributes: {
...attributes,
device_class: device_class,
},
last_changed: new Date().toString(),
last_updated: new Date().toString(),
context: {
id: "1",
parent_id: null,
user_id: null,
},
};
}
type EntityRowData = {
stateObj: HassEntity;
entity_id: string;
state: string;
device_class?: string;
domain: string;
};
function createRowData(stateObj: HassEntity): EntityRowData {
return {
stateObj,
entity_id: stateObj.entity_id,
state: stateObj.state,
device_class: stateObj.attributes.device_class,
domain: computeDomain(stateObj.entity_id),
};
}
@customElement("demo-misc-entity-state")
export class DemoEntityState extends LitElement {
@property({ attribute: false }) hass?: HomeAssistant;
private _columns = memoizeOne(
(hass: HomeAssistant): DataTableColumnContainer => {
const columns: DataTableColumnContainer<EntityRowData> = {
icon: {
title: "Icon",
template: (_, entry) => {
const cssColor = stateColorCss(entry.stateObj);
return html`
<ha-svg-icon
style=${styleMap({
color: `rgb(${cssColor})`,
})}
.path=${stateIconPath(entry.stateObj)}
>
</ha-svg-icon>
`;
},
},
entity_id: {
title: "Entity id",
width: "30%",
filterable: true,
sortable: true,
},
state: {
title: "State",
width: "20%",
sortable: true,
template: (_, entry) =>
html`${computeStateDisplay(
hass.localize,
entry.stateObj,
hass.locale
)}`,
},
device_class: {
title: "Device class",
template: (dc) => html`${dc ?? "-"}`,
width: "20%",
filterable: true,
sortable: true,
},
domain: {
title: "Domain",
template: (_, entry) => html`${computeDomain(entry.entity_id)}`,
width: "20%",
filterable: true,
sortable: true,
},
};
return columns;
}
);
private _rows = memoizeOne((): EntityRowData[] =>
ENTITIES.map(createRowData)
);
protected firstUpdated(changedProps) {
super.firstUpdated(changedProps);
const hass = provideHass(this);
hass.updateTranslations(null, "en");
hass.updateTranslations("config", "en");
}
protected render(): TemplateResult {
if (!this.hass) {
return html``;
}
return html`
<ha-data-table
.hass=${this.hass}
.columns=${this._columns(this.hass)}
.data=${this._rows()}
auto-height
></ha-data-table>
`;
}
static get styles() {
return css`
.color {
display: block;
height: 20px;
width: 20px;
border-radius: 10px;
background-color: rgb(--color);
}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"demo-misc-entity-state": DemoEntityState;
}
}

View File

@ -8,10 +8,11 @@ export const alarmControlPanelColor = (state?: string): string | undefined => {
return "alarm-armed"; return "alarm-armed";
case "pending": case "pending":
return "alarm-pending"; return "alarm-pending";
case "arming":
case "disarming":
return "alarm-arming";
case "triggered": case "triggered":
return "alarm-triggered"; return "alarm-triggered";
case "disarmed":
return "alarm-disarmed";
default: default:
return undefined; return undefined;
} }

View File

@ -1,20 +1,20 @@
import { HassEntity } from "home-assistant-js-websocket"; import { HassEntity } from "home-assistant-js-websocket";
const NORMAL_DEVICE_CLASSES = new Set([ const ALERTING_DEVICE_CLASSES = new Set([
"battery_charging", "battery",
"connectivity", "carbon_monoxide",
"light", "gas",
"moving", "heat",
"plug", "problem",
"power", "safety",
"presence", "smoke",
"running", "tamper",
]); ]);
export const binarySensorColor = (stateObj: HassEntity): string | undefined => { export const binarySensorColor = (stateObj: HassEntity): string | undefined => {
const deviceClass = stateObj?.attributes.device_class; const deviceClass = stateObj?.attributes.device_class;
return deviceClass && NORMAL_DEVICE_CLASSES.has(deviceClass) return deviceClass && ALERTING_DEVICE_CLASSES.has(deviceClass)
? "binary-sensor" ? "binary-sensor-alerting"
: "binary-sensor-danger"; : "binary-sensor";
}; };

View File

@ -1,10 +0,0 @@
import { HassEntity } from "home-assistant-js-websocket";
const SECURE_DEVICE_CLASSES = new Set(["door", "gate", "garage", "window"]);
export const coverColor = (stateObj?: HassEntity): string | undefined => {
const isSecure =
stateObj?.attributes.device_class &&
SECURE_DEVICE_CLASSES.has(stateObj.attributes.device_class);
return isSecure ? "cover-secure" : "cover";
};

View File

@ -2,8 +2,6 @@ export const lockColor = (state?: string): string | undefined => {
switch (state) { switch (state) {
case "locked": case "locked":
return "lock-locked"; return "lock-locked";
case "unlocked":
return "lock-unlocked";
case "jammed": case "jammed":
return "lock-jammed"; return "lock-jammed";
case "locking": case "locking":

View File

@ -8,25 +8,5 @@ export const sensorColor = (stateObj: HassEntity): string | undefined => {
return batteryStateColor(stateObj); return batteryStateColor(stateObj);
} }
switch (deviceClass) { return undefined;
case "apparent_power":
case "current":
case "energy":
case "gas":
case "power_factor":
case "power":
case "reactive_power":
case "voltage":
return "sensor-energy";
case "temperature":
return "sensor-temperature";
case "humidity":
return "sensor-humidity";
case "illuminance":
return "sensor-illuminance";
case "moisture":
return "sensor-moisture";
}
return "sensor";
}; };

View File

@ -21,6 +21,10 @@ export function stateActive(stateObj: HassEntity, state?: string): boolean {
case "device_tracker": case "device_tracker":
case "person": case "person":
return compareState !== "not_home"; return compareState !== "not_home";
case "alarm_control_panel":
return compareState !== "disarmed";
case "lock":
return compareState !== "unlocked";
case "media_player": case "media_player":
return compareState !== "standby"; return compareState !== "standby";
case "vacuum": case "vacuum":

View File

@ -4,7 +4,6 @@ import { UpdateEntity, updateIsInstalling } from "../../data/update";
import { alarmControlPanelColor } from "./color/alarm_control_panel_color"; import { alarmControlPanelColor } from "./color/alarm_control_panel_color";
import { binarySensorColor } from "./color/binary_sensor_color"; import { binarySensorColor } from "./color/binary_sensor_color";
import { climateColor } from "./color/climate_color"; import { climateColor } from "./color/climate_color";
import { coverColor } from "./color/cover_color";
import { lockColor } from "./color/lock_color"; import { lockColor } from "./color/lock_color";
import { sensorColor } from "./color/sensor_color"; import { sensorColor } from "./color/sensor_color";
import { computeDomain } from "./compute_domain"; import { computeDomain } from "./compute_domain";
@ -21,7 +20,7 @@ export const stateColorCss = (stateObj?: HassEntity, state?: string) => {
return `var(--rgb-state-${color}-color)`; return `var(--rgb-state-${color}-color)`;
} }
return `var(--rgb-primary-color)`; return `var(--rgb-state-default-color)`;
}; };
export const stateColor = (stateObj: HassEntity, state?: string) => { export const stateColor = (stateObj: HassEntity, state?: string) => {
@ -36,11 +35,14 @@ export const stateColor = (stateObj: HassEntity, state?: string) => {
return binarySensorColor(stateObj); return binarySensorColor(stateObj);
case "cover": case "cover":
return coverColor(stateObj); return "cover";
case "climate": case "climate":
return climateColor(compareState); return climateColor(compareState);
case "fan":
return "fan";
case "lock": case "lock":
return lockColor(compareState); return lockColor(compareState);
@ -53,19 +55,21 @@ export const stateColor = (stateObj: HassEntity, state?: string) => {
case "media_player": case "media_player":
return "media-player"; return "media-player";
case "person":
case "device_tracker":
return "person";
case "sensor": case "sensor":
return sensorColor(stateObj); return sensorColor(stateObj);
case "vacuum": case "vacuum":
return "vacuum"; return "vacuum";
case "siren":
return "siren";
case "sun": case "sun":
return compareState === "above_horizon" ? "sun-day" : "sun-night"; return compareState === "above_horizon" ? "sun-day" : "sun-night";
case "switch":
return "switch";
case "update": case "update":
return updateIsInstalling(stateObj as UpdateEntity) return updateIsInstalling(stateObj as UpdateEntity)
? "update-installing" ? "update-installing"

View File

@ -136,22 +136,21 @@ documentContainer.innerHTML = `<custom-style>
--rgb-white-color: 255, 255, 255; --rgb-white-color: 255, 255, 255;
/* rgb state color */ /* rgb state color */
--rgb-state-alarm-armed-color: var(--rgb-green-color); --rgb-state-default-color: 68, 115, 158;
--rgb-state-alarm-disarmed-color: var(--rgb-primary-color); --rgb-state-alarm-armed-color: var(--rgb-red-color);
--rgb-state-alarm-pending-color: var(--rgb-orange-color); --rgb-state-alarm-pending-color: var(--rgb-orange-color);
--rgb-state-alarm-arming-color: var(--rgb-orange-color);
--rgb-state-alarm-triggered-color: var(--rgb-red-color); --rgb-state-alarm-triggered-color: var(--rgb-red-color);
--rgb-state-binary-sensor-color: var(--rgb-green-color); --rgb-state-binary-sensor-color: var(--rgb-primary-color);
--rgb-state-binary-sensor-danger-color: var(--rgb-red-color); --rgb-state-binary-sensor-alerting-color: var(--rgb-red-color);
--rgb-state-cover-color: var(--rgb-blue-color); --rgb-state-cover-color: var(--rgb-purple-color);
--rgb-state-cover-secure-color: var(--rgb-red-color); --rgb-state-fan-color: var(--rgb-cyan-color);
--rgb-state-humidifier-color: var(--rgb-deep-purple-color); --rgb-state-humidifier-color: var(--rgb-blue-color);
--rgb-state-light-color: var(--rgb-orange-color); --rgb-state-light-color: var(--rgb-amber-color);
--rgb-state-lock-jammed-color: var(--rgb-red-color); --rgb-state-lock-jammed-color: var(--rgb-red-color);
--rgb-state-lock-locked-color: var(--rgb-green-color); --rgb-state-lock-locked-color: var(--rgb-red-color);
--rgb-state-lock-pending-color: var(--rgb-orange-color); --rgb-state-lock-pending-color: var(--rgb-orange-color);
--rgb-state-lock-unlocked-color: var(--rgb-red-color);
--rgb-state-media-player-color: var(--rgb-indigo-color); --rgb-state-media-player-color: var(--rgb-indigo-color);
--rgb-state-person-color: var(--rgb-blue-grey-color);
--rgb-state-person-home-color: var(--rgb-green-color); --rgb-state-person-home-color: var(--rgb-green-color);
--rgb-state-person-not-home-color: var(--rgb-red-color); --rgb-state-person-not-home-color: var(--rgb-red-color);
--rgb-state-person-zone-color: var(--rgb-blue-color); --rgb-state-person-zone-color: var(--rgb-blue-color);
@ -159,23 +158,19 @@ documentContainer.innerHTML = `<custom-style>
--rgb-state-sensor-battery-low-color: var(--rgb-red-color); --rgb-state-sensor-battery-low-color: var(--rgb-red-color);
--rgb-state-sensor-battery-medium-color: var(--rgb-orange-color); --rgb-state-sensor-battery-medium-color: var(--rgb-orange-color);
--rgb-state-sensor-battery-unknown-color: var(--rgb-disabled-color); --rgb-state-sensor-battery-unknown-color: var(--rgb-disabled-color);
--rgb-state-sensor-color: var(--rgb-blue-grey-color); --rgb-state-siren-color: var(--rgb-red-color);
--rgb-state-sensor-energy-color: var(--rgb-amber-color);
--rgb-state-sensor-humidity-color: var(--rgb-deep-purple-color);
--rgb-state-sensor-illuminance-color: var(--rgb-amber-color);
--rgb-state-sensor-moisture-color: var(--rgb-light-blue-color);
--rgb-state-sensor-temperature-color: var(--rgb-deep-orange-color);
--rgb-state-sun-day-color: var(--rgb-amber-color); --rgb-state-sun-day-color: var(--rgb-amber-color);
--rgb-state-sun-night-color: var(--rgb-deep-purple-color); --rgb-state-sun-night-color: var(--rgb-deep-purple-color);
--rgb-state-switch-color: var(--rgb-amber-color);
--rgb-state-update-color: var(--rgb-green-color); --rgb-state-update-color: var(--rgb-green-color);
--rgb-state-update-installing-color: var(--rgb-orange-color); --rgb-state-update-installing-color: var(--rgb-orange-color);
--rgb-state-vacuum-color: var(--rgb-teal-color); --rgb-state-vacuum-color: var(--rgb-teal-color);
--rgb-state-climate-auto-color: var(--rgb-green-color); --rgb-state-climate-auto-color: var(--rgb-green-color);
--rgb-state-climate-cool-color: var(--rgb-blue-color); --rgb-state-climate-cool-color: var(--rgb-blue-color);
--rgb-state-climate-dry-color: var(--rgb-orange-color); --rgb-state-climate-dry-color: var(--rgb-orange-color);
--rgb-state-climate-fan-only-color: var(--rgb-teal-color); --rgb-state-climate-fan-only-color: var(--rgb-cyan-color);
--rgb-state-climate-heat-color: var(--rgb-deep-orange-color); --rgb-state-climate-heat-color: var(--rgb-deep-orange-color);
--rgb-state-climate-heat-cool-color: var(--rgb-green-color); --rgb-state-climate-heat-cool-color: var(--rgb-state-default-color);
--rgb-state-climate-idle-color: var(--rgb-disabled-color); --rgb-state-climate-idle-color: var(--rgb-disabled-color);
/* input components */ /* input components */