diff --git a/lib/extension/homeassistant.ts b/lib/extension/homeassistant.ts index a004948e..193b95ad 100644 --- a/lib/extension/homeassistant.ts +++ b/lib/extension/homeassistant.ts @@ -335,6 +335,29 @@ const featurePropertyWithoutEndpoint = (feature: zhc.Feature): string => { return feature.property; }; +const applyHomeAssistantExposeMetadata = (payload: KeyValue, homeAssistant: zhc.Expose["homeassistant"]): void => { + const metadata = homeAssistant as KeyValue | undefined; + if (!metadata) { + return; + } + + if (typeof metadata.entityCategory === "string") { + payload.entity_category = metadata.entityCategory; + } + + if (typeof metadata.deviceClass === "string") { + payload.device_class = metadata.deviceClass; + } + + if (typeof metadata.enabledByDefault === "boolean") { + payload.enabled_by_default = metadata.enabledByDefault; + } + + if (typeof metadata.icon === "string") { + payload.icon = metadata.icon; + } +}; + /** * This class handles the bridge entity configuration for Home Assistant Discovery. */ @@ -1344,6 +1367,8 @@ export class HomeAssistant extends Extension { } for (const entry of discoveryEntries) { + applyHomeAssistantExposeMetadata(entry.discovery_payload, firstExpose.homeassistant); + // If a sensor has entity category `config`, then change // it to `diagnostic`. Sensors have no input, so can't be configured. // https://github.com/Koenkk/zigbee2mqtt/pull/19474 diff --git a/test/extensions/homeassistant.test.ts b/test/extensions/homeassistant.test.ts index 3045f02a..d0719fdd 100644 --- a/test/extensions/homeassistant.test.ts +++ b/test/extensions/homeassistant.test.ts @@ -174,6 +174,40 @@ describe("Extension: HomeAssistant", () => { } }); + it("Should apply expose-level Home Assistant discovery metadata", () => { + const createDevice = (exposes: zhc.Expose[]): Device => + ({ + definition: {}, + isDevice: (): boolean => true, + isGroup: (): boolean => false, + endpoint: () => undefined, + options: {}, + exposes: (): zhc.Expose[] => exposes, + zh: {endpoints: []}, + }) as Device; + + const voltageExpose = new zhc.Numeric("voltage", zhc.access.STATE).withUnit("V"); + Object.assign(voltageExpose, { + homeassistant: { + type: "valve", + entityCategory: "diagnostic", + deviceClass: "voltage", + enabledByDefault: false, + icon: "mdi:flash", + }, + }); + + // @ts-expect-error private + const configs = extension.getConfigs(createDevice([voltageExpose])); + expect(configs.find((config) => config.object_id === "voltage")?.discovery_payload).toMatchObject({ + device_class: "voltage", + enabled_by_default: false, + entity_category: "diagnostic", + icon: "mdi:flash", + }); + expect(configs.find((config) => config.object_id === "voltage")?.discovery_payload).not.toHaveProperty("type"); + }); + it("Should discover devices and groups", async () => { settings.set(["homeassistant", "experimental_event_entities"], true); settings.set(["groups", "9", "homeassistant"], {name: "HA Discovery Group", icon: "mdi:lightbulb-group"});