use device and area names in service call description (#13532)
This commit is contained in:
parent
93debac19a
commit
d041bd9fd3
|
@ -61,6 +61,7 @@ class HaDemo extends HomeAssistantAppEl {
|
|||
area_id: null,
|
||||
disabled_by: null,
|
||||
entity_id: "sensor.co2_intensity",
|
||||
unique_id: "sensor.co2_intensity",
|
||||
name: null,
|
||||
icon: null,
|
||||
platform: "co2signal",
|
||||
|
@ -74,6 +75,7 @@ class HaDemo extends HomeAssistantAppEl {
|
|||
area_id: null,
|
||||
disabled_by: null,
|
||||
entity_id: "sensor.grid_fossil_fuel_percentage",
|
||||
unique_id: "sensor.co2_intensity",
|
||||
name: null,
|
||||
icon: null,
|
||||
platform: "co2signal",
|
||||
|
|
|
@ -191,6 +191,7 @@ const createEntityRegistryEntries = (
|
|||
hidden_by: null,
|
||||
entity_category: null,
|
||||
entity_id: "binary_sensor.updater",
|
||||
unique_id: "binary_sensor.updater",
|
||||
name: null,
|
||||
icon: null,
|
||||
platform: "updater",
|
||||
|
|
|
@ -2,6 +2,12 @@ import secondsToDuration from "../common/datetime/seconds_to_duration";
|
|||
import { computeStateName } from "../common/entity/compute_state_name";
|
||||
import type { HomeAssistant } from "../types";
|
||||
import { Condition, Trigger } from "./automation";
|
||||
import {
|
||||
DeviceCondition,
|
||||
DeviceTrigger,
|
||||
localizeDeviceAutomationCondition,
|
||||
localizeDeviceAutomationTrigger,
|
||||
} from "./device_automation";
|
||||
import { formatAttributeName } from "./entity_attributes";
|
||||
|
||||
export const describeTrigger = (
|
||||
|
@ -292,6 +298,19 @@ export const describeTrigger = (
|
|||
if (trigger.platform === "webhook") {
|
||||
return "When a Webhook payload has been received";
|
||||
}
|
||||
|
||||
if (trigger.platform === "device") {
|
||||
const config = trigger as DeviceTrigger;
|
||||
const localized = localizeDeviceAutomationTrigger(hass, config);
|
||||
if (localized) {
|
||||
return localized;
|
||||
}
|
||||
const stateObj = hass.states[config.entity_id as string];
|
||||
return `${stateObj ? computeStateName(stateObj) : config.entity_id} ${
|
||||
config.type
|
||||
}`;
|
||||
}
|
||||
|
||||
return `${trigger.platform || "Unknown"} trigger`;
|
||||
};
|
||||
|
||||
|
@ -467,5 +486,17 @@ export const describeCondition = (
|
|||
}`;
|
||||
}
|
||||
|
||||
if (condition.condition === "device") {
|
||||
const config = condition as DeviceCondition;
|
||||
const localized = localizeDeviceAutomationCondition(hass, config);
|
||||
if (localized) {
|
||||
return localized;
|
||||
}
|
||||
const stateObj = hass.states[config.entity_id as string];
|
||||
return `${stateObj ? computeStateName(stateObj) : config.entity_id} ${
|
||||
config.type
|
||||
}`;
|
||||
}
|
||||
|
||||
return `${condition.condition} condition`;
|
||||
};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { Connection, createCollection } from "home-assistant-js-websocket";
|
||||
import { Store } from "home-assistant-js-websocket/dist/store";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { computeStateName } from "../common/entity/compute_state_name";
|
||||
import { caseInsensitiveStringCompare } from "../common/string/compare";
|
||||
import { debounce } from "../common/util/debounce";
|
||||
|
@ -7,6 +8,7 @@ import { HomeAssistant } from "../types";
|
|||
|
||||
export interface EntityRegistryEntry {
|
||||
entity_id: string;
|
||||
unique_id: string;
|
||||
name: string | null;
|
||||
icon: string | null;
|
||||
platform: string;
|
||||
|
@ -21,7 +23,6 @@ export interface EntityRegistryEntry {
|
|||
}
|
||||
|
||||
export interface ExtEntityRegistryEntry extends EntityRegistryEntry {
|
||||
unique_id: string;
|
||||
capabilities: Record<string, unknown>;
|
||||
original_icon?: string;
|
||||
device_class?: string;
|
||||
|
@ -161,6 +162,16 @@ export const sortEntityRegistryByName = (entries: EntityRegistryEntry[]) =>
|
|||
caseInsensitiveStringCompare(entry1.name || "", entry2.name || "")
|
||||
);
|
||||
|
||||
export const entityRegistryByUniqueId = memoizeOne(
|
||||
(entries: HomeAssistant["entities"]) => {
|
||||
const entities: HomeAssistant["entities"] = {};
|
||||
for (const entity of Object.values(entries)) {
|
||||
entities[entity.unique_id] = entity;
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
);
|
||||
|
||||
export const getEntityPlatformLookup = (
|
||||
entities: EntityRegistryEntry[]
|
||||
): Record<string, string> => {
|
||||
|
|
|
@ -5,6 +5,13 @@ import { isTemplate } from "../common/string/has-template";
|
|||
import { HomeAssistant } from "../types";
|
||||
import { Condition } from "./automation";
|
||||
import { describeCondition, describeTrigger } from "./automation_i18n";
|
||||
import { localizeDeviceAutomationAction } from "./device_automation";
|
||||
import { computeDeviceName } from "./device_registry";
|
||||
import {
|
||||
computeEntityRegistryName,
|
||||
entityRegistryByUniqueId,
|
||||
} from "./entity_registry";
|
||||
import { domainToName } from "./integration";
|
||||
import {
|
||||
ActionType,
|
||||
ActionTypes,
|
||||
|
@ -47,7 +54,11 @@ export const describeAction = <T extends ActionType>(
|
|||
) {
|
||||
base = "Call a service based on a template";
|
||||
} else if (config.service) {
|
||||
base = `Call service ${config.service}`;
|
||||
const [domain, serviceName] = config.service.split(".", 2);
|
||||
const service = hass.services[domain][serviceName];
|
||||
base = service
|
||||
? `${domainToName(hass.localize, domain)}: ${service.name}`
|
||||
: `Call service: ${config.service}`;
|
||||
} else {
|
||||
return actionType;
|
||||
}
|
||||
|
@ -66,26 +77,51 @@ export const describeAction = <T extends ActionType>(
|
|||
? config.target[key]
|
||||
: [config.target[key]];
|
||||
|
||||
const values: string[] = [];
|
||||
|
||||
let renderValues = true;
|
||||
|
||||
for (const targetThing of keyConf) {
|
||||
if (isTemplate(targetThing)) {
|
||||
targets.push(`templated ${label}`);
|
||||
renderValues = false;
|
||||
break;
|
||||
} else if (key === "entity_id") {
|
||||
if (targetThing.includes(".")) {
|
||||
const state = hass.states[targetThing];
|
||||
if (state) {
|
||||
targets.push(computeStateName(state));
|
||||
} else {
|
||||
targets.push(targetThing);
|
||||
}
|
||||
} else {
|
||||
const entityReg = entityRegistryByUniqueId(hass.entities)[
|
||||
targetThing
|
||||
];
|
||||
if (entityReg) {
|
||||
targets.push(
|
||||
computeEntityRegistryName(hass, entityReg) || targetThing
|
||||
);
|
||||
} else {
|
||||
targets.push(targetThing);
|
||||
}
|
||||
}
|
||||
} else if (key === "device_id") {
|
||||
const device = hass.devices[targetThing];
|
||||
if (device) {
|
||||
targets.push(computeDeviceName(device, hass));
|
||||
} else {
|
||||
targets.push(targetThing);
|
||||
}
|
||||
} else if (key === "area_id") {
|
||||
const area = hass.areas[targetThing];
|
||||
if (area?.name) {
|
||||
targets.push(area.name);
|
||||
} else {
|
||||
targets.push(targetThing);
|
||||
}
|
||||
} else {
|
||||
values.push(targetThing);
|
||||
targets.push(targetThing);
|
||||
}
|
||||
}
|
||||
|
||||
if (renderValues) {
|
||||
targets.push(`${label} ${values.join(", ")}`);
|
||||
}
|
||||
}
|
||||
if (targets.length > 0) {
|
||||
base += ` on ${targets.join(", ")}`;
|
||||
base += ` ${targets.join(", ")}`;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -175,11 +211,15 @@ export const describeAction = <T extends ActionType>(
|
|||
if (actionType === "if") {
|
||||
const config = action as IfAction;
|
||||
return `Perform an action if: ${
|
||||
typeof config.if === "string"
|
||||
!config.if
|
||||
? ""
|
||||
: typeof config.if === "string"
|
||||
? config.if
|
||||
: ensureArray(config.if).length > 1
|
||||
? `${ensureArray(config.if).length} conditions`
|
||||
: describeCondition(ensureArray(config.if)[0], hass)
|
||||
: ensureArray(config.if).length
|
||||
? describeCondition(ensureArray(config.if)[0], hass)
|
||||
: ""
|
||||
}${config.else ? " (or else!)" : ""}`;
|
||||
}
|
||||
|
||||
|
@ -219,6 +259,10 @@ export const describeAction = <T extends ActionType>(
|
|||
|
||||
if (actionType === "device_action") {
|
||||
const config = action as DeviceAction;
|
||||
const localized = localizeDeviceAutomationAction(hass, config);
|
||||
if (localized) {
|
||||
return localized;
|
||||
}
|
||||
const stateObj = hass.states[config.entity_id as string];
|
||||
return `${config.type || "Perform action with"} ${
|
||||
stateObj ? computeStateName(stateObj) : config.entity_id
|
||||
|
|
|
@ -68,9 +68,10 @@ import type { HomeAssistant, Route } from "../../../types";
|
|||
import { configSections } from "../ha-panel-config";
|
||||
import "../integrations/ha-integration-overflow-menu";
|
||||
|
||||
export interface StateEntity extends EntityRegistryEntry {
|
||||
export interface StateEntity extends Omit<EntityRegistryEntry, "unique_id"> {
|
||||
readonly?: boolean;
|
||||
selectable?: boolean;
|
||||
unique_id?: string;
|
||||
}
|
||||
|
||||
export interface EntityRow extends StateEntity {
|
||||
|
@ -302,7 +303,7 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
|
|||
|
||||
private _filteredEntitiesAndDomains = memoize(
|
||||
(
|
||||
entities: EntityRegistryEntry[],
|
||||
entities: StateEntity[],
|
||||
devices: DeviceRegistryEntry[] | undefined,
|
||||
areas: AreaRegistryEntry[] | undefined,
|
||||
stateEntities: StateEntity[],
|
||||
|
@ -392,7 +393,10 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
|
|||
result.push({
|
||||
...entry,
|
||||
entity,
|
||||
name: computeEntityRegistryName(this.hass!, entry),
|
||||
name: computeEntityRegistryName(
|
||||
this.hass!,
|
||||
entry as EntityRegistryEntry
|
||||
),
|
||||
unavailable,
|
||||
restored,
|
||||
area: area ? area.name : "—",
|
||||
|
|
Loading…
Reference in New Issue